diff options
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | libdw/ChangeLog | 7 | ||||
-rw-r--r-- | libdw/libdw.map | 8 | ||||
-rw-r--r-- | libdwfl/ChangeLog | 36 | ||||
-rw-r--r-- | libdwfl/Makefile.am | 4 | ||||
-rw-r--r-- | libdwfl/dwfl_line_comp_dir.c | 64 | ||||
-rw-r--r-- | libdwfl/dwfl_linecu.c | 62 | ||||
-rw-r--r-- | libdwfl/dwfl_lineinfo.c | 4 | ||||
-rw-r--r-- | libdwfl/dwfl_module.c | 11 | ||||
-rw-r--r-- | libdwfl/dwfl_module_addrname.c | 70 | ||||
-rw-r--r-- | libdwfl/dwfl_module_getdwarf.c | 78 | ||||
-rw-r--r-- | libdwfl/dwfl_module_getsym.c | 116 | ||||
-rw-r--r-- | libdwfl/dwfl_module_return_value_location.c | 8 | ||||
-rw-r--r-- | libdwfl/libdwfl.h | 45 | ||||
-rw-r--r-- | libdwfl/libdwflP.h | 9 | ||||
-rw-r--r-- | libdwfl/relocate.c | 39 | ||||
-rw-r--r-- | src/ChangeLog | 7 | ||||
-rw-r--r-- | src/addr2line.c | 24 |
18 files changed, 464 insertions, 130 deletions
@@ -1,5 +1,7 @@ Version 0.122: +libdwfl: New functions dwfl_module_getsymtab, dwfl_module_getsym. + libebl:add function to test for relative relocation elflint: fix and extend DT_RELCOUNT/DT_RELACOUNT checks diff --git a/libdw/ChangeLog b/libdw/ChangeLog index 95312497..d1b2dc6d 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,10 @@ +2006-06-28 Roland McGrath <roland@redhat.com> + + * libdw.map: Export dwfl_linecu, dwfl_line_comp_dir. + + * libdw.map: Bump to 0.122; export dwfl_module_getsymtab and + dwfl_module_getsym. + 2006-05-27 Ulrich Drepper <drepper@redhat.com> * libdw.h: Add extern "C". diff --git a/libdw/libdw.map b/libdw/libdw.map index 08b01982..6ee42ece 100644 --- a/libdw/libdw.map +++ b/libdw/libdw.map @@ -1,5 +1,5 @@ ELFUTILS_0 { }; -ELFUTILS_0.120 { +ELFUTILS_0.122 { global: dwarf_abbrevhaschildren; dwarf_addrdie; @@ -104,6 +104,8 @@ ELFUTILS_0.120 { dwfl_getmodules; dwfl_getsrc; dwfl_getsrclines; + dwfl_line_comp_dir; + dwfl_linecu; dwfl_lineinfo; dwfl_linemodule; dwfl_linux_kernel_find_elf; @@ -112,14 +114,16 @@ ELFUTILS_0.120 { dwfl_linux_kernel_report_modules; dwfl_linux_kernel_report_offline; dwfl_linux_proc_find_elf; - dwfl_linux_proc_report; dwfl_linux_proc_maps_report; + dwfl_linux_proc_report; dwfl_module_addrdie; dwfl_module_addrname; dwfl_module_getdwarf; dwfl_module_getelf; dwfl_module_getsrc; dwfl_module_getsrc_file; + dwfl_module_getsym; + dwfl_module_getsymtab; dwfl_module_info; dwfl_module_nextcu; dwfl_module_register_names; diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index bdfd12c2..dd0b9b69 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -4,11 +4,47 @@ it can overflow the return value type. Patch by Tim Moore <timoore@redhat.com>. +2006-06-28 Roland McGrath <roland@redhat.com> + + * libdwfl.h: Cosmetic changes. + + * dwfl_line_comp_dir.c: New file. + * Makefile.am (libdwfl_a_SOURCES): Add it. + * libdwfl.h: Declare dwfl_line_comp_dir. + + * dwfl_lineinfo.c (dwfl_lineinfo): Remove stray extern in defn. + + * dwfl_linecu.c: New file. + * Makefile.am (libdwfl_a_SOURCES): Add it. + * libdwfl.h: Declare dwfl_linecu. + + * libdwflP.h (dwfl_linecu_inline): Function renamed from dwfl_linecu. + (dwfl_linecu): Define as macro. + + * relocate.c (__libdwfl_relocate): Use dwfl_module_getsym. + + * dwfl_module_getdwarf.c (dwfl_module_getsymtab): New function. + (dwfl_module_addrname): Function moved ... + * dwfl_module_addrname.c: ... here, new file. + * dwfl_module_getsym.c: New file. + * Makefile.am (libdwfl_a_SOURCES): Add them. + * libdwfl.h: Declare dwfl_module_getsymtab, dwfl_module_getsym. + * libdwflP.h: Add INTDECLs. + +2006-06-27 Roland McGrath <roland@redhat.com> + + * dwfl_module.c (dwfl_report_end): Whitespace fix. + 2006-06-13 Roland McGrath <roland@redhat.com> * elf-from-memory.c (elf_from_remote_memory): Fix 32/64 typo. Use __libdwfl_seterrno for elf_memory failure. +2006-05-22 Roland McGrath <roland@redhat.com> + + * dwfl_module_return_value_location.c + (dwfl_module_return_value_location): Use __libdwfl_module_getebl. + 2006-05-27 Ulrich Drepper <drepper@redhat.com> * libdwfl.h: Add extern "C". diff --git a/libdwfl/Makefile.am b/libdwfl/Makefile.am index 4583ed63..ee9efec9 100644 --- a/libdwfl/Makefile.am +++ b/libdwfl/Makefile.am @@ -59,12 +59,14 @@ libdwfl_a_SOURCES = dwfl_begin.c dwfl_end.c dwfl_error.c dwfl_version.c \ dwfl_addrmodule.c dwfl_addrdwarf.c \ cu.c dwfl_module_nextcu.c dwfl_nextcu.c dwfl_cumodule.c \ dwfl_module_addrdie.c dwfl_addrdie.c \ - lines.c dwfl_lineinfo.c dwfl_linemodule.c \ + lines.c dwfl_lineinfo.c dwfl_line_comp_dir.c \ + dwfl_linemodule.c dwfl_linecu.c \ dwfl_getsrclines.c dwfl_onesrcline.c \ dwfl_module_getsrc.c dwfl_getsrc.c \ dwfl_module_getsrc_file.c \ libdwfl_crc32.c libdwfl_crc32_file.c \ elf-from-memory.c \ + dwfl_module_getsym.c dwfl_module_addrname.c \ dwfl_module_return_value_location.c \ dwfl_module_register_names.c diff --git a/libdwfl/dwfl_line_comp_dir.c b/libdwfl/dwfl_line_comp_dir.c new file mode 100644 index 00000000..a755524d --- /dev/null +++ b/libdwfl/dwfl_line_comp_dir.c @@ -0,0 +1,64 @@ +/* Get information from a source line record returned by libdwfl. + Copyright (C) 2005, 2006 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#include "libdwflP.h" +#include <dwarf.h> + +const char * +dwfl_line_comp_dir (Dwfl_Line *line) +{ + if (line == NULL) + return NULL; + + struct dwfl_cu *cu = dwfl_linecu (line); + Dwarf_Attribute attr_mem; + return INTUSE(dwarf_formstring) (INTUSE(dwarf_attr) (&cu->die, + DW_AT_comp_dir, + &attr_mem)); +} diff --git a/libdwfl/dwfl_linecu.c b/libdwfl/dwfl_linecu.c new file mode 100644 index 00000000..34f5bb10 --- /dev/null +++ b/libdwfl/dwfl_linecu.c @@ -0,0 +1,62 @@ +/* Fetch the module containing a source line record returned by libdwfl. + Copyright (C) 2006 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#include "libdwflP.h" + +#undef dwfl_linecu + +Dwarf_Die * +dwfl_linecu (Dwfl_Line *line) +{ + if (line == NULL) + return NULL; + + struct dwfl_cu *cu = dwfl_linecu_inline (line); + return &cu->die; +} diff --git a/libdwfl/dwfl_lineinfo.c b/libdwfl/dwfl_lineinfo.c index 9fd343b6..0d8a6887 100644 --- a/libdwfl/dwfl_lineinfo.c +++ b/libdwfl/dwfl_lineinfo.c @@ -1,5 +1,5 @@ /* Get information from a source line record returned by libdwfl. - Copyright (C) 2005 Red Hat, Inc. + Copyright (C) 2005, 2006 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -50,7 +50,7 @@ #include "libdwflP.h" #include "../libdw/libdwP.h" -extern const char * +const char * dwfl_lineinfo (Dwfl_Line *line, Dwarf_Addr *addr, int *linep, int *colp, Dwarf_Word *mtime, Dwarf_Word *length) { diff --git a/libdwfl/dwfl_module.c b/libdwfl/dwfl_module.c index 6f3aa849..e3db1e06 100644 --- a/libdwfl/dwfl_module.c +++ b/libdwfl/dwfl_module.c @@ -186,11 +186,12 @@ compare_modules (const void *a, const void *b) existed before but was not included in the current report. Returns a nonzero return value from the callback. DWFL cannot be used until this function has returned zero. */ -int dwfl_report_end (Dwfl *dwfl, - int (*removed) (Dwfl_Module *, void *, - const char *, Dwarf_Addr, - void *arg), - void *arg) +int +dwfl_report_end (Dwfl *dwfl, + int (*removed) (Dwfl_Module *, void *, + const char *, Dwarf_Addr, + void *arg), + void *arg) { assert (dwfl->modules == NULL); diff --git a/libdwfl/dwfl_module_addrname.c b/libdwfl/dwfl_module_addrname.c new file mode 100644 index 00000000..19b4c2d3 --- /dev/null +++ b/libdwfl/dwfl_module_addrname.c @@ -0,0 +1,70 @@ +/* Find debugging and symbol information for a module in libdwfl. + Copyright (C) 2005, 2006 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#include "libdwflP.h" + +const char * +dwfl_module_addrname (Dwfl_Module *mod, GElf_Addr addr) +{ + int syments = INTUSE(dwfl_module_getsymtab) (mod); + if (syments < 0) + return NULL; + + /* Look through the symbol table for a matching symbol. */ + for (int i = 1; i < syments; ++i) + { + GElf_Sym sym; + const char *name = INTUSE(dwfl_module_getsym) (mod, i, &sym, NULL); + if (name != NULL + && sym.st_value <= addr && addr < sym.st_value + sym.st_size) + return name; + } + + return NULL; +} diff --git a/libdwfl/dwfl_module_getdwarf.c b/libdwfl/dwfl_module_getdwarf.c index 56a40fa6..1688f1e4 100644 --- a/libdwfl/dwfl_module_getdwarf.c +++ b/libdwfl/dwfl_module_getdwarf.c @@ -1,5 +1,5 @@ /* Find debugging and symbol information for a module in libdwfl. - Copyright (C) 2005 Red Hat, Inc. + Copyright (C) 2005, 2006 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -471,77 +471,17 @@ dwfl_module_getdwarf (Dwfl_Module *mod, Dwarf_Addr *bias) } INTDEF (dwfl_module_getdwarf) - -const char * -dwfl_module_addrname (Dwfl_Module *mod, GElf_Addr addr) +int +dwfl_module_getsymtab (Dwfl_Module *mod) { if (mod == NULL) - return NULL; + return -1; find_symtab (mod); - if (mod->symerr != DWFL_E_NOERROR) - { - __libdwfl_seterrno (mod->symerr); - return NULL; - } - - addr -= mod->symfile->bias; + if (mod->symerr == DWFL_E_NOERROR) + return mod->syments; - /* Look through the symbol table for a matching symbol. */ - size_t symshstrndx = SHN_UNDEF; - for (size_t i = 1; i < mod->syments; ++i) - { - GElf_Sym sym_mem; - GElf_Word shndx; - GElf_Sym *sym = gelf_getsymshndx (mod->symdata, mod->symxndxdata, - i, &sym_mem, &shndx); - if (sym != NULL) - { - GElf_Addr symaddr = sym->st_value; - - if (sym->st_shndx != SHN_XINDEX) - shndx = sym->st_shndx; - - if (mod->e_type == ET_REL) - /* In an ET_REL file, the symbol table values are relative - to the section, not to the module's load base. */ - switch (shndx) - { - case SHN_UNDEF: /* Undefined symbol can't match an address. */ - case SHN_COMMON: /* Nor can a common defn. */ - continue; - - case SHN_ABS: /* Symbol value is already absolute. */ - break; - - default: - { - Dwfl_Error result = DWFL_E_LIBELF; - if (likely (symshstrndx != SHN_UNDEF) - || elf_getshstrndx (mod->symfile->elf, - &symshstrndx) == 0) - result = __libdwfl_relocate_value (mod, symshstrndx, - shndx, &symaddr); - if (unlikely (result != DWFL_E_NOERROR)) - { - __libdwfl_seterrno (result); - return NULL; - } - break; - } - } - - if (symaddr <= addr && addr < symaddr + sym->st_size) - { - if (unlikely (sym->st_name >= mod->symstrdata->d_size)) - { - __libdwfl_seterrno (DWFL_E_BADSTROFF); - return NULL; - } - return (const char *) mod->symstrdata->d_buf + sym->st_name; - } - } - } - - return NULL; + __libdwfl_seterrno (mod->symerr); + return -1; } +INTDEF (dwfl_module_getsymtab) diff --git a/libdwfl/dwfl_module_getsym.c b/libdwfl/dwfl_module_getsym.c new file mode 100644 index 00000000..0c076e87 --- /dev/null +++ b/libdwfl/dwfl_module_getsym.c @@ -0,0 +1,116 @@ +/* Find debugging and symbol information for a module in libdwfl. + Copyright (C) 2006 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#include "libdwflP.h" + +const char * +dwfl_module_getsym (Dwfl_Module *mod, int ndx, + GElf_Sym *sym, GElf_Word *shndxp) +{ + if (unlikely (mod == NULL)) + return NULL; + + if (unlikely (mod->symdata == NULL)) + { + int result = INTUSE(dwfl_module_getsymtab) (mod); + if (result < 0) + return NULL; + } + + GElf_Word shndx; + sym = gelf_getsymshndx (mod->symdata, mod->symxndxdata, ndx, sym, &shndx); + if (unlikely (sym == NULL)) + { + __libdwfl_seterrno (DWFL_E_LIBELF); + return NULL; + } + + if (sym->st_shndx != SHN_XINDEX) + shndx = sym->st_shndx; + + if (shndxp != NULL) + *shndxp = shndx; + + switch (shndx) + { + case SHN_ABS: + case SHN_UNDEF: + case SHN_COMMON: + break; + + default: + if (mod->e_type != ET_REL) + /* Apply the bias to the symbol value. */ + sym->st_value += mod->symfile->bias; + else + { + /* In an ET_REL file, the symbol table values are relative + to the section, not to the module's load base. */ + size_t symshstrndx; + Dwfl_Error result = DWFL_E_LIBELF; + if (elf_getshstrndx (mod->symfile->elf, &symshstrndx) == 0) + result = __libdwfl_relocate_value (mod, symshstrndx, + shndx, &sym->st_value); + if (unlikely (result != DWFL_E_NOERROR)) + { + __libdwfl_seterrno (result); + return NULL; + } + } + break; + } + + if (unlikely (sym->st_name >= mod->symstrdata->d_size)) + { + __libdwfl_seterrno (DWFL_E_BADSTROFF); + return NULL; + } + return (const char *) mod->symstrdata->d_buf + sym->st_name; +} +INTDEF (dwfl_module_getsym) diff --git a/libdwfl/dwfl_module_return_value_location.c b/libdwfl/dwfl_module_return_value_location.c index 91493351..3d5154e2 100644 --- a/libdwfl/dwfl_module_return_value_location.c +++ b/libdwfl/dwfl_module_return_value_location.c @@ -1,5 +1,5 @@ /* Return location expression to find return value given a function type DIE. - Copyright (C) 2005 Red Hat, Inc. + Copyright (C) 2005, 2006 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -61,10 +61,10 @@ dwfl_module_return_value_location (mod, functypedie, locops) if (mod->ebl == NULL) { - mod->ebl = ebl_openbackend (mod->main.elf); - if (mod->ebl == NULL) + Dwfl_Error error = __libdwfl_module_getebl (mod); + if (error != DWFL_E_NOERROR) { - __libdwfl_seterrno (DWFL_E_LIBEBL); + __libdwfl_seterrno (error); return -1; } } diff --git a/libdwfl/libdwfl.h b/libdwfl/libdwfl.h index 170ba3e0..ce85a6bb 100644 --- a/libdwfl/libdwfl.h +++ b/libdwfl/libdwfl.h @@ -82,7 +82,7 @@ typedef struct int (*section_address) (Dwfl_Module *mod, void **userdata, const char *modname, Dwarf_Addr base, const char *secname, - Elf32_Word shndx, const GElf_Shdr *shdr, + GElf_Word shndx, const GElf_Shdr *shdr, Dwarf_Addr *addr); char **debuginfo_path; /* See dwfl_standard_find_debuginfo. */ @@ -179,6 +179,9 @@ extern ptrdiff_t dwfl_getmodules (Dwfl *dwfl, void *arg, ptrdiff_t offset); +/* Find the module containing the given address. */ +extern Dwfl_Module *dwfl_addrmodule (Dwfl *dwfl, Dwarf_Addr address); + /*** Standard callbacks ***/ @@ -211,7 +214,7 @@ extern int dwfl_standard_find_debuginfo (Dwfl_Module *, void **, if ET_REL is to be supported. */ extern int dwfl_offline_section_address (Dwfl_Module *, void **, const char *, Dwarf_Addr, - const char *, Elf32_Word, + const char *, GElf_Word, const GElf_Shdr *, Dwarf_Addr *addr); @@ -222,7 +225,7 @@ extern int dwfl_linux_kernel_find_elf (Dwfl_Module *, void **, char **, Elf **); extern int dwfl_linux_kernel_module_section_address (Dwfl_Module *, void **, const char *, Dwarf_Addr, - const char *, Elf32_Word, + const char *, GElf_Word, const GElf_Shdr *, Dwarf_Addr *addr); @@ -292,7 +295,7 @@ extern int dwfl_module_relocate_address (Dwfl_Module *mod, Returns null for errors. */ extern const char *dwfl_module_relocation_info (Dwfl_Module *mod, unsigned int idx, - Elf32_Word *shndxp); + GElf_Word *shndxp); /* Validate that ADDRESS and ADDRESS+OFFSET lie in a known module and both within the same contiguous region for relocation purposes. @@ -301,10 +304,7 @@ extern int dwfl_validate_address (Dwfl *dwfl, Dwarf_Addr address, Dwarf_Sword offset); -/*** Dwarf access functions ***/ - -/* Find the module containing the given address. */ -extern Dwfl_Module *dwfl_addrmodule (Dwfl *dwfl, Dwarf_Addr address); +/*** ELF access functions ***/ /* Fetch the module main ELF file (where the allocated sections are found) for use with libelf. If successful, fills in *BIAS @@ -312,6 +312,26 @@ extern Dwfl_Module *dwfl_addrmodule (Dwfl *dwfl, Dwarf_Addr address); and those in symbol tables or Dwarf information referring to it. */ extern Elf *dwfl_module_getelf (Dwfl_Module *, GElf_Addr *bias); +/* Return the number of symbols in the module's symbol table, + or -1 for errors. */ +extern int dwfl_module_getsymtab (Dwfl_Module *mod); + +/* Fetch one entry from the module's symbol table. On errors, returns + NULL. If successful, fills in *SYM and returns the string for st_name. + This works like gelf_getsym except that st_value is always adjusted + to an absolute value based on the module's location. If SHNDXP is + non-null, it's set with the section index (whether from st_shndx or + extended index table). */ +extern const char *dwfl_module_getsym (Dwfl_Module *mod, int ndx, + GElf_Sym *sym, GElf_Word *shndxp) + __nonnull_attribute__ (3); + +/* Find the symbol that ADDRESS lies inside, and return its name. */ +extern const char *dwfl_module_addrname (Dwfl_Module *mod, GElf_Addr address); + + +/*** Dwarf access functions ***/ + /* Fetch the module's debug information for use with libdw. If successful, fills in *BIAS with the difference between addresses within the loaded module and those to use with libdw. */ @@ -368,17 +388,20 @@ extern int dwfl_module_getsrc_file (Dwfl_Module *mod, /* Return the module containing this line record. */ extern Dwfl_Module *dwfl_linemodule (Dwfl_Line *line); +/* Return the CU containing this line record. */ +extern Dwarf_Die *dwfl_linecu (Dwfl_Line *line); + /* Return the source file name and fill in other information. Arguments may be null for unneeded fields. */ extern const char *dwfl_lineinfo (Dwfl_Line *line, Dwarf_Addr *addr, int *linep, int *colp, Dwarf_Word *mtime, Dwarf_Word *length); - -/* Find the symbol that ADDRESS lies inside, and return its name. */ -extern const char *dwfl_module_addrname (Dwfl_Module *mod, GElf_Addr address); +/* Return the compilation directory (AT_comp_dir) from this line's CU. */ +extern const char *dwfl_line_comp_dir (Dwfl_Line *line); +/*** Machine backend access functions ***/ /* Return location expression to find return value given a DW_TAG_subprogram, DW_TAG_subroutine_type, or similar DIE describing diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h index bc798fa1..949e0d7e 100644 --- a/libdwfl/libdwflP.h +++ b/libdwfl/libdwflP.h @@ -1,5 +1,5 @@ /* Internal definitions for libdwfl. - Copyright (C) 2005 Red Hat, Inc. + Copyright (C) 2005, 2006 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -144,7 +144,7 @@ struct Dwfl_Module struct dwfl_file *symfile; /* Either main or debug. */ Elf_Data *symdata; /* Data in the ELF symbol table section. */ size_t syments; /* sh_size / sh_entsize of that section. */ - const Elf_Data *symstrdata; /* Data for its string table. */ + Elf_Data *symstrdata; /* Data for its string table. */ Elf_Data *symxndxdata; /* Data in the extended section index table. */ Dwfl_Error symerr; /* Previous failure to load symbols. */ @@ -198,13 +198,14 @@ struct Dwfl_Lines }; static inline struct dwfl_cu * -dwfl_linecu (const Dwfl_Line *line) +dwfl_linecu_inline (const Dwfl_Line *line) { const struct Dwfl_Lines *lines = ((const void *) line - offsetof (struct Dwfl_Lines, idx[line->idx])); return lines->cu; } +#define dwfl_linecu dwfl_linecu_inline /* This describes a contiguous address range that lies in a single CU. We condense runs of Dwarf_Arange entries for the same CU into this. */ @@ -270,6 +271,8 @@ INTDECL (dwfl_addrdie) INTDECL (dwfl_module_addrdie) INTDECL (dwfl_module_getdwarf) INTDECL (dwfl_module_getelf) +INTDECL (dwfl_module_getsym) +INTDECL (dwfl_module_getsymtab) INTDECL (dwfl_module_getsrc) INTDECL (dwfl_report_elf) INTDECL (dwfl_report_begin) diff --git a/libdwfl/relocate.c b/libdwfl/relocate.c index 3431743b..f0013e3b 100644 --- a/libdwfl/relocate.c +++ b/libdwfl/relocate.c @@ -1,5 +1,5 @@ /* Relocate debug information. - Copyright (C) 2005 Red Hat, Inc. + Copyright (C) 2005, 2006 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -156,11 +156,6 @@ __libdwfl_relocate (Dwfl_Module *mod, Elf *debugfile) { /* First, resolve the symbol to an absolute value. */ GElf_Addr value; - inline Dwfl_Error adjust (GElf_Word shndx) - { - return __libdwfl_relocate_value (mod, symshstrndx, - shndx, &value); - } if (symndx == STN_UNDEF) /* When strip removes a section symbol referring to a @@ -172,35 +167,17 @@ __libdwfl_relocate (Dwfl_Module *mod, Elf *debugfile) value = 0; else { - GElf_Sym sym_mem; + GElf_Sym sym; GElf_Word shndx; - GElf_Sym *sym = gelf_getsymshndx (mod->symdata, - mod->symxndxdata, - symndx, &sym_mem, - &shndx); - if (sym == NULL) - return DWFL_E_LIBELF; - value = sym->st_value; - if (sym->st_shndx != SHN_XINDEX) - shndx = sym->st_shndx; - switch (shndx) - { - case SHN_ABS: - break; + if (INTUSE(dwfl_module_getsym) (mod, symndx, + &sym, &shndx) == NULL) + return dwfl_errno (); - case SHN_UNDEF: - case SHN_COMMON: - return DWFL_E_RELUNDEF; + if (shndx == SHN_UNDEF || shndx == SHN_COMMON) + return DWFL_E_RELUNDEF; - default: - { - Dwfl_Error error = adjust (shndx); - if (error != DWFL_E_NOERROR) - return error; - break; - } - } + value = sym.st_value; } /* These are the types we can relocate. */ diff --git a/src/ChangeLog b/src/ChangeLog index 7ac79785..3432dce6 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -45,6 +45,13 @@ * Makefile.am: Add hacks to create dependency files for non-generic linker. +2006-06-28 Roland McGrath <roland@redhat.com> + + * addr2line.c (use_comp_dir): New variable. + (options, parse_opt): Grok -A/--absolute to set it. + (handle_address): If set, prepend dwfl_line_comp_dir results to + relative file names. + 2006-06-12 Ulrich Drepper <drepper@redhat.com> * ldgeneric.c (ld_generic_generate_sections): Don't create .interp diff --git a/src/addr2line.c b/src/addr2line.c index 1729058e..c849ec79 100644 --- a/src/addr2line.c +++ b/src/addr2line.c @@ -63,6 +63,8 @@ static const struct argp_option options[] = { { NULL, 0, NULL, 0, N_("Output Selection:"), 0 }, { "basenames", 's', NULL, 0, N_("Show only base names of source files"), 0 }, + { "absolute", 'A', NULL, 0, + N_("Show absolute file names using compilation directory"), 0 }, { "functions", 'f', NULL, 0, N_("Additional show function names"), 0 }, { NULL, 0, NULL, 0, N_("Miscellaneous:"), 0 }, @@ -99,6 +101,9 @@ static void handle_address (GElf_Addr addr, Dwfl *dwfl); /* True if only base names of files should be shown. */ static bool only_basenames; +/* True if absolute file names based on DW_AT_comp_dir should be shown. */ +static bool use_comp_dir; + /* True if function names should be shown. */ static bool show_functions; @@ -207,6 +212,10 @@ parse_opt (int key, char *arg __attribute__ ((unused)), only_basenames = true; break; + case 'A': + use_comp_dir = true; + break; + case 'f': show_functions = true; break; @@ -307,13 +316,24 @@ handle_address (GElf_Addr addr, Dwfl *dwfl) if (line != NULL && (src = dwfl_lineinfo (line, &addr, &lineno, &linecol, NULL, NULL)) != NULL) { + const char *comp_dir = ""; + const char *comp_dir_sep = ""; + if (only_basenames) src = basename (src); + else if (use_comp_dir && src[0] != '/') + { + comp_dir = dwfl_line_comp_dir (line); + if (comp_dir != NULL) + comp_dir_sep = "/"; + } if (linecol != 0) - printf ("%s:%d:%d\n", src, lineno, linecol); + printf ("%s%s%s:%d:%d\n", + comp_dir, comp_dir_sep, src, lineno, linecol); else - printf ("%s:%d\n", src, lineno); + printf ("%s%s%s:%d\n", + comp_dir, comp_dir_sep, src, lineno); } else puts ("??:0"); |