This was reported as gcc bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101575 but can also be seen as a gas bug, which means, that the test-case defs.adb/defs.ads from a gdb testcase https://sourceware.org/git/?p=binutils-gdb.git;a=tree;f=gdb/testsuite/gdb.ada/formatted_ref (when compiled with -gdwarf-4) has some mixed entries in the line table, that is the source file from the .file <n> directive, but line numbers from the assembler file. That is due to gas/dwarf2dbg.c if (num_of_auto_assigned) { /* Clear slots auto-assigned before the first .file <NUMBER> directive was seen. */ if (files_in_use != (num_of_auto_assigned + 1)) abort (); for (i = 1; i < files_in_use; i++) files[i].filename = NULL; files_in_use = 0; num_of_auto_assigned = 0; } so the previous file(s) are replaced with new files, but the previous line data remain, and reference an unrelated new file from the .file directive.
Note it is also undesirable to reference the (possibly temporary) filename of the assembler file as a "fix", even though that would seem to be the fix if the compiler asked the assembler to produce line info. It's the behavior you get when assembling without any .file directive.
More generally, you can ask gas to assemble multiple .s files to produce a single object. How are conflicting file numbers supposed to be handled then?
another test case I just discovered: $ cat test1.c asm("nop"); int main () { return 0; } $ gcc -g test1.c $ readelf --debug-dump=decodedline a.out Contents of the .debug_line section: CU: ./test1.c: File name Line number Starting address View Stmt test1.c 5 0x401106 x test1.c 3 0x401107 x test1.c 4 0x40110b x test1.c 5 0x401110 x test1.c - 0x401112 The first line 5 is the line number of the nop from the .s file.
I can reproduce the comment #3 behaviour only when using -Wa,-gdwarf or similar gas options when using gcc-10. gcc-11 and gcc-12 pass -gdwarf-5 to gas. That seems to be the source of these problems, which is that -gdwarf* passed to gas means not only to select the DWARF level but also have gas generate its own DWARF line info. So why is gcc passing -gdwarf-5 to gas? That seems quite silly! Can't gas figure the dwarf level out itself? Note that current gas decides on dwarf5 if seeing a .file or .loc specifying file 0.
(In reply to Alan Modra from comment #4) > I can reproduce the comment #3 behaviour only when using -Wa,-gdwarf or > similar gas options when using gcc-10. gcc-11 and gcc-12 pass -gdwarf-5 to > gas. That seems to be the source of these problems, which is that -gdwarf* > passed to gas means not only to select the DWARF level but also have gas > generate its own DWARF line info. > > So why is gcc passing -gdwarf-5 to gas? That seems quite silly! Can't gas > figure the dwarf level out itself? Note that current gas decides on dwarf5 > if seeing a .file or .loc specifying file 0. https://gcc.gnu.org/pipermail/gcc-patches/2020-September/553527.html had the discussion for the -gdwarf-5 behavior. gas' detection of DWARF v5 .debug_line was added later: https://sourceware.org/pipermail/binutils/2021-January/115000.html If DWARF v6 or a future version ever bumps the line table version again (after v2->v5), perhaps having a directive is fine. LLVM folks do not object to a directive (https://reviews.llvm.org/D94882). I agree that passing -gdwarf-* to gas is probably not very useful.
Note: latest gcc master has meanwhile a work around for this: The work around for this issue is to emit a dummy .file directive before the first function is compiled, unless another .file directive was already emitted previously. https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=96c82a16b2076891a9974d0f0e96a0b85fbc2df4
The master branch has been updated by Alan Modra <amodra@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=51298b330327a568358da069d9808f51c6cb1672 commit 51298b330327a568358da069d9808f51c6cb1672 Author: Alan Modra <amodra@gmail.com> Date: Fri Sep 17 09:08:15 2021 +0930 PR28149, debug info with wrong file association gcc-11 and gcc-12 pass -gdwarf-5 to gas, in order to prime gas for DWARF 5 level debug info. Unfortunately it seems there are cases where the compiler does not emit a .file or .loc dwarf debug directive before any machine instructions. (Note that the .file directive typically emitted as the first line of assembly output doesn't count as a dwarf debug directive. The dwarf .file has a file number before the file name string.) This patch delays allocation of file numbers for gas generated line debug info until the end of assembly, thus avoiding any clashes with compiler generated file numbers. Two fixes for test case source are necessary; A .loc can't use a file number that hasn't already been specified with .file. A followup patch will remove all the gas generated line info on seeing a .file directive. PR 28149 * dwarf2dbg.c (num_of_auto_assigned): Delete. (current): Update initialisation. (set_or_check_view): Replace all accesses to view with u.view. (dwarf2_consume_line_info): Likewise. (dwarf2_directive_loc): Likewise. Assert that we aren't generating line info. (dwarf2_gen_line_info_1): Don't call set_or_check_view on gas generated line entries. (dwarf2_gen_line_info): Set and track filenames for gas generated line entries. Simplify generation of labels. (get_directory_table_entry): Use filename_cmp when comparing dirs. (do_allocate_filenum): New function. (dwarf2_where): Set u.filename and filenum to -1 for gas generated line entries. (dwarf2_directive_filename): Remove num_of_auto_assigned handling. (process_entries): Update view field access. Call do_allocate_filenum. * dwarf2dbg.h (struct dwarf2_line_info): Add filename field in union aliasing view. * testsuite/gas/i386/dwarf2-line-3.s: Add .file directive. * testsuite/gas/i386/dwarf2-line-4.s: Likewise. * testsuite/gas/i386/dwarf2-line-4.d: Update expected output. * testsuite/gas/i386/dwarf4-line-1.d: Likewise. * testsuite/gas/i386/dwarf5-line-1.d: Likewise. * testsuite/gas/i386/dwarf5-line-2.d: Likewise.
The master branch has been updated by Alan Modra <amodra@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=ef9768e37e34bec50aa8cbb0ce25708b06f09255 commit ef9768e37e34bec50aa8cbb0ce25708b06f09255 Author: Alan Modra <amodra@gmail.com> Date: Fri Sep 17 09:21:21 2021 +0930 PR28149 part 2, purge generated line info Mixing compiler generated line info with gas generated line info is generally just confusing. Also .loc directives with non-zero view fields might reference a previous .loc. It becomes a little more tricky to locate that previous .loc if there might be gas generated line info present too. Mind you, we turn off gas generation of line info on seeing compiler generated line info, so any reference back won't hit gas generated line info. At least, if the view info is sane. Unfortunately, gas needs to handle mangled source. PR 28149 * dwarf2dbg.c (purge_generated_debug): New function. (dwarf2_directive_filename): Call the above. (out_debug_line): Don't segfault after purging. * testsuite/gas/i386/dwarf2-line-4.d: Update expected output. * testsuite/gas/i386/dwarf4-line-1.d: Likewise. * testsuite/gas/i386/dwarf5-line-1.d: Likewise. * testsuite/gas/i386/dwarf5-line-2.d: Likewise.
Fixed in binutils and gcc.
The master branch has been updated by Alan Modra <amodra@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=5b4846283c3d49138a58a3bb4d61ed3e2dfffff4 commit 5b4846283c3d49138a58a3bb4d61ed3e2dfffff4 Author: Alan Modra <amodra@gmail.com> Date: Mon Sep 20 11:30:41 2021 +0930 Re: PR28149, debug info with wrong file association Fixes segfaults when building aarch64-linux kernel, due to only doing part of the work necessary when allocating file numbers late. I'd missed looping over subsegments, which resulted in some u.filename entries left around and later interpreted as u.view. PR 28149 * dwarf2dbg.c (purge_generated_debug): Iterate over subsegs too. (dwarf2_finish): Call do_allocate_filenum for all subsegs too, in a separate loop before subsegs are chained.