From patchwork Mon Sep 6 00:07:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Mellor-Crummey X-Patchwork-Id: 45957 From: John M Mellor-Crummey Message-Id: <7C166312-4876-444F-9B85-C7E30C8F4959@rice.edu> Subject: [PATCH] Read inlining info in NVIDIA extended line map Date: Sun, 5 Sep 2021 19:07:45 -0500 To: elfutils-devel@sourceware.org X-Mailer: Apple Mail (2.3608.120.23.2.4) X-Proofpoint-ORIG-GUID: JH9RxzbGEePNNR2Hu4zaOmXdUlpNV8wj X-Proofpoint-GUID: JH9RxzbGEePNNR2Hu4zaOmXdUlpNV8wj X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.182.1,Aquarius:18.0.790,Hydra:6.0.391,FMLib:17.0.607.475 definitions=2021-09-05_04,2021-09-03_01,2020-04-07_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 adultscore=0 mlxlogscore=729 spamscore=0 impostorscore=0 mlxscore=0 suspectscore=0 lowpriorityscore=0 clxscore=1011 bulkscore=0 phishscore=0 malwarescore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2108310000 definitions=main-2109050170 X-BeenThere: elfutils-devel@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Elfutils-devel mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , Reply-To: John Mellor-Crummey Cc: Xiaozhu Meng Errors-To: elfutils-devel-bounces+mark=klomp.org@sourceware.org Sender: "Elfutils-devel" X-Soverin-Spam-Result: default: False [-1.42 / 15.00]; DMARC_POLICY_ALLOW(-0.50)[sourceware.org,none]; RCVD_DKIM_ARC_DNSWL_MED(-0.50)[]; MV_CASE(0.50)[]; R_DKIM_ALLOW(-0.20)[sourceware.org:s=default]; R_SPF_ALLOW(-0.20)[+a]; RCVD_IN_DNSWL_MED(-0.20)[8.43.85.97:from]; MAILLIST(-0.20)[mailman]; MIME_GOOD(-0.10)[multipart/mixed,text/plain]; MX_GOOD(-0.01)[]; HAS_LIST_UNSUB(-0.01)[]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; FROM_HAS_DN(0.00)[]; HAS_REPLYTO(0.00)[johnmc@rice.edu]; REPLYTO_DOM_NEQ_FROM_DOM(0.00)[]; ARC_NA(0.00)[]; NEURAL_HAM(-0.00)[-0.975]; CLAM_VIRUS_FAIL(0.00)[failed to scan and retransmits exceed]; FROM_NEQ_ENVFROM(0.00)[elfutils-devel@sourceware.org,elfutils-devel-bounces@sourceware.org]; MIME_TRACE(0.00)[0:+,1:+,2:~,3:+]; ASN(0.00)[asn:17314, ipnet:8.43.84.0/22, country:US]; HAS_ATTACHMENT(0.00)[]; TO_DN_SOME(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; TAGGED_FROM(0.00)[mark=klomp.org]; DKIM_TRACE(0.00)[sourceware.org:+]; RECEIVED_SPAMHAUS_PBL(0.00)[98.200.175.18:received]; RCPT_COUNT_TWO(0.00)[2]; RCVD_TLS_LAST(0.00)[]; RCVD_COUNT_SEVEN(0.00)[9]; FORGED_SENDER_MAILLIST(0.00)[] X-Soverin-Spam-Status: No, score=-1.42 X-Soverin-Spam-Bar: - Authentication-Results: mx.soverin.net; dkim=pass header.d=sourceware.org header.s=default header.b=PcxR2ZEd; dmarc=pass (policy=none) header.from=sourceware.org; spf=pass (mx.soverin.net: domain of "elfutils-devel-bounces+mark=klomp.org@sourceware.org" designates 8.43.85.97 as permitted sender) smtp.mailfrom="elfutils-devel-bounces+mark=klomp.org@sourceware.org" X-getmail-retrieved-from-mailbox: INBOX --Apple-Mail=_EB22CA76-EC65-45E3-8A9F-E0830BF864E9 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 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=20 information: context, and functionname, - two new DWARF extended opcodes: DW_LNE_inlined_call,=20 DW_LNE_set_function_name, - an additional word in the line table header that indicates=20 the offset in the .debug_str function where the function=20 names for this line table begin, and - two new functions in the libdw API: dwarf_linecontext and=20 dwarf_linefunctionname, which return the new line table fields. A line table row for an inlined function contains a non-zero "context" value. The =E2=80=9Ccontext=E2=80=9D 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=3D140906.1) by Cary Coutant, but are not identical. This patch adds integrates support for handling NVIDIA's extended line maps into elfutil's libdw library and the readelf command line utility. Since this support is a non-standard extension to DWARF, all code that implements the extensions is implemented between markers =20 /* Begin NVIDIA_LINEMAP_INLINING_EXTENSIONS */ and=20 /* End NVIDIA_LINEMAP_INLINING_EXTENSIONS */. The definition below #define NVIDIA_LINEMAP_INLINING_EXTENSIONS 1 is added to elfutils/version.h, which enables a client of elfutils=20 to test whether the NVIDIA line map extensions are present.=20 Note: The support for NVIDIA extended line maps adds two integer fields (context and functionname) to struct Dwarf_Line_s, which makes the structure about 30% larger. The patch includes a binary testfile_nvidia_linemap.bz2 that contains an NVIDIA extended linemap along with two tests that read the line map. - A test script run-nvidia-extended-linemap-readelf.sh=20 checks the output of readelf on the new test binary to=20 validate its dump of the line op codes containing context=20 and functionname entries. - A test program tests/nvidia_extended_linemap_libdw.c reads=20 the extended line map with dwarf_next_lines and dumps the=20 context and functionname fields of the line map where they=20 are relevant, i.e. the value of context is non-zero. A test=20 script run-nvidia-extended-linemap-libdw.sh runs this test=20 and validates its output. A patch with the new functionality described above is attached. --- John Mellor-Crummey Professor Dept of Computer Science Rice University email: johnmc@rice.edu phone: 713-348-5179 Signed-off-by: John M Mellor-Crummey --- ChangeLog | 4 + config/version.h.in | 4 + libdw/Makefile.am | 1 + libdw/dwarf.h | 4 + libdw/dwarf_getsrclines.c | 52 ++++++- libdw/dwarf_linecontext.c | 47 ++++++ libdw/dwarf_linefunctionname.c | 47 ++++++ libdw/libdw.h | 12 ++ libdw/libdw.map | 2 + libdw/libdwP.h | 4 + src/readelf.c | 46 ++++++ tests/Makefile.am | 3 + tests/nvidia_extended_linemap_libdw.c | 153 +++++++++++++++++++ tests/run-nvidia-extended-linemap-libdw.sh | 41 +++++ tests/run-nvidia-extended-linemap-readelf.sh | 114 ++++++++++++++ tests/testfile_nvidia_linemap.bz2 | Bin 0 -> 2365 bytes 16 files changed, 533 insertions(+), 1 deletion(-) create mode 100644 libdw/dwarf_linecontext.c create mode 100644 libdw/dwarf_linefunctionname.c create mode 100644 tests/nvidia_extended_linemap_libdw.c create mode 100755 tests/run-nvidia-extended-linemap-libdw.sh create mode 100755 tests/run-nvidia-extended-linemap-readelf.sh create mode 100644 tests/testfile_nvidia_linemap.bz2 GIT binary patch literal 2365 zcmV-D3BvY5T4*^jL0KkKSq)>6PXG%lfB*mg|L^|i|Nqm@%YXm>|9|bF;0gptplMZb z+z@oxek$MzA3=Le*sZ4QFf%trk<(lJVeQ+CXEdl4WbN< z003wJ222QOG|4JO$`Q^Ookzl7$XsrKr|R55rS!>07C#HCYdx~lTt}N z38AT?G}BEz6Gx~S0Av6%G&D2~0017KWB>pLfCE4P28bFNG}BB>fu@E=hD|gy8euXR zhCpD9Moj?FV2nlyri=j$0F0Vs(Sk(*1jt54hEjf{$kR~t(lp+b(p@T+?W=XfGcS&L5UbU0?35a#xs8L!r-U)TF1&F!__dKhBSQp!#+wj$%m9uMNR-G!K_M%dqZ6H; zp6s^6LtA42tC>wzChpmB6xue3L}H1b!5}H>R`jsiDJG5(on{65{32{>NRWayf(z@`1E`3y{ zl~q+m1VF!oZ8R)6HEO=U!CjHKL=i#lMp8Ugu|_5N>}!I}P<2H9jm?W|S`&9IL7fYl&9&Tajy_+U zco?v~b4#nESGuIQ`WznwnVcDcvISVY32sJ@;zMlYbDE<_Ci5dU5WJ7A^d;1t&%hFdjAKBEu4x*h0Wpf#4;~SW1h|NlaA3mRdio<% zGpjR0sd)xQTDw99PZxme&R|Hv~Sh-6jvSs*KAN5Z798xL3$; z9FnOe=%tyNnVINO5fKqInrWo~+BvML@!#9pbEQiVVg!noOb1AemW7{KqN380XnRY1 z6{JWGivo+!W+h-4Y3?|6%5MW0g;{{xNZkBE)Ja^Fk-a=Dk zS=wXMwrouPmhh`==%Vz67fDh|NyHUm+g!3v8g!M10QsMnf&`Qk+^IDn5Z;=Pj1~a5 zH&O@Dx5OLVo51JwnP)1TKRjw}r3i|mBC4vaL`EVgtVLB-h={~hRw5{4IBBKH!Y!!n8(v!LfgK&f~C6?3$*akx+tT+~` zQ&mt=O;aXEkO2drE@PBN-FLcr75GzJg+W0&@WT#_C_bl!Qmkb@|P;)P6=sVtW;lDLBoVZy4hQ58{8Mk=bRAgk!m5)flbxZQ3X+O!1lp@o(X z+SMs00cDV_Ba9V5-r^D{G#CoWD#*P+kpPw8M6zZih>HSCTG3%@-dffX$!=A)MiVAu zjx63v@7iqgAu&330$@?#DN z6NEditP%rEZN^JA8Y?;mfGz=a@`QwllSz_F08}3)mY~3kP&Ps_ZMmM0c!-Q49`B4# zcb+A-d|*WH1GzczT?Nf5cK!b{F_9@3pgiJJ3pWL7W>gA4 zGiDm}BpCOl$LYMDSzZy{NiuK^^pSeEbtH;V1z?N>)ah6m1~G-bIK(87XT3qK5)l9x z40mqd)(~-IuM57Vl3(pymwh1aNiBL67qdt&_v%@YFH69NQHiccgh3-{yq!_dYu|g@ z=@*8TomE+8s9{vLJ*R@(ZQtwkpx|qDhM_ZY0%9&mHga|(YR7p3b|5p@TdqM_Eg+-s zLL!iMrX_|_A~gsaL?&2rselIk+iLV;pl>wLF0}Gs9l=WS)!Yq_pXg3`#*M}(Q-g2@ z1`~`<3%;7Tx%_a8VyAZl!6_V$UBw`=4iMR4eXP@L*K7((7gR*|jKtwYBx*=67Nb8((Hm10 zTeLcBi18~G1vRWQDD}RujxL{FF1l1;K}-aDVK9GC32vRua)mg)2*#^e6+Jh`NDdNs zn#lrvt*a9C4j5hys&rMN&Pg;`(RCy8V3aTH7)tkQALtOK1(%p_BZdf^uW4^<3GX)mdW&zZuC%MyCDnGxGg7 j? + + * NEWS: Read inlining info in NVIDIA extended line map + 2021-08-10 Adrian Ratiu * configure.ac (AC_CACHE_CHECK): Rework std=gnu99 check to allow clang. diff --git a/config/version.h.in b/config/version.h.in index 34e62c3b..8b30d144 100644 --- a/config/version.h.in +++ b/config/version.h.in @@ -35,4 +35,8 @@ #define _ELFUTILS_PREREQ(major, minor) \ (_ELFUTILS_VERSION >= ((major) * 1000 + (minor))) +/* Begin NVIDIA_LINEMAP_INLINING_EXTENSIONS */ +#define NVIDIA_LINEMAP_INLINING_EXTENSIONS 1 +/* End NVIDIA_LINEMAP_INLINING_EXTENSIONS */ + #endif /* elfutils/version.h */ diff --git a/libdw/Makefile.am b/libdw/Makefile.am index 6b7834af..4fda33bd 100644 --- a/libdw/Makefile.am +++ b/libdw/Makefile.am @@ -63,6 +63,7 @@ libdw_a_SOURCES = dwarf_begin.c dwarf_begin_elf.c dwarf_end.c dwarf_getelf.c \ dwarf_linesrc.c dwarf_lineno.c dwarf_lineaddr.c \ dwarf_linecol.c dwarf_linebeginstatement.c \ dwarf_lineendsequence.c dwarf_lineblock.c \ + dwarf_linecontext.c dwarf_linefunctionname.c \ dwarf_lineprologueend.c dwarf_lineepiloguebegin.c \ dwarf_lineisa.c dwarf_linediscriminator.c \ dwarf_lineop_index.c dwarf_line_file.c \ diff --git a/libdw/dwarf.h b/libdw/dwarf.h index 19a4be96..2faf852a 100644 --- a/libdw/dwarf.h +++ b/libdw/dwarf.h @@ -844,6 +844,10 @@ enum DW_LNE_set_discriminator = 4, DW_LNE_lo_user = 128, + /* Begin NVIDIA_LINEMAP_INLINING_EXTENSIONS */ + DW_LNE_inlined_call = 144, + DW_LNE_set_function_name = 145, + /* End NVIDIA_LINEMAP_INLINING_EXTENSIONS */ DW_LNE_hi_user = 255 }; diff --git a/libdw/dwarf_getsrclines.c b/libdw/dwarf_getsrclines.c index d6a581ad..d7907d4d 100644 --- a/libdw/dwarf_getsrclines.c +++ b/libdw/dwarf_getsrclines.c @@ -93,6 +93,10 @@ struct line_state struct linelist *linelist; size_t nlinelist; unsigned int end_sequence; +/* Begin NVIDIA_LINEMAP_INLINING_EXTENSIONS */ + unsigned int context; + unsigned int function_name; +/* End NVIDIA_LINEMAP_INLINING_EXTENSIONS */ }; static inline void @@ -139,6 +143,10 @@ add_new_line (struct line_state *state, struct linelist *new_line) SET (epilogue_begin); SET (isa); SET (discriminator); +/* Begin NVIDIA_LINEMAP_INLINING_EXTENSIONS */ + SET (context); + SET (function_name); +/* End NVIDIA_LINEMAP_INLINING_EXTENSIONS */ #undef SET @@ -165,6 +173,13 @@ read_srclines (Dwarf *dbg, #define MAX_STACK_FILES (MAX_STACK_ALLOC / 4) #define MAX_STACK_DIRS (MAX_STACK_ALLOC / 16) +/* Begin NVIDIA_LINEMAP_INLINING_EXTENSIONS */ + /* reduce the MAX_STACK_LINES when using NVIDIA linemap inlining extensions, which + increase the size of the line structure by two unsigned int */ +#undef MAX_STACK_LINES +#define MAX_STACK_LINES (MAX_STACK_ALLOC / 2) +/* End NVIDIA_LINEMAP_INLINING_EXTENSIONS */ + /* Initial statement program state (except for stmt_list, see below). */ struct line_state state = { @@ -180,7 +195,11 @@ read_srclines (Dwarf *dbg, .prologue_end = false, .epilogue_begin = false, .isa = 0, - .discriminator = 0 + .discriminator = 0, +/* Begin NVIDIA_LINEMAP_INLINING_EXTENSIONS */ + .context = 0, + .function_name = 0 +/* End NVIDIA_LINEMAP_INLINING_EXTENSIONS */ }; /* The dirs normally go on the stack, but if there are too many @@ -648,6 +667,14 @@ read_srclines (Dwarf *dbg, } } +/* Begin NVIDIA_LINEMAP_INLINING_EXTENSIONS */ + unsigned int debug_str_offset __attribute__((unused)) = 0; + if (unlikely (linep < header_start + header_length)) { + /* CUBINs contain an unsigned 4-byte offset */ + debug_str_offset = read_4ubyte_unaligned_inc (dbg, linep); + } +/* End NVIDIA_LINEMAP_INLINING_EXTENSIONS */ + /* Consistency check. */ if (unlikely (linep != header_start + header_length)) { @@ -753,6 +780,10 @@ read_srclines (Dwarf *dbg, state.epilogue_begin = false; state.isa = 0; state.discriminator = 0; +/* Begin NVIDIA_LINEMAP_INLINING_EXTENSIONS */ + state.context = 0; + state.function_name = 0; +/* End NVIDIA_LINEMAP_INLINING_EXTENSIONS */ break; case DW_LNE_set_address: @@ -831,6 +862,25 @@ read_srclines (Dwarf *dbg, get_uleb128 (state.discriminator, linep, lineendp); break; +/* Begin NVIDIA_LINEMAP_INLINING_EXTENSIONS */ + case DW_LNE_inlined_call: + if (unlikely (linep >= lineendp)) + goto invalid_data; + get_uleb128 (state.context, linep, lineendp); + if (unlikely (linep >= lineendp)) + goto invalid_data; + get_uleb128 (state.function_name, linep, lineendp); + state.function_name += debug_str_offset; + break; + + case DW_LNE_set_function_name: + if (unlikely (linep >= lineendp)) + goto invalid_data; + get_uleb128 (state.function_name, linep, lineendp); + state.function_name += debug_str_offset; + break; +/* End NVIDIA_LINEMAP_INLINING_EXTENSIONS */ + default: /* Unknown, ignore it. */ if (unlikely ((size_t) (lineendp - (linep - 1)) < len)) diff --git a/libdw/dwarf_linecontext.c b/libdw/dwarf_linecontext.c new file mode 100644 index 00000000..f1c78dfd --- /dev/null +++ b/libdw/dwarf_linecontext.c @@ -0,0 +1,47 @@ +/* Return context in line. + This file is part of elfutils. + Written by John Mellor-Crummey , 2021. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + 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 copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "libdwP.h" + + +/* Begin NVIDIA_LINEMAP_INLINING_EXTENSIONS */ +int +dwarf_linecontext (Dwarf_Line *line, unsigned int *contextp) +{ + if (line == NULL) + return -1; + + *contextp = line->context; + + return 0; +} +/* End NVIDIA_LINEMAP_INLINING_EXTENSIONS */ diff --git a/libdw/dwarf_linefunctionname.c b/libdw/dwarf_linefunctionname.c new file mode 100644 index 00000000..a7027135 --- /dev/null +++ b/libdw/dwarf_linefunctionname.c @@ -0,0 +1,47 @@ +/* Return function name in line. + This file is part of elfutils. + Written by John Mellor-Crummey , 2021. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + 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 copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "libdwP.h" + + +/* Begin NVIDIA_LINEMAP_INLINING_EXTENSIONS */ +int +dwarf_linefunctionname (Dwarf_Line *line, unsigned int *functionnamep) +{ + if (line == NULL) + return -1; + + *functionnamep = line->function_name; + + return 0; +} +/* End NVIDIA_LINEMAP_INLINING_EXTENSIONS */ diff --git a/libdw/libdw.h b/libdw/libdw.h index 77174d28..730f9338 100644 --- a/libdw/libdw.h +++ b/libdw/libdw.h @@ -701,6 +701,18 @@ extern int dwarf_linediscriminator (Dwarf_Line *line, unsigned int *discp) extern const char *dwarf_linesrc (Dwarf_Line *line, Dwarf_Word *mtime, Dwarf_Word *length); +/* Begin NVIDIA_LINEMAP_INLINING_EXTENSIONS */ +/* NVIDIA extension: Return inline context in this record. A non-zero context + value represents an inline context */ +extern int dwarf_linecontext (Dwarf_Line *line, unsigned int *contextp); + +/* NVIDIA extension: Return function name in this record. When context is + non-zero, the value of function name is an offset into the .debug_str section, + which contains a character string that specifies the name of an inlined + function. */ +extern int dwarf_linefunctionname (Dwarf_Line *line, unsigned int *functionnamep); +/* End NVIDIA_LINEMAP_INLINING_EXTENSIONS */ + /* Return file information. The returned string is NULL when an error occurred, or the file path. The file path is either absolute or relative to the compilation directory. See dwarf_decl_file. */ diff --git a/libdw/libdw.map b/libdw/libdw.map index 8ab0a2a0..2505cd46 100644 --- a/libdw/libdw.map +++ b/libdw/libdw.map @@ -67,8 +67,10 @@ ELFUTILS_0.122 { dwarf_linebeginstatement; dwarf_lineblock; dwarf_linecol; + dwarf_linecontext; dwarf_lineendsequence; dwarf_lineepiloguebegin; + dwarf_linefunctionname; dwarf_lineno; dwarf_lineprologueend; dwarf_linesrc; diff --git a/libdw/libdwP.h b/libdw/libdwP.h index 7174ea93..d8fa7e7e 100644 --- a/libdw/libdwP.h +++ b/libdw/libdwP.h @@ -291,6 +291,10 @@ struct Dwarf_Line_s unsigned int op_index:8; unsigned int isa:8; unsigned int discriminator:24; +/* Begin NVIDIA_LINEMAP_INLINING_EXTENSIONS */ + unsigned int context; + unsigned int function_name; +/* End NVIDIA_LINEMAP_INLINING_EXTENSIONS */ }; struct Dwarf_Lines_s diff --git a/src/readelf.c b/src/readelf.c index 8191bde2..050f2592 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -8481,6 +8481,9 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, goto invalid_data; header_length = read_8ubyte_unaligned_inc (dbg, linep); } +/* Begin NVIDIA_LINEMAP_INLINING_EXTENSIONS */ + const unsigned char *header_start = linep; +/* End NVIDIA_LINEMAP_INLINING_EXTENSIONS */ /* Next the minimum instruction length. */ if ((size_t) (lineendp - linep) < 1) @@ -8765,6 +8768,14 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, ++linep; } +/* Begin NVIDIA_LINEMAP_INLINING_EXTENSIONS */ + unsigned int debug_str_offset __attribute__((unused)) = 0; + if (unlikely (linep < header_start + header_length)) { + /* CUBINs contain an unsigned 4-byte offset */ + debug_str_offset = read_4ubyte_unaligned_inc (dbg, linep); + } +/* End NVIDIA_LINEMAP_INLINING_EXTENSIONS */ + if (linep == lineendp) { puts (_("\nNo line number statements.")); @@ -8913,6 +8924,41 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, printf (_(" set discriminator to %u\n"), u128); break; +/* Begin NVIDIA_LINEMAP_INLINING_EXTENSIONS */ + case DW_LNE_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; + + printf (_(" inlined context %u, function name 0x%x \n"), + context, function_name); + break; + } + + case DW_LNE_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; + + printf (_(" set function name %u\n"), function_name); + } + break; +/* End NVIDIA_LINEMAP_INLINING_EXTENSIONS */ + default: /* Unknown, ignore it. */ puts (_(" unknown opcode")); diff --git a/tests/Makefile.am b/tests/Makefile.am index c586422e..263d6bc5 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -61,6 +61,7 @@ check_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \ dwelf_elf_e_machine_string \ getphdrnum leb128 read_unaligned \ msg_tst system-elf-libelf-test \ + nvidia_extended_linemap_libdw \ $(asm_TESTS) asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \ @@ -189,6 +190,7 @@ TESTS = run-arextract.sh run-arsymtest.sh run-ar.sh newfile test-nlist \ leb128 read_unaligned \ msg_tst system-elf-libelf-test \ $(asm_TESTS) run-disasm-bpf.sh run-low_high_pc-dw-form-indirect.sh \ + run-nvidia-extended-linemap-libdw.sh run-nvidia-extended-linemap-readelf.sh \ run-readelf-dw-form-indirect.sh run-strip-largealign.sh if !BIARCH @@ -725,6 +727,7 @@ dwelf_elf_e_machine_string_LDADD = $(libelf) $(libdw) getphdrnum_LDADD = $(libelf) $(libdw) leb128_LDADD = $(libelf) $(libdw) read_unaligned_LDADD = $(libelf) $(libdw) +nvidia_extended_linemap_libdw_LDADD = $(libelf) $(libdw) # We want to test the libelf header against the system elf.h header. # Don't include any -I CPPFLAGS. Except when we install our own elf.h. diff --git a/tests/nvidia_extended_linemap_libdw.c b/tests/nvidia_extended_linemap_libdw.c new file mode 100644 index 00000000..9f1e5efd --- /dev/null +++ b/tests/nvidia_extended_linemap_libdw.c @@ -0,0 +1,153 @@ +/* Inspect nvidia extended linemap with dwarf_next_lines. + Copyright (C) 2002, 2004, 2018 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 . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include ELFUTILS_HEADER(dw) +#include +#include +#include + + +int +main (int argc, char *argv[]) +{ + int result = 0; + int cnt; + + for (cnt = 1; cnt < argc; ++cnt) + { + int fd = open (argv[cnt], O_RDONLY); + + Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ); + if (dbg == NULL) + { + printf ("%s not usable: %s\n", argv[cnt], dwarf_errmsg (-1)); + close (fd); + continue; + } + + Dwarf_Off off; + Dwarf_Off next_off = 0; + Dwarf_CU *cu = NULL; + Dwarf_Lines *lb; + size_t nlb; + int res; + while ((res = dwarf_next_lines (dbg, off = next_off, &next_off, &cu, + NULL, NULL, &lb, &nlb)) == 0) + { + printf ("off = %" PRIu64 "\n", off); + printf (" %zu lines\n", nlb); + + for (size_t i = 0; i < nlb; ++i) + { + Dwarf_Line *l = dwarf_onesrcline (lb, i); + if (l == NULL) + { + printf ("%s: cannot get individual line\n", argv[cnt]); + result = 1; + break; + } + + Dwarf_Addr addr; + if (dwarf_lineaddr (l, &addr) != 0) + addr = 0; + const char *file = dwarf_linesrc (l, NULL, NULL); + int line; + if (dwarf_lineno (l, &line) != 0) + line = 0; + + printf ("%" PRIx64 ": %s:%d:", (uint64_t) addr, + file ?: "???", line); + + /* Getting the file path through the Dwarf_Files should + result in the same path. */ + Dwarf_Files *files; + size_t idx; + if (dwarf_line_file (l, &files, &idx) != 0) + { + printf ("%s: cannot get file from line (%zd): %s\n", + argv[cnt], i, dwarf_errmsg (-1)); + result = 1; + break; + } + const char *path = dwarf_filesrc (files, idx, NULL, NULL); + if ((path == NULL && file != NULL) + || (path != NULL && file == NULL) + || (strcmp (file, path) != 0)) + { + printf ("%s: line %zd srcline (%s) != file srcline (%s)\n", + argv[cnt], i, file ?: "???", path ?: "???"); + result = 1; + break; + } + + int column; + if (dwarf_linecol (l, &column) != 0) + column = 0; + if (column >= 0) + printf ("%d:", column); + + unsigned int context; + if (dwarf_linecontext (l, &context) != 0) + context = 0; + unsigned int functionname; + if (dwarf_linefunctionname (l, &functionname) != 0) + functionname = 0; + if (context > 0) { + printf (" context:%u, functionname:%u,", context, functionname); + } + + bool is_stmt; + if (dwarf_linebeginstatement (l, &is_stmt) != 0) + is_stmt = false; + bool end_sequence; + if (dwarf_lineendsequence (l, &end_sequence) != 0) + end_sequence = false; + bool basic_block; + if (dwarf_lineblock (l, &basic_block) != 0) + basic_block = false; + bool prologue_end; + if (dwarf_lineprologueend (l, &prologue_end) != 0) + prologue_end = false; + bool epilogue_begin; + if (dwarf_lineepiloguebegin (l, &epilogue_begin) != 0) + epilogue_begin = false; + printf (" is_stmt:%s, end_seq:%s, bb:%s, prologue:%s, epilogue:%s\n", + is_stmt ? "yes" : "no", end_sequence ? "yes" : "no", + basic_block ? "yes" : "no", prologue_end ? "yes" : "no", + epilogue_begin ? "yes" : "no"); + } + } + + if (res < 0) + { + printf ("dwarf_next_lines failed: %s\n", dwarf_errmsg (-1)); + result = 1; + } + + dwarf_end (dbg); + close (fd); + } + + return result; +} diff --git a/tests/run-nvidia-extended-linemap-libdw.sh b/tests/run-nvidia-extended-linemap-libdw.sh new file mode 100755 index 00000000..b0386b49 --- /dev/null +++ b/tests/run-nvidia-extended-linemap-libdw.sh @@ -0,0 +1,41 @@ +# Copyright (C) 2011 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 + +testfiles testfile_nvidia_linemap +testrun_compare ${abs_top_builddir}/tests/nvidia_extended_linemap_libdw testfile_nvidia_linemap << EOF +off = 0 + 18 lines +0: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:25:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no +10: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:26:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no +40: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:27:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no +90: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:25:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no +a0: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:28:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no +100: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:28:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no +100: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:8:0: context:6, functionname:0, is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no +150: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:9:0: context:6, functionname:0, is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no +1e0: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:31:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no +1e0: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/bar.h:6:0: context:9, functionname:4, is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no +1e0: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:8:0: context:10, functionname:0, is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no +220: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:9:0: context:10, functionname:0, is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no +2b0: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/bar.h:7:0: context:9, functionname:4, is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no +2f0: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/bar.h:8:0: context:9, functionname:4, is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no +2f0: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:18:0: context:14, functionname:8, is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no +330: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:19:0: context:14, functionname:8, is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no +3c0: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:33:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no +480: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:33:0: is_stmt:yes, end_seq:yes, bb:no, prologue:no, epilogue:no +EOF diff --git a/tests/run-nvidia-extended-linemap-readelf.sh b/tests/run-nvidia-extended-linemap-readelf.sh new file mode 100755 index 00000000..6ad96027 --- /dev/null +++ b/tests/run-nvidia-extended-linemap-readelf.sh @@ -0,0 +1,114 @@ +# Copyright (C) 2011 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 + +testfiles testfile_nvidia_linemap +testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=line testfile_nvidia_linemap << EOF + +DWARF section [ 5] '.debug_line' at offset 0x3e0: + +Table at offset 0: + + Length: 253 + DWARF version: 2 + Prologue length: 111 + Address size: 8 + Segment selector size: 0 + Min instruction length: 1 + Max operations per instruction: 1 + Initial value if 'is_stmt': 1 + Line base: -5 + Line range: 14 + Opcode base: 10 + +Opcodes: + [1] 0 arguments + [2] 1 argument + [3] 1 argument + [4] 1 argument + [5] 1 argument + [6] 0 arguments + [7] 0 arguments + [8] 0 arguments + [9] 1 argument + +Directory table: + /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4 + +File name table: + Entry Dir Time Size Name + 1 1 1626104146 1819 main.cu + 2 1 1626104111 211 bar.h + +Line number statements: + [ 79] extended opcode 2: set address to 0 + [ 84] set file to 1 + [ 86] advance line by constant 24 to 25 + [ 88] copy + [ 89] special opcode 240: address+16 = 0x10 , line+1 = 26 + [ 8a] advance line by constant 1 to 27 + [ 8c] advance address by 48 to 0x40 + [ 8e] copy + [ 8f] advance line by constant -2 to 25 + [ 91] advance address by 80 to 0x90 + [ 94] copy + [ 95] special opcode 242: address+16 = 0xa0 , line+3 = 28 + [ 96] advance address by 96 to 0x100 + [ 99] copy + [ 9a] extended opcode 144: inlined context 6, function name 0x0 + [ 9f] advance line by constant -20 to 8 + [ a1] copy + [ a2] advance line by constant 1 to 9 + [ a4] advance address by 80 to 0x150 + [ a7] copy + [ a8] extended opcode 144: inlined context 0, function name 0x0 + [ ad] advance line by constant 22 to 31 + [ af] advance address by 144 to 0x1e0 + [ b2] copy + [ b3] set file to 2 + [ b5] extended opcode 144: inlined context 9, function name 0x4 + [ ba] advance line by constant -25 to 6 + [ bc] copy + [ bd] set file to 1 + [ bf] extended opcode 144: inlined context 10, function name 0x0 + [ c4] advance line by constant 2 to 8 + [ c6] copy + [ c7] advance line by constant 1 to 9 + [ c9] advance address by 64 to 0x220 + [ cc] copy + [ cd] set file to 2 + [ cf] extended opcode 144: inlined context 9, function name 0x4 + [ d4] advance line by constant -2 to 7 + [ d6] advance address by 144 to 0x2b0 + [ d9] copy + [ da] advance line by constant 1 to 8 + [ dc] advance address by 64 to 0x2f0 + [ df] copy + [ e0] set file to 1 + [ e2] extended opcode 144: inlined context 14, function name 0x8 + [ e7] advance line by constant 10 to 18 + [ e9] copy + [ ea] advance line by constant 1 to 19 + [ ec] advance address by 64 to 0x330 + [ ef] copy + [ f0] extended opcode 144: inlined context 0, function name 0x0 + [ f5] advance line by constant 14 to 33 + [ f7] advance address by 144 to 0x3c0 + [ fa] copy + [ fb] advance address by 192 to 0x480 + [ fe] extended opcode 1: end of sequence +EOF diff --git a/tests/testfile_nvidia_linemap.bz2 b/tests/testfile_nvidia_linemap.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..8a6d09fbd1419af2b4664e8751207be470198f1a