[PATCH] D74781: Wasm-ld emits invalid .debug_ranges entries for non-live symbols
David Blaikie via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Thu Mar 26 13:02:47 PDT 2020
dblaikie added a comment.
In D74781#1940564 <https://reviews.llvm.org/D74781#1940564>, @paolosev wrote:
> In D74781#1939787 <https://reviews.llvm.org/D74781#1939787>, @dblaikie wrote:
>
> > In D74781#1938336 <https://reviews.llvm.org/D74781#1938336>, @paolosev wrote:
> >
> > > @sbc100 Adding a test.
> > >
> > > @dblaikie Strangely, I can't find a way to generate a **.debug_loc** section for Wasm.
> >
> >
> > Maybe it's not applicable to wasm, I don't know much about it - but if it optimizes variables into registers (or out of them), then it shuold be producible.
> >
> > Here's a simple test case I use for debug_loc in C++ on a silicon target:
> >
> > void f1();
> > int main() {
> > int i = 3;
> > f1();
> > i = 7;
> > f1();
> > }
> >
> >
> > Compiled with optimizations enabled, the storage for 'i' will be eliminated and a DWARF location list will be used to describe 'i' as having the value 3 over the first call instruction, and the value 7 over the second call instruction.
>
>
> Yes, I managed to get a .debug_loc section also for Wasm with similar code, and debug_loc does not seem to present the same problems with GC'd functions.
Even without your patch? If without your patch you were getting range list entries of zero/zero, I'd expect you to get debug_loc entries with zero/zero too. Any ideas why it doesn't? They should be a similar pair of relocations (though it looks like your fix should work for debug_loc too, which is good).
> 1 void f1(int& n) { n++; }
> 2
> 3 int f2(int& n) {
> 4 int i = 42;
> 5 f1(i);
> 6 i = 21;
> 7 f1(i);
> 8 return i;
> 9 }
> 10
> 11 extern "C" {
> 12 int _start() {
> 13 int i = 3;
> 14 f1(i);
> 15 i = 7;
> 16 f1(i);
> 17 return i;
> 18 }
> 19 }
>
>
> compiled with: `clang++ main.cc -o main.wasm --target=wasm32 -nostdlib -gfull -O1`, produce a module with this DWARF data:
>
> .debug_info contents:
> [...]
> 0x0000000b: DW_TAG_compile_unit
> DW_AT_producer ("clang version 11.0.0 (https://github.com/llvm/llvm-project.git f6cf848a2ccc6f63ebce27a52857c291a7ec4eec)")
> DW_AT_language (DW_LANG_C_plus_plus_14)
> DW_AT_name ("main.cc")
> DW_AT_stmt_list (0x00000000)
> DW_AT_comp_dir ("C:\\dev\\llvm-project\\release_x64\\T")
> DW_AT_low_pc (0x0000000000000000)
> DW_AT_ranges (0x00000000
> [0x00000002, 0x00000011)
> [0x00000000, 0x0000004d)
> [0x00000012, 0x0000005f))
>
> 0x00000026: DW_TAG_subprogram
> DW_AT_low_pc (0x0000000000000002)
> DW_AT_high_pc (0x0000000000000011)
> DW_AT_frame_base (DW_OP_WASM_location 0x1 +0, DW_OP_stack_value)
> DW_AT_GNU_all_call_sites (true)
> DW_AT_linkage_name ("_Z2f1Ri")
> DW_AT_name ("f1")
> DW_AT_decl_file ("C:\dev\llvm-project\release_x64\T\main.cc")
> DW_AT_decl_line (1)
> DW_AT_external (true)
> [...]
>
> 0x0000004a: DW_TAG_subprogram
> DW_AT_low_pc (0x0000000000000000)
> DW_AT_high_pc (0x000000000000004d)
> DW_AT_frame_base (DW_OP_WASM_location 0x0 +1, DW_OP_stack_value)
> DW_AT_GNU_all_call_sites (true)
> DW_AT_linkage_name ("_Z2f2Ri")
> DW_AT_name ("f2")
> DW_AT_decl_file ("C:\dev\llvm-project\release_x64\T\main.cc")
> DW_AT_decl_line (3)
> DW_AT_type (0x000000cd "int")
> DW_AT_external (true)
> [...]
>
> 0x00000071: DW_TAG_variable
> DW_AT_location (0x00000000:
> [0x00000014, 0x0000001b): DW_OP_consts +42, DW_OP_stack_value
> [0x00000026, 0x0000002d): DW_OP_consts +21, DW_OP_stack_value
> [0x0000003f, 0x0000004d): DW_OP_WASM_location 0x0 +2, DW_OP_stack_value)
> DW_AT_name ("i")
> DW_AT_decl_file ("C:\dev\llvm-project\release_x64\T\main.cc")
> DW_AT_decl_line (4)
> DW_AT_type (0x000000cd "int")
> [...]
>
> 0x00000093: DW_TAG_subprogram
> DW_AT_low_pc (0x0000000000000012)
> DW_AT_high_pc (0x000000000000005f)
> DW_AT_frame_base (DW_OP_WASM_location 0x0 +0, DW_OP_stack_value)
> DW_AT_GNU_all_call_sites (true)
> DW_AT_name ("_start")
> DW_AT_decl_file ("C:\dev\llvm-project\release_x64\T\main.cc")
> DW_AT_decl_line (12)
> DW_AT_type (0x000000cd "int")
> DW_AT_external (true)
>
> 0x000000ab: DW_TAG_variable
> DW_AT_location (0x00000038:
> [0x00000026, 0x0000002d): DW_OP_consts +3, DW_OP_stack_value
> [0x00000038, 0x0000003f): DW_OP_consts +7, DW_OP_stack_value
> [0x00000051, 0x0000005f): DW_OP_WASM_location 0x0 +1, DW_OP_stack_value)
> DW_AT_name ("i")
> DW_AT_decl_file ("C:\dev\llvm-project\release_x64\T\main.cc")
> DW_AT_decl_line (13)
> DW_AT_type (0x000000cd "int")
> [...]
>
> .debug_loc contents:
> 0x00000000:
> [0x00000014, 0x0000001b): DW_OP_consts +42, DW_OP_stack_value
> [0x00000026, 0x0000002d): DW_OP_consts +21, DW_OP_stack_value
> [0x0000003f, 0x0000004d): DW_OP_WASM_location 0x0 +2, DW_OP_stack_value
>
> 0x00000038:
> [0x00000026, 0x0000002d): DW_OP_consts +3, DW_OP_stack_value
> [0x00000038, 0x0000003f): DW_OP_consts +7, DW_OP_stack_value
> [0x00000051, 0x0000005f): DW_OP_WASM_location 0x0 +1, DW_OP_stack_value
> [...]
>
> .debug_line contents:
> [...]
> Address Line Column File ISA Discriminator Flags
> ------------------ ------ ------ ------ --- ------------- -------------
> 0x0000000000000002 1 0 1 0 0 is_stmt
> 0x0000000000000003 1 20 1 0 0 is_stmt prologue_end
> 0x0000000000000010 1 24 1 0 0
> 0x0000000000000011 1 24 1 0 0 end_sequence
> 0x0000000000000000 3 0 1 0 0 is_stmt
> 0x0000000000000014 4 7 1 0 0 is_stmt prologue_end
> 0x000000000000001b 5 3 1 0 0 is_stmt
> 0x0000000000000026 6 5 1 0 0 is_stmt
> 0x000000000000002d 7 3 1 0 0 is_stmt
> 0x0000000000000038 8 10 1 0 0 is_stmt
> 0x000000000000003f 8 3 1 0 0
> 0x000000000000004d 8 3 1 0 0 end_sequence
> 0x0000000000000012 12 0 1 0 0 is_stmt
> 0x0000000000000026 13 7 1 0 0 is_stmt prologue_end
> 0x000000000000002d 14 3 1 0 0 is_stmt
> 0x0000000000000038 15 5 1 0 0 is_stmt
> 0x000000000000003f 16 3 1 0 0 is_stmt
> 0x000000000000004a 17 10 1 0 0 is_stmt
> 0x0000000000000051 17 3 1 0 0
> 0x000000000000005f 17 3 1 0 0 end_sequence
> [...]
>
> .debug_ranges contents:
> 00000000 00000002 00000011
> 00000000 00000000 0000004d
> 00000000 00000012 0000005f
> 00000000 <End of list>
>
>
> Function `f2` is not used and removed by the linker. Now .debug_ranges is correct: there is a line
> 00000000 00000000 0000004d
> which at least it's not interpreted as a terminator.
>
> However, in the generated DWARF there is also useless/invalid information for f2 also in all the sections, with invalid code offsets.
> I suspect that the presence of this data for removed functions could still break debuggers, which don't expect overlapping ranges.
> It is also an useless waste of space. Would it be difficult to avoid generating DWARF data at all for GC'd functions?
Yes, it's difficult for "Classic" targets like ELF/COFF/etc - the linker isn't DWARF aware (except for a couple of special cases like this relocation application - and in fact binutils ld does a different workaround for debug_ranges (it resolves all of them to 1 for dropped code, so you get a 1/1 entry rather than a 0/0 entry or a 0/N entry (like gold/lld)) & doesn't have a fix for debug_loc, which isn't exactly a problem except for DWARF dumping tools) & it's unclear that DWARF-aware linking is going to be worthwhile - it means linking probably using a lot more memory and processing time to reconstruct a bunch of DWARF (you can't just rip out the DIEs - there are other offsets that would then be invalidated and have to be rewritten, etc).
There is work to add DWARF-aware linking based on Apple dsymutil implementation in LLVM, to lld for ELF DWARF linking - but yeah, unclear it'll be an absolute win in terms of performance - and in terms of correctness, debuggers have been having to live with this "ranges that start at zero are magic/represent dropped code" for a while now & if that was shown to be really unworkable from a correctness standpoint we'd probably want to consider some other magic value, rather than requiring full DWARF rewriting to get correctness.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D74781/new/
https://reviews.llvm.org/D74781
More information about the llvm-commits
mailing list