public inbox for frysk-cvs@sourceware.org help / color / mirror / Atom feed
From: cagney@sourceware.org To: frysk-cvs@sourceware.org Subject: [SCM] master: Prototype lib/dwfl in JNI. Date: Mon, 26 May 2008 18:20:00 -0000 [thread overview] Message-ID: <20080526182043.19336.qmail@sourceware.org> (raw) The branch, master has been updated via 24f79f595d4d0b1123dc6270f76de92f3b0b9ad4 (commit) from 908e55a3ee987daa0209107ae8a09ab1e562c936 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email. - Log ----------------------------------------------------------------- commit 24f79f595d4d0b1123dc6270f76de92f3b0b9ad4 Author: Andrew Cagney <cagney@redhat.com> Date: Mon May 26 14:16:47 2008 -0400 Prototype lib/dwfl in JNI. frysk-sys/ChangeLog 2008-05-26 Andrew Cagney <cagney@redhat.com> * Makefile.am (JNIXX_CLASSES): Add DwAttributeNotFoundException, ElfException, and java.lang.Long. frysk-sys/lib/dwfl/ChangeLog 2008-05-26 Andrew Cagney <cagney@redhat.com> * jni/ElfSymbol.cxx: Implement. * jni/ElfSection.cxx: Implement. * jni/ElfRel.cxx: Implement. * jni/ElfPrXFPRegSet.cxx: Implement. * jni/ElfPrpsinfo.cxx: Implement. * jni/ElfPrFPRegSet.cxx: Implement. * jni/ElfPrAuxv.cxx: Implement. * jni/ElfNhdr.cxx: Implement. * jni/ElfDynamic.cxx: Implement. * jni/ElfData.cxx: Implement. * jni/Elf.cxx: Implement. * jni/ElfArchiveSymbol.cxx: Implement. * jni/DwflModule.cxx: Implement. * jni/DwflLine.cxx: Implement. * jni/Dwfl.cxx: Implement. * jni/DwException.cxx: Implement. * jni/DwarfDie.cxx: Implement. * jni/Dwarf.cxx: Implement. * jni/Disassembler.cxx: Implement. ----------------------------------------------------------------------- Summary of changes: frysk-sys/ChangeLog | 5 + frysk-sys/Makefile.am | 3 + frysk-sys/lib/dwfl/ChangeLog | 22 + frysk-sys/lib/dwfl/jni/DwException.cxx | 20 +- frysk-sys/lib/dwfl/jni/Dwarf.cxx | 128 ++++++- frysk-sys/lib/dwfl/jni/DwarfDie.cxx | 566 ++++++++++++++++++++++++++- frysk-sys/lib/dwfl/jni/Dwfl.cxx | 233 +++++++++++- frysk-sys/lib/dwfl/jni/DwflLine.cxx | 47 +++- frysk-sys/lib/dwfl/jni/DwflModule.cxx | 372 ++++++++++++++++++- frysk-sys/lib/dwfl/jni/Elf.cxx | 336 ++++++++++++++++- frysk-sys/lib/dwfl/jni/ElfArchiveSymbol.cxx | 25 ++- frysk-sys/lib/dwfl/jni/ElfData.cxx | 133 +++++++- frysk-sys/lib/dwfl/jni/ElfDynamic.cxx | 20 +- frysk-sys/lib/dwfl/jni/ElfNhdr.cxx | 54 +++ frysk-sys/lib/dwfl/jni/ElfPrAuxv.cxx | 78 ++++- frysk-sys/lib/dwfl/jni/ElfPrFPRegSet.cxx | 88 ++++- frysk-sys/lib/dwfl/jni/ElfPrXFPRegSet.cxx | 91 +++++- frysk-sys/lib/dwfl/jni/ElfPrpsinfo.cxx | 186 +++++++++- frysk-sys/lib/dwfl/jni/ElfPrstatus.cxx | 273 +++++++++++++- frysk-sys/lib/dwfl/jni/ElfRel.cxx | 34 ++- frysk-sys/lib/dwfl/jni/ElfSection.cxx | 93 +++++- frysk-sys/lib/dwfl/jni/ElfSymbol.cxx | 141 +++++++- 22 files changed, 2930 insertions(+), 18 deletions(-) First 500 lines of diff: diff --git a/frysk-sys/ChangeLog b/frysk-sys/ChangeLog index abf4466..89258b2 100644 --- a/frysk-sys/ChangeLog +++ b/frysk-sys/ChangeLog @@ -1,3 +1,8 @@ +2008-05-26 Andrew Cagney <cagney@redhat.com> + + * Makefile.am (JNIXX_CLASSES): Add DwAttributeNotFoundException, + ElfException, and java.lang.Long. + 2008-05-22 Andrew Cagney <cagney@redhat.com> * lib/opcodes/: Delete. diff --git a/frysk-sys/Makefile.am b/frysk-sys/Makefile.am index d65e207..10221c5 100644 --- a/frysk-sys/Makefile.am +++ b/frysk-sys/Makefile.am @@ -76,6 +76,9 @@ lib/unwind/Unwind%.java: lib/unwind/Unwind.java JNIXX_CLASSES += frysk.sys.ProcessIdentifierFactory JNIXX_CLASSES += java.lang.ArrayIndexOutOfBoundsException JNIXX_CLASSES += frysk.sys.Errno$$Esrch +JNIXX_CLASSES += lib.dwfl.DwAttributeNotFoundException +JNIXX_CLASSES += java.lang.Long +JNIXX_CLASSES += lib.dwfl.ElfException \f # Quick hack to get a test JNI program up-and-running; as a package is diff --git a/frysk-sys/lib/dwfl/ChangeLog b/frysk-sys/lib/dwfl/ChangeLog index 33044d1..d16b387 100644 --- a/frysk-sys/lib/dwfl/ChangeLog +++ b/frysk-sys/lib/dwfl/ChangeLog @@ -1,3 +1,25 @@ +2008-05-26 Andrew Cagney <cagney@redhat.com> + + * jni/ElfSymbol.cxx: Implement. + * jni/ElfSection.cxx: Implement. + * jni/ElfRel.cxx: Implement. + * jni/ElfPrXFPRegSet.cxx: Implement. + * jni/ElfPrpsinfo.cxx: Implement. + * jni/ElfPrFPRegSet.cxx: Implement. + * jni/ElfPrAuxv.cxx: Implement. + * jni/ElfNhdr.cxx: Implement. + * jni/ElfDynamic.cxx: Implement. + * jni/ElfData.cxx: Implement. + * jni/Elf.cxx: Implement. + * jni/ElfArchiveSymbol.cxx: Implement. + * jni/DwflModule.cxx: Implement. + * jni/DwflLine.cxx: Implement. + * jni/Dwfl.cxx: Implement. + * jni/DwException.cxx: Implement. + * jni/DwarfDie.cxx: Implement. + * jni/Dwarf.cxx: Implement. + * jni/Disassembler.cxx: Implement. + 2008-05-24 Andrew Cagney <cagney@redhat.com> * Elf.java: Replace RawData with long. diff --git a/frysk-sys/lib/dwfl/jni/DwException.cxx b/frysk-sys/lib/dwfl/jni/DwException.cxx index b358932..abd01de 100644 --- a/frysk-sys/lib/dwfl/jni/DwException.cxx +++ b/frysk-sys/lib/dwfl/jni/DwException.cxx @@ -1,6 +1,6 @@ // This file is part of the program FRYSK. // -// Copyright 2008, Red Hat Inc. +// Copyright 2005, 2008, Red Hat Inc. // // FRYSK is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by @@ -37,4 +37,22 @@ // version and license this file solely under the GPL without // exception. +#include <libdw.h> + #include "jni.hxx" + +using namespace java::lang; + +String +lib::dwfl::DwException::getDwErrMessage(jnixx::env env, jint errno) { + const char *message = dwarf_errmsg(errno); + if (message != NULL) + return String::NewStringUTF(env, message); + else + return String(env, NULL); +} + +void +lib::dwfl::DwException::throwDwException(jnixx::env env) { + throwDwException(env, dwarf_errno()); +} diff --git a/frysk-sys/lib/dwfl/jni/Dwarf.cxx b/frysk-sys/lib/dwfl/jni/Dwarf.cxx index b358932..4a9bbf4 100644 --- a/frysk-sys/lib/dwfl/jni/Dwarf.cxx +++ b/frysk-sys/lib/dwfl/jni/Dwarf.cxx @@ -1,6 +1,6 @@ // This file is part of the program FRYSK. // -// Copyright 2008, Red Hat Inc. +// Copyright 2005, 2007, 2008, Red Hat Inc. // // FRYSK is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by @@ -37,4 +37,130 @@ // version and license this file solely under the GPL without // exception. +#include <alloca.h> +#include <string.h> +#include <malloc.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> + +#include <libdw.h> + #include "jni.hxx" + +#include "jnixx/elements.hxx" + +using namespace java::lang; +using namespace java::util; + +#define DWARF_POINTER ((::Dwarf *) GetPointer(env)) + +void +lib::dwfl::Dwarf::dwarf_begin_elf(jnixx::env env, jlong elf, jint command, + jlong section) { + jlong pointer = (jlong) + ::dwarf_begin_elf((::Elf*) elf, (::Dwarf_Cmd) command, + (::Elf_Scn*) section); + SetPointer(env, pointer); +} + +void +lib::dwfl::Dwarf::dwarf_begin(jnixx::env env, String file, jint command){ + jstringUTFChars fileName = jstringUTFChars(env, file); + errno = 0; + int fd = ::open(fileName.elements(), O_RDONLY); + jlong pointer = (jlong) ::dwarf_begin(fd, (::Dwarf_Cmd) command); + SetPointer(env, pointer); +} + + +LinkedList +lib::dwfl::Dwarf::get_cu_by_name(jnixx::env env, String name) { + LinkedList list = LinkedList::New(env); + + Dwarf_Off offset = 0; + Dwarf_Off old_offset; + Dwarf_Die cudie_mem; + size_t hsize; + + while (dwarf_nextcu(DWARF_POINTER, old_offset = offset, + &offset, &hsize, NULL, NULL, NULL) == 0) { + + Dwarf_Die *cudie = dwarf_offdie(DWARF_POINTER, old_offset + hsize, + &cudie_mem); + const char *die_name = dwarf_diename (cudie); + String die_name_string = String::NewStringUTF(env, die_name); + + if (die_name_string.endsWith(env, name)) { + + Dwarf_Die *die = (Dwarf_Die*)::malloc(sizeof(Dwarf_Die)); + memcpy(die, cudie, sizeof(*die)); + lib::dwfl::DwarfDie cuDie = lib::dwfl::DwarfDieFactory::getFactory(env) + .makeDie(env, (jlong)die, lib::dwfl::DwflModule(env, NULL)); + cuDie.setManageDie(env, true); + list.add(env, cuDie); + } + die_name_string.DeleteLocalRef(env); + } + return list; +} + + +jnixx::array<String> +lib::dwfl::Dwarf::get_source_files(jnixx::env env) { + Dwarf_Off offset = 0; + Dwarf_Off old_offset; + Dwarf_Die cudie_mem; + size_t hsize; + Dwarf_Files **files; + size_t *nfiles; + size_t cu_cnt; + + // Allocate Dwarf_Files for each compile unit + cu_cnt = 0; + while (dwarf_nextcu(DWARF_POINTER, old_offset = offset, &offset, + &hsize, NULL, NULL, NULL) == 0) { + cu_cnt += 1; + } + files = (Dwarf_Files**)alloca (cu_cnt * sizeof (Dwarf_Files*)); + nfiles = (size_t*)alloca (cu_cnt * sizeof (size_t)); + + // Fill Dwarf_Files + cu_cnt = 0; + offset = 0; + while (dwarf_nextcu(DWARF_POINTER, old_offset = offset, &offset, + &hsize, NULL, NULL, NULL) == 0) { + size_t fcnt = 0; + Dwarf_Die *cudie = dwarf_offdie (DWARF_POINTER, old_offset + hsize, &cudie_mem); + if (dwarf_getsrcfiles (cudie, &files[cu_cnt], &fcnt) != 0) + continue; + nfiles[cu_cnt] = fcnt; + cu_cnt += 1; + } + + // Allocate JArray for each source file + size_t entry_cnt = 0; + for (size_t cu = 0 ; cu < cu_cnt; cu += 1) + for (size_t f = 0; f < nfiles[cu]; f += 1) + entry_cnt += 1; + jnixx::array<String> jfiles + = jnixx::array<String>::NewObjectArray(env, entry_cnt); + + // Fill JArray + size_t j = 0; + for (size_t cu = 0 ; cu < cu_cnt; cu += 1) { + for (size_t f = 0; f < nfiles[cu]; f += 1) { + const char *file = dwarf_filesrc (files[cu], f, NULL, NULL); + String jfile = String::NewStringUTF(env, file); + jfiles.SetObjectArrayElement(env, j, jfile); + jfile.DeleteLocalRef(env); + j += 1; + } + } + return jfiles; +} + +jint +lib::dwfl::Dwarf::dwarf_end(jnixx::env env){ + return ::dwarf_end(DWARF_POINTER); +} diff --git a/frysk-sys/lib/dwfl/jni/DwarfDie.cxx b/frysk-sys/lib/dwfl/jni/DwarfDie.cxx index b358932..250217a 100644 --- a/frysk-sys/lib/dwfl/jni/DwarfDie.cxx +++ b/frysk-sys/lib/dwfl/jni/DwarfDie.cxx @@ -1,6 +1,6 @@ // This file is part of the program FRYSK. // -// Copyright 2008, Red Hat Inc. +// Copyright 2005, 2007, 2008, Red Hat Inc. // // FRYSK is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by @@ -37,4 +37,568 @@ // version and license this file solely under the GPL without // exception. +#include <stdio.h> +#include <stdlib.h> + +#include <libdw.h> +#include <dwarf.h> + #include "jni.hxx" + +#include "jnixx/elements.hxx" + +using namespace java::lang; + +#define DWARF_DIE_POINTER ((Dwarf_Die *) GetPointer(env)) + +jlong +lib::dwfl::DwarfDie::get_lowpc(jnixx::env env) { + Dwarf_Addr lowpc; + ::dwarf_lowpc(DWARF_DIE_POINTER, &lowpc); + return (jlong) lowpc; +} + +jlong +lib::dwfl::DwarfDie::get_highpc(jnixx::env env) { + Dwarf_Addr highpc; + ::dwarf_highpc(DWARF_DIE_POINTER, &highpc); + return (jlong) highpc; +} + +jlong +lib::dwfl::DwarfDie::get_entrypc(jnixx::env env) { + Dwarf_Addr entrypc; + ::dwarf_entrypc(DWARF_DIE_POINTER, &entrypc); + return (jlong) entrypc; +} + +String +lib::dwfl::DwarfDie::get_diename(jnixx::env env) { + const char *name = dwarf_diename (DWARF_DIE_POINTER); + if (name != NULL) + return String::NewStringUTF(env, name); + else + return String::NewStringUTF(env, ""); +} + +String +lib::dwfl::DwarfDie::get_decl_file(jnixx::env env, jlong var_die) { + Dwarf_Die *die = (Dwarf_Die*) var_die; + const char *name = dwarf_decl_file (die); + if (name == NULL) { + lib::dwfl::DwAttributeNotFoundException::throwDwException(env, (jint)DW_AT_decl_file); + } + return String::NewStringUTF(env, name); +} + +jint +lib::dwfl::DwarfDie::get_decl_line(jnixx::env env, jlong var_die) { + Dwarf_Die *die = (Dwarf_Die*) var_die; + int lineno; + if (dwarf_decl_line (die, &lineno) != 0){ + Dwarf_Attribute type_attr; + Dwarf_Word constant; + if (dwarf_attr_integrate (die, DW_AT_decl_line, &type_attr)){ + dwarf_formudata (&type_attr, &constant); + return constant; + }else{ + lib::dwfl::DwAttributeNotFoundException::throwDwException(env, (jint)DW_AT_decl_line); + } + } + + return lineno; +} + +jint +lib::dwfl::DwarfDie::get_decl_column(jnixx::env env, jlong var_die) { + Dwarf_Die *die = (Dwarf_Die*) var_die; + int column; + int code = dwarf_decl_column (die, &column); + if (code != 0) + column = 0; + return column; +} + +jnixx::jlongArray +lib::dwfl::DwarfDie::get_scopes(jnixx::env env, jlong addr) { + Dwarf_Die *dies; + int count = dwarf_getscopes(DWARF_DIE_POINTER, (Dwarf_Addr) addr, &dies); + if (count == -1) + count = 0; + jnixx::jlongArray scopes = jnixx::jlongArray::NewLongArray(env, (jint) count); + jlongArrayElements longs = jlongArrayElements(env, scopes); + for(int i = 0; i < count; i++) { + longs.elements()[i] = (jlong) &dies[i]; + } + return scopes; +} + +jnixx::jlongArray +lib::dwfl::DwarfDie::get_scopes_die(jnixx::env env) { + Dwarf_Die *dies; + int count = dwarf_getscopes_die(DWARF_DIE_POINTER, &dies); + if (count == -1) + count = 0; + jnixx::jlongArray longs = jnixx::jlongArray::NewLongArray(env, (jint) count); + jlongArrayElements longsp = jlongArrayElements(env, longs); + for(int i = 0; i < count; i++) { + longsp.elements()[i] = (jlong) &dies[i]; + } + return longs; +} + +jlong +lib::dwfl::DwarfDie::get_scopevar(jnixx::env env, jnixx::jlongArray jdie_scope, + jnixx::jlongArray jscopes, String jvariable) { + // FIXME: This appears to be leaked? + Dwarf_Die *var_die = (Dwarf_Die*)::malloc(sizeof(Dwarf_Die)); + jlongArrayElements scopes = jlongArrayElements(env, jscopes); + Dwarf_Die *dies[scopes.length()]; + for(int i = 0; i < scopes.length(); i++) { + jlong dieptr = scopes.elements()[i]; + dies[i] = (Dwarf_Die*)dieptr; + } + jstringUTFChars variable = jstringUTFChars(env, jvariable); + int code = dwarf_getscopevar (*dies, scopes.length(), + variable.elements(), + 0, NULL, 0, 0, var_die); + if (code >= 0) { + if (dwarf_tag (var_die) != DW_TAG_variable) + return -1; + jlongArrayElements die_scope = jlongArrayElements(env, jdie_scope); + die_scope.elements()[0] = (jlong)var_die; // Die for variable + die_scope.elements()[1] = code; // Die for scope + } else if (dwarf_tag (var_die) != DW_TAG_variable) { + return -1; + } + return code; +} + +static Dwarf_Die +get_first_struct_member(Dwarf_Die &result) { + Dwarf_Attribute attr_mem; + do { + dwarf_formref_die (dwarf_attr_integrate (&result, DW_AT_type, &attr_mem), + &result); + if (dwarf_tag (&result) == DW_TAG_structure_type) { + dwarf_child (&result, &result); + break; + } + } while (1); + return result; +} + +jlong +lib::dwfl::DwarfDie::get_scopevar_names(jnixx::env env, + jnixx::jlongArray jscopes, + String jvariable) { + jlongArrayElements scopes = jlongArrayElements(env, jscopes); + Dwarf_Die *scope_dies[scopes.length()]; + Dwarf_Die result; + int get_struct_members = 0; + + jstringUTFChars variablep = jstringUTFChars(env, jvariable); + int variable_len = variablep.length(); + char variable[variable_len + 1]; + strcpy(variable, variablep.elements()); + if (variable[variable_len - 1] == '.') { + variable[variable_len - 1] = '\0'; + get_struct_members = 1; + } + + for(int i = 0; i < scopes.length(); i++) { + jlong dieptr = scopes.elements()[i]; + scope_dies[i] = (Dwarf_Die*)dieptr; + } + + /* Start with the innermost scope and move out. */ + for (int out = 0; out < scopes.length(); ++out) { + if (dwarf_haschildren (scope_dies[out])) { + if (dwarf_child (scope_dies[out], &result) != 0) { + return -1; + } + do { + switch (dwarf_tag (&result)) { + case DW_TAG_variable: + case DW_TAG_formal_parameter: + case DW_TAG_subprogram: + break; + + default: + continue; + } + + Dwarf_Attribute attr_mem; + const char *diename = dwarf_formstring + (dwarf_attr_integrate (&result, DW_AT_name, &attr_mem)); + if (diename != NULL && !strncmp (diename, variable, variable_len)) { + if (get_struct_members) { + result = get_first_struct_member (result); + do { + diename = dwarf_formstring + (dwarf_attr_integrate (&result, DW_AT_name, &attr_mem)); + lib::dwfl::DwarfDie::addScopeVarName(env, String::NewStringUTF(env, diename)); + } while (dwarf_siblingof (&result, &result) == 0); + return 0; + } + addScopeVarName(env, String::NewStringUTF(env, diename)); + } + } while (dwarf_siblingof (&result, &result) == 0); + } + } + return 0; +} + +void +lib::dwfl::DwarfDie::get_addr(jnixx::env env, jlong var_die, jlong pc) { + + Dwarf_Die *die = (Dwarf_Die*) var_die; + Dwarf_Attribute loc_attr; + Dwarf_Op *fb_expr; + size_t fb_len; + + if (dwarf_attr_integrate (die, DW_AT_location, &loc_attr)) { + size_t i = 0; + int nlocs; + bool ok = false; + + if (pc == 0){ + nlocs = dwarf_getlocation (&loc_attr, &fb_expr, &fb_len); + if (nlocs >= 0 && fb_len > 0) + ok = true; + } else { + nlocs = dwarf_getlocation_addr (&loc_attr,pc, &fb_expr, &fb_len, 5); + if (nlocs > 0 && fb_len > 0) + ok = true; + } + + if (ok) { + do { + addOps(env, fb_expr[i].atom, fb_expr[i].number, fb_expr[i].number2, + fb_expr[i].offset); + i += 1; + } while (i < fb_len); + } + } +} + +jlong +lib::dwfl::DwarfDie::get_type(jnixx::env env, jlong var_die, + bool follow_type_def) { + Dwarf_Die *die = (Dwarf_Die*) var_die; hooks/post-receive -- frysk system monitor/debugger
reply other threads:[~2008-05-26 18:20 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20080526182043.19336.qmail@sourceware.org \ --to=cagney@sourceware.org \ --cc=frysk-cvs@sourceware.org \ --cc=frysk@sourceware.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).