public inbox for frysk-cvs@sourceware.org help / color / mirror / Atom feed
From: mark@sourceware.org To: frysk-cvs@sourceware.org Subject: [SCM] master: Add new libunwind get_unwind_table interface. Date: Tue, 11 Dec 2007 14:35:00 -0000 [thread overview] Message-ID: <20071211143548.25846.qmail@sourceware.org> (raw) The branch, master has been updated via 2579d604e2b8ce0bc583e872642ecdfefb957cfa (commit) from 5f078697788883be959202a9643d29430587e182 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email. - Log ----------------------------------------------------------------- commit 2579d604e2b8ce0bc583e872642ecdfefb957cfa Author: Mark Wielaard <mwielaard@redhat.com> Date: Tue Dec 11 15:35:01 2007 +0100 Add new libunwind get_unwind_table interface. frysk-imports/libunwind/ChangeLog 2007-12-11 Mark Wielaard <mwielaard@redhat.com> * include/libunwind-common.h.in (unw_get_unwind_table): Add unw_accessor_t, remove elf image arguments. * src/mi/Gget_unwind_table.c (unw_get_unwind_table): Likewise. Rewrite to use unw_accessor_t for reading all data. frysk-sys/lib/unwind/ChangeLog 2007-12-11 Mark Wielaard <mwielaard@redhat.com> * ElfImage.java (name): New field. (ElfImage): Set name. (toString): Add name. * cni/ElfImage.cxx (mapElfImage): Pass in name. * cni/UnwindH.hxx (access_mem): Handle memory holes. (get_eh_frame_hdr_addr): New static function. (local_access_mem): Likewise. (createProcInfoFromElfImage): Use get_eh_frame_hdr_addr and local_access_mem. (createElfImageFromVDSO): Set name to [vdso]. ----------------------------------------------------------------------- Summary of changes: frysk-imports/libunwind/ChangeLog | 7 + .../libunwind/include/libunwind-common.h.in | 8 +- frysk-imports/libunwind/src/mi/Gget_unwind_table.c | 229 ++++++-------------- frysk-sys/lib/unwind/ChangeLog | 13 ++ frysk-sys/lib/unwind/ElfImage.java | 8 +- frysk-sys/lib/unwind/cni/ElfImage.cxx | 2 +- frysk-sys/lib/unwind/cni/UnwindH.hxx | 194 +++++++++++++++-- 7 files changed, 273 insertions(+), 188 deletions(-) First 500 lines of diff: diff --git a/frysk-imports/libunwind/ChangeLog b/frysk-imports/libunwind/ChangeLog index f7af421..3e02b0d 100644 --- a/frysk-imports/libunwind/ChangeLog +++ b/frysk-imports/libunwind/ChangeLog @@ -1,3 +1,10 @@ +2007-12-11 Mark Wielaard <mwielaard@redhat.com> + + * include/libunwind-common.h.in (unw_get_unwind_table): Add + unw_accessor_t, remove elf image arguments. + * src/mi/Gget_unwind_table.c (unw_get_unwind_table): Likewise. + Rewrite to use unw_accessor_t for reading all data. + 2007-11-28 Mark Wielaard <mwielaard@redhat.com> * src/mi/Gget_unwind_table.c (unw_get_unwind_table): Make addr a diff --git a/frysk-imports/libunwind/include/libunwind-common.h.in b/frysk-imports/libunwind/include/libunwind-common.h.in index 497a7b4..a837055 100644 --- a/frysk-imports/libunwind/include/libunwind-common.h.in +++ b/frysk-imports/libunwind/include/libunwind-common.h.in @@ -252,8 +252,10 @@ extern int unw_get_proc_name (unw_cursor_t *, char *, size_t, unw_word_t *); extern const char *unw_strerror (int); extern int unw_get_unwind_table(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, int need_unwind_info, - void *image, size_t size, - unsigned long segbase, unsigned long mapoff, - void *arg); + void *arg, + unw_accessors_t *eh_frame_accessors, + unw_word_t eh_frame_hdr_address, + void *eh_frame_arg, + unw_word_t peh_vaddr); extern unw_addr_space_t unw_local_addr_space; diff --git a/frysk-imports/libunwind/src/mi/Gget_unwind_table.c b/frysk-imports/libunwind/src/mi/Gget_unwind_table.c index 2acb947..1d905b6 100644 --- a/frysk-imports/libunwind/src/mi/Gget_unwind_table.c +++ b/frysk-imports/libunwind/src/mi/Gget_unwind_table.c @@ -22,177 +22,72 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "libunwind_i.h" -//#include "remote.h" +#include "dwarf_i.h" #include "dwarf-eh.h" int -unw_get_unwind_table(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, - int need_unwind_info, void *image, size_t size, - unsigned long segbase, unsigned long mapoff, void *arg) +unw_get_unwind_table(unw_addr_space_t as, unw_word_t ip, + unw_proc_info_t *pi, int need_unwind_info, void *arg, + unw_accessors_t *eh_frame_accessors, + unw_word_t eh_frame_hdr_address, + void *eh_frame_arg, + unw_word_t peh_vaddr) { - Debug(99, "Entering get_unwind_table\n"); - Elf_W(Phdr) *phdr, *ptxt = NULL, *peh_hdr = NULL, *pdyn = NULL; - unw_word_t eh_frame_start, fde_count, load_base; - char *addr; - struct dwarf_eh_frame_hdr *hdr; - Elf_W(Ehdr) *ehdr; - int i, ret; - unw_dyn_info_t di_cache; - - if (size <= EI_CLASS) - return -1; - - Debug(99, "Checking elf size\n"); - if (!(memcmp (image, ELFMAG, SELFMAG) == 0 - && ((uint8_t *) image)[EI_CLASS] == ELF_CLASS)) - return -1; - - Debug(99, "Checked elf class\n"); - ehdr = image; - phdr = (Elf_W(Phdr) *) ((char *) image + ehdr->e_phoff); - for (i = 0; i < ehdr->e_phnum; ++i) - { - switch (phdr[i].p_type) - { - case PT_LOAD: - if (phdr[i].p_offset == mapoff) - ptxt = phdr + i; - break; - - case PT_GNU_EH_FRAME: - peh_hdr = phdr + i; - break; - - case PT_DYNAMIC: - pdyn = phdr + i; - break; - - default: - break; - } - } - - Debug(99, "Traversed headers\n"); - if (!ptxt || !peh_hdr) - return -UNW_ENOINFO; - - if (pdyn) - { - Debug(99, "Got dynamic header\n"); - /* For dynamicly linked executables and shared libraries, - DT_PLTGOT is the value that data-relative addresses are - relative to for that object. We call this the "gp". */ - Elf_W(Dyn) *dyn = (Elf_W(Dyn) *)(pdyn->p_offset - + (char *) image); - for (; dyn->d_tag != DT_NULL; ++dyn) - if (dyn->d_tag == DT_PLTGOT) - { - /* Assume that _DYNAMIC is writable and GLIBC has - relocated it (true for x86 at least). */ - di_cache.gp = dyn->d_un.d_ptr; - break; - } - } - else - /* Otherwise this is a static executable with no _DYNAMIC. Assume - that data-relative addresses are relative to 0, i.e., - absolute. */ - di_cache.gp = 0; - - Debug(99, "Got eh_frame_hdr\n"); - hdr = (struct dwarf_eh_frame_hdr *) (peh_hdr->p_offset - + (char *) image); - if (hdr->version != DW_EH_VERSION) - { - Debug (1, "table has unexpected version %d\n", - hdr->version); - return 0; - } - - Debug(99, "EH_VERSION is correct\n"); - - addr = hdr + 1; - Debug (99, "Got addr\n"); - /* Fill in a dummy proc_info structure. We just need to fill in - enough to ensure that dwarf_read_encoded_pointer() can do it's - job. Since we don't have a procedure-context at this point, all - we have to do is fill in the global-pointer. */ - memset (pi, 0, sizeof (*pi)); - Debug(99, "cleared pi\n"); - pi->gp = di_cache.gp; - - Debug(99, "set pi gp\n"); - -// The following is a local address space memory accessor used by -// dwarf_read_encoded_pointer. The arg pointer is the base address, -// addr is the offset from the base address. - int - local_access_mem (unw_addr_space_t as, unw_word_t addr, - unw_word_t *val, int write, void *arg) - { - Debug(99, "entering local_access_mem, reading addr: 0x%lx into: %p\n", - (long) addr, val); - if (write) - { - // Writing is not supported - return -UNW_EINVAL; - } - else - { - *val = *(unw_word_t *) (addr + (char *) arg); - Debug (16, "mem[%x] -> %x\n", (addr + (char *) arg), *val); - } - Debug(99, "leaving local_access_mem\n"); - return 0; - } - - unw_accessors_t local_accessors = {NULL, NULL, NULL, local_access_mem, - NULL, NULL, NULL, NULL, NULL}; - unw_addr_space_t local_addr_space - = unw_create_addr_space(&local_accessors, 0); - - unw_word_t start = 0; + int ret; + unw_word_t start = eh_frame_hdr_address; + + // Version + unsigned char version; + if ((ret = dwarf_readu8 (as, eh_frame_accessors, &start, + &version, eh_frame_arg)) < 0) + return -UNW_ENOINFO; + + if (version != DW_EH_VERSION) + return -UNW_ENOINFO; + + unsigned char eh_frame_ptr_enc; + if ((ret = dwarf_readu8 (as, eh_frame_accessors, &start, + &eh_frame_ptr_enc, eh_frame_arg)) < 0) + return -UNW_ENOINFO; + + unsigned char fde_count_enc; + if ((ret = dwarf_readu8 (as, eh_frame_accessors, &start, + &fde_count_enc, eh_frame_arg)) < 0) + return -UNW_ENOINFO; + + unsigned char table_enc; + if ((ret = dwarf_readu8 (as, eh_frame_accessors, &start, + &table_enc, eh_frame_arg)) < 0) + return -UNW_ENOINFO; - /* (Optionally) read eh_frame_ptr: */ - if ((ret = dwarf_read_encoded_pointer (local_addr_space, &local_accessors, - &start, hdr->eh_frame_ptr_enc, pi, - &eh_frame_start, addr)) < 0) - return -1; - - Debug(99, "read eh_frame_start: 0x%lx\n", (long) eh_frame_start); - - /* (Optionally) read fde_count: */ - if ((ret = dwarf_read_encoded_pointer (local_addr_space, &local_accessors, - &start, hdr->fde_count_enc, pi, - &fde_count, addr)) < 0) - return -1; - - Debug(99, "read fde_count: 0x%lx\n", (long) fde_count); - if (hdr->table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4)) - { - return -1; - } + if (table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4)) + return -UNW_ENOINFO; + + unw_word_t eh_frame_start; + if ((ret = dwarf_read_encoded_pointer (as, eh_frame_accessors, + &start, eh_frame_ptr_enc, pi, + &eh_frame_start, eh_frame_arg)) < 0) + return -UNW_ENOINFO; - addr += start; - - load_base = segbase - ptxt->p_vaddr; - - di_cache.start_ip = segbase; - di_cache.end_ip = di_cache.start_ip + ptxt->p_memsz; - di_cache.format = UNW_INFO_FORMAT_REMOTE_TABLE; - di_cache.u.rti.name_ptr = 0; - /* two 32-bit values (ip_offset/fde_offset) per table-entry: */ - di_cache.u.rti.table_len = (fde_count * 8) / sizeof (unw_word_t); - di_cache.u.rti.table_data = ((load_base + peh_hdr->p_vaddr) - + (addr - (unw_word_t) image - - peh_hdr->p_offset)); - - /* For the binary-search table in the eh_frame_hdr, data-relative - means relative to the start of that section... */ - di_cache.u.rti.segbase = ((load_base + peh_hdr->p_vaddr) - + ((unw_word_t) hdr - (unw_word_t) image - - peh_hdr->p_offset)); - - Debug(99, "Leaving get_unwind_table\n"); - return tdep_search_unwind_table (as, ip, &di_cache, pi, need_unwind_info, arg); + unw_word_t fde_count; + if ((ret = dwarf_read_encoded_pointer (as, eh_frame_accessors, + &start, fde_count_enc, pi, + &fde_count, eh_frame_arg)) < 0) + return -UNW_ENOINFO; + + unw_dyn_info_t di; + di.start_ip = pi->start_ip; + di.end_ip = pi->end_ip; + di.format = UNW_INFO_FORMAT_REMOTE_TABLE; + di.gp = pi->gp; + di.u.rti.name_ptr = 0; + /* two 32-bit values (ip_offset/fde_offset) per table-entry: + For the binary-search table in the eh_frame_hdr, data-relative + means relative to the start of that section... + So for now we pass in peh_vaddr and use the main as for access. */ + di.u.rti.table_len = (fde_count * 8) / sizeof (unw_word_t); + di.u.rti.table_data = peh_vaddr + 12; + di.u.rti.segbase = peh_vaddr; + + return tdep_search_unwind_table (as, ip, &di, pi, need_unwind_info, arg); } diff --git a/frysk-sys/lib/unwind/ChangeLog b/frysk-sys/lib/unwind/ChangeLog index 1078b4a..933bca8 100644 --- a/frysk-sys/lib/unwind/ChangeLog +++ b/frysk-sys/lib/unwind/ChangeLog @@ -1,3 +1,16 @@ +2007-12-11 Mark Wielaard <mwielaard@redhat.com> + + * ElfImage.java (name): New field. + (ElfImage): Set name. + (toString): Add name. + * cni/ElfImage.cxx (mapElfImage): Pass in name. + * cni/UnwindH.hxx (access_mem): Handle memory holes. + (get_eh_frame_hdr_addr): New static function. + (local_access_mem): Likewise. + (createProcInfoFromElfImage): Use get_eh_frame_hdr_addr and + local_access_mem. + (createElfImageFromVDSO): Set name to [vdso]. + 2007-12-10 Andrew Cagney <cagney@redhat.com> * cni/UnwindH.hxx (access_fpreg): Allocate a buffer big enough for diff --git a/frysk-sys/lib/unwind/ElfImage.java b/frysk-sys/lib/unwind/ElfImage.java index 7707f09..e938c96 100644 --- a/frysk-sys/lib/unwind/ElfImage.java +++ b/frysk-sys/lib/unwind/ElfImage.java @@ -43,6 +43,8 @@ package lib.unwind; public class ElfImage { + final String name; + long elfImage; long size; @@ -53,8 +55,9 @@ public class ElfImage int ret = 0; - public ElfImage (long elfImage, long size, long segbase, long mapoff) + public ElfImage (String name, long elfImage, long size, long segbase, long mapoff) { + this.name = name; this.elfImage = elfImage; this.size = size; this.segbase = segbase; @@ -63,6 +66,7 @@ public class ElfImage public ElfImage (int ret) { + this.name = "ERROR: " + Integer.toString(ret); this.ret = ret; } @@ -71,7 +75,7 @@ public class ElfImage if (ret != 0) return "Bad Elf Image, ret: " + ret; - return "Elf Image: 0x" + Long.toHexString(elfImage) + " size: " + size + return "Elf Image (" + name + "): 0x" + Long.toHexString(elfImage) + " size: " + size + " segbase: 0x" + Long.toHexString(segbase) + " mapoff: 0x" + Long.toHexString(mapoff); } diff --git a/frysk-sys/lib/unwind/cni/ElfImage.cxx b/frysk-sys/lib/unwind/cni/ElfImage.cxx index d521643..3f7fdd3 100644 --- a/frysk-sys/lib/unwind/cni/ElfImage.cxx +++ b/frysk-sys/lib/unwind/cni/ElfImage.cxx @@ -80,7 +80,7 @@ lib::unwind::ElfImage::mapElfImage(jstring elfImageName, jlong segbase, jlong hi return new lib::unwind::ElfImage((jint) -1); lib::unwind::ElfImage* elfImage - = new lib::unwind::ElfImage((jlong) image, (jlong) size, + = new lib::unwind::ElfImage(elfImageName, (jlong) image, (jlong) size, (jlong) segbase, (jlong) mapoff); return elfImage; diff --git a/frysk-sys/lib/unwind/cni/UnwindH.hxx b/frysk-sys/lib/unwind/cni/UnwindH.hxx index 1d13156..e1cc430 100644 --- a/frysk-sys/lib/unwind/cni/UnwindH.hxx +++ b/frysk-sys/lib/unwind/cni/UnwindH.hxx @@ -47,7 +47,9 @@ #include <libdwfl.h> #include LIBUNWIND_TARGET_H -#include <dwarf.h> + +#include <libelf.h> +#include <gelf.h> #include <gcj/cni.h> @@ -135,11 +137,22 @@ static int access_mem (::unw_addr_space_t as, ::unw_word_t addr, ::unw_word_t *valp, int write, void *arg) { - jbyteArray tmp = JvNewByteArray (sizeof (unw_word_t)); - memcpy (elements(tmp), valp, JvGetArrayLength(tmp)); - int ret = addressSpace(arg)->accessMem((jlong) addr, tmp, (jboolean) write); - memcpy(valp, elements(tmp), JvGetArrayLength(tmp)); - return ret; + try + { + jbyteArray tmp = JvNewByteArray (sizeof (unw_word_t)); + memcpy (elements(tmp), valp, JvGetArrayLength(tmp)); + int ret = addressSpace(arg)->accessMem((jlong) addr, + tmp, (jboolean) write); + memcpy(valp, elements(tmp), JvGetArrayLength(tmp)); + return ret; + } + catch (java::lang::RuntimeException *t) + { + // We have to catch all RuntimeExceptions here since there + // is no indicator for just "invalid memory location". + // Core files might have "holes" in their memory. + return -UNW_EINVAL; + } } /* @@ -429,26 +442,177 @@ lib::unwind::TARGET::getProcInfo(gnu::gcj::RawDataManaged* cursor) return myInfo; } +// Return NULL when eh_frame_hdr cannot be found. +// Also fills in ip->start_ip, ip->end_ip and ip->gp. +// peh_vaddr will point to the address of the eh_frame_hdr in the main +// address space of the inferior. +static void * +get_eh_frame_hdr_addr(unw_proc_info_t *pi, char *image, size_t size, + unsigned long segbase, unw_word_t *peh_vaddr) +{ + if (elf_version(EV_CURRENT) == EV_NONE) + return NULL; + + Elf *elf = elf_memory(image, size); + if (elf == NULL) + return NULL; + + GElf_Ehdr ehdr; + if (gelf_getehdr(elf, &ehdr) == NULL) + return NULL; + + GElf_Phdr phdr; + int ptxt_ndx = -1, peh_hdr_ndx = -1, pdyn_ndx = -1; + for (int i = 0; i < ehdr.e_phnum; i++) + { + if (gelf_getphdr (elf, i, &phdr) == NULL) + return NULL; + + switch (phdr.p_type) + { + case PT_LOAD: + if (phdr.p_vaddr == segbase) + ptxt_ndx = i; + break; + + case PT_GNU_EH_FRAME: + peh_hdr_ndx = i; + break; + + case PT_DYNAMIC: + pdyn_ndx = i; + break; + + default: + break; + } + } + + if (ptxt_ndx == -1 || peh_hdr_ndx == -1) + return NULL; + + GElf_Phdr ptxt, peh_hdr; + if (gelf_getphdr (elf, ptxt_ndx, &ptxt) == NULL) + return NULL; + + if (gelf_getphdr (elf, peh_hdr_ndx, &peh_hdr) == NULL) + return NULL; + + if (pdyn_ndx != -1) + { + /* For dynamicly linked executables and shared libraries, + DT_PLTGOT is the value that data-relative addresses are + relative to for that object. We call this the "gp". */ + GElf_Phdr pdyn; + if (gelf_getphdr (elf, pdyn_ndx, &pdyn) == NULL) + return NULL; + + Elf_Scn *pdyn_scn = gelf_offscn(elf, pdyn.p_offset); + if (pdyn_scn == NULL) + return NULL; + + Elf_Data *pdyn_data; + pdyn_data = elf_getdata (pdyn_scn, NULL); + if (pdyn_data == NULL) + return NULL; + + GElf_Shdr pdyn_shdr; + if (gelf_getshdr (pdyn_scn, &pdyn_shdr) == NULL) + return NULL; + + for (unsigned int i = 0; + i < pdyn_shdr.sh_size / pdyn_shdr.sh_entsize; i++) + { + GElf_Dyn dyn; + if (gelf_getdyn (pdyn_data, i, &dyn) == NULL) + return NULL; + + if (dyn.d_tag == DT_PLTGOT) + { + /* Assume that _DYNAMIC is writable and GLIBC has + relocated it (true for x86 at least). */ + pi->gp = dyn.d_un.d_ptr; + break; + } + } + } + else + /* Otherwise this is a static executable with no _DYNAMIC. Assume + that data-relative addresses are relative to 0, i.e., + absolute. */ + pi->gp = 0; + + pi->start_ip = segbase; hooks/post-receive -- frysk system monitor/debugger
reply other threads:[~2007-12-11 14:35 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=20071211143548.25846.qmail@sourceware.org \ --to=mark@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).