]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
readelf: Support .gdb_index version 9
authorAaron Merey <amerey@redhat.com>
Tue, 31 Oct 2023 20:00:27 +0000 (16:00 -0400)
committerAaron Merey <amerey@redhat.com>
Thu, 2 Nov 2023 17:16:53 +0000 (13:16 -0400)
Version 9 adds a "shortcut table" to the index.  The shortcut table contains
the name and language of the main function, if it exists.

A testcase added in this patch uses an executable written with Fortran.
This is because gdb does not currently populate the shortcut table of
C/C++ programs (see sourceware PR30996).

Signed-off-by: Aaron Merey <amerey@redhat.com>
src/readelf.c
tests/Makefile.am
tests/run-readelf-gdb_index.sh
tests/testfilegdbindex9-no-maininfo.bz2 [new file with mode: 0755]
tests/testfilegdbindex9.bz2 [new file with mode: 0755]

index db31ad09dbe48456bbea9185e0ddf2dcbdd6957f..decfaf1553eefbcad45da20b52456b72478342fb 100644 (file)
@@ -11539,8 +11539,9 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl,
   // hash used for generating the table.  Version 6 contains symbols
   // for inlined functions, older versions didn't.  Version 7 adds
   // symbol kinds.  Version 8 just indicates that it correctly includes
-  // TUs for symbols.
-  if (vers < 4 || vers > 8)
+  // TUs for symbols.  Version 9 adds shortcut table for information
+  // regarding the main function.
+  if (vers < 4 || vers > 9)
     {
       printf (_("  unknown version, cannot parse section\n"));
       return;
@@ -11578,6 +11579,17 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl,
   if (unlikely (readp + 4 > dataend))
     goto invalid_data;
 
+  uint32_t shortcut_off = 0;
+  if (vers >= 9)
+    {
+      shortcut_off = read_4ubyte_unaligned (dbg, readp);
+      printf (_(" shortcut offset: %#" PRIx32 "\n"), shortcut_off);
+
+      readp += 4;
+      if (unlikely (readp + 4 > dataend))
+       goto invalid_data;
+    }
+
   uint32_t const_off = read_4ubyte_unaligned (dbg, readp);
   printf (_(" constant offset: %#" PRIx32 "\n"), const_off);
 
@@ -11675,8 +11687,19 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl,
   if (const_off >= data->d_size)
     goto invalid_data;
 
+  const unsigned char *shortcut_start = NULL;
+  if (vers >= 9)
+    {
+      if (shortcut_off >= data->d_size)
+       goto invalid_data;
+
+      shortcut_start = data->d_buf + shortcut_off;
+      nextp = shortcut_start;
+    }
+  else
+    nextp = const_start;
+
   readp = data->d_buf + sym_off;
-  nextp = const_start;
   size_t sym_nr = (nextp - readp) / 8;
 
   printf (_("\n Symbol table at offset %#" PRIx32
@@ -11750,6 +11773,49 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl,
        }
       n++;
     }
+
+  if (vers < 9)
+    return;
+
+  if (unlikely (shortcut_start == NULL))
+    goto invalid_data;
+
+  readp = shortcut_start;
+  nextp = const_start;
+  size_t shortcut_nr = (nextp - readp) / 4;
+
+  if (unlikely (shortcut_nr != 2))
+    goto invalid_data;
+
+  printf (_("\nShortcut table at offset %#" PRIx32 " contains %zu slots:\n"),
+         shortcut_off, shortcut_nr);
+
+  uint32_t lang = read_4ubyte_unaligned (dbg, readp);
+  readp += 4;
+
+  /* Include the hex number of LANG in the output if the language
+     is unknown.  */
+  const char *lang_str = dwarf_lang_string (lang);
+  lang_str = string_or_unknown (lang_str, lang, DW_LANG_lo_user,
+                               DW_LANG_hi_user, true);
+
+  printf (_("Language of main: %s\n"), lang_str);
+  printf (_("Name of main: "));
+
+  if (lang != 0)
+    {
+      uint32_t name = read_4ubyte_unaligned (dbg, readp);
+      readp += 4;
+      const unsigned char *sym = const_start + name;
+
+      if (unlikely ((size_t) (dataend - const_start) < name
+                   || memchr (sym, '\0', dataend - sym) == NULL))
+       goto invalid_data;
+
+      printf ("%s\n", sym);
+    }
+  else
+    printf ("<unknown>\n");
 }
 
 /* Returns true and sets split DWARF CU id if there is a split compile
index d0ae7c6d323c23b6882bf7f2b1f61e6991a13afc..7fb8efb13aafabaa14114ca256e92452be59a52b 100644 (file)
@@ -419,7 +419,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
             run-readelf-Dd.sh \
             testfile-s390x-hash-both.bz2 \
             run-readelf-gdb_index.sh testfilegdbindex5.bz2 \
-            testfilegdbindex7.bz2 \
+            testfilegdbindex7.bz2 testfilegdbindex9.bz2 \
+            testfilegdbindex9-no-maininfo.bz2 \
             run-readelf-s.sh testfilebazdbg.bz2 testfilebazdyn.bz2 \
             testfilebazmin.bz2 testfilebazdbg.debug.bz2 testfilebazmdb.bz2 \
             testfilebaztab.bz2 testfilebasmin.bz2 testfilebaxmin.bz2 \
index fcbc3c571d537585249935f56ffb658774525ad5..cd437f523ec6051fcacc62be0fee6b43bc6abd5d 100755 (executable)
@@ -63,7 +63,7 @@
 # (gdb) save gdb-index .
 # objcopy --add-section .gdb_index=testfilegdbindex7.gdb-index --set-section-flags .gdb_index=readonly testfilegdbindex7 testfilegdbindex7
 
-testfiles testfilegdbindex5 testfilegdbindex7
+testfiles testfilegdbindex5 testfilegdbindex7 testfilegdbindex9 testfilegdbindex9-no-maininfo
 
 testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=gdb_index testfilegdbindex5 <<\EOF
 
@@ -127,4 +127,97 @@ GDB section [33] '.gdb_index' at offset 0xe76 contains 8399 bytes :
  [ 754] symbol: int, CUs: 0 (type:S)
 EOF
 
+# testfilegdbindex9-no-maininfo is built the same way as testfilegdbindex7.
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=gdb_index testfilegdbindex9-no-maininfo <<\EOF
+
+GDB section [33] '.gdb_index' at offset 0x38e1 contains 8415 bytes :
+ Version:         9
+ CU offset:       0x1c
+ TU offset:       0x3c
+ address offset:  0x54
+ symbol offset:   0x7c
+ shortcut offset: 0x207c
+ constant offset: 0x2084
+
+ CU list at offset 0x1c contains 2 entries:
+ [   0] start: 0x00004c, length:   220
+ [   1] start: 0x000128, length:   214
+
+ TU list at offset 0x3c contains 1 entries:
+ [   0] CU offset:     0, type offset:    30, signature: 0x87e03f92cc37cdf0
+
+ Address list at offset 0x54 contains 2 entries:
+ [   0] 0x0000000000401106 <main>..0x000000000040113b <main+0x35>, CU index:     1
+ [   1] 0x000000000040113c <hello>..0x0000000000401173 <say+0x1c>, CU index:     2
+
+ Symbol table at offset 0x54 contains 1024 slots:
+ [ 123] symbol: global, CUs: 1 (var:G), 0T (var:G)
+ [ 489] symbol: main, CUs: 1 (func:G)
+ [ 518] symbol: char, CUs: 0 (type:S)
+ [ 661] symbol: foo, CUs: 0 (type:S)
+ [ 741] symbol: hello, CUs: 1 (var:S), 0T (func:S)
+ [ 746] symbol: say, CUs: 0T (func:G)
+ [ 754] symbol: int, CUs: 1 (type:S)
+
+Shortcut table at offset 0x207c contains 2 slots:
+Language of main: ??? (0)
+Name of main: <unknown>
+EOF
+
+# testfilegdbindex9.f90
+#
+# program repro
+#  type small_stride
+#     character*40 long_string
+#     integer      small_pad
+#  end type small_stride
+#  type(small_stride), dimension (20), target :: unpleasant
+#  character*40, pointer, dimension(:):: c40pt
+#  integer i
+#  do i = 0,19
+#     unpleasant(i+1)%small_pad = i+1
+#     unpleasant(i+1)%long_string = char (ichar('0') + i)
+#  end do
+#  c40pt => unpleasant%long_string
+#  print *, c40pt
+#end program repro
+
+# gfortran -g -o testfilegdbindex9 testfilegdbindex9.f90
+# gdb-add-index testfilegdbindex9
+
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=gdb_index testfilegdbindex9 <<\EOF
+
+GDB section [35] '.gdb_index' at offset 0x37d9 contains 8395 bytes :
+ Version:         9
+ CU offset:       0x1c
+ TU offset:       0x2c
+ address offset:  0x2c
+ symbol offset:   0x40
+ shortcut offset: 0x2040
+ constant offset: 0x2048
+
+ CU list at offset 0x1c contains 1 entries:
+ [   0] start: 00000000, length:   307
+
+ TU list at offset 0x2c contains 0 entries:
+
+ Address list at offset 0x2c contains 1 entries:
+ [   0] 0x0000000000401166 <MAIN__>..0x00000000004013f0 <main+0x3a>, CU index:     0
+
+ Symbol table at offset 0x2c contains 1024 slots:
+ [  61] symbol: small_stride, CUs: 0 (type:S)
+ [  71] symbol: integer(kind=8), CUs: 0 (type:S)
+ [ 161] symbol: character(kind=1), CUs: 0 (type:S)
+ [ 397] symbol: unpleasant, CUs: 0 (var:S)
+ [ 489] symbol: main, CUs: 0 (func:G)
+ [ 827] symbol: integer(kind=4), CUs: 0 (type:S)
+ [ 858] symbol: c40pt, CUs: 0 (var:S)
+ [ 965] symbol: repro, CUs: 0 (func:S)
+ [1016] symbol: i, CUs: 0 (var:S)
+
+Shortcut table at offset 0x2040 contains 2 slots:
+Language of main: Fortran08
+Name of main: repro
+EOF
+
 exit 0
diff --git a/tests/testfilegdbindex9-no-maininfo.bz2 b/tests/testfilegdbindex9-no-maininfo.bz2
new file mode 100755 (executable)
index 0000000..043b8d3
Binary files /dev/null and b/tests/testfilegdbindex9-no-maininfo.bz2 differ
diff --git a/tests/testfilegdbindex9.bz2 b/tests/testfilegdbindex9.bz2
new file mode 100755 (executable)
index 0000000..9a2c189
Binary files /dev/null and b/tests/testfilegdbindex9.bz2 differ