From b79788c8dcef524ad207f5e961dc11c216e86ffc Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Mon, 25 Mar 2013 11:45:22 +0100 Subject: [PATCH] readelf: Display raw .debug_aranges. Use libdw only for decodedaranges. Display "raw" .debug_aranges by default. Only use libdw parsing when --debug-dump=decodedaranges is given. Signed-off-by: Mark Wielaard --- src/ChangeLog | 9 ++ src/readelf.c | 177 ++++++++++++++++++++++++++++++++++- tests/ChangeLog | 7 ++ tests/Makefile.am | 2 + tests/run-readelf-aranges.sh | 161 +++++++++++++++++++++++++++++++ tests/testfilefoobarbaz.bz2 | Bin 0 -> 3974 bytes 6 files changed, 351 insertions(+), 5 deletions(-) create mode 100755 tests/run-readelf-aranges.sh create mode 100755 tests/testfilefoobarbaz.bz2 diff --git a/src/ChangeLog b/src/ChangeLog index 24bc6bfad..30d186056 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,12 @@ +2013-03-25 Mark Wielaard + + * readelf.c (argp_option): Add decodedaranges. + (decodedaranges): New boolean initialized to false. + (parse_opt): Set decodedaranges when arg is decodedaranges. + (print_debug_aranges_section): Reimplemented and original + implementation renamed to... + (print_decoded_aranges_section): this. + 2013-03-25 Mark Wielaard * readelf.c (attrcb_args): Add Dwarf_Die. diff --git a/src/readelf.c b/src/readelf.c index 6d9db73f3..7252d724f 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -94,8 +94,8 @@ static const struct argp_option options[] = { NULL, 0, NULL, 0, N_("Additional output selection:"), 0 }, { "debug-dump", 'w', "SECTION", OPTION_ARG_OPTIONAL, N_("Display DWARF section content. SECTION can be one of abbrev, " - "aranges, frame, gdb_index, info, loc, line, ranges, pubnames, str, " - "macinfo, macro or exception"), 0 }, + "aranges, decodedaranges, frame, gdb_index, info, loc, line, ranges, " + "pubnames, str, macinfo, macro or exception"), 0 }, { "hex-dump", 'x', "SECTION", 0, N_("Dump the uninterpreted contents of SECTION, by number or name"), 0 }, { "strings", 'p', "SECTION", OPTION_ARG_OPTIONAL, @@ -183,6 +183,9 @@ static bool print_address_names = true; /* True if we should print raw values instead of relativized addresses. */ static bool print_unresolved_addresses = false; +/* True if we should print the .debug_aranges section using libdw. */ +static bool decodedaranges = false; + /* Select printing of debugging sections. */ static enum section_e { @@ -391,6 +394,11 @@ parse_opt (int key, char *arg, print_debug_sections |= section_abbrev; else if (strcmp (arg, "aranges") == 0) print_debug_sections |= section_aranges; + else if (strcmp (arg, "decodedaranges") == 0) + { + print_debug_sections |= section_aranges; + decodedaranges = true; + } else if (strcmp (arg, "ranges") == 0) { print_debug_sections |= section_ranges; @@ -4330,9 +4338,8 @@ print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)), not have to know a bit about the structure of the section, libdwarf takes care of it. */ static void -print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)), - Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, - GElf_Shdr *shdr, Dwarf *dbg) +print_decoded_aranges_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, + GElf_Shdr *shdr, Dwarf *dbg) { Dwarf_Aranges *aranges; size_t cnt; @@ -4384,6 +4391,166 @@ print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)), } } + +/* Print content of DWARF .debug_aranges section. */ +static void +print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)), + Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, + GElf_Shdr *shdr, Dwarf *dbg) +{ + if (decodedaranges) + { + print_decoded_aranges_section (ebl, ehdr, scn, shdr, dbg); + return; + } + + Elf_Data *data = elf_rawdata (scn, NULL); + + if (unlikely (data == NULL)) + { + error (0, 0, gettext ("cannot get .debug_aranges content: %s"), + elf_errmsg (-1)); + return; + } + + printf (gettext ("\ +\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"), + elf_ndxscn (scn), section_name (ebl, ehdr, shdr), + (uint64_t) shdr->sh_offset); + + const unsigned char *readp = data->d_buf; + const unsigned char *readendp = readp + data->d_size; + + while (readp < readendp) + { + const unsigned char *hdrstart = readp; + size_t start_offset = hdrstart - (const unsigned char *) data->d_buf; + + printf (gettext ("\nTable at offset %Zu:\n"), start_offset); + if (readp + 4 > readendp) + { + invalid_data: + error (0, 0, gettext ("invalid data in section [%zu] '%s'"), + elf_ndxscn (scn), section_name (ebl, ehdr, shdr)); + return; + } + + Dwarf_Word length = read_4ubyte_unaligned_inc (dbg, readp); + unsigned int length_bytes = 4; + if (length == DWARF3_LENGTH_64_BIT) + { + if (readp + 8 > readendp) + goto invalid_data; + length = read_8ubyte_unaligned_inc (dbg, readp); + length_bytes = 8; + } + + const unsigned char *nexthdr = readp + length; + printf (gettext ("\n Length: %6" PRIu64 "\n"), + (uint64_t) length); + + if (nexthdr > readendp) + goto invalid_data; + + if (length == 0) + continue; + + if (readp + 2 > readendp) + goto invalid_data; + uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, readp); + printf (gettext (" DWARF version: %6" PRIuFAST16 "\n"), + version); + if (version != 2) + { + error (0, 0, gettext ("unsupported aranges version")); + goto next_table; + } + + Dwarf_Word offset; + if (readp + length_bytes > readendp) + goto invalid_data; + if (length_bytes == 8) + offset = read_8ubyte_unaligned_inc (dbg, readp); + else + offset = read_4ubyte_unaligned_inc (dbg, readp); + printf (gettext (" CU offset: %6" PRIx64 "\n"), + (uint64_t) offset); + + if (readp + 1 > readendp) + goto invalid_data; + unsigned int address_size = *readp++; + printf (gettext (" Address size: %6" PRIu64 "\n"), + (uint64_t) address_size); + if (address_size != 4 && address_size != 8) + { + error (0, 0, gettext ("unsupported address size")); + goto next_table; + } + + unsigned int segment_size = *readp++; + printf (gettext (" Segment size: %6" PRIu64 "\n\n"), + (uint64_t) segment_size); + if (segment_size != 0 && segment_size != 4 && segment_size != 8) + { + error (0, 0, gettext ("unsupported segment size")); + goto next_table; + } + + /* Round the address to the next multiple of 2*address_size. */ + readp += ((2 * address_size - ((readp - hdrstart) % (2 * address_size))) + % (2 * address_size)); + + while (readp < nexthdr) + { + Dwarf_Word range_address; + Dwarf_Word range_length; + Dwarf_Word segment = 0; + if (readp + 2 * address_size + segment_size > readendp) + goto invalid_data; + if (address_size == 4) + { + range_address = read_4ubyte_unaligned_inc (dbg, readp); + range_length = read_4ubyte_unaligned_inc (dbg, readp); + } + else + { + range_address = read_8ubyte_unaligned_inc (dbg, readp); + range_length = read_8ubyte_unaligned_inc (dbg, readp); + } + + if (segment_size == 4) + segment = read_4ubyte_unaligned_inc (dbg, readp); + else if (segment_size == 8) + segment = read_8ubyte_unaligned_inc (dbg, readp); + + if (range_address == 0 && range_length == 0 && segment == 0) + break; + + char *b = format_dwarf_addr (dwflmod, address_size, range_address, + range_address); + char *e = format_dwarf_addr (dwflmod, address_size, + range_address + range_length - 1, + range_length); + if (segment_size != 0) + printf (gettext (" %s..%s (%" PRIx64 ")\n"), b, e, + (uint64_t) segment); + else + printf (gettext (" %s..%s\n"), b, e); + free (b); + free (e); + } + + next_table: + if (readp != nexthdr) + { + size_t padding = nexthdr - readp; + printf (gettext (" %Zu padding bytes\n"), padding); + readp = nexthdr; + } + } +} + + /* Print content of DWARF .debug_ranges section. */ static void print_debug_ranges_section (Dwfl_Module *dwflmod, diff --git a/tests/ChangeLog b/tests/ChangeLog index 346577739..2da85cf06 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,10 @@ +2013-03-25 Mark Wielaard + + * run-readelf-aranges.sh: New test. + * testfilefoobarbaz.bz2: New test file. + * Makefile.am (TESTS): Add run-readelf-aranges.sh. + (EXTRA_DIST): Add run-readelf-aranges.sh and testfilefoobarbaz.bz2. + 2013-03-25 Mark Wielaard * run-readelf-dwz-multi.sh: Expect high_pc also as address. diff --git a/tests/Makefile.am b/tests/Makefile.am index 9b0bbf1a7..4e630398a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -75,6 +75,7 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \ run-readelf-test1.sh run-readelf-test2.sh run-readelf-test3.sh \ run-readelf-test4.sh run-readelf-twofiles.sh \ run-readelf-macro.sh run-readelf-loc.sh \ + run-readelf-aranges.sh \ run-native-test.sh run-bug1-test.sh \ dwfl-bug-addr-overflow run-addrname-test.sh \ dwfl-bug-fd-leak dwfl-bug-report \ @@ -157,6 +158,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \ testfile49.bz2 testfile50.bz2 testfile51.bz2 \ run-readelf-macro.sh testfilemacro.bz2 \ run-readelf-loc.sh testfileloc.bz2 \ + run-readelf-aranges.sh testfilefoobarbaz.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 \ diff --git a/tests/run-readelf-aranges.sh b/tests/run-readelf-aranges.sh new file mode 100755 index 000000000..a610fca01 --- /dev/null +++ b/tests/run-readelf-aranges.sh @@ -0,0 +1,161 @@ +#! /bin/sh +# Copyright (C) 2013 Red Hat, Inc. +# This file is part of elfutils. +# +# This file 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; either version 3 of the License, or +# (at your option) any later version. +# +# 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 this program. If not, see . + +. $srcdir/test-subr.sh + +# Tests readelf --debug-dump=aranges and --debug-dump=decodedaranges +# +# - foobarbaz.h +# +# int bar (); +# int baz (int i); +# +# - bar.c +# +# #include "foobarbaz.h" +# +# static int bi; +# +# static int +# barbaz (int i) +# { +# return i * 2 - 1; +# } +# +# __attribute__ ((constructor)) void +# nobar () +# { +# bi = 1; +# } +# +# int +# bar () +# { +# bi++; +# return barbaz (bi); +# } +# +# - foo.c +# +# include "foobarbaz.h" +# +# static int fi = 0; +# +# static int +# foo (int i, int j) +# { +# if (i > j) +# return i - j + fi; +# else +# return (2 * j) - i + fi; +# } +# +# int +# main (int argc, char **argv) +# { +# int a = bar (); +# int b = baz (a + argc); +# int r = foo (a, b) - 1; +# +# return r - 48; +# } +# +# - baz.c +# include "foobarbaz.h" +# +# static int bj; +# +# static int +# bazbaz (int j) +# { +# return bj * j - bar (); +# } +# +# __attribute__ ((constructor)) void +# nobaz () +# { +# bj = 1; +# } +# +# int +# baz (int i) +# { +# if (i < 0) +# return bazbaz (i); +# else +# { +# while (i-- > 0) +# bj += bar (); +# } +# return bazbaz (i); +# } +# +# gcc -g -O2 -m32 -c baz.c +# gcc -g -O2 -m32 -c bar.c +# gcc -g -O2 -m32 -c foo.c +# gcc -g -O2 -m32 -o testfilefoobarbaz foo.o bar.o baz.o + +testfiles testfilefoobarbaz + +testrun_compare ../src/readelf --debug-dump=aranges testfilefoobarbaz <..0x08048323 + +Table at offset 32: + + Length: 36 + DWARF version: 2 + CU offset: 136 + Address size: 4 + Segment size: 0 + + 0x08048440 ..0x08048451 + 0x08048330 ..0x0804833a + +Table at offset 72: + + Length: 36 + DWARF version: 2 + CU offset: 1d1 + Address size: 4 + Segment size: 0 + + 0x08048460 ..0x080484bb + 0x08048340 ..0x0804834a +EOF + +testrun_compare ../src/readelf --debug-dump=decodedaranges testfilefoobarbaz <<\EOF + +DWARF section [27] '.debug_aranges' at offset 0x1044 contains 5 entries: + [0] start: 0x080482f0, length: 52, CU DIE offset: 11 + [1] start: 0x08048330, length: 11, CU DIE offset: 321 + [2] start: 0x08048340, length: 11, CU DIE offset: 476 + [3] start: 0x08048440, length: 18, CU DIE offset: 321 + [4] start: 0x08048460, length: 92, CU DIE offset: 476 +EOF + +exit 0 diff --git a/tests/testfilefoobarbaz.bz2 b/tests/testfilefoobarbaz.bz2 new file mode 100755 index 0000000000000000000000000000000000000000..0e721ffe6f55010f1527bda088b4d579280d67b5 GIT binary patch literal 3974 zc-jGm4|(uHT4*^jL0KkKS%IY}Pyh_+fB*mg|NsC0|NsC0|L_0*|NsC0e(mc=@7@3O z{eAEL|IgqJ$=Kg!_23?ZduZI*wDDq8J-zPA>F#XL8yY=5(Xq2{LqeKrVgN+iDdjz> zrqtOH=qA!_NY6zLlSK7Ap_-X9P&D-#HjO3|Lui>aXf)FZ43ASyp)zRlYH5(kh||dsL36$~%nhENgMD)`{(W&Y*dYDZ#^nvJ^8fa;wO*9$bW8V^&_8hK4ULneJ6v>00E$A0000r0LYp$5lnzArFE|?rAl`F#=!*6cew>oXGKNuzrNo@ zkYeW=?xf-{1zjoE&{4HA`0eDWT5|feyDNq(*sWQ$PWj7cfj|p4b;JV)C4$f(Q>s^Z z#B*muUVDLyLWs=q4FeB6WLx>bGJH(~Fx?bY-pbvD+QO=<;rf2h{J9+e!Qb}YClhtO z@NS%2X63gXsMqK3+e?c~Y6O$*NSP|Szp$Ky*>H>jbYvcwyQ4xKGayDq4FfSZFeq?8 zepmPURf+B0=GSok1PnGP)JSI95i%G~x3~yP*>9NKZ&0;6WT}*dGbdho6C!wKWCQ2$ zOsa7hzS2` z`D(%DdDhAi?47X0?(h1o?c(;de_u`BmzJ1s=mcmPCKg1TZgxr)oVJOe;ptA@=9%b_ z%Tgp&u?f2j)DWht+_}A6$JMu7XLZ}l!Rs@x|PPT2*bA9GtS<$P% zD+c;fVYJePd&kdrhfF2cG40KyD$p)*(Y-Wdc&TvOD1tL;J4(0v?fO<{$pf)e4>)x3 z{>G8k#{!Kn(}t8N{@3ldfcC-%1(yI5kHwmtREXFkA_9aMgg7h!vOU}QRG z1jQXw8&+ZJ(n=E&B11_FB(`}{%mT?Rl7dSj$;~h};!bZVQcLf(i!zX=o%US|27Wp* zp=LN*+?2fwCVLI4O?RYWoWrS1$V`pM)1#qrNNC(qqJ?ED1uZl!Rqd?96Dce)V4@_U zg51(s78I1(&`9ID(BQZsW@M_EFy=e065;a+NtKdq5Zf~B>XMwO7@3J6ZXQb~DSZ+b zF;dW~mr5taoaif!7SVCh-VZ^mkYSERkmMB&J0W~L2r95KFw@P))7o{}V@h@W>4~sp$7ZX;Ja_~6jZif$u*qk` zVYNc*Qv+mjWt0*GZM`&*yN5>;E-W+aP{eJyeT!~Wg^LSb$z%m4?qZ;~5~b`}HXG2r z&BCqQCk-%ZIi_60224a`Ii?(5n!h8sj}y=eiB{Fi!RUJ5yN{wtgMgY^wE#|-C{o!H z+OfXN*xv1(lzPoO79P>%X&)rr`era;`8FA>+ryKm-C+K_YOMC6wsNj6M*VlA%tp-m z%+Ul51?odm1~qvKW(V(w3~1TfOERz&1xE=m(5w{4YG-B(QPTw?#Z!H6DKWyax=pgx zlV@>7>%*uS@Xg$<)TPh8sxiblzeTQ2pxN%8-L|Izih~AVjNtL()@XcwQ>m&t5pOR+ zJ3tiC0R)faGO{uiumo7j3=jx_G-fbGqrBpu_S(j}yEGua`;fq*Fk~=6#Q}2&GVH%s z@^S&TOnM$ZMKrZSf}gge0(Q!ol_#0S)moTs-wH{MR=u_FCcD$-wL*$N{*^Qf2T%#3&5ciB@R?dQgahShDr$;*dQh;Oc@b_27(j? z5P^de2{Xh7a2c5m5IA&JFmVbD2^etVK?1{|W0N2?Co*L-K&K35$`z3bBxH?pUzqZ(Xj-Z8VSPbg4Y_j)J12eXFgXgf?WmkSi-u^TsOaScVo92BsFKJsF; zv|;Y073wc9Y+PRut(>W1>XPeowRE2`n8zBobhKS+m?v7(XN_AsY>{+Oke&4`c4TLY zfs~B5KWgDjC`2_E;}D8rY7W`$HDc&E9-UP&h(svTf$j=?8Wsfc+|Rw+8D*1-0($>G zf=b%CaZY0a2GT28mu!@;0+Ea3bYx9a?hHRWR!A&ECsursx7c38*pgVm5_<7zTEnrl zYumYu1?3d)0}PnKMnz;}hylvO=uqQ98CfOzo)KRcq?o+*F|o{oMito@)(Xh!ei}s+ z`jns}4v9gQ_nE9>y}r!tF4wuqydGuf50gX%>?=LzqP@Qb5rjlp0Ze37ZJ`AQ&=w_V z1?;4TYZ+PHinnI+3v_z6NbC|$MtEBdZYg6IL}{j$kk1@OMotGs_|&A|oFvteUX2nBqs73!m6mouMW<+KR z&2HmPp&1cDnb51+cn+TW_3QR6Ljt*`dCoE4I z_04}2gWP^pX$NDUVW^dOzr#o-hvQ^n@P^yQ213-cr80Dx40BXmkB#E%fw1-?twSO+ z2wD3|U3P6Ld&5ax%Q0#3W8-YE?4|lMgbGh$BNg50nwwISoZwNM?=%lDl&m>7p`*W; z1`!}JhM`+p*)#+B$ezIxT)b^y9bmED7z>_Vinx4BwqEW+^g~V!Bh8V5ZgPJ*AcJc$ z4@~ggLt=GYEZFE=bV7(L1aeXb@@G1gM$)gSH5u=Pd559{0%44CXcFdVpBXf$v-2t7 zv#k4ggL0R0qT7#k&_=nAtABr4v^dSxl0fOo=@EJ(Cxtv=T=O-}`G?I@$X818F}lSL zKPjb?9xUb;8K)w&FYGb9DS{E74W{T89?rRUoI|r`Ll6PFp(+8X4}koL6i8s2GGp(e z!8SlltF9Sh3=V>Hfj>yDYm8i6^eYBNOU2Qt<8Tlh=0ha6M#Altt#U+!9I8!7TbSrp zicAgdD5xZx15sv{={x0cH$i9(=UHbAM2O-_FJ?i&TUnF@;MkC@NUlZ{MAEzpfWnI! z5J3tA(+D6`V9QL_yFG&DYqSN!eU5eMaHkVlK7thzJBmN+W^TF-88%ye6E>_5fPk5R zf;5Ec;IEm0!3fY9mRyl>iv%DdpB(hU zM(NC*n65RBP8oSFXudDh{Sp#S2;j&Dgsm1;yP&4b)a)1LQkqr;clheq+Rmb-iiJRCQj|esFLZ+qFyLtjLnR7jP%s7q zc;2nFpY!Yc+ZG-H(Jjyd0GCjR+C9cbmF^yzn06XbWi3uP;z!{XDjE_UAxH}~AYl{+ zLkQW28p9$-hJ^It>Vgxj&4f>jgTOOVj2KdtOwrHqv;}2dfw}jvF;@wO>1YiSrND`^ z#QwPmuHdY?C(LO7b<1^{4R^t&xXXoj>w1ny0;*?Ov(vbN>d9qq4s3L~bU1X#V<>Zo zPMQ|Tm0BK$M+=n{*}vdZFACWDQ9s3?H_ow_L6?T;DBOVl;o;s0M*X4A!osA8A`0yt ze-pn|Bz2ns7D`{I8OIKT)JrPGWuQ!Msl_)Z)!)Oc%UnEw-iRNOt05(gyk)@)LA#-U z$INa1MzU@RG6}P0p-<|85U%!C9fheRM!UU$;84UasRa$DGlzRs5@W_alq!Xs4kG83UdY_h zYClZ&M%P!a{4q}>6UeX5gCI2bdIek%dYm|n#a=3I9it=!5@EO)i^>INT&)C5HzI<0P8R}Q2+n{ literal 0 Hc-jL100001 -- 2.47.2