Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Failed to generate native debug information for optimized C code with debug info about dead functions #3403

Closed
alexcrichton opened this issue Oct 1, 2021 · 1 comment
Labels
wasmtime:debugging Issues related to debugging of JIT'ed code wasmtime Issues about wasmtime that don't fall into another label

Comments

@alexcrichton
Copy link
Member

I've been attempting to debug some C code recently but unfortunately I keep running into an error that indicates "failed to emit DWARF debug information" when passing the -g flag to the wasmtime CLI. The reproduction of this is:

// foo.c
__attribute__((export_name("foo")))
int foo() { return 3; }

int bar(int a) {
  int b[50];
  b[0] = a;
  b[29] = a;
  return a;
}
$  clang -O3 foo.c -o foo.wasm -mexec-model=reactor -g 
$ wasmtime -g ./foo.wasm
Error: failed to run main module `./foo.wasm`

Caused by:
    0: failed to emit DWARF debug information
    1: The end offset of a location list entry must not be before the beginning.

Inspecting the results of llvm-dwarfdump I see:

foo.wasm:       file format WASM

.debug_info contents:
0x00000000: Compile Unit: length = 0x00000093, format = DWARF32, version = 0x0004, abbr_offset = 0x0000, addr_size = 0x04 (next unit at 0x00000097)

0x0000000b: DW_TAG_compile_unit
              DW_AT_producer    ("clang version 12.0.0 (https://github.com/llvm/llvm-project d28af7c654d8db0b68c175db5ce212d74fb5e9bc)")
              DW_AT_language    (DW_LANG_C99)
              DW_AT_name        ("foo.c")
              DW_AT_stmt_list   (0x00000000)
              DW_AT_comp_dir    ("/home/acrichto/code/wasmtime")
              DW_AT_low_pc      (0x00000000)
              DW_AT_ranges      (0x00000000
                 [0x0000000e, 0x00000012))

0x00000026:   DW_TAG_subprogram
                DW_AT_low_pc    (0x0000000e)
                DW_AT_high_pc   (0x00000012)
                DW_AT_frame_base        (DW_OP_WASM_location 0x3 0x0, DW_OP_stack_value)
                DW_AT_GNU_all_call_sites        (true)
                DW_AT_name      ("foo")
                DW_AT_decl_file ("/home/acrichto/code/wasmtime/foo.c")
                DW_AT_decl_line (2)
                DW_AT_type      (0x0000007c "int")
                DW_AT_external  (true)

0x00000041:   DW_TAG_subprogram
                DW_AT_low_pc    (dead code)
                DW_AT_high_pc   (0x00000004)
                DW_AT_frame_base        (DW_OP_WASM_location 0x3 0x0, DW_OP_stack_value)
                DW_AT_GNU_all_call_sites        (true)
                DW_AT_name      ("bar")
                DW_AT_decl_file ("/home/acrichto/code/wasmtime/foo.c")
                DW_AT_decl_line (4)
                DW_AT_prototyped        (true)
                DW_AT_type      (0x0000007c "int")
                DW_AT_external  (true)

0x0000005c:     DW_TAG_formal_parameter
                  DW_AT_location        (DW_OP_WASM_location 0x0 0x0, DW_OP_stack_value)
                  DW_AT_name    ("a")
                  DW_AT_decl_file       ("/home/acrichto/code/wasmtime/foo.c")
                  DW_AT_decl_line       (4)
                  DW_AT_type    (0x0000007c "int")

0x0000006c:     DW_TAG_variable
                  DW_AT_location        (0x00000000:
                     [0xfffffffe, 0x100000002): DW_OP_WASM_location 0x0 0x0, DW_OP_stack_value, DW_OP_piece 0x4, DW_OP_piece 0x70, DW_OP_WASM_location 0x0 0x0, DW_OP_stack_value, DW_OP_piece 0x4)
                  DW_AT_name    ("b")
                  DW_AT_decl_file       ("/home/acrichto/code/wasmtime/foo.c")
                  DW_AT_decl_line       (5)
                  DW_AT_type    (0x00000083 "int[50]")

0x0000007b:     NULL

0x0000007c:   DW_TAG_base_type
                DW_AT_name      ("int")
                DW_AT_encoding  (DW_ATE_signed)
                DW_AT_byte_size (0x04)

0x00000083:   DW_TAG_array_type
                DW_AT_type      (0x0000007c "int")

0x00000088:     DW_TAG_subrange_type
                  DW_AT_type    (0x0000008f "__ARRAY_SIZE_TYPE__")
                  DW_AT_count   (0x32)

0x0000008e:     NULL

0x0000008f:   DW_TAG_base_type
                DW_AT_name      ("__ARRAY_SIZE_TYPE__")
                DW_AT_byte_size (0x08)
                DW_AT_encoding  (DW_ATE_unsigned)

0x00000096:   NULL

With some digging the issue appears to be this:

0x0000006c:     DW_TAG_variable
                  DW_AT_location        (0x00000000:
                     [0xfffffffe, 0x100000002): DW_OP_WASM_location 0x0 0x0, DW_OP_stack_value, DW_OP_piece 0x4, DW_OP_piece 0x70, DW_OP_WASM_location 0x0 0x0, DW_OP_stack_value, DW_OP_piece 0x4)

where gimli is doing addition in the 32-bit address space for ranges which means that from gimli's perspective the start address of this variable is 0xfffffffe and the end address is 0x2, hence the error from gimli itself.

This appears to come about with DWARF debug information for dead code in a program. It appears that LLD specifically uses the value of -2 for representing relocations against dead functions that don't actually show up in the output. The DW_AT_location attribute here I believe is encoded as a offset/length which means that the offset receives the relocation of -2 and when gimli adds the length it gets the error that the range is messed up.

I believe the real fix here is to basically avoid generating native DWARF debugging information for dead code, or code that comes at the address of -1. llvm-dwarfdump already itself prints:

0x00000041:   DW_TAG_subprogram
                DW_AT_low_pc    (dead code)

and for something like that we should probably just skip over that and not copy over any other attributes related to this subprogram (function). I unfortunately don't know the dwarf code well enough in Wasmtime to know of a great place to put this.

@alexcrichton alexcrichton added wasmtime Issues about wasmtime that don't fall into another label wasmtime:debugging Issues related to debugging of JIT'ed code labels Oct 1, 2021
@alexcrichton alexcrichton changed the title "failed to emit DWARF debug information" for seemingly semi-valid DWARF info Failed to generate native debug information for optimized C code with debug info about dead functions Oct 1, 2021
@alexcrichton
Copy link
Member Author

Fixed in #3498

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
wasmtime:debugging Issues related to debugging of JIT'ed code wasmtime Issues about wasmtime that don't fall into another label
Projects
None yet
Development

No branches or pull requests

1 participant