[Issue 20460] [OSX] DMD writes the same address everywhere in DWARF debug infos
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Tue Jan 19 18:59:45 UTC 2021
https://issues.dlang.org/show_bug.cgi?id=20460
Mathias LANG <pro.mathias.lang at gmail.com> changed:
What |Removed |Added
----------------------------------------------------------------------------
Keywords|pull |backend, industry
Summary|[OSX] Stack traces |[OSX] DMD writes the same
|involving extern(C++) can |address everywhere in DWARF
|show wrong file / line |debug infos
--- Comment #4 from Mathias LANG <pro.mathias.lang at gmail.com> ---
Did some more investigation on this. Turns out the issue is that DMD writes
complete nonsense in the debug infos!
Take the following example, in C:
```C
#include <stdio.h>
void callB ()
{
printf("Hello World\n");
}
int main (void)
{
callB();
return 0;
}
```
Compiled with `gcc -g -c ca.c`.
Using `dwarfdump` on it gives a pretty standard output:
```
ca.o: file format Mach-O 64-bit x86-64
.debug_info contents:
0x00000000: Compile Unit: length = 0x00000064 version = 0x0004 abbr_offset =
0x0000 addr_size = 0x08 (next unit at 0x00000068)
0x0000000b: DW_TAG_compile_unit
DW_AT_producer ("Apple clang version 12.0.0
(clang-1200.0.32.28)")
DW_AT_language (DW_LANG_C99)
DW_AT_name ("ca.c")
DW_AT_LLVM_sysroot
("/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk")
DW_AT_APPLE_sdk ("MacOSX.sdk")
DW_AT_stmt_list (0x00000000)
DW_AT_comp_dir ("/Users/geod24/projects/dlang/druntime")
DW_AT_low_pc (0x0000000000000000)
DW_AT_high_pc (0x000000000000003c)
0x00000032: DW_TAG_subprogram
DW_AT_low_pc (0x0000000000000000)
DW_AT_high_pc (0x0000000000000014)
DW_AT_frame_base (DW_OP_reg6 RBP)
DW_AT_name ("callB")
DW_AT_decl_file ("/Users/geod24/projects/dlang/druntime/ca.c")
DW_AT_decl_line (3)
DW_AT_external (true)
0x00000047: DW_TAG_subprogram
DW_AT_low_pc (0x0000000000000020)
DW_AT_high_pc (0x000000000000003c)
DW_AT_frame_base (DW_OP_reg6 RBP)
DW_AT_name ("main")
DW_AT_decl_file ("/Users/geod24/projects/dlang/druntime/ca.c")
DW_AT_decl_line (8)
DW_AT_prototyped (true)
DW_AT_type (0x00000060 "int")
DW_AT_external (true)
0x00000060: DW_TAG_base_type
DW_AT_name ("int")
DW_AT_encoding (DW_ATE_signed)
DW_AT_byte_size (0x04)
0x00000067: NULL
```
We can see that the DW_TAG_compile_unit contain a DW_AT_low_pc which is the
DW_AT_low_pc of callB, and a DW_AT_high_pc which is that of main. In other
words, the two functions are stored contiguously in the binary.
We can verify this using `nm`:
```
0000000000000000 T _callB
0000000000000020 T _main <== Value is DW_AT_low_pc, as expected
U _printf
```
Now what does DMD produce for equivalent code:
```D
import core.stdc.stdio;
void callB ()
{
printf("Hello World\n");
}
int main ()
{
callB();
return 0;
}
```
Compiled with `dmd -g -c ca.d`, using v2.095.0, and using dwarfdump:
```
ca.o: file format Mach-O 64-bit x86-64
.debug_info contents:
0x00000000: Compile Unit: length = 0x00000135 version = 0x0003 abbr_offset =
0x0000 addr_size = 0x08 (next unit at 0x00000139)
0x0000000b: DW_TAG_compile_unit
DW_AT_producer ("Digital Mars D v2.095.0\n")
DW_AT_language (DW_LANG_D)
DW_AT_name ("ca.d")
DW_AT_comp_dir ("/Users/geod24/projects/dlang/druntime")
DW_AT_low_pc (0x0000000000000000)
DW_AT_entry_pc (0x0000000000000000)
DW_AT_ranges (0x00000000
[0x0000000000000500, 0x0000000000000500))
DW_AT_stmt_list (0x00000000)
0x00000069: DW_TAG_module
DW_AT_name ("ca")
0x0000006d: DW_TAG_subprogram
DW_AT_name ("ca.callB")
DW_AT_MIPS_linkage_name ("_D2ca5callBFZv")
DW_AT_decl_file ("/Users/geod24/projects/dlang/druntime/ca.d")
DW_AT_decl_line (3)
DW_AT_low_pc (0x0000000000000500)
DW_AT_high_pc (0x0000000000000500)
DW_AT_frame_base (0x00000000:
[0x0000000000000500, 0x0000000000000500): DW_OP_breg7 RSP+8
[0x0000000000000500, 0x0000000000000500): DW_OP_breg7 RSP+16
[0x0000000000000500, 0x0000000000000500): DW_OP_breg6
RBP+16)
0x0000009d: DW_TAG_base_type
DW_AT_name ("int")
DW_AT_byte_size (0x04)
DW_AT_encoding (DW_ATE_signed)
0x000000a4: DW_TAG_subprogram
DW_AT_name ("D main")
DW_AT_MIPS_linkage_name ("_Dmain")
DW_AT_decl_file ("/Users/geod24/projects/dlang/druntime/ca.d")
DW_AT_decl_line (8)
DW_AT_type (0x0000009d "int")
DW_AT_external (0x01)
DW_AT_low_pc (0x0000000000000000)
DW_AT_high_pc (0x0000000000000000)
DW_AT_frame_base (0x0000004c: )
0x000000cf: DW_TAG_base_type
DW_AT_name ("char")
DW_AT_byte_size (0x01)
DW_AT_encoding (DW_ATE_unsigned_char)
0x000000d7: DW_TAG_pointer_type
DW_AT_type (0x000000cf "char")
0x000000dc: DW_TAG_pointer_type
DW_AT_type (0x000000d7 "char*")
0x000000e1: DW_TAG_subprogram
DW_AT_sibling (0x00000138)
DW_AT_name ("ca._d_cmain!().main")
DW_AT_MIPS_linkage_name ("main")
DW_AT_decl_file
("/usr/local/opt/dmd/include/dlang/dmd/core/internal/entrypoint.d")
DW_AT_decl_line (27)
DW_AT_type (0x0000009d "int")
DW_AT_external (0x01)
DW_AT_low_pc (0x0000000000000000)
DW_AT_high_pc (0x0000000000000000)
DW_AT_frame_base (0x00000098: )
0x0000011b: DW_TAG_formal_parameter
DW_AT_name ("argc")
DW_AT_type (0x0000009d "int")
DW_AT_artificial (0x00)
DW_AT_location (DW_OP_fbreg -32)
0x00000129: DW_TAG_formal_parameter
DW_AT_name ("argv")
DW_AT_type (0x000000dc "char**")
DW_AT_artificial (0x00)
DW_AT_location (DW_OP_fbreg -24)
0x00000137: NULL
0x00000138: NULL
```
And here we have complete nonsense in terms of address. Either we get 0 - 0, or
0x0000000000000500 - 0x0000000000000500. Neither of those is correct.
Using `nm` on the binary outputs:
```
0000000000000060 s EH_frame0
00000000000000a0 S _D main.eh
0000000000000050 S __D2ca12__ModuleInfoZ
0000000000000500 S __D2ca5callBFZv
0000000000000000 T __Dmain
U __Dmain
U __d_run_main
00000000000000c8 S _ca._d_cmain!().main.eh
0000000000000078 S _ca.callB.eh
U _main
0000000000000010 T _main
U _printf
```
Here we can see that 0x0000000000000500 is the start address of callB, and so
the DW_AT_low_pc for "D main" and "callB" are the only two things correct with
this.
I took a look at the backend, and somehow it seems that all relocations end up
with the same addresses.
For reference, LDC's output here is much saner, and as expected:
```
.debug_info contents:
0x00000000: Compile Unit: length = 0x000000d4 version = 0x0004 abbr_offset =
0x0000 addr_size = 0x08 (next unit at 0x000000d8)
0x0000000b: DW_TAG_compile_unit
DW_AT_producer ("LDC 1.24.0 (LLVM 9.0.1)")
DW_AT_language (DW_LANG_D)
DW_AT_name ("ca.d")
DW_AT_stmt_list (0x00000000)
DW_AT_comp_dir ("/Users/geod24/projects/dlang/druntime")
DW_AT_APPLE_major_runtime_vers (0x01)
DW_AT_low_pc (0x0000000000000000)
DW_AT_high_pc (0x000000000000005b)
0x0000002b: DW_TAG_module
DW_AT_name ("ca")
0x00000030: DW_TAG_imported_module
DW_AT_import (0x000000ad)
0x00000035: DW_TAG_imported_module
DW_AT_decl_file
("/Users/geod24/projects/dlang/druntime/ca.d")
DW_AT_decl_line (1)
DW_AT_import (0x000000b2)
0x0000003c: DW_TAG_subprogram
DW_AT_low_pc (0x0000000000000000)
DW_AT_high_pc (0x0000000000000014)
DW_AT_frame_base (DW_OP_reg6 RBP)
DW_AT_linkage_name ("_D2ca5callBFZv")
DW_AT_name ("callB")
DW_AT_decl_file
("/Users/geod24/projects/dlang/druntime/ca.d")
DW_AT_decl_line (3)
DW_AT_external (true)
0x00000055: DW_TAG_subprogram
DW_AT_low_pc (0x0000000000000020)
DW_AT_high_pc (0x000000000000002d)
DW_AT_frame_base (DW_OP_reg6 RBP)
DW_AT_linkage_name ("_Dmain")
DW_AT_name ("D main")
DW_AT_decl_file
("/Users/geod24/projects/dlang/druntime/ca.d")
DW_AT_decl_line (8)
DW_AT_type (0x000000b7 "int")
DW_AT_external (true)
0x00000072: DW_TAG_subprogram
DW_AT_low_pc (0x0000000000000030)
DW_AT_high_pc (0x000000000000005b)
DW_AT_frame_base (DW_OP_reg6 RBP)
DW_AT_linkage_name ("main")
DW_AT_name ("main")
DW_AT_decl_file
("/usr/local/Cellar/ldc/1.24.0/include/dlang/ldc/core/internal/entrypoint.d")
DW_AT_decl_line (39)
DW_AT_type (0x000000b7 "int")
DW_AT_external (true)
```
--
More information about the Digitalmars-d-bugs
mailing list