[PATCH] elflint: Add two more symbols to gnuld list of allowed bad values.
by Mark Wielaard
Add __bss_start and __TMC_END__ to the list of symbols allowed to have
out of section values because of the following GNU ld bug:
http://sourceware.org/bugzilla/show_bug.cgi?id=13621.
Allow them to appear in either .symtab or .dynsym, but only when they
are zero sized. It is impossible to define a general rule for this bug,
but this should catch most common issues that are mostly harmless
because the symbols signify the removed section was empty to being with.
This catches at least all symbols often flagged in the tests.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
src/ChangeLog | 7 +++++++
src/elflint.c | 13 ++++++++++---
2 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/src/ChangeLog b/src/ChangeLog
index 4d00013..4c6a872 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,10 @@
+2013-02-06 Mark Wielaard <mjw(a)redhat.com>
+
+ * elflint.c (check_symtab): Add __bss_start and __TMC_END__ to the
+ list of symbols allowed to have out of section values because of
+ GNU ld bugs in either .symtab or .dynsym, but only when they are
+ zero sized.
+
2013-01-29 Jan Kratochvil <jan.kratochvil(a)redhat.com>
* readelf.c (handle_core_items): Limit special repeated items handling
diff --git a/src/elflint.c b/src/elflint.c
index 4084987..bc5ed33 100644
--- a/src/elflint.c
+++ b/src/elflint.c
@@ -767,15 +767,22 @@ section [%2d] '%s': symbol %zu: function in COMMON section is nonsense\n"),
{
/* GNU ld has severe bugs. When it decides to remove
empty sections it leaves symbols referencing them
- behind. These are symbols in .symtab. */
+ behind. These are symbols in .symtab or .dynsym
+ and for the named symbols have zero size. See
+ sourceware PR13621. */
if (!gnuld
- || strcmp (section_name (ebl, idx), ".symtab")
+ || (strcmp (section_name (ebl, idx), ".symtab")
+ && strcmp (section_name (ebl, idx),
+ ".dynsym"))
+ || sym->st_size != 0
|| (strcmp (name, "__preinit_array_start") != 0
&& strcmp (name, "__preinit_array_end") != 0
&& strcmp (name, "__init_array_start") != 0
&& strcmp (name, "__init_array_end") != 0
&& strcmp (name, "__fini_array_start") != 0
- && strcmp (name, "__fini_array_end") != 0))
+ && strcmp (name, "__fini_array_end") != 0
+ && strcmp (name, "__bss_start") != 0
+ && strcmp (name, "__TMC_END__") != 0))
ERROR (gettext ("\
section [%2d] '%s': symbol %zu: st_value out of bounds\n"),
idx, section_name (ebl, idx), cnt);
--
1.7.1
11 years, 1 month
[PATCH] libdw: Handle FORM_GNU_strp_alt for files with string data only in dwz file.
by Mark Wielaard
dwarf_formstring should check that the dbg file from which we want the
strp data actually has a IDX_debug_str section.
Reported-By: Tom Tromey <tromey(a)redhat.com>
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libdw/ChangeLog | 5 +++
libdw/dwarf_formstring.c | 4 +--
tests/ChangeLog | 8 +++++
tests/Makefile.am | 1 +
tests/run-readelf-dwz-multi.sh | 73 +++++++++++++++++++++++++++++++++++++++-
tests/testfile-dwzstr.bz2 | Bin 0 -> 2768 bytes
tests/testfile-dwzstr.multi.bz2 | Bin 0 -> 518 bytes
7 files changed, 88 insertions(+), 3 deletions(-)
create mode 100755 tests/testfile-dwzstr.bz2
create mode 100644 tests/testfile-dwzstr.multi.bz2
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 3cf3032..2900ef6 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,8 @@
+2013-02-15 Mark Wielaard <mjw(a)redhat.com>
+
+ * dwarf_formstring.c (dwarf_formstring): Check dbg_ret->sectiondata,
+ not dbg->sectiondata.
+
2013-01-07 Roland McGrath <roland(a)hack.frob.com>
* memory-access.h
diff --git a/libdw/dwarf_formstring.c b/libdw/dwarf_formstring.c
index c66454e..02b56d4 100644
--- a/libdw/dwarf_formstring.c
+++ b/libdw/dwarf_formstring.c
@@ -1,5 +1,5 @@
/* Return string associated with given attribute.
- Copyright (C) 2003-2010 Red Hat, Inc.
+ Copyright (C) 2003-2010, 2013 Red Hat, Inc.
This file is part of elfutils.
Written by Ulrich Drepper <drepper(a)redhat.com>, 2003.
@@ -60,7 +60,7 @@ dwarf_formstring (attrp)
if (unlikely (attrp->form != DW_FORM_strp
&& attrp->form != DW_FORM_GNU_strp_alt)
- || dbg->sectiondata[IDX_debug_str] == NULL)
+ || dbg_ret->sectiondata[IDX_debug_str] == NULL)
{
__libdw_seterrno (DWARF_E_NO_STRING);
return NULL;
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 0a26e7e..c1e0ef9 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,11 @@
+2013-02-15 Mark Wielaard <mjw(a)redhat.com>
+
+ * testfile-dwzstr.bz2: New testfile.
+ * testfile-dwzstr.multi.bz2: Likewise.
+ * run-readelf-dwz-multi.sh: Add readelf testfile-dwzstr test.
+ * Makefile.am (EXTRA_DIST): Add testfile-dwzstr.bz2 and
+ testfile-dwzstr.multi.bz2.
+
2013-01-30 Mark Wielaard <mjw(a)redhat.com>
* testfileloc.bz2: New testfile.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index a26e5c2..44b4e61 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -154,6 +154,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \
run-readelf-loc.sh testfileloc.bz2 \
run-readelf-dwz-multi.sh libtestfile_multi_shared.so.bz2 \
testfile_multi.dwz.bz2 testfile_multi_main.bz2 \
+ testfile-dwzstr.bz2 testfile-dwzstr.multi.bz2 \
run-prelink-addr-test.sh \
testfile52-32.so.bz2 testfile52-32.so.debug.bz2 \
testfile52-32.prelink.so.bz2 testfile52-32.noshdrs.so.bz2 \
diff --git a/tests/run-readelf-dwz-multi.sh b/tests/run-readelf-dwz-multi.sh
index aadbbbe..20c00c5 100755
--- a/tests/run-readelf-dwz-multi.sh
+++ b/tests/run-readelf-dwz-multi.sh
@@ -1,5 +1,5 @@
#! /bin/sh
-# Copyright (C) 2012 Red Hat, Inc.
+# Copyright (C) 2012, 2013 Red Hat, Inc.
# This file is part of elfutils.
#
# This file is free software; you can redistribute it and/or modify
@@ -56,7 +56,27 @@
# gcc -g -o testfile_multi_main -L. -ltestfile_multi_shared main.c -Wl,-rpath,.
# dwz -m testfile_multi.dwz testfile_multi_main libtestfile_multi_shared.so
+# main.c
+#
+# struct foobarbaz
+# {
+# int counter;
+# char *bookstore;
+# };
+#
+# int
+# main (int argc, char **argv)
+# {
+# struct foobarbaz fbb;
+# return 0;
+# }
+
+# gcc -g -o testfile-dwzstr main.c
+# cp testfile-dwzstr testfile-dwzstr.alt
+# dwz -m testfile-dwzstr.multi testfile-dwzstr testfile-dwzstr.alt
+
testfiles libtestfile_multi_shared.so testfile_multi_main testfile_multi.dwz
+testfiles testfile-dwzstr testfile-dwzstr.multi
testrun_compare ../src/readelf --debug-dump=info testfile_multi_main <<\EOF
@@ -153,4 +173,55 @@ DWARF section [25] '.debug_info' at offset 0x106c:
[ 0] fbreg -24
EOF
+testrun_compare ../src/readelf --debug-dump=info testfile-dwzstr <<\EOF
+
+DWARF section [28] '.debug_info' at offset 0x1088:
+ [Offset]
+ Compilation unit at offset 0:
+ Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4
+ [ b] compile_unit
+ producer (GNU_strp_alt) "GNU C 4.7.2 20121109 (Red Hat 4.7.2-8) -mtune=generic -march=x86-64 -g"
+ language (data1) C89 (1)
+ name (GNU_strp_alt) "main.c"
+ comp_dir (GNU_strp_alt) "/home/mark/src/tests"
+ low_pc (addr) 0x00000000004004ec <main>
+ high_pc (udata) 18
+ stmt_list (sec_offset) 0
+ [ 26] imported_unit
+ import (GNU_ref_alt) [ b]
+ [ 2b] subprogram
+ external (flag_present)
+ name (GNU_strp_alt) "main"
+ decl_file (data1) 1
+ decl_line (data1) 8
+ prototyped (flag_present)
+ type (GNU_ref_alt) [ 30]
+ low_pc (addr) 0x00000000004004ec <main>
+ high_pc (udata) 18
+ frame_base (exprloc)
+ [ 0] call_frame_cfa
+ GNU_all_call_sites (flag_present)
+ [ 41] formal_parameter
+ name (GNU_strp_alt) "argc"
+ decl_file (data1) 1
+ decl_line (data1) 8
+ type (GNU_ref_alt) [ 30]
+ location (exprloc)
+ [ 0] fbreg -36
+ [ 4f] formal_parameter
+ name (GNU_strp_alt) "argv"
+ decl_file (data1) 1
+ decl_line (data1) 8
+ type (GNU_ref_alt) [ 41]
+ location (exprloc)
+ [ 0] fbreg -48
+ [ 5d] variable
+ name (string) "fbb"
+ decl_file (data1) 1
+ decl_line (data1) 10
+ type (GNU_ref_alt) [ 14]
+ location (exprloc)
+ [ 0] fbreg -32
+EOF
+
exit 0
diff --git a/tests/testfile-dwzstr.bz2 b/tests/testfile-dwzstr.bz2
new file mode 100755
index 0000000000000000000000000000000000000000..8d2d326e0b0f5cd84b91097b51a17084c7162f82
GIT binary patch
literal 2768
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
W3U>F~jV8^1i@744C`fkcp8J4TR{XR8
literal 0
HcmV?d00001
diff --git a/tests/testfile-dwzstr.multi.bz2 b/tests/testfile-dwzstr.multi.bz2
new file mode 100644
index 0000000000000000000000000000000000000000..5e84991d42ec673a87a2caf4ce39cc8847c3e3fc
GIT binary patch
literal 518
zcmV+h0{Q(yT4*^jL0KkKS>m>W+yDVhfA|02?uu38_y23<k_Er-pHz?_C;<>4004jx
z0sue&FaeAs5Y;@URPv4JQ!<CBJwwuZgF{U{Ks_cv2A+|S2dH^Xs5LYu6*kdNQRr%D
z!ejxaO#>igGH3t+p^2cxkv$|Hp!EYyJt3ge(EtWO05kv@00xefrD|jAp#%4hNH15}
zZIB&o!1=AQYTraHK*00XF;i5<;sbdKXb?UmrxX?N7z0%kQ4q>|n1XlE4@SZydR1U%
zm5i~m%tYgg%mJAS7VY}?R>pJgRESQ{w5>klDlW<K(GtV-;2{D92C9+6UtxqRokaE&
z7fL<o2vAV42^Lh4btdRlEHI4;$X?~ShE18S-bI|?!em4dgbb2xk#ST3b(T>P74U1;
z!+uz#mPq2WI+b5aj_%j=Je)#^X@^JUp!ixcx<@u@??BcNRxk$<RKu>|vlAh!skWvu
z>=52%@1sDtaONVeT>i$uLPWBI^!F6C_s`fsZcR83B-{lu`CpZ9Uqcl*!k@_qe^?e7
zn3iE%3@Zla#E48Vt>luP#F#1T>sT;ju955vUI<#|8hmBMqR){dEN^8#qoqa?vyTZP
zYt)?4NfakZEbfd;CamEkr3hl#jm&+pK8836=ztl@Y(*rjZqWWHA#j_;O8?^SNT&)C
I99Ga<fS^U`Z2$lO
literal 0
HcmV?d00001
--
1.8.1.2
11 years, 2 months
[PATCH] libdwfl: Use actual file names in parse_opt failure cases.
by Mark Wielaard
When handling ARGP_KEY_SUCCESS the failure handling code would use 'arg'
as failure string. But 'arg' would be NULL in such cases leading to failure
messages like: "cannot open '(null)': No such file or directory".
Use opt->e and opt->core explicitly to show file names that caused failure.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libdwfl/ChangeLog | 6 ++++++
libdwfl/argp-std.c | 10 +++++++---
2 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 11d599b..1311dea 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,9 @@
+2013-02-10 Mark Wielaard <mjw(a)redhat.com>
+
+ * argp-std.c (parse_opt): Use opt->core and opt->e explicitly in
+ failure messages When handling ARGP_KEY_SUCCESS because arg will
+ not have been set.
+
2013-01-30 Jan Kratochvil <jan.kratochvil(a)redhat.com>
* linux-proc-maps.c: Include system.h.
diff --git a/libdwfl/argp-std.c b/libdwfl/argp-std.c
index 7584054..e54f720 100644
--- a/libdwfl/argp-std.c
+++ b/libdwfl/argp-std.c
@@ -210,7 +210,6 @@ parse_opt (int key, char *arg, struct argp_state *state)
{
FILE *f = fopen (arg, "r");
if (f == NULL)
- nofile:
{
int code = errno;
argp_failure (state, EXIT_FAILURE, code,
@@ -298,7 +297,12 @@ parse_opt (int key, char *arg, struct argp_state *state)
{
int fd = open64 (opt->core, O_RDONLY);
if (fd < 0)
- goto nofile;
+ {
+ int code = errno;
+ argp_failure (state, EXIT_FAILURE, code,
+ "cannot open '%s'", opt->core);
+ return code;
+ }
Elf *core;
Dwfl_Error error = __libdw_open_file (&fd, &core, true, false);
@@ -333,7 +337,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
else if (opt->e)
{
if (INTUSE(dwfl_report_offline) (dwfl, "", opt->e, -1) == NULL)
- return fail (dwfl, -1, arg);
+ return fail (dwfl, -1, opt->e);
}
/* One of the three flavors has done dwfl_begin and some reporting
--
1.7.1
11 years, 2 months
[PATCH] backends: Check type DIE exists before calling dwarf_tag ().
by Mark Wielaard
dwarf_attr () or dwarf_form () functions leave typedie NULL when they fail
because of missing attribute or unexpected form. In such cases first check
the DIE exists and return error instead of calling dwarf_tag () and crashing.
This also happens in the testsuite with native tests when elfutils is build
without DWZ support on a distro that uses DWZ DWARF compression on system
libraries. Only the backends used dwarf_tag () directly without checking,
all other uses in elfutils already checked whether the given DIE was NULL.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
backends/ChangeLog | 17 +++++++++++++++++
backends/alpha_retval.c | 7 ++++---
backends/arm_retval.c | 7 ++++---
backends/i386_retval.c | 7 ++++---
backends/ia64_retval.c | 10 ++++++----
backends/libebl_CPU.h | 11 +++++++++++
backends/ppc64_retval.c | 3 ++-
backends/ppc_retval.c | 7 ++++---
backends/s390_retval.c | 7 ++++---
backends/sh_retval.c | 7 ++++---
backends/sparc_retval.c | 7 ++++---
backends/tilegx_retval.c | 9 +++++----
backends/x86_64_retval.c | 7 ++++---
13 files changed, 73 insertions(+), 33 deletions(-)
diff --git a/backends/ChangeLog b/backends/ChangeLog
index ab9cde9..0e51af2 100644
--- a/backends/ChangeLog
+++ b/backends/ChangeLog
@@ -1,3 +1,20 @@
+2013-02-06 Mark Wielaard <mjw(a)redhat.com>
+
+ * libebl_CPU.h (CHECK_DWARF_TAG): New macro.
+ * backends/alpha_retval.c (alpha_return_value_location): Use new
+ CHECK_DWARF_TAG macro instead of dwarf_tag ().
+ * backends/arm_retval.c (arm_return_value_location): Likewise.
+ * backends/i386_retval.c (i386_return_value_location): Likewise.
+ * backends/ia64_retval.c (hfa_type): Likewise.
+ (ia64_return_value_location): Likewise.
+ * backends/ppc64_retval.c (ppc64_return_value_location): Likewise.
+ * backends/ppc_retval.c (ppc_return_value_location): Likewise.
+ * backends/s390_retval.c (s390_return_value_location): Likewise.
+ * backends/sh_retval.c (sh_return_value_location): Likewise.
+ * backends/sparc_retval.c (sparc_return_value_location): Likewise.
+ * backends/tilegx_retval.c (tilegx_return_value_location): Likewise.
+ * backends/x86_64_retval.c (x86_64_return_value_location): Likewise.
+
2013-01-29 Jan Kratochvil <jan.kratochvil(a)redhat.com>
Roland McGrath <roland(a)hack.frob.com>
diff --git a/backends/alpha_retval.c b/backends/alpha_retval.c
index 62cbfc7..19a6253 100644
--- a/backends/alpha_retval.c
+++ b/backends/alpha_retval.c
@@ -75,9 +75,10 @@ alpha_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
/* The function has no return value, like a `void' function in C. */
return 0;
+ int tag;
Dwarf_Die die_mem;
Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem);
- int tag = dwarf_tag (typedie);
+ CHECK_DWARF_TAG (typedie, tag);
/* Follow typedefs and qualifiers to get to the actual type. */
while (tag == DW_TAG_typedef
@@ -86,7 +87,7 @@ alpha_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
{
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
- tag = dwarf_tag (typedie);
+ CHECK_DWARF_TAG (typedie, tag);
}
switch (tag)
@@ -99,7 +100,7 @@ alpha_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
{
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
- tag = dwarf_tag (typedie);
+ CHECK_DWARF_TAG (typedie, tag);
}
/* Fall through. */
diff --git a/backends/arm_retval.c b/backends/arm_retval.c
index 0c33c5b..6483bc2 100644
--- a/backends/arm_retval.c
+++ b/backends/arm_retval.c
@@ -71,9 +71,10 @@ arm_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
/* The function has no return value, like a `void' function in C. */
return 0;
+ int tag;
Dwarf_Die die_mem;
Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem);
- int tag = dwarf_tag (typedie);
+ CHECK_DWARF_TAG (typedie, tag);
/* Follow typedefs and qualifiers to get to the actual type. */
while (tag == DW_TAG_typedef
@@ -82,7 +83,7 @@ arm_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
{
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
- tag = dwarf_tag (typedie);
+ CHECK_DWARF_TAG (typedie, tag);
}
Dwarf_Word size;
@@ -96,7 +97,7 @@ arm_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
{
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
- tag = dwarf_tag (typedie);
+ CHECK_DWARF_TAG (typedie, tag);
}
/* Fall through. */
diff --git a/backends/i386_retval.c b/backends/i386_retval.c
index 95f5b92..ce5bb13 100644
--- a/backends/i386_retval.c
+++ b/backends/i386_retval.c
@@ -75,9 +75,10 @@ i386_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
/* The function has no return value, like a `void' function in C. */
return 0;
+ int tag;
Dwarf_Die die_mem;
Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem);
- int tag = dwarf_tag (typedie);
+ CHECK_DWARF_TAG (typedie, tag);
/* Follow typedefs and qualifiers to get to the actual type. */
while (tag == DW_TAG_typedef
@@ -86,7 +87,7 @@ i386_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
{
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
- tag = dwarf_tag (typedie);
+ CHECK_DWARF_TAG (typedie, tag);
}
switch (tag)
@@ -99,7 +100,7 @@ i386_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
{
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
- tag = dwarf_tag (typedie);
+ CHECK_DWARF_TAG (typedie, tag);
}
/* Fall through. */
diff --git a/backends/ia64_retval.c b/backends/ia64_retval.c
index 644359b..26472b5 100644
--- a/backends/ia64_retval.c
+++ b/backends/ia64_retval.c
@@ -109,7 +109,8 @@ hfa_type (Dwarf_Die *typedie, Dwarf_Word size,
return fpregs_used + nregs;
}
- int tag = dwarf_tag (typedie);
+ int tag;
+ CHECK_DWARF_TAG (typedie, tag);
switch (tag)
{
Dwarf_Attribute attr_mem;
@@ -246,9 +247,10 @@ ia64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
/* The function has no return value, like a `void' function in C. */
return 0;
+ int tag;
Dwarf_Die die_mem;
Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem);
- int tag = dwarf_tag (typedie);
+ CHECK_DWARF_TAG (typedie, tag);
/* Follow typedefs and qualifiers to get to the actual type. */
while (tag == DW_TAG_typedef
@@ -257,7 +259,7 @@ ia64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
{
attr = dwarf_attr (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
- tag = dwarf_tag (typedie);
+ CHECK_DWARF_TAG (typedie, tag);
}
Dwarf_Word size;
@@ -271,7 +273,7 @@ ia64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
{
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
- tag = dwarf_tag (typedie);
+ CHECK_DWARF_TAG (typedie, tag);
}
/* Fall through. */
diff --git a/backends/libebl_CPU.h b/backends/libebl_CPU.h
index 36b3a4a..2cfa980 100644
--- a/backends/libebl_CPU.h
+++ b/backends/libebl_CPU.h
@@ -45,5 +45,16 @@ extern const char *EBLHOOK(init) (Elf *elf, GElf_Half machine,
extern bool (*generic_debugscn_p) (const char *) attribute_hidden;
+/* Helper for retval. Does tag = dwarf_tag (die), but returns early
+ if there where previous errors that leave die NULL. */
+#define CHECK_DWARF_TAG(die, tag) \
+ do \
+ { \
+ if (! die) \
+ return -1; \
+ tag = dwarf_tag (die); \
+ } \
+ while (0);
+
#endif /* libebl_CPU.h */
diff --git a/backends/ppc64_retval.c b/backends/ppc64_retval.c
index b26bb1e..4962b9c 100644
--- a/backends/ppc64_retval.c
+++ b/backends/ppc64_retval.c
@@ -85,9 +85,10 @@ ppc64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
/* The function has no return value, like a `void' function in C. */
return 0;
+ int tag;
Dwarf_Die die_mem;
Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem);
- int tag = dwarf_tag (typedie);
+ CHECK_DWARF_TAG (typedie, tag);
/* Follow typedefs and qualifiers to get to the actual type. */
while (tag == DW_TAG_typedef
diff --git a/backends/ppc_retval.c b/backends/ppc_retval.c
index 29f5a23..e55d916 100644
--- a/backends/ppc_retval.c
+++ b/backends/ppc_retval.c
@@ -97,9 +97,10 @@ ppc_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
/* The function has no return value, like a `void' function in C. */
return 0;
+ int tag;
Dwarf_Die die_mem;
Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem);
- int tag = dwarf_tag (typedie);
+ CHECK_DWARF_TAG (typedie, tag);
/* Follow typedefs and qualifiers to get to the actual type. */
while (tag == DW_TAG_typedef
@@ -108,7 +109,7 @@ ppc_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
{
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
- tag = dwarf_tag (typedie);
+ CHECK_DWARF_TAG (typedie, tag);
}
Dwarf_Word size;
@@ -122,7 +123,7 @@ ppc_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
{
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
- tag = dwarf_tag (typedie);
+ CHECK_DWARF_TAG (typedie, tag);
}
/* Fall through. */
diff --git a/backends/s390_retval.c b/backends/s390_retval.c
index 4cebe45..822455e 100644
--- a/backends/s390_retval.c
+++ b/backends/s390_retval.c
@@ -76,9 +76,10 @@ s390_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
/* The function has no return value, like a `void' function in C. */
return 0;
+ int tag;
Dwarf_Die die_mem;
Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem);
- int tag = dwarf_tag (typedie);
+ CHECK_DWARF_TAG (typedie, tag);
/* Follow typedefs and qualifiers to get to the actual type. */
while (tag == DW_TAG_typedef
@@ -87,7 +88,7 @@ s390_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
{
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
- tag = dwarf_tag (typedie);
+ CHECK_DWARF_TAG (typedie, tag);
}
Dwarf_Word size;
@@ -101,7 +102,7 @@ s390_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
{
attr = dwarf_attr (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
- tag = dwarf_tag (typedie);
+ CHECK_DWARF_TAG (typedie, tag);
}
/* Fall through. */
diff --git a/backends/sh_retval.c b/backends/sh_retval.c
index 4692d35..b723916 100644
--- a/backends/sh_retval.c
+++ b/backends/sh_retval.c
@@ -73,9 +73,10 @@ sh_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
/* The function has no return value, like a `void' function in C. */
return 0;
+ int tag;
Dwarf_Die die_mem;
Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem);
- int tag = dwarf_tag (typedie);
+ CHECK_DWARF_TAG (typedie, tag);
/* Follow typedefs and qualifiers to get to the actual type. */
while (tag == DW_TAG_typedef
@@ -84,7 +85,7 @@ sh_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
{
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
- tag = dwarf_tag (typedie);
+ CHECK_DWARF_TAG (typedie, tag);
}
Dwarf_Word size;
@@ -98,7 +99,7 @@ sh_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
{
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
- tag = dwarf_tag (typedie);
+ CHECK_DWARF_TAG (typedie, tag);
}
/* Fall through. */
diff --git a/backends/sparc_retval.c b/backends/sparc_retval.c
index 2c2728c..2dafb99 100644
--- a/backends/sparc_retval.c
+++ b/backends/sparc_retval.c
@@ -80,9 +80,10 @@ sparc_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
/* The function has no return value, like a `void' function in C. */
return 0;
+ int tag;
Dwarf_Die die_mem;
Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem);
- int tag = dwarf_tag (typedie);
+ CHECK_DWARF_TAG (typedie, tag);
/* Follow typedefs and qualifiers to get to the actual type. */
while (tag == DW_TAG_typedef
@@ -91,7 +92,7 @@ sparc_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
{
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
- tag = dwarf_tag (typedie);
+ CHECK_DWARF_TAG (typedie, tag);
}
Dwarf_Word size;
@@ -105,7 +106,7 @@ sparc_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
{
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
- tag = dwarf_tag (typedie);
+ CHECK_DWARF_TAG (typedie, tag);
}
/* Fall through. */
diff --git a/backends/tilegx_retval.c b/backends/tilegx_retval.c
index fd4feef..1ddce37 100644
--- a/backends/tilegx_retval.c
+++ b/backends/tilegx_retval.c
@@ -67,9 +67,10 @@ tilegx_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
/* The function has no return value, like a `void' function in C. */
return 0;
+ int tag;
Dwarf_Die die_mem;
Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem);
- int tag = dwarf_tag (typedie);
+ CHECK_DWARF_TAG (typedie, tag);
/* Follow typedefs and qualifiers to get to the actual type. */
while (tag == DW_TAG_typedef
@@ -78,7 +79,7 @@ tilegx_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
{
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
- tag = dwarf_tag (typedie);
+ CHECK_DWARF_TAG (typedie, tag);
}
Dwarf_Word size;
@@ -92,7 +93,7 @@ tilegx_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
{
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
- tag = dwarf_tag (typedie);
+ CHECK_DWARF_TAG (typedie, tag);
}
/* Fall through. */
@@ -142,7 +143,7 @@ tilegx_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
/* Check if it's a character array. */
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
- tag = dwarf_tag (typedie);
+ CHECK_DWARF_TAG (typedie, tag);
if (tag != DW_TAG_base_type)
goto aggregate;
if (dwarf_formudata (dwarf_attr_integrate (typedie,
diff --git a/backends/x86_64_retval.c b/backends/x86_64_retval.c
index d67b05f..15cc258 100644
--- a/backends/x86_64_retval.c
+++ b/backends/x86_64_retval.c
@@ -89,9 +89,10 @@ x86_64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
/* The function has no return value, like a `void' function in C. */
return 0;
+ int tag;
Dwarf_Die die_mem;
Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem);
- int tag = dwarf_tag (typedie);
+ CHECK_DWARF_TAG (typedie, tag);
/* Follow typedefs and qualifiers to get to the actual type. */
while (tag == DW_TAG_typedef
@@ -100,7 +101,7 @@ x86_64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
{
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
- tag = dwarf_tag (typedie);
+ CHECK_DWARF_TAG (typedie, tag);
}
Dwarf_Word size;
@@ -114,7 +115,7 @@ x86_64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
{
attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
typedie = dwarf_formref_die (attr, &die_mem);
- tag = dwarf_tag (typedie);
+ CHECK_DWARF_TAG (typedie, tag);
}
/* Fall through. */
--
1.7.1
11 years, 2 months
[PATCH] readelf: Add base to offsets in format_dwarf_addr for debug_loc/ranges.
by Mark Wielaard
Collect the base address of the CU while creating the listptr_tables
and use them when printing debug ranges and location entries with
format_dwarf_addr ().
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
src/ChangeLog | 13 ++++++++++++
src/readelf.c | 58 +++++++++++++++++++++++++++++++++++++++++++-------------
2 files changed, 57 insertions(+), 14 deletions(-)
diff --git a/src/ChangeLog b/src/ChangeLog
index 11a9cb5..58fefd0 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,16 @@
+2013-01-18 Mark Wielaard <mjw(a)redhat.com>
+
+ * readelf.c (struct listptr): Add base Dwarf_Addr field.
+ (compare_listptr): Warn for same offset with different base.
+ (notice_listptr): Take base argument and set it.
+ (skip_listptr_hole): Likewise.
+ (struct attrcb_args): Removed unused cu_offset field.
+ Add cu_base Dwarf_Addr field.
+ (attr_callback): Call notice_listptr with cbargs->cu_base.
+ (print_debug_units): Set args.cu_base.
+ (print_debug_ranges_section): Get base and use for format_dwarf_addr.
+ (print_debug_loc_section): Likewise.
+
2013-01-13 David Abdurachmanov <David.Abdurachmanov(a)cern.ch>
ar.c (do_oper_delete): Fix num passed to memset.
diff --git a/src/readelf.c b/src/readelf.c
index 0a9629a..8983f49 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -3944,6 +3944,7 @@ struct listptr
bool addr64:1;
bool dwarf64:1;
bool warned:1;
+ Dwarf_Addr base;
};
#define listptr_offset_size(p) ((p)->dwarf64 ? 8 : 4)
@@ -3977,6 +3978,13 @@ compare_listptr (const void *a, const void *b, void *arg)
gettext ("%s %#" PRIx64 " used with different offset sizes"),
name, (uint64_t) p1->offset);
}
+ if (p1->base != p2->base)
+ {
+ p1->warned = p2->warned = true;
+ error (0, 0,
+ gettext ("%s %#" PRIx64 " used with different base addresses"),
+ name, (uint64_t) p1->offset);
+ }
}
return 0;
@@ -4003,7 +4011,7 @@ reset_listptr (struct listptr_table *table)
static void
notice_listptr (enum section_e section, struct listptr_table *table,
uint_fast8_t address_size, uint_fast8_t offset_size,
- Dwarf_Off offset)
+ Dwarf_Addr base, Dwarf_Off offset)
{
if (print_debug_sections & section)
{
@@ -4023,7 +4031,8 @@ notice_listptr (enum section_e section, struct listptr_table *table,
{
.addr64 = address_size == 8,
.dwarf64 = offset_size == 8,
- .offset = offset
+ .offset = offset,
+ .base = base
};
assert (p->offset == offset);
}
@@ -4040,7 +4049,8 @@ sort_listptr (struct listptr_table *table, const char *name)
static bool
skip_listptr_hole (struct listptr_table *table, size_t *idxp,
uint_fast8_t *address_sizep, uint_fast8_t *offset_sizep,
- ptrdiff_t offset, unsigned char **readp, unsigned char *endp)
+ Dwarf_Addr *base, ptrdiff_t offset,
+ unsigned char **readp, unsigned char *endp)
{
if (table->n == 0)
return false;
@@ -4071,6 +4081,8 @@ skip_listptr_hole (struct listptr_table *table, size_t *idxp,
*address_sizep = listptr_address_size (p);
if (offset_sizep != NULL)
*offset_sizep = listptr_offset_size (p);
+ if (base != NULL)
+ *base = p->base;
return false;
}
@@ -4232,6 +4244,7 @@ print_debug_ranges_section (Dwfl_Module *dwflmod,
uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
bool first = true;
+ Dwarf_Addr base = 0;
unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
unsigned char *readp = data->d_buf;
while (readp < endp)
@@ -4239,7 +4252,7 @@ print_debug_ranges_section (Dwfl_Module *dwflmod,
ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
if (first && skip_listptr_hole (&known_rangelistptr, &listptr_idx,
- &address_size, NULL,
+ &address_size, NULL, &base,
offset, &readp, endp))
continue;
@@ -4269,6 +4282,7 @@ print_debug_ranges_section (Dwfl_Module *dwflmod,
char *b = format_dwarf_addr (dwflmod, address_size, end);
printf (gettext (" [%6tx] base address %s\n"), offset, b);
free (b);
+ base = end;
}
else if (begin == 0 && end == 0) /* End of list entry. */
{
@@ -4278,8 +4292,8 @@ print_debug_ranges_section (Dwfl_Module *dwflmod,
}
else
{
- char *b = format_dwarf_addr (dwflmod, address_size, begin);
- char *e = format_dwarf_addr (dwflmod, address_size, end);
+ char *b = format_dwarf_addr (dwflmod, address_size, base + begin);
+ char *e = format_dwarf_addr (dwflmod, address_size, base + end);
/* We have an address range entry. */
if (first) /* First address range entry in a list. */
printf (gettext (" [%6tx] %s..%s\n"), offset, b, e);
@@ -5064,7 +5078,7 @@ struct attrcb_args
unsigned int version;
unsigned int addrsize;
unsigned int offset_size;
- Dwarf_Off cu_offset;
+ Dwarf_Addr cu_base;
};
@@ -5197,7 +5211,8 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
case DW_AT_GNU_call_site_target:
case DW_AT_GNU_call_site_target_clobbered:
notice_listptr (section_loc, &known_loclistptr,
- cbargs->addrsize, cbargs->offset_size, num);
+ cbargs->addrsize, cbargs->offset_size,
+ cbargs->cu_base, num);
if (!cbargs->silent)
printf (" %*s%-20s (%s) location list [%6" PRIxMAX "]\n",
(int) (level * 2), "", dwarf_attr_name (attr),
@@ -5206,7 +5221,8 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
case DW_AT_ranges:
notice_listptr (section_ranges, &known_rangelistptr,
- cbargs->addrsize, cbargs->offset_size, num);
+ cbargs->addrsize, cbargs->offset_size,
+ cbargs->cu_base, num);
if (!cbargs->silent)
printf (" %*s%-20s (%s) range list [%6" PRIxMAX "]\n",
(int) (level * 2), "", dwarf_attr_name (attr),
@@ -5415,8 +5431,7 @@ print_debug_units (Dwfl_Module *dwflmod,
.silent = silent,
.version = version,
.addrsize = addrsize,
- .offset_size = offsize,
- .cu_offset = offset
+ .offset_size = offsize
};
offset += cuhl;
@@ -5433,6 +5448,19 @@ print_debug_units (Dwfl_Module *dwflmod,
goto do_return;
}
+ /* Find the base address of the compilation unit. It will
+ normally be specified by DW_AT_low_pc. In DWARF-3 draft 4,
+ the base address could be overridden by DW_AT_entry_pc. It's
+ been removed, but GCC emits DW_AT_entry_pc and not DW_AT_lowpc
+ for compilation units with discontinuous ranges. */
+ if (unlikely (dwarf_lowpc (&dies[0], &args.cu_base) != 0))
+ {
+ Dwarf_Attribute attr_mem;
+ if (dwarf_formaddr (dwarf_attr (&dies[0], DW_AT_entry_pc, &attr_mem),
+ &args.cu_base) != 0)
+ args.cu_base = 0;
+ }
+
do
{
offset = dwarf_dieoffset (&dies[level]);
@@ -6036,6 +6064,7 @@ print_debug_loc_section (Dwfl_Module *dwflmod,
uint_fast8_t offset_size = 4;
bool first = true;
+ Dwarf_Addr base = 0;
unsigned char *readp = data->d_buf;
unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
while (readp < endp)
@@ -6043,7 +6072,7 @@ print_debug_loc_section (Dwfl_Module *dwflmod,
ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
if (first && skip_listptr_hole (&known_loclistptr, &listptr_idx,
- &address_size, &offset_size,
+ &address_size, &offset_size, &base,
offset, &readp, endp))
continue;
@@ -6073,6 +6102,7 @@ print_debug_loc_section (Dwfl_Module *dwflmod,
char *b = format_dwarf_addr (dwflmod, address_size, end);
printf (gettext (" [%6tx] base address %s\n"), offset, b);
free (b);
+ base = end;
}
else if (begin == 0 && end == 0) /* End of list entry. */
{
@@ -6085,8 +6115,8 @@ print_debug_loc_section (Dwfl_Module *dwflmod,
/* We have a location expression entry. */
uint_fast16_t len = read_2ubyte_unaligned_inc (dbg, readp);
- char *b = format_dwarf_addr (dwflmod, address_size, begin);
- char *e = format_dwarf_addr (dwflmod, address_size, end);
+ char *b = format_dwarf_addr (dwflmod, address_size, base + begin);
+ char *e = format_dwarf_addr (dwflmod, address_size, base + end);
if (first) /* First entry in a list. */
printf (gettext (" [%6tx] %s..%s"), offset, b, e);
--
1.7.1
11 years, 2 months
[patch] Fix 64-bit->32-bit vDSO reporting
by Jan Kratochvil
Hi Mark,
jankratochvil/auxv32
On Tue, 29 Jan 2013 11:22:17 +0100, Mark Wielaard wrote:
> > Re: [patch] Fix 64-bit->32-bit vDSO reporting
> > https://lists.fedorahosted.org/pipermail/elfutils-devel/2012-October/0027...
> > Message-ID: <20121012150900.GA24645(a)host2.jankratochvil.net>
>
> I think this one is fine. Though I admit that I found the first less
> efficient version a bit easier to understand. Could add a comment in the
> code to explain when/why the valid32/64 heuristic works/doesn't work and
> that it is there to prevent having to open pid/exe in normal cases?
added the comment.
Thanks,
Jan
commit 911d38861fb6abe4d1305e594dc0005e283f33e9
Author: Jan Kratochvil <jan.kratochvil(a)redhat.com>
Date: Wed Oct 10 20:42:30 2012 +0200
libdwfl/
linux-proc-maps.c: Include system.h.
(PROCEXEFMT, get_pid_class): New.
(grovel_auxv): Detect 32-bit vs. 64-bit auxv, possibly call get_pid_class.
Signed-off-by: Jan Kratochvil <jan.kratochvil(a)redhat.com>
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index cf5b42e..f38c495 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,10 @@
+2013-01-29 Jan Kratochvil <jan.kratochvil(a)redhat.com>
+
+ * linux-proc-maps.c: Include system.h.
+ (PROCEXEFMT, get_pid_class): New.
+ (grovel_auxv): Detect 32-bit vs. 64-bit auxv, possibly call
+ get_pid_class.
+
2013-01-23 Mark Wielaard <mjw(a)redhat.com>
* dwfl_module_getdwarf.c (find_aux_sym): Don't substract one
diff --git a/libdwfl/linux-proc-maps.c b/libdwfl/linux-proc-maps.c
index 4fbe90d..e96b008 100644
--- a/libdwfl/linux-proc-maps.c
+++ b/libdwfl/linux-proc-maps.c
@@ -39,14 +39,53 @@
#include <unistd.h>
#include <assert.h>
#include <endian.h>
+#include "system.h"
#define PROCMAPSFMT "/proc/%d/maps"
#define PROCMEMFMT "/proc/%d/mem"
#define PROCAUXVFMT "/proc/%d/auxv"
+#define PROCEXEFMT "/proc/%d/exe"
-/* Search /proc/PID/auxv for the AT_SYSINFO_EHDR tag. */
+/* Return ELFCLASS64 or ELFCLASS32 for the main ELF executable. Return
+ ELFCLASSNONE for an error. */
+
+static unsigned char
+get_pid_class (pid_t pid)
+{
+ char *fname;
+ if (asprintf (&fname, PROCEXEFMT, pid) < 0)
+ return ELFCLASSNONE;
+
+ int fd = open64 (fname, O_RDONLY);
+ free (fname);
+ if (fd < 0)
+ return ELFCLASSNONE;
+
+ unsigned char buf[EI_CLASS + 1];
+ ssize_t nread = pread_retry (fd, &buf, sizeof buf, 0);
+ close (fd);
+ if (nread != sizeof (buf) || buf[EI_MAG0] != ELFMAG0
+ || buf[EI_MAG1] != ELFMAG1 || buf[EI_MAG2] != ELFMAG2
+ || buf[EI_MAG3] != ELFMAG3
+ || (buf[EI_CLASS] != ELFCLASS64 && buf[EI_CLASS] != ELFCLASS32))
+ return ELFCLASSNONE;
+
+ return buf[EI_CLASS];
+}
+
+/* Search /proc/PID/auxv for the AT_SYSINFO_EHDR tag.
+
+ It would be most easier to call get_pid_class and parse everything according
+ to the 32-bit or 64-bit class. But this would bring an overhead of syscalls
+ opening the "/proc/%d/exe" file.
+
+ Therefore this function tries to parse the "/proc/%d/auxv" content both
+ ways, as if it was the 32-bit format and also if it was the 64-bit format.
+ Only if it gives some valid data in both cases get_pid_class gets called.
+ In most cases only one of the format bit sizes gives valid data and the
+ get_pid_class call overhead can be saved. */
static int
grovel_auxv (pid_t pid, Dwfl *dwfl, GElf_Addr *sysinfo_ehdr)
@@ -60,61 +99,72 @@ grovel_auxv (pid_t pid, Dwfl *dwfl, GElf_Addr *sysinfo_ehdr)
if (fd < 0)
return errno == ENOENT ? 0 : errno;
+ GElf_Addr sysinfo_ehdr64 = 0, sysinfo_ehdr32 = 0;
+ GElf_Addr segment_align64 = dwfl->segment_align;
+ GElf_Addr segment_align32 = dwfl->segment_align;
+ off_t offset = 0;
ssize_t nread;
+ union
+ {
+ Elf64_auxv_t a64[64];
+ Elf32_auxv_t a32[128];
+ } d;
do
{
- union
- {
- char buffer[sizeof (long int) * 2 * 64];
- Elf64_auxv_t a64[sizeof (long int) * 2 * 64 / sizeof (Elf64_auxv_t)];
- Elf32_auxv_t a32[sizeof (long int) * 2 * 32 / sizeof (Elf32_auxv_t)];
- } d;
- nread = read (fd, &d, sizeof d);
- if (nread > 0)
+ eu_static_assert (sizeof d.a64 == sizeof d.a32);
+ nread = pread_retry (fd, d.a64, sizeof d.a64, offset);
+ if (nread < 0)
+ return errno;
+ for (unsigned a32i = 0; a32i < nread / sizeof d.a32[0]; a32i++)
{
- switch (sizeof (long int))
- {
- case 4:
- for (size_t i = 0; (char *) &d.a32[i] < &d.buffer[nread]; ++i)
- if (d.a32[i].a_type == AT_SYSINFO_EHDR)
- {
- *sysinfo_ehdr = d.a32[i].a_un.a_val;
- if (dwfl->segment_align > 1)
- {
- nread = 0;
- break;
- }
- }
- else if (d.a32[i].a_type == AT_PAGESZ
- && dwfl->segment_align <= 1)
- dwfl->segment_align = d.a32[i].a_un.a_val;
+ const Elf32_auxv_t *a32 = d.a32 + a32i;
+ switch (a32->a_type)
+ {
+ case AT_SYSINFO_EHDR:
+ sysinfo_ehdr32 = a32->a_un.a_val;
+ break;
+ case AT_PAGESZ:
+ segment_align32 = a32->a_un.a_val;
break;
- case 8:
- for (size_t i = 0; (char *) &d.a64[i] < &d.buffer[nread]; ++i)
- if (d.a64[i].a_type == AT_SYSINFO_EHDR)
- {
- *sysinfo_ehdr = d.a64[i].a_un.a_val;
- if (dwfl->segment_align > 1)
- {
- nread = 0;
- break;
- }
- }
- else if (d.a64[i].a_type == AT_PAGESZ
- && dwfl->segment_align <= 1)
- dwfl->segment_align = d.a64[i].a_un.a_val;
+ }
+ }
+ for (unsigned a64i = 0; a64i < nread / sizeof d.a64[0]; a64i++)
+ {
+ const Elf64_auxv_t *a64 = d.a64 + a64i;
+ switch (a64->a_type)
+ {
+ case AT_SYSINFO_EHDR:
+ sysinfo_ehdr64 = a64->a_un.a_val;
break;
- default:
- abort ();
+ case AT_PAGESZ:
+ segment_align64 = a64->a_un.a_val;
break;
- }
+ }
}
+ offset += nread;
}
- while (nread > 0);
+ while (nread == sizeof d.a64);
close (fd);
- return nread < 0 ? errno : 0;
+ bool valid64 = sysinfo_ehdr64 || segment_align64 != dwfl->segment_align;
+ bool valid32 = sysinfo_ehdr32 || segment_align32 != dwfl->segment_align;
+
+ unsigned char pid_class = ELFCLASSNONE;
+ if (valid64 && valid32)
+ pid_class = get_pid_class (pid);
+
+ if (pid_class == ELFCLASS64 || (valid64 && ! valid32))
+ {
+ *sysinfo_ehdr = sysinfo_ehdr64;
+ dwfl->segment_align = segment_align64;
+ }
+ if (pid_class == ELFCLASS32 || (! valid64 && valid32))
+ {
+ *sysinfo_ehdr = sysinfo_ehdr32;
+ dwfl->segment_align = segment_align32;
+ }
+ return 0;
}
static int
11 years, 2 months