diff options
author | Roland McGrath <roland@redhat.com> | 2008-08-07 08:39:41 +0000 |
---|---|---|
committer | Roland McGrath <roland@redhat.com> | 2008-08-07 08:39:41 +0000 |
commit | 1d8bb25cac06b5af57f8733e5ea7a068a79edfe0 (patch) | |
tree | f794a75ef8e1f324185d2850e6e4da59323fe9ca | |
parent | 9d2f3ee2554185a9df70f434eddc4405a4aff0fa (diff) | |
download | elfutils-1d8bb25cac06b5af57f8733e5ea7a068a79edfe0.tar.gz |
src/
(find_symbol): Likewise.
Convert plain number, or handle strings like "(section)+offset"
or "symbol+offset".
-rw-r--r-- | backends/ChangeLog | 19 | ||||
-rw-r--r-- | backends/Makefile.am | 8 | ||||
-rw-r--r-- | backends/i386_init.c | 3 | ||||
-rw-r--r-- | backends/i386_syscall.c | 47 | ||||
-rw-r--r-- | backends/linux-core-note.c | 6 | ||||
-rw-r--r-- | backends/ppc64_init.c | 3 | ||||
-rw-r--r-- | backends/ppc_corenote.c | 7 | ||||
-rw-r--r-- | backends/ppc_init.c | 1 | ||||
-rw-r--r-- | backends/ppc_syscall.c | 50 | ||||
-rw-r--r-- | backends/x86_64_init.c | 1 | ||||
-rw-r--r-- | backends/x86_64_syscall.c | 47 | ||||
-rw-r--r-- | libdwfl/ChangeLog | 14 | ||||
-rw-r--r-- | libdwfl/dwfl_build_id_find_elf.c | 7 | ||||
-rw-r--r-- | libdwfl/dwfl_module_addrsym.c | 3 | ||||
-rw-r--r-- | libdwfl/linux-kernel-modules.c | 7 | ||||
-rw-r--r-- | libebl/ChangeLog | 16 | ||||
-rw-r--r-- | libebl/Makefile.am | 2 | ||||
-rw-r--r-- | libebl/ebl-hooks.h | 4 | ||||
-rw-r--r-- | libebl/ebl_syscall_abi.c | 66 | ||||
-rw-r--r-- | libebl/eblauxvinfo.c | 5 | ||||
-rw-r--r-- | libebl/eblopenbackend.c | 17 | ||||
-rw-r--r-- | libebl/libebl.h | 7 | ||||
-rw-r--r-- | libelf/ChangeLog | 4 | ||||
-rw-r--r-- | libelf/elf.h | 24 | ||||
-rw-r--r-- | src/ChangeLog | 27 | ||||
-rw-r--r-- | src/addr2line.c | 148 | ||||
-rw-r--r-- | src/readelf.c | 151 |
27 files changed, 622 insertions, 72 deletions
diff --git a/backends/ChangeLog b/backends/ChangeLog index 06e9041f..96b64794 100644 --- a/backends/ChangeLog +++ b/backends/ChangeLog @@ -1,3 +1,22 @@ +2008-08-01 Roland McGrath <roland@redhat.com> + + * linux-core-note.c (prstatus_items): Use 'B' instead of 'b' + for sigpend and sighold. + +2008-07-04 Roland McGrath <roland@redhat.com> + + * i386_syscall.c: New file. + * x86_64_syscall.c: New file. + * ppc_syscall.c: New file. + * Makefile.am (i386_SRCS, x86_64_SRCS, ppc_SRCS, ppc64_SRCS): Add them. + * i386_init.c (i386_init): Initialize syscall_abi hook. + * x86_64_init.c (x86_64_init): Likewise. + * ppc_init.c (ppc_init): Likewise. + * ppc64_init.c (ppc64_init): Likewise. + + * ppc_corenote.c (PRSTATUS_REGSET_ITEMS): Add nip. + Fix offset calculation for 64-bit case. + 2008-04-04 Roland McGrath <roland@redhat.com> * alpha_symbol.c (alpha_check_special_section): New function. diff --git a/backends/Makefile.am b/backends/Makefile.am index 75eacde9..ebf6b09e 100644 --- a/backends/Makefile.am +++ b/backends/Makefile.am @@ -61,7 +61,7 @@ textrel_check = if readelf -d $@ | fgrep -q TEXTREL; then exit 1; fi i386_SRCS = i386_init.c i386_symbol.c i386_corenote.c \ - i386_retval.c i386_regs.c i386_auxv.c + i386_retval.c i386_regs.c i386_auxv.c i386_syscall.c cpu_i386 = ../libcpu/libcpu_i386.a libebl_i386_pic_a_SOURCES = $(i386_SRCS) am_libebl_i386_pic_a_OBJECTS = $(i386_SRCS:.c=.os) @@ -71,7 +71,7 @@ libebl_sh_pic_a_SOURCES = $(sh_SRCS) am_libebl_sh_pic_a_OBJECTS = $(sh_SRCS:.c=.os) x86_64_SRCS = x86_64_init.c x86_64_symbol.c x86_64_corenote.c \ - x86_64_retval.c x86_64_regs.c i386_auxv.c + x86_64_retval.c x86_64_regs.c i386_auxv.c x86_64_syscall.c cpu_x86_64 = ../libcpu/libcpu_x86_64.a libebl_x86_64_pic_a_SOURCES = $(x86_64_SRCS) am_libebl_x86_64_pic_a_OBJECTS = $(x86_64_SRCS:.c=.os) @@ -95,12 +95,12 @@ libebl_sparc_pic_a_SOURCES = $(sparc_SRCS) am_libebl_sparc_pic_a_OBJECTS = $(sparc_SRCS:.c=.os) ppc_SRCS = ppc_init.c ppc_symbol.c ppc_retval.c ppc_regs.c \ - ppc_corenote.c ppc_auxv.c ppc_attrs.c + ppc_corenote.c ppc_auxv.c ppc_attrs.c ppc_syscall.c libebl_ppc_pic_a_SOURCES = $(ppc_SRCS) am_libebl_ppc_pic_a_OBJECTS = $(ppc_SRCS:.c=.os) ppc64_SRCS = ppc64_init.c ppc64_symbol.c ppc64_retval.c \ - ppc64_corenote.c ppc_regs.c ppc_auxv.c ppc_attrs.c + ppc64_corenote.c ppc_regs.c ppc_auxv.c ppc_attrs.c ppc_syscall.c libebl_ppc64_pic_a_SOURCES = $(ppc64_SRCS) am_libebl_ppc64_pic_a_OBJECTS = $(ppc64_SRCS:.c=.os) diff --git a/backends/i386_init.c b/backends/i386_init.c index bf6c130c..f046dfb6 100644 --- a/backends/i386_init.c +++ b/backends/i386_init.c @@ -1,5 +1,5 @@ /* Initialization of i386 specific backend library. - Copyright (C) 2000, 2001, 2002, 2005, 2006, 2007 Red Hat, Inc. + Copyright (C) 2000, 2001, 2002, 2005, 2006, 2007, 2008 Red Hat, Inc. This file is part of Red Hat elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2000. @@ -56,6 +56,7 @@ i386_init (elf, machine, eh, ehlen) HOOK (eh, debugscn_p); HOOK (eh, return_value_location); HOOK (eh, register_info); + HOOK (eh, syscall_abi); HOOK (eh, auxv_info); HOOK (eh, disasm); diff --git a/backends/i386_syscall.c b/backends/i386_syscall.c new file mode 100644 index 00000000..4d6e438c --- /dev/null +++ b/backends/i386_syscall.c @@ -0,0 +1,47 @@ +/* Linux/i386 system call ABI in DWARF register numbers. + Copyright (C) 2008 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. + + 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>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#define BACKEND i386_ +#include "libebl_CPU.h" + +int +i386_syscall_abi (Ebl *ebl __attribute__ ((unused)), + int *sp, int *pc, int *callno, int args[6]) +{ + *sp = 4; /* %esp */ + *pc = 8; /* %eip */ + *callno = 0; /* %eax */ + args[0] = 3; /* %ebx */ + args[1] = 1; /* %ecx */ + args[2] = 2; /* %edx */ + args[3] = 6; /* %esi */ + args[4] = 7; /* %edi */ + args[5] = 5; /* %ebp */ + return 0; +} diff --git a/backends/linux-core-note.c b/backends/linux-core-note.c index 3dc41373..7b1fc025 100644 --- a/backends/linux-core-note.c +++ b/backends/linux-core-note.c @@ -1,5 +1,5 @@ /* Common core note type descriptions for Linux. - Copyright (C) 2007 Red Hat, Inc. + Copyright (C) 2007, 2008 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -118,8 +118,8 @@ static const Ebl_Core_Item prstatus_items[] = FIELD (signal, INT, info.si_code, 'd'), FIELD (signal, INT, info.si_errno, 'd'), FIELD (signal, SHORT, cursig, 'd'), - FIELD (signal, ULONG, sigpend, 'b'), - FIELD (signal, ULONG, sighold, 'b'), + FIELD (signal, ULONG, sigpend, 'B'), + FIELD (signal, ULONG, sighold, 'B'), FIELD (identity, PID_T, pid, 'd', .thread_identifier = true), FIELD (identity, PID_T, ppid, 'd'), FIELD (identity, PID_T, pgrp, 'd'), diff --git a/backends/ppc64_init.c b/backends/ppc64_init.c index 02a592fd..3060a605 100644 --- a/backends/ppc64_init.c +++ b/backends/ppc64_init.c @@ -1,5 +1,5 @@ /* Initialization of PPC64 specific backend library. - Copyright (C) 2004, 2005, 2006, 2007 Red Hat, Inc. + Copyright (C) 2004, 2005, 2006, 2007, 2008 Red Hat, Inc. This file is part of Red Hat elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2004. @@ -58,6 +58,7 @@ ppc64_init (elf, machine, eh, ehlen) HOOK (eh, bss_plt_p); HOOK (eh, return_value_location); HOOK (eh, register_info); + HOOK (eh, syscall_abi); HOOK (eh, core_note); HOOK (eh, auxv_info); diff --git a/backends/ppc_corenote.c b/backends/ppc_corenote.c index 59e619e1..af0c46aa 100644 --- a/backends/ppc_corenote.c +++ b/backends/ppc_corenote.c @@ -118,8 +118,13 @@ static const Ebl_Register_Location spe_regs[] = #define PRSTATUS_REGSET_ITEMS \ { \ + .name = "nip", .type = ELF_T_ADDR, .format = 'x', \ + .offset = offsetof (struct EBLHOOK(prstatus), pr_reg[32]), \ + .group = "register" \ + }, \ + { \ .name = "orig_gpr3", .type = TYPE_LONG, .format = 'd', \ - .offset = offsetof (struct EBLHOOK(prstatus), pr_reg) + (4 * 34), \ + .offset = offsetof (struct EBLHOOK(prstatus), pr_reg[34]), \ .group = "register" \ } diff --git a/backends/ppc_init.c b/backends/ppc_init.c index 2e587167..523c6583 100644 --- a/backends/ppc_init.c +++ b/backends/ppc_init.c @@ -57,6 +57,7 @@ ppc_init (elf, machine, eh, ehlen) HOOK (eh, bss_plt_p); HOOK (eh, return_value_location); HOOK (eh, register_info); + HOOK (eh, syscall_abi); HOOK (eh, core_note); HOOK (eh, auxv_info); HOOK (eh, check_object_attribute); diff --git a/backends/ppc_syscall.c b/backends/ppc_syscall.c new file mode 100644 index 00000000..23eff812 --- /dev/null +++ b/backends/ppc_syscall.c @@ -0,0 +1,50 @@ +/* Linux/PPC system call ABI in DWARF register numbers. + Copyright (C) 2008 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. + + 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>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#define BACKEND ppc_ +#include "libebl_CPU.h" + +int +ppc_syscall_abi (Ebl *ebl __attribute__ ((unused)), + int *sp, int *pc, int *callno, int args[6]) +{ + *sp = 1; + *pc = -1; + *callno = 0; + args[0] = 3; + args[1] = 4; + args[2] = 5; + args[3] = 6; + args[4] = 7; + args[5] = 8; + return 0; +} + +__typeof (ppc_syscall_abi) +ppc64_syscall_abi __attribute__ ((alias ("ppc_syscall_abi"))); diff --git a/backends/x86_64_init.c b/backends/x86_64_init.c index 4e9eb55c..a2eaffa5 100644 --- a/backends/x86_64_init.c +++ b/backends/x86_64_init.c @@ -53,6 +53,7 @@ x86_64_init (elf, machine, eh, ehlen) HOOK (eh, core_note); HOOK (eh, return_value_location); HOOK (eh, register_info); + HOOK (eh, syscall_abi); HOOK (eh, auxv_info); HOOK (eh, disasm); diff --git a/backends/x86_64_syscall.c b/backends/x86_64_syscall.c new file mode 100644 index 00000000..c3db715d --- /dev/null +++ b/backends/x86_64_syscall.c @@ -0,0 +1,47 @@ +/* Linux/x86-64 system call ABI in DWARF register numbers. + Copyright (C) 2008 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. + + 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>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#define BACKEND x86_64_ +#include "libebl_CPU.h" + +int +x86_64_syscall_abi (Ebl *ebl __attribute__ ((unused)), + int *sp, int *pc, int *callno, int args[6]) +{ + *sp = 7; /* %rsp */ + *pc = 16; /* %rip */ + *callno = 0; /* %rax */ + args[0] = 5; /* %rdi */ + args[1] = 4; /* %rsi */ + args[2] = 1; /* %rdx */ + args[3] = 10; /* %r10 */ + args[4] = 8; /* %r8 */ + args[5] = 9; /* %r9 */ + return 0; +} diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index 38f6be73..28c6ee3c 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,3 +1,17 @@ +2008-08-03 Roland McGrath <roland@redhat.com> + + * linux-kernel-modules.c: Include <fts.h> before <config.h>. + +2008-07-17 Roland McGrath <roland@redhat.com> + + * dwfl_build_id_find_elf.c (__libdwfl_open_by_build_id): Set errno to + zero if the failure was only ENOENT. + +2008-06-03 Roland McGrath <roland@redhat.com> + + * dwfl_module_addrsym.c (dwfl_module_addrsym): Exclude undefined + symbols. + 2008-05-22 Petr Machata <pmachata@redhat.com> * dwfl_module_getdwarf.c (open_elf): Bias of ET_EXEC files is always 0. diff --git a/libdwfl/dwfl_build_id_find_elf.c b/libdwfl/dwfl_build_id_find_elf.c index a6e38ce7..1a226dfd 100644 --- a/libdwfl/dwfl_build_id_find_elf.c +++ b/libdwfl/dwfl_build_id_find_elf.c @@ -119,6 +119,13 @@ __libdwfl_open_by_build_id (Dwfl_Module *mod, bool debug, char **file_name) free (name); } + /* If we simply found nothing, clear errno. If we had some other error + with the file, report that. Possibly this should treat other errors + like ENOENT too. But ignoring all errors could mask some that should + be reported. */ + if (fd < 0 && errno == ENOENT) + errno = 0; + return fd; } diff --git a/libdwfl/dwfl_module_addrsym.c b/libdwfl/dwfl_module_addrsym.c index f16de116..bc1d556e 100644 --- a/libdwfl/dwfl_module_addrsym.c +++ b/libdwfl/dwfl_module_addrsym.c @@ -1,5 +1,5 @@ /* Find debugging and symbol information for a module in libdwfl. - Copyright (C) 2005, 2006, 2007 Red Hat, Inc. + Copyright (C) 2005, 2006, 2007, 2008 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -117,6 +117,7 @@ dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr, GElf_Word shndx; const char *name = INTUSE(dwfl_module_getsym) (mod, i, &sym, &shndx); if (name != NULL + && sym.st_shndx != SHN_UNDEF && sym.st_value <= addr && (sym.st_size == 0 || addr - sym.st_value < sym.st_size)) { diff --git a/libdwfl/linux-kernel-modules.c b/libdwfl/linux-kernel-modules.c index 2cfe6bc8..5bbb384a 100644 --- a/libdwfl/linux-kernel-modules.c +++ b/libdwfl/linux-kernel-modules.c @@ -47,8 +47,12 @@ Network licensing program, please visit www.openinventionnetwork.com <http://www.openinventionnetwork.com>. */ +/* We include this before config.h because it can't handle _FILE_OFFSET_BITS. + Everything we need here is fine if its declarations just come first. */ + +#include <fts.h> + #include <config.h> -#undef _FILE_OFFSET_BITS /* Doesn't jibe with fts. */ #include "libdwflP.h" #include <inttypes.h> @@ -60,7 +64,6 @@ #include <sys/utsname.h> #include <fcntl.h> #include <unistd.h> -#include <fts.h> #define KERNEL_MODNAME "kernel" diff --git a/libebl/ChangeLog b/libebl/ChangeLog index 9838727a..57ac2c8c 100644 --- a/libebl/ChangeLog +++ b/libebl/ChangeLog @@ -1,3 +1,19 @@ +2008-07-28 Roland McGrath <roland@redhat.com> + + * eblauxvinfo.c (AUXV_TYPES): Add EXECFN. + + * eblauxvinfo.c (ebl_auxv_info): Handle missing elements of standard + table. + +2008-07-04 Roland McGrath <roland@redhat.com> + + * libebl.h: Declare ebl_syscall_abi. + * ebl_syscall_abi.c: New file. + * Makefile.am (gen_SOURCES): Add it. + * ebl-hooks.h: New hook syscall_abi. + * eblopenbackend.c (default_syscall_abi): New function. + (fill_defaults): Use it. + 2008-03-31 Roland McGrath <roland@redhat.com> * ebldynamictagname.c (ebl_dynamic_tag_name): Use hex for unknown tag. diff --git a/libebl/Makefile.am b/libebl/Makefile.am index 0d06a859..c4e4a076 100644 --- a/libebl/Makefile.am +++ b/libebl/Makefile.am @@ -59,7 +59,7 @@ gen_SOURCES = eblopenbackend.c eblclosebackend.c eblstrtab.c \ ebl_check_special_symbol.c eblbsspltp.c eblretval.c \ eblreginfo.c eblnonerelocp.c eblrelativerelocp.c \ eblsysvhashentrysize.c eblauxvinfo.c eblcheckobjattr.c \ - ebl_check_special_section.c + ebl_check_special_section.c ebl_syscall_abi.c libebl_a_SOURCES = $(gen_SOURCES) diff --git a/libebl/ebl-hooks.h b/libebl/ebl-hooks.h index 9f6c8d2c..2db1e208 100644 --- a/libebl/ebl-hooks.h +++ b/libebl/ebl-hooks.h @@ -158,6 +158,10 @@ ssize_t EBLHOOK(register_info) (Ebl *ebl, const char **prefix, const char **setname, int *bits, int *type); +/* Return system call ABI registers. */ +int EBLHOOK(syscall_abi) (Ebl *ebl, int *sp, int *pc, + int *callno, int args[6]); + /* Disassembler function. */ int EBLHOOK(disasm) (const uint8_t **startp, const uint8_t *end, GElf_Addr addr, const char *fmt, DisasmOutputCB_t outcb, diff --git a/libebl/ebl_syscall_abi.c b/libebl/ebl_syscall_abi.c new file mode 100644 index 00000000..2d9a26b6 --- /dev/null +++ b/libebl/ebl_syscall_abi.c @@ -0,0 +1,66 @@ +/* Return system call ABI mapped to DWARF register numbers. + Copyright (C) 2008 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>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <libeblP.h> + + +int +ebl_syscall_abi (ebl, sp, pc, callno, args) + Ebl *ebl; + int *sp; + int *pc; + int *callno; + int args[6]; +{ + return ebl != NULL ? ebl->syscall_abi (ebl, sp, pc, callno, args) : -1; +} diff --git a/libebl/eblauxvinfo.c b/libebl/eblauxvinfo.c index 54583f9f..af65c47b 100644 --- a/libebl/eblauxvinfo.c +++ b/libebl/eblauxvinfo.c @@ -1,5 +1,5 @@ /* Describe known auxv types. - Copyright (C) 2007 Red Hat, Inc. + Copyright (C) 2007, 2008 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -63,6 +63,7 @@ TYPE (NULL, "") \ TYPE (IGNORE, "") \ TYPE (EXECFD, "d") \ + TYPE (EXECFN, "s") \ TYPE (PHDR, "p") \ TYPE (PHENT, "u") \ TYPE (PHNUM, "u") \ @@ -110,7 +111,7 @@ ebl_auxv_info (ebl, a_type, name, format) const char **format; { int result = ebl->auxv_info (a_type, name, format); - if (result == 0 && a_type < nauxv_types) + if (result == 0 && a_type < nauxv_types && auxv_types[a_type].name != NULL) { /* The machine specific function did not know this type. */ *name = auxv_types[a_type].name; diff --git a/libebl/eblopenbackend.c b/libebl/eblopenbackend.c index 672e834b..8cf42189 100644 --- a/libebl/eblopenbackend.c +++ b/libebl/eblopenbackend.c @@ -212,6 +212,8 @@ static ssize_t default_register_info (Ebl *ebl, const char **prefix, const char **setname, int *bits, int *type); +static int default_syscall_abi (Ebl *ebl, int *sp, int *pc, + int *callno, int args[6]); static bool default_check_object_attribute (Ebl *ebl, const char *vendor, int tag, uint64_t value, const char **tag_name, @@ -253,6 +255,7 @@ fill_defaults (Ebl *result) result->bss_plt_p = default_bss_plt_p; result->return_value_location = default_return_value_location; result->register_info = default_register_info; + result->syscall_abi = default_syscall_abi; result->check_object_attribute = default_check_object_attribute; result->disasm = NULL; result->destr = default_destr; @@ -718,6 +721,20 @@ default_register_info (Ebl *ebl __attribute__ ((unused)), return snprintf (name, namelen, "reg%d", regno); } +static int +default_syscall_abi (Ebl *ebl __attribute__ ((unused)), + int *sp, int *pc, int *callno, int args[6]) +{ + *sp = *pc = *callno = -1; + args[0] = -1; + args[1] = -1; + args[2] = -1; + args[3] = -1; + args[4] = -1; + args[5] = -1; + return -1; +} + static bool default_check_object_attribute (Ebl *ebl __attribute__ ((unused)), const char *vendor __attribute__ ((unused)), diff --git a/libebl/libebl.h b/libebl/libebl.h index 118ae7e7..50258690 100644 --- a/libebl/libebl.h +++ b/libebl/libebl.h @@ -248,6 +248,13 @@ extern ssize_t ebl_register_info (Ebl *ebl, const char **prefix, const char **setname, int *bits, int *type); +/* Fill in the DWARF register numbers for the registers used in system calls. + The SP and PC are what kernel reports call the user stack pointer and PC. + The CALLNO and ARGS are the system call number and incoming arguments. + Each of these is filled with the DWARF register number corresponding, + or -1 if there is none. Returns zero when the information is available. */ +extern int ebl_syscall_abi (Ebl *ebl, int *sp, int *pc, + int *callno, int args[6]); /* ELF string table handling. */ struct Ebl_Strtab; diff --git a/libelf/ChangeLog b/libelf/ChangeLog index f646c06b..8e07b9de 100644 --- a/libelf/ChangeLog +++ b/libelf/ChangeLog @@ -1,3 +1,7 @@ +2008-07-28 Roland McGrath <roland@redhat.com> + + * elf.h: Update from glibc. + 2008-03-31 Roland McGrath <roland@redhat.com> * elf32_offscn.c: Make sure shdrs have been read in. diff --git a/libelf/elf.h b/libelf/elf.h index 928e9ec9..a4134462 100644 --- a/libelf/elf.h +++ b/libelf/elf.h @@ -970,6 +970,8 @@ typedef struct #define AT_SECURE 23 /* Boolean, was exec setuid-like? */ +#define AT_EXECFN 31 /* Filename of executable. */ + /* Pointer to the global system page used for system calls and other nice things. */ #define AT_SYSINFO 32 @@ -1159,8 +1161,17 @@ typedef struct #define R_386_TLS_DTPMOD32 35 /* ID of module containing symbol */ #define R_386_TLS_DTPOFF32 36 /* Offset in TLS block */ #define R_386_TLS_TPOFF32 37 /* Negated offset in static TLS block */ +/* 38? */ +#define R_386_TLS_GOTDESC 39 /* GOT offset for TLS descriptor. */ +#define R_386_TLS_DESC_CALL 40 /* Marker of call through TLS + descriptor for + relaxation. */ +#define R_386_TLS_DESC 41 /* TLS descriptor containing + pointer to code and to + argument, returning the TLS + offset for the symbol. */ /* Keep this the last entry. */ -#define R_386_NUM 38 +#define R_386_NUM 42 /* SUN SPARC specific definitions. */ @@ -2557,8 +2568,17 @@ typedef Elf32_Addr Elf32_Conflict; #define R_X86_64_GOTTPOFF 22 /* 32 bit signed PC relative offset to GOT entry for IE symbol */ #define R_X86_64_TPOFF32 23 /* Offset in initial TLS block */ +#define R_X86_64_PC64 24 /* PC relative 64 bit */ +#define R_X86_64_GOTOFF64 25 /* 64 bit offset to GOT */ +#define R_X86_64_GOTPC32 26 /* 32 bit signed pc relative + offset to GOT */ +/* 27 .. 33 */ +#define R_X86_64_GOTPC32_TLSDESC 34 /* GOT offset for TLS descriptor. */ +#define R_X86_64_TLSDESC_CALL 35 /* Marker for call through TLS + descriptor. */ +#define R_X86_64_TLSDESC 36 /* TLS descriptor. */ -#define R_X86_64_NUM 24 +#define R_X86_64_NUM 37 /* AM33 relocations. */ diff --git a/src/ChangeLog b/src/ChangeLog index 94444c58..4ef23a22 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,30 @@ +2008-08-07 Roland McGrath <roland@redhat.com> + + * addr2line.c (main): Pass string to handle_address. + (see_one_module): New function, subroutine of handle_address. + (find_symbol): Likewise. + (handle_address): Take string argument rather than address. + Convert plain number, or handle strings like "(section)+offset" + or "symbol+offset". + +2008-08-01 Roland McGrath <roland@redhat.com> + + * readelf.c (handle_core_item): Handle 'B' type for 1-origin bitset. + For 'b' and 'B', print <x-y,z> or ~<x,y-z> rather than 1/0 string. + + * readelf.c (convert): Take new argument SIZE. + (handle_core_register, handle_core_item): Update callers. + (handle_core_item): Take new arg REPEATED_SIZE. + (handle_core_items): Special case for a singleton item, + let handle_core_item handle repeats if it wants to. + + * readelf.c (handle_core_items): Give abridged output + for identical groups repeated more than twice. + +2008-07-04 Roland McGrath <roland@redhat.com> + + * readelf.c (handle_core_items): Handle ELF_T_ADDR. + 2008-04-10 Roland McGrath <roland@redhat.com> * strip.c (handle_elf): Don't keep sections that kept symbol tables diff --git a/src/addr2line.c b/src/addr2line.c index 4b1d13e7..0d11e188 100644 --- a/src/addr2line.c +++ b/src/addr2line.c @@ -1,5 +1,5 @@ /* Locate source files and line information for given addresses - Copyright (C) 2005, 2006, 2007 Red Hat, Inc. + Copyright (C) 2005, 2006, 2007, 2008 Red Hat, Inc. This file is part of Red Hat elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2005. @@ -96,7 +96,7 @@ static const struct argp argp = /* Handle ADDR. */ -static void handle_address (GElf_Addr addr, Dwfl *dwfl); +static int handle_address (const char *addr, Dwfl *dwfl); /* True if only base names of files should be shown. */ @@ -154,12 +154,7 @@ main (int argc, char *argv[]) if (getline (&buf, &len, stdin) < 0) break; - char *endp; - uintmax_t addr = strtoumax (buf, &endp, 0); - if (endp != buf) - handle_address (addr, dwfl); - else - result = 1; + result = handle_address (buf, dwfl); } free (buf); @@ -167,14 +162,7 @@ main (int argc, char *argv[]) else { do - { - char *endp; - uintmax_t addr = strtoumax (argv[remaining], &endp, 0); - if (endp != argv[remaining]) - handle_address (addr, dwfl); - else - result = 1; - } + result = handle_address (argv[remaining], dwfl); while (++remaining < argc); } @@ -328,9 +316,131 @@ print_addrsym (Dwfl_Module *mod, GElf_Addr addr) printf ("%s+%#" PRIx64 "\n", name, addr - s.st_value); } -static void -handle_address (GElf_Addr addr, Dwfl *dwfl) +static int +see_one_module (Dwfl_Module *mod, + void **userdata __attribute__ ((unused)), + const char *name __attribute__ ((unused)), + Dwarf_Addr start __attribute__ ((unused)), + void *arg) +{ + Dwfl_Module **result = arg; + if (*result != NULL) + return DWARF_CB_ABORT; + *result = mod; + return DWARF_CB_OK; +} + +static int +find_symbol (Dwfl_Module *mod, + void **userdata __attribute__ ((unused)), + const char *name __attribute__ ((unused)), + Dwarf_Addr start __attribute__ ((unused)), + void *arg) +{ + const char *looking_for = ((void **) arg)[0]; + GElf_Sym *symbol = ((void **) arg)[1]; + + int n = dwfl_module_getsymtab (mod); + for (int i = 1; i < n; ++i) + { + const char *symbol_name = dwfl_module_getsym (mod, i, symbol, NULL); + if (symbol_name == NULL) + continue; + switch (GELF_ST_TYPE (symbol->st_info)) + { + case STT_SECTION: + case STT_FILE: + case STT_TLS: + break; + default: + if (!strcmp (symbol_name, looking_for)) + { + ((void **) arg)[0] = NULL; + return DWARF_CB_ABORT; + } + } + } + + return DWARF_CB_OK; +} + +static int +handle_address (const char *string, Dwfl *dwfl) { + char *endp; + uintmax_t addr = strtoumax (string, &endp, 0); + if (endp == string) + { + bool parsed = false; + int n; + char *name = NULL; + if (sscanf (string, "(%m[^)])%" PRIiMAX "%n", &name, &addr, &n) == 2 + && string[n] == '\0') + { + /* It was (section)+offset. This makes sense if there is + only one module to look in for a section. */ + Dwfl_Module *mod = NULL; + if (dwfl_getmodules (dwfl, &see_one_module, &mod, 0) != 0 + || mod == NULL) + error (EXIT_FAILURE, 0, gettext ("Section syntax requires" + " exactly one module")); + + int nscn = dwfl_module_relocations (mod); + for (int i = 0; i < nscn; ++i) + { + GElf_Word shndx; + const char *scn = dwfl_module_relocation_info (mod, i, &shndx); + if (unlikely (scn == NULL)) + break; + if (!strcmp (scn, name)) + { + /* Found the section. */ + GElf_Shdr shdr_mem; + GElf_Addr shdr_bias; + GElf_Shdr *shdr = gelf_getshdr + (elf_getscn (dwfl_module_getelf (mod, &shdr_bias), shndx), + &shdr_mem); + if (unlikely (shdr == NULL)) + break; + + if (addr >= shdr->sh_size) + error (0, 0, + gettext ("offset %#" PRIxMAX " lies outside" + " section '%s'"), + addr, scn); + + addr += shdr->sh_addr + shdr_bias; + parsed = true; + break; + } + } + } + else if (sscanf (string, "%m[^-+]%" PRIiMAX "%n", &name, &addr, &n) == 2 + && string[n] == '\0') + { + /* It was symbol+offset. */ + GElf_Sym sym; + void *arg[2] = { name, &sym }; + (void) dwfl_getmodules (dwfl, &find_symbol, arg, 0); + if (arg[0] != NULL) + error (0, 0, gettext ("cannot find symbol '%s'"), name); + else + { + if (sym.st_size != 0 && addr >= sym.st_size) + error (0, 0, + gettext ("offset %#" PRIxMAX " lies outside" + " contents of '%s'"), + addr, name); + addr += sym.st_value; + parsed = true; + } + } + + free (name); + if (!parsed) + return 1; + } + Dwfl_Module *mod = dwfl_addrmodule (dwfl, addr); if (show_functions) @@ -372,6 +482,8 @@ handle_address (GElf_Addr addr, Dwfl *dwfl) } else puts ("??:0"); + + return 0; } diff --git a/src/readelf.c b/src/readelf.c index 96b5d436..7b599ec8 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -5389,13 +5389,13 @@ print_core_item (unsigned int colno, char sep, unsigned int wrap, static const void * convert (Elf *core, Elf_Type type, uint_fast16_t count, - void *value, const void *data) + void *value, const void *data, size_t size) { Elf_Data valuedata = { .d_type = type, .d_buf = value, - .d_size = gelf_fsize (core, type, count, EV_CURRENT), + .d_size = size ?: gelf_fsize (core, type, count, EV_CURRENT), .d_version = EV_CURRENT, }; Elf_Data indata = @@ -5420,7 +5420,7 @@ typedef uint8_t GElf_Byte; static unsigned int handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc, - unsigned int colno) + unsigned int colno, size_t *repeated_size) { uint_fast16_t count = item->count ?: 1; @@ -5436,13 +5436,33 @@ handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc, union { TYPES; } value; #undef DO_TYPE - desc = convert (core, item->type, count, &value, desc + item->offset); + void *data = &value; + size_t size = gelf_fsize (core, item->type, count, EV_CURRENT); + size_t convsize = size; + if (repeated_size != NULL) + { + if (*repeated_size > size && (item->format == 'b' || item->format == 'B')) + { + data = alloca (*repeated_size); + count *= *repeated_size / size; + convsize = count * size; + *repeated_size -= convsize; + } + else + *repeated_size -= size; + } + + desc = convert (core, item->type, count, data, desc + item->offset, convsize); + + Elf_Type type = item->type; + if (type == ELF_T_ADDR) + type = gelf_getclass (core) == ELFCLASS32 ? ELF_T_WORD : ELF_T_XWORD; switch (item->format) { case 'd': assert (count == 1); - switch (item->type) + switch (type) { #define DO_TYPE(NAME, Name, hex, dec, max) \ case ELF_T_##NAME: \ @@ -5458,7 +5478,7 @@ handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc, case 'x': assert (count == 1); - switch (item->type) + switch (type) { #define DO_TYPE(NAME, Name, hex, dec, max) \ case ELF_T_##NAME: \ @@ -5473,30 +5493,59 @@ handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc, break; case 'b': - assert (count == 1); - Dwarf_Word bits = 0; - Dwarf_Word bit = 0; - switch (item->type) - { -#define DO_TYPE(NAME, Name, hex, dec, max) \ - case ELF_T_##NAME: \ - bits = value.Name[0]; \ - bit = (Dwarf_Word) 1 << ((sizeof value.Name[0] * 8) - 1); \ - break - TYPES; -#undef DO_TYPE - default: - abort (); - } - char printed[sizeof (Dwarf_Word) * 8 + 1]; - int i = 0; - while (bit != 0) - { - printed[i++] = (bits & bit) ? '1' : '0'; - bit >>= 1; - } - colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name, - sizeof printed - 1, "%.*s", i, printed); + case 'B': + assert (size % sizeof (unsigned int) == 0); + unsigned int nbits = count * size * 8; + unsigned int pop = 0; + for (const unsigned int *i = data; (void *) i < data + count * size; ++i) + pop += __builtin_popcount (*i); + bool negate = pop > nbits / 2; + const unsigned int bias = item->format == 'b'; + + { + char printed[(negate ? nbits - pop : pop) * 16]; + char *p = printed; + *p = '\0'; + + if (BYTE_ORDER != LITTLE_ENDIAN && size > sizeof (unsigned int)) + { + assert (size == sizeof (unsigned int) * 2); + for (unsigned int *i = data; + (void *) i < data + count * size; i += 2) + { + unsigned int w = i[1]; + i[1] = i[0]; + i[0] = w; + } + } + + unsigned int lastbit = 0; + for (const unsigned int *i = data; + (void *) i < data + count * size; ++i) + { + unsigned int bit = ((void *) i - data) * 8; + unsigned int w = negate ? ~*i : *i; + while (w != 0) + { + int n = ffs (w); + w >>= n; + bit += n; + + if (lastbit + 1 != bit) + p += sprintf (p, "-%u,%u", lastbit - bias, bit - bias); + else if (lastbit == 0) + p += sprintf (p, "%u", bit - bias); + + lastbit = bit; + } + } + if (lastbit > 0 && lastbit + 1 != nbits) + p += sprintf (p, "-%u", nbits - bias); + + colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name, + 4 + nbits * 4, + negate ? "~<%s>" : "<%s>", printed); + } break; case 'T': @@ -5505,7 +5554,7 @@ handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc, Dwarf_Word sec; Dwarf_Word usec; size_t maxfmt = 7; - switch (item->type) + switch (type) { #define DO_TYPE(NAME, Name, hex, dec, max) \ case ELF_T_##NAME: \ @@ -5615,6 +5664,17 @@ handle_core_items (Elf *core, const void *desc, size_t descsz, /* Write out all the groups. */ unsigned int colno = 0; + const void *last = desc; + if (nitems == 1) + { + size_t size = descsz; + colno = handle_core_item (core, sorted_items[0], desc, colno, &size); + if (size == 0) + return colno; + desc += descsz - size; + descsz = size; + } + do { for (size_t i = 0; i < ngroups; ++i) @@ -5624,7 +5684,7 @@ handle_core_items (Elf *core, const void *desc, size_t descsz, && ((*item)->group == groups[i][0]->group || !strcmp ((*item)->group, groups[i][0]->group))); ++item) - colno = handle_core_item (core, *item, desc, colno); + colno = handle_core_item (core, *item, desc, colno, NULL); /* Force a line break at the end of the group. */ colno = ITEM_WRAP_COLUMN; @@ -5639,8 +5699,27 @@ handle_core_items (Elf *core, const void *desc, size_t descsz, const Ebl_Core_Item *item = &items[nitems - 1]; size_t eltsz = item->offset + gelf_fsize (core, item->type, item->count ?: 1, EV_CURRENT); - descsz -= eltsz; - desc += eltsz; + + int reps = -1; + do + { + ++reps; + desc += eltsz; + descsz -= eltsz; + } + while (descsz >= eltsz && !memcmp (desc, last, eltsz)); + + if (reps == 1) + { + /* For just one repeat, print it unabridged twice. */ + desc -= eltsz; + descsz += eltsz; + } + else if (reps > 1) + printf (gettext ("\n%*s... <repeats %u more times> ..."), + ITEM_INDENT, "", reps); + + last = desc; } while (descsz > 0); @@ -5702,7 +5781,7 @@ handle_core_register (Ebl *ebl, Elf *core, int maxregname, { #define BITS(bits, xtype, sfmt, ufmt, max) \ case bits: \ - desc = convert (core, ELF_T_##xtype, 1, &value, desc); \ + desc = convert (core, ELF_T_##xtype, 1, &value, desc, 0); \ if (type == DW_ATE_signed) \ colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN, \ maxregname, name, \ @@ -5717,7 +5796,7 @@ handle_core_register (Ebl *ebl, Elf *core, int maxregname, case 128: assert (type == DW_ATE_unsigned); - desc = convert (core, ELF_T_XWORD, 2, &value, desc); + desc = convert (core, ELF_T_XWORD, 2, &value, desc, 0); int be = elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB; colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN, maxregname, name, |