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
Hasn't this already been reported? Should probably be connected to the bounty: https://www.flipcause.com/secure/cause_pdetails/NjI2NjQ=
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.
@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
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) ```
This is also blocking me from fixing 20510.
@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
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