summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland McGrath <roland@redhat.com>2008-08-07 08:39:41 +0000
committerRoland McGrath <roland@redhat.com>2008-08-07 08:39:41 +0000
commit1d8bb25cac06b5af57f8733e5ea7a068a79edfe0 (patch)
treef794a75ef8e1f324185d2850e6e4da59323fe9ca
parent9d2f3ee2554185a9df70f434eddc4405a4aff0fa (diff)
downloadelfutils-1d8bb25cac06b5af57f8733e5ea7a068a79edfe0.tar.gz
src/
(find_symbol): Likewise. Convert plain number, or handle strings like "(section)+offset" or "symbol+offset".
-rw-r--r--backends/ChangeLog19
-rw-r--r--backends/Makefile.am8
-rw-r--r--backends/i386_init.c3
-rw-r--r--backends/i386_syscall.c47
-rw-r--r--backends/linux-core-note.c6
-rw-r--r--backends/ppc64_init.c3
-rw-r--r--backends/ppc_corenote.c7
-rw-r--r--backends/ppc_init.c1
-rw-r--r--backends/ppc_syscall.c50
-rw-r--r--backends/x86_64_init.c1
-rw-r--r--backends/x86_64_syscall.c47
-rw-r--r--libdwfl/ChangeLog14
-rw-r--r--libdwfl/dwfl_build_id_find_elf.c7
-rw-r--r--libdwfl/dwfl_module_addrsym.c3
-rw-r--r--libdwfl/linux-kernel-modules.c7
-rw-r--r--libebl/ChangeLog16
-rw-r--r--libebl/Makefile.am2
-rw-r--r--libebl/ebl-hooks.h4
-rw-r--r--libebl/ebl_syscall_abi.c66
-rw-r--r--libebl/eblauxvinfo.c5
-rw-r--r--libebl/eblopenbackend.c17
-rw-r--r--libebl/libebl.h7
-rw-r--r--libelf/ChangeLog4
-rw-r--r--libelf/elf.h24
-rw-r--r--src/ChangeLog27
-rw-r--r--src/addr2line.c148
-rw-r--r--src/readelf.c151
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,