diff options
author | John M Mellor-Crummey <johnmc@rice.edu> | 2021-10-20 18:19:38 -0500 |
---|---|---|
committer | Mark Wielaard <mark@klomp.org> | 2021-11-10 11:03:32 +0100 |
commit | dbd44e96f101a81f387ca6ff46910ab74ed7b1dc (patch) | |
tree | 062f1ea987223df99a9dae87aaa4a9e25c294b00 /src | |
parent | 5b21e70216b853065fa2fef34273db5f7dcdc88b (diff) | |
download | elfutils-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/ChangeLog | 6 | ||||
-rw-r--r-- | src/readelf.c | 62 |
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")); |