summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn M Mellor-Crummey <johnmc@rice.edu>2021-10-20 18:19:38 -0500
committerMark Wielaard <mark@klomp.org>2021-11-10 11:03:32 +0100
commitdbd44e96f101a81f387ca6ff46910ab74ed7b1dc (patch)
tree062f1ea987223df99a9dae87aaa4a9e25c294b00 /src
parent5b21e70216b853065fa2fef34273db5f7dcdc88b (diff)
downloadelfutils-dbd44e96f101a81f387ca6ff46910ab74ed7b1dc.tar.gz
libdw, readelf: Read inlining info in NVIDIA extended line map
As of CUDA 11.2, NVIDIA added extensions to the line map section of CUDA binaries to represent inlined functions. These extensions include - two new fields in a line table row to represent inline information: context, and functionname, - two new DWARF extended opcodes: DW_LNE_NVIDIA_inlined_call, DW_LNE_NVIDIA_set_function_name, - an additional word in the line table header that indicates the offset in the .debug_str function where the function names for this line table begin, and A line table row for an inlined function contains a non-zero "context" value. The “context” field indicates the index of the line table row that serves as the call site for an inlined context. The "functionname" field in a line table row is only meaningful if the "context" field of the row is non-zero. A meaningful "functionname" field contains an index into the .debug_str section relative to the base offset established in the line table header; the position in the .debug_str section indicates the name of the inlined function. These extensions resemble the proposed DWARF extensions (http://dwarfstd.org/ShowIssue.php?issue=140906.1) by Cary Coutant, but are not identical. This commit integrates support for handling NVIDIA's extended line maps into elfutil's libdw library, by adding two functions dwarf_linecontext and dwarf_linefunctionname, and the readelf --debug-dump=line command line utility. Signed-off-by: John M Mellor-Crummey <johnmc@rice.edu> Signed-off-by: Mark Wielaard <mark@klomp.org>
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog6
-rw-r--r--src/readelf.c62
2 files changed, 68 insertions, 0 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 316bcb6d..05b2522d 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,9 @@
+2021-10-20 John M Mellor-Crummey <johnmc@rice.edu>
+
+ * readelf.c (print_debug_line_section): Try to read
+ debug_str_offset if available. Handle DW_LNE_NVIDIA_inlined_call
+ and DW_LNE_NVIDIA_set_function_name.
+
2021-10-06 Mark Wielaard <mark@klomp.org>
* elflint.c (check_sections): Don't dereference databits if bad.
diff --git a/src/readelf.c b/src/readelf.c
index 3a199068..c10038e3 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -8478,6 +8478,8 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
header_length = read_8ubyte_unaligned_inc (dbg, linep);
}
+ const unsigned char *header_start = linep;
+
/* Next the minimum instruction length. */
if ((size_t) (lineendp - linep) < 1)
goto invalid_data;
@@ -8761,6 +8763,13 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
++linep;
}
+ unsigned int debug_str_offset = 0;
+ if (unlikely (linep == header_start + header_length - 4))
+ {
+ /* CUBINs contain an unsigned 4-byte offset */
+ debug_str_offset = read_4ubyte_unaligned_inc (dbg, linep);
+ }
+
if (linep == lineendp)
{
puts (_("\nNo line number statements."));
@@ -8909,6 +8918,59 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
printf (_(" set discriminator to %u\n"), u128);
break;
+ case DW_LNE_NVIDIA_inlined_call:
+ {
+ if (unlikely (linep >= lineendp))
+ goto invalid_data;
+
+ unsigned int context;
+ get_uleb128 (context, linep, lineendp);
+
+ if (unlikely (linep >= lineendp))
+ goto invalid_data;
+
+ unsigned int function_name;
+ get_uleb128 (function_name, linep, lineendp);
+ function_name += debug_str_offset;
+
+ Elf_Data *str_data = dbg->sectiondata[IDX_debug_str];
+ char *function_str;
+ if (str_data == NULL || function_name >= str_data->d_size
+ || memchr (str_data->d_buf + function_name, '\0',
+ str_data->d_size - function_name) == NULL)
+ function_str = "???";
+ else
+ function_str = (char *) str_data->d_buf + function_name;
+
+ printf (_(" set inlined context %u,"
+ " function name %s (0x%x)\n"),
+ context, function_str, function_name);
+ break;
+ }
+
+ case DW_LNE_NVIDIA_set_function_name:
+ {
+ if (unlikely (linep >= lineendp))
+ goto invalid_data;
+
+ unsigned int function_name;
+ get_uleb128 (function_name, linep, lineendp);
+ function_name += debug_str_offset;
+
+ Elf_Data *str_data = dbg->sectiondata[IDX_debug_str];
+ char *function_str;
+ if (str_data == NULL || function_name >= str_data->d_size
+ || memchr (str_data->d_buf + function_name, '\0',
+ str_data->d_size - function_name) == NULL)
+ function_str = "???";
+ else
+ function_str = (char *) str_data->d_buf + function_name;
+
+ printf (_(" set function name %s (0x%x)\n"),
+ function_str, function_name);
+ }
+ break;
+
default:
/* Unknown, ignore it. */
puts (_(" unknown opcode"));