www.fgks.org   »   [go: up one dir, main page]

Issue 20460 - [OSX] DMD writes the same address everywhere in DWARF debug infos
Summary: [OSX] DMD writes the same address everywhere in DWARF debug infos
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: x86_64 Mac OS X
: P1 critical
Assignee: No Owner
URL:
Keywords: backend, industry, pull
Depends on:
Blocks: 20510
  Show dependency treegraph
 
Reported: 2019-12-20 15:01 UTC by Mathias LANG
Modified: 2021-04-26 01:13 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Mathias LANG 2019-12-20 15:01:53 UTC
To reproduce:
- Add an assert(0) anywhere in DMD in a code path that will be triggered;
- Compile dmd
- Run it on some source code that triggers the assert:

In my case I used:
```
diff --git a/src/dmd/expressionsem.d b/src/dmd/expressionsem.d
index 577ae7abe..a18ecfbb6 100644
--- a/src/dmd/expressionsem.d
+++ b/src/dmd/expressionsem.d
@@ -392,6 +392,9 @@ private Expression searchUFCS(Scope* sc, UnaExp ue, Identifier ident)
     //printf("searchUFCS(ident = %s)\n", ident.toChars());
     Loc loc = ue.loc;

+    if (sc || !sc)
+        assert(0);
+
     // TODO: merge with Scope.search.searchScopes()
     Dsymbol searchScopes(int flags)
     {
```

Test file:
```
int foo;
void bar(int) {}
void main()
{
    foo.bar;
}
```

Result:
```
% ./generated/osx/release/64/dmd -run wysig.d
---
ERROR: This is a compiler bug.
Please report it via https://issues.dlang.org/enter_bug.cgi
with, preferably, a reduced, reproducible example and the information below.
DustMite (https://github.com/CyberShadow/DustMite/wiki) can help with the reduction.
---
DMD v2.089.1-333-g403f33603-dirty
predefs   DigitalMars Posix OSX CppRuntime_Clang darwin LittleEndian D_Version2 all D_SIMD D_InlineAsm_X86_64 X86_64 D_LP64 D_PIC assert D_ModuleInfo D_Exceptions D_TypeInfo D_HardFloat D_ObjectiveC
binary    ./generated/osx/release/64/dmd
version   v2.089.1-333-g403f33603-dirty
config    ./generated/osx/release/64/dmd.conf
DFLAGS    -I./generated/osx/release/64/../../../../../druntime/import -I./generated/osx/release/64/../../../../../phobos -L-L./generated/osx/release/64/../../../../../phobos/generated/osx/release/64 -fPIC
---
core.exception.AssertError@dmd/expressionsem.d(396): Assertion failure
----------------
??:? _d_assertp [0x1082169fd]
dmd/access.d:394 dmd.expression.Expression dmd.expressionsem.searchUFCS(dmd.dscope.Scope*, dmd.expression.UnaExp, dmd.identifier.Identifier) [0x108010c70]
dmd/access.d:394 dmd.expression.Expression dmd.expressionsem.resolveUFCSProperties(dmd.dscope.Scope*, dmd.expression.Expression, dmd.expression.Expression) [0x1080115f8]
dmd/access.d:394 _ZN25ExpressionSemanticVisitor5visitEP8DotIdExp [0x1080232f4]
dmd/access.d:394 _ZN8DotIdExp6acceptEP7Visitor [0x1080092a9]
dmd/access.d:394 _Z18expressionSemanticP10ExpressionP5Scope [0x10803386b]
dmd/access.d:394 _ZN24StatementSemanticVisitor5visitEP12ExpStatement [0x1080d86a9]
dmd/access.d:394 _ZN12ExpStatement6acceptEP7Visitor [0x1080d3f11]
dmd/access.d:394 _Z17statementSemanticP9StatementP5Scope [0x1080d858b]
dmd/access.d:394 _ZN24StatementSemanticVisitor5visitEP17CompoundStatement [0x1080d896f]
dmd/access.d:394 _ZN17CompoundStatement6acceptEP7Visitor [0x1080d4889]
dmd/access.d:394 _Z17statementSemanticP9StatementP5Scope [0x1080d858b]
dmd/access.d:394 _ZN16Semantic3Visitor5visitEP15FuncDeclaration [0x1080ce365]
dmd/access.d:394 _ZN15FuncDeclaration6acceptEP7Visitor [0x10803c399]
dmd/access.d:394 _Z9semantic3P7DsymbolP5Scope [0x1080ccbd1]
dmd/access.d:394 _ZN16Semantic3Visitor5visitEP6Module [0x1080ccfd7]
dmd/access.d:394 _ZN6Module6acceptEP7Visitor [0x107fb1369]
dmd/access.d:394 _Z9semantic3P7DsymbolP5Scope [0x1080ccbd1]
dmd/access.d:394 int dmd.mars.tryMain(ulong, const(char)**, ref dmd.globals.Param) [0x10808f2e9]
dmd/access.d:394 _Dmain [0x1080908fd]
```

Notice the repetitive dmd/access.d
Comment 1 Jacob Carlborg 2019-12-21 12:31:30 UTC
Hasn't this already been reported?

Should probably be connected to the bounty: https://www.flipcause.com/secure/cause_pdetails/NjI2NjQ=
Comment 2 Mathias LANG 2020-01-10 10:45:17 UTC
Found a way to reproduce:

--- a.d
module a;

import b;
import c;

void main ()
{
    auto o1 = new Foo();
    o1.bar(5);
}
--- b.d
module b;

extern(C++) void func() {}
--- c.d
module c;

extern(C++) class Foo
{
    void bar(int rec)
    {
        assert(0);
    }
}

Compile and run:
$ dmd -g b.d c.d -run a.d
core.exception.AssertError@c.d(9): Assertion failure
----------------
??:? _d_assertp [0x10916d89d]
b.d:3 _ZN3Foo3barEi [0x1091608d7]
a.d:9 _Dmain [0x109160881]


The file/line points to `b.d:3` (the first function in that file) while it should be `c.d:7`. Note that even if `bar` calls other functions, all their file/line will point to the same entry.
Comment 3 Dlang Bot 2020-01-13 10:59:13 UTC
@Geod24 created dlang/dmd pull request #10722 "Fix issue 20460: Stack traces involving extern(C++) can show wrong file/line" fixing this issue:

- Fix issue 20460: Stack traces involving extern(C++) can show wrong file/line
  
  The comment mentions writing the 'function prologue',
  but this seems to be a long-gone heritage (perhaps from DM exceptions?)
  Before this change, some functions would have their 'end' address
  set at the end of the next file's last function,
  which in practice would mean that the last function in the module
  would 'eat' the whole file, and all the stack traces would point
  to the same line.
  This was witnessed with extern(C++) and the _Dmain function.

https://github.com/dlang/dmd/pull/10722
Comment 4 Mathias LANG 2021-01-19 18:59:45 UTC
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)
```
Comment 5 Mathias LANG 2021-01-19 19:00:38 UTC
This is also blocking me from fixing 20510.
Comment 6 Dlang Bot 2021-04-24 08:03:16 UTC
@WalterBright created dlang/dmd pull request #12466 "fix Issue 20460 - [OSX] DMD writes the same address everywhere in DWA…" fixing this issue:

- fix Issue 20460 - [OSX] DMD writes the same address everywhere in DWARF debug infos

https://github.com/dlang/dmd/pull/12466
Comment 7 Dlang Bot 2021-04-26 01:13:37 UTC
dlang/dmd pull request #12466 "fix Issue 20460 - [OSX] DMD writes the same address everywhere in DWA…" was merged into master:

- c1270ea0603afaa98d4e18f88a6fe58cb25092b4 by Walter Bright:
  fix Issue 20460 - [OSX] DMD writes the same address everywhere in DWARF debug infos

https://github.com/dlang/dmd/pull/12466