From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 19376 invoked by alias); 26 May 2008 18:20:44 -0000 Received: (qmail 19351 invoked by uid 367); 26 May 2008 18:20:43 -0000 Date: Mon, 26 May 2008 18:20:00 -0000 Message-ID: <20080526182043.19336.qmail@sourceware.org> From: cagney@sourceware.org To: frysk-cvs@sourceware.org Subject: [SCM] master: Prototype lib/dwfl in JNI. X-Git-Refname: refs/heads/master X-Git-Reftype: branch X-Git-Oldrev: 908e55a3ee987daa0209107ae8a09ab1e562c936 X-Git-Newrev: 24f79f595d4d0b1123dc6270f76de92f3b0b9ad4 Mailing-List: contact frysk-cvs-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: frysk-cvs-owner@sourceware.org Reply-To: frysk@sourceware.org X-SW-Source: 2008-q2/txt/msg00289.txt.bz2 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 Date: Mon May 26 14:16:47 2008 -0400 Prototype lib/dwfl in JNI. frysk-sys/ChangeLog 2008-05-26 Andrew Cagney * Makefile.am (JNIXX_CLASSES): Add DwAttributeNotFoundException, ElfException, and java.lang.Long. frysk-sys/lib/dwfl/ChangeLog 2008-05-26 Andrew Cagney * 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 + + * Makefile.am (JNIXX_CLASSES): Add DwAttributeNotFoundException, + ElfException, and java.lang.Long. + 2008-05-22 Andrew Cagney * 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 # 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 + + * 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 * 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 + #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 +#include +#include +#include +#include +#include + +#include + #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 +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 jfiles + = jnixx::array::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 +#include + +#include +#include + #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