diff -up frysk-0.4/frysk-sys/lib/dwfl/cni/Dwfl.cxx.noelfmem frysk-0.4/frysk-sys/lib/dwfl/cni/Dwfl.cxx --- frysk-0.4/frysk-sys/lib/dwfl/cni/Dwfl.cxx.noelfmem 2010-03-25 11:41:04.000000000 -0400 +++ frysk-0.4/frysk-sys/lib/dwfl/cni/Dwfl.cxx 2010-03-25 12:26:09.000000000 -0400 @@ -57,38 +57,26 @@ #include "inua/eio/ByteBuffer.h" using namespace java::lang; - -// Suck in elf_from_remote_memory from elfutils - -extern "C" -{ - extern ::Elf *elf_from_remote_memory (GElf_Addr ehdr_vma, - GElf_Addr *loadbasep, - ssize_t (*read_memory) (void *arg, - void *data, - GElf_Addr address, - size_t minread, - size_t maxread), - void *arg); -} #define DWFL_POINTER ((::Dwfl *) pointer) #define DWFL_CALLBACKS ((::Dwfl_Callbacks *) callbacks) -static ssize_t -read_proc_memory (void *arg, void *data, GElf_Addr address, - size_t minread, size_t maxread) -{ - inua::eio::ByteBuffer* memory = (inua::eio::ByteBuffer *) arg; - jbyteArray bytes = JvNewByteArray(maxread); - ssize_t nread = memory->safeGet((off64_t) address, bytes, 0, maxread); - memcpy(data, elements(bytes), nread); - if (nread > 0 && (size_t) nread < minread) - nread = 0; - return nread; +jlong +lib::dwfl::Dwfl::dwfl_slap_module_memory(jlong module, inua::eio::ByteBuffer* memory, + jlong address, jlong length) { + jbyteArray bounceBuffer = JvNewByteArray(length); + ssize_t nread = memory->safeGet((off64_t) address, bounceBuffer, 0, length); + if (nread < length) { + return 0; // what ever + } + void **userdatap; + ::dwfl_module_info((Dwfl_Module*)module, &userdatap, NULL, NULL, NULL, NULL, NULL, NULL); + (*userdatap) = ::malloc(length); + memcpy((*userdatap), elements(bounceBuffer), length); + return (jlong)(*userdatap); } int -dwfl_frysk_proc_find_elf (Dwfl_Module *mod, +dwfl_frysk_proc_find_elf (Dwfl_Module *module, void **userdata, const char *module_name, Dwarf_Addr base, char **file_name, Elf **elfp) @@ -105,21 +93,29 @@ dwfl_frysk_proc_find_elf (Dwfl_Module *m *file_name = strdup (module_name); return -1; } else { - *elfp = elf_from_remote_memory (base, NULL, &read_proc_memory, *userdata); - if (*elfp != NULL) { - *file_name = ::strdup(module_name); - } + // During module creation the Dwfl_Module USERDATA point was set + // to a raw buffer that contains the entire in-memory section + // contents. Create an elf from that. DwflModule is responsible + // for freeing the memory. + char *memory = (char*)(*userdata); + // Compute the size of the memory using the module's bound. + ::Dwarf_Addr bound; + ::dwfl_module_info(module, NULL, NULL, &bound, NULL, NULL, NULL, NULL); + ssize_t memory_size = bound - base; + // Turn that memory into an ELF. The obvious thing to do here is + // to tell elfutils that it is responsible for the memory - by + // calling elf_flagelf(ELF_F_MALLOCED) - except all the flags + // including ELF_F_MALLOCED are not public and setting that + // particular flag is prohibited. + *elfp = elf_memory((char*)memory, memory_size); + if (*elfp == NULL) { return -1; } -} - -jlong -lib::dwfl::Dwfl::dwfl_userdata_begin(inua::eio::ByteBuffer *memory) { - return (jlong)memory; -} - -void -lib::dwfl::Dwfl::dwfl_userdata_end(jlong userdata) { + // Poke something into FILE_NAME so that the caller notices that + // we've done something to ELF. + *file_name = ::strdup(module_name); + return -1; + } } jlong @@ -169,7 +165,7 @@ lib::dwfl::Dwfl::dwfl_report_end(jlong p jlong lib::dwfl::Dwfl::dwfl_report_module(jlong pointer, jstring moduleName, - jlong low, jlong high, jlong userdata) { + jlong low, jlong high) { jsize len = JvGetStringUTFLength(moduleName); char modName[len+1]; @@ -179,14 +175,6 @@ lib::dwfl::Dwfl::dwfl_report_module(jlon Dwfl_Module* module = ::dwfl_report_module(DWFL_POINTER, modName, (::Dwarf_Addr) low, (::Dwarf_Addr) high); - if (userdata != 0) { - // Get the address of the module's userdata, and store a global - // reference to memory in there. The global ref is detroyed along - // with the Dwfl. - void **userdatap; - ::dwfl_module_info(module, &userdatap, NULL, NULL, NULL, NULL, NULL, NULL); - *userdatap = (void*)userdata; - } return (jlong) module; } diff -up frysk-0.4/frysk-sys/lib/dwfl/cni/DwflModule.cxx.noelfmem frysk-0.4/frysk-sys/lib/dwfl/cni/DwflModule.cxx --- frysk-0.4/frysk-sys/lib/dwfl/cni/DwflModule.cxx.noelfmem 2010-03-25 11:41:04.000000000 -0400 +++ frysk-0.4/frysk-sys/lib/dwfl/cni/DwflModule.cxx 2010-03-25 11:41:04.000000000 -0400 @@ -478,3 +478,8 @@ jlong lib::dwfl::DwflModule::dwfl_module_getsrc(jlong pointer, jlong addr) { return (jlong) ::dwfl_module_getsrc(DWFL_MODULE_POINTER, (Dwarf_Addr)addr); } + +void +lib::dwfl::DwflModule::dwfl_module_free_memory(jlong memory) { + ::free((void*)memory); +} diff -up frysk-0.4/frysk-sys/lib/dwfl/Dwfl.java.noelfmem frysk-0.4/frysk-sys/lib/dwfl/Dwfl.java --- frysk-0.4/frysk-sys/lib/dwfl/Dwfl.java.noelfmem 2010-03-25 11:41:04.000000000 -0400 +++ frysk-0.4/frysk-sys/lib/dwfl/Dwfl.java 2010-03-25 12:19:08.000000000 -0400 @@ -49,7 +49,7 @@ public class Dwfl { private static final Log fine = Log.fine(Dwfl.class); private static final Log finest = Log.finest(Dwfl.class); - private long userdata; + private ByteBuffer memory; private long pointer; private long callbacks; @@ -61,11 +61,10 @@ public class Dwfl { */ public Dwfl(String debugInfoPath, ByteBuffer memory) { callbacks = dwfl_callbacks_begin(debugInfoPath); - userdata = dwfl_userdata_begin(memory); pointer = dwfl_begin(callbacks); + this.memory = memory; } private static native long dwfl_callbacks_begin(String debugInfoSearchPath); - private static native long dwfl_userdata_begin(ByteBuffer memory); private static native long dwfl_begin(long callbacks); /** * Create a dwfl with the specified debug-info search path and @@ -85,13 +84,11 @@ public class Dwfl { if (this.pointer != 0) { dwfl_end(pointer); this.pointer = 0; - dwfl_userdata_end(userdata); dwfl_callbacks_end(callbacks); this.callbacks = 0; } } private static native void dwfl_end(long pointer); - private static native void dwfl_userdata_end(long userdata); private static native void dwfl_callbacks_end(long callbacks); public DwflLine getSourceLine (long addr) { @@ -197,8 +194,7 @@ public class Dwfl { */ public void reportModule(String moduleName, long low, long high) { fine.log(this, "reportModule", moduleName, "low", low, "high", high); - long modulePointer = dwfl_report_module(pointer, moduleName, low, high, - userdata); + long modulePointer = dwfl_report_module(pointer, moduleName, low, high); for (int i = 0; i < modulesArray.length; i++) { DwflModule module = modulesArray[i]; if (module.getName().equals(moduleName) @@ -212,15 +208,26 @@ public class Dwfl { return; } } + long bytes; + if (moduleName.startsWith("[") + && ULong.GT(high, low) && ULong.LT(high - low, 0x10000)) { + // If it looks like a mapped elf region and is small (like + // only a page or so) just suck it in. + bytes = dwfl_slap_module_memory(modulePointer, memory, low, high - low); + fine.log(this, "slapped module memory at", bytes, "count", high - low); + } else { + bytes = 0; + } DwflModule module = new DwflModule(modulePointer, this, moduleName, - low, high); + low, high, bytes); finest.log(this, "reportModule creating", module); modules.put(new Long(modulePointer), module); } private static native long dwfl_report_module(long pointer, String moduleName, - long low, long high, - long userdata); + long low, long high); + private static native long dwfl_slap_module_memory(long modulePointer, ByteBuffer memory, + long low, long high); private String name; private long low; diff -up frysk-0.4/frysk-sys/lib/dwfl/DwflModule.java.noelfmem frysk-0.4/frysk-sys/lib/dwfl/DwflModule.java --- frysk-0.4/frysk-sys/lib/dwfl/DwflModule.java.noelfmem 2010-03-25 11:41:04.000000000 -0400 +++ frysk-0.4/frysk-sys/lib/dwfl/DwflModule.java 2010-03-25 11:41:04.000000000 -0400 @@ -50,26 +50,39 @@ public class DwflModule { protected LinkedList pubNames; protected LinkedList symbolTable; + private final long memory; private final long pointer; private final Dwfl parent; private final String name; private final long low; private final long high; - DwflModule(long val, Dwfl parent, String name, long low, long high) { - this.pointer = val; + DwflModule(long pointer, Dwfl parent, String name, long low, long high, long memory) { + this.pointer = pointer; this.parent = parent; this.name = name; this.low = low; this.high = high; + this.memory = memory; } + /** + * If a raw memory buffer was allocated, delete it when this is + * deleted; note that elfutils takes care of deleting the pointer. + */ + public void finalize() { + if (memory != 0) { + dwfl_module_free_memory(memory); + } + } + private static native void dwfl_module_free_memory(long memory); public String toString() { return name + " 0x" + Long.toHexString(low) + "..0x" + Long.toHexString(high) - + " pointer=0x" + Long.toHexString(pointer); + + " pointer=0x" + Long.toHexString(pointer) + + " memory=0x" + Long.toHexString(memory); } public long lowAddress() { diff -up frysk-0.4/frysk-sys/lib/dwfl/jni/Dwfl.cxx.noelfmem frysk-0.4/frysk-sys/lib/dwfl/jni/Dwfl.cxx --- frysk-0.4/frysk-sys/lib/dwfl/jni/Dwfl.cxx.noelfmem 2010-03-25 11:41:04.000000000 -0400 +++ frysk-0.4/frysk-sys/lib/dwfl/jni/Dwfl.cxx 2010-03-25 11:41:04.000000000 -0400 @@ -51,52 +51,31 @@ using namespace java::lang; -// Suck in elf_from_remote_memory from elfutils - -extern "C" { - extern ::Elf *elf_from_remote_memory(GElf_Addr ehdr_vma, - GElf_Addr *loadbasep, - ssize_t (*read_memory) (void *arg, - void *data, - GElf_Addr address, - size_t minread, - size_t maxread), - void *arg); -} - -// Grub the pointer out of the object; replace this with ... -#define DWFL_POINTER_FIXME ((::Dwfl *)GetPointer(env)) - // Assume the method was parameterised with POINTER. #define DWFL_POINTER ((::Dwfl *)pointer) -// Our data associated with the dwfl (well actually the Dwfl_Module). -// Need to make memory available so that, in the case of the vdso, it -// can be slurped from memory. - -static ssize_t -read_proc_memory(void *userdata, void *data, GElf_Addr address, - size_t minread, size_t maxread) { - // Get the current thread's ENV; can't save it in dwfl_userdata - // since can't determine, ahead of time, which thread will call this - // code. - ::jnixx::env env = Object::_env_(); - ::inua::eio::ByteBuffer memory - = ::inua::eio::ByteBuffer(env, (jobject)userdata); - jnixx::jbyteArray bytes = jnixx::jbyteArray::NewByteArray(env, maxread); - ssize_t nread = memory.safeGet(env, (off64_t) address, bytes, 0, maxread); - jbyteArrayElements bytesp = jbyteArrayElements(env, bytes); - memcpy(data, bytesp.elements(), nread); - if (nread > 0 && (size_t) nread < minread) - nread = 0; - bytes.DeleteLocalRef(env); - return nread; +jlong +lib::dwfl::Dwfl::dwfl_slap_module_memory(jnixx::env env, jlong module, + inua::eio::ByteBuffer memory, + jlong address, jlong length) { + jnixx::jbyteArray bounceBuffer = jnixx::jbyteArray::NewByteArray(env, length); + ssize_t nread = memory.safeGet(env, (off64_t) address, bounceBuffer, 0, length); + if (nread < length) { + bounceBuffer.DeleteLocalRef(env); + return 0; // what ever + } + void **userdatap; + ::dwfl_module_info((Dwfl_Module*)module, &userdatap, NULL, NULL, NULL, NULL, NULL, NULL); + (*userdatap) = ::malloc(length); + memcpy((*userdatap), jbyteArrayElements(env, bounceBuffer).elements(), length); + bounceBuffer.DeleteLocalRef(env); + return (jlong)(*userdatap); } static int -dwfl_frysk_proc_find_elf(Dwfl_Module *mod, +dwfl_frysk_proc_find_elf(Dwfl_Module *module, void **userdata, const char *module_name, Dwarf_Addr base, char **file_name, Elf **elfp) { @@ -111,30 +90,31 @@ dwfl_frysk_proc_find_elf(Dwfl_Module *mo *file_name = ::strdup(module_name); return -1; } else { - // dwfl passes in the address of the Dwfl_Module user pointer - // contained within. That pointer has been previously stuffed - // with our "userdata". - *elfp = elf_from_remote_memory (base, NULL, &read_proc_memory, *userdata); - if (*elfp != NULL) { - // Poke something into FILE_NAME so that the caller notices that - // we've done something to ELF. - *file_name = ::strdup(module_name); + // During module creation the Dwfl_Module USERDATA point was set + // to a raw buffer that contains the entire in-memory section + // contents. Create an elf from that. DwflModule is responsible + // for freeing the memory. + char *memory = (char*)(*userdata); + // Compute the size of the memory using the module's bound. + ::Dwarf_Addr bound; + ::dwfl_module_info(module, NULL, NULL, &bound, NULL, NULL, NULL, NULL); + ssize_t memory_size = bound - base; + // Turn that memory into an ELF. The obvious thing to do here is + // to tell elfutils that it is responsible for the memory - by + // calling elf_flagelf(ELF_F_MALLOCED) - except all the flags + // including ELF_F_MALLOCED are not public and setting that + // particular flag is prohibited. + *elfp = elf_memory((char*)memory, memory_size); + if (*elfp == NULL) { + return -1; } + // Poke something into FILE_NAME so that the caller notices that + // we've done something to ELF. + *file_name = ::strdup(module_name); return -1; } } -jlong -lib::dwfl::Dwfl::dwfl_userdata_begin(jnixx::env env, - inua::eio::ByteBuffer memory) { - return (jlong) env.NewGlobalRef(memory._object); -} - -void -lib::dwfl::Dwfl::dwfl_userdata_end(jnixx::env env, jlong userdata) { - env.DeleteGlobalRef((jobject)userdata); -} - #define DWFL_CALLBACKS ((::Dwfl_Callbacks*)callbacks) @@ -185,20 +165,11 @@ lib::dwfl::Dwfl::dwfl_report_end(jnixx:: jlong lib::dwfl::Dwfl::dwfl_report_module(jnixx::env env, jlong pointer, - String jmoduleName, jlong low, jlong high, - jlong userdata) { + String jmoduleName, jlong low, jlong high) { jstringUTFChars moduleName = jstringUTFChars(env, jmoduleName); Dwfl_Module *module = ::dwfl_report_module(DWFL_POINTER, moduleName.elements(), (::Dwarf_Addr) low, (::Dwarf_Addr) high); - if (userdata != 0) { - // Get the address of the module's userdata, and store a global - // reference to memory in there. The global ref is detroyed along - // with the Dwfl. - void **userdatap; - ::dwfl_module_info(module, &userdatap, NULL, NULL, NULL, NULL, NULL, NULL); - *userdatap = (void*)userdata; - } return (jlong)module; } diff -up frysk-0.4/frysk-sys/lib/dwfl/jni/DwflModule.cxx.noelfmem frysk-0.4/frysk-sys/lib/dwfl/jni/DwflModule.cxx --- frysk-0.4/frysk-sys/lib/dwfl/jni/DwflModule.cxx.noelfmem 2010-03-25 11:41:04.000000000 -0400 +++ frysk-0.4/frysk-sys/lib/dwfl/jni/DwflModule.cxx 2010-03-25 11:41:04.000000000 -0400 @@ -436,3 +436,8 @@ lib::dwfl::DwflModule::dwfl_module_getsr jlong addr) { return (jlong) ::dwfl_module_getsrc(DWFL_MODULE_POINTER, (Dwarf_Addr)addr); } + +void +lib::dwfl::DwflModule::dwfl_module_free_memory(jnixx::env env, jlong memory) { + ::free((void*)memory); +}