Skip to content
This repository has been archived by the owner on Feb 8, 2024. It is now read-only.

Add FreeBSD/aarch64 support #146

Merged
merged 2 commits into from
Dec 15, 2018
Merged

Conversation

valpackett
Copy link

I hope this is correct… This makes the 0.17 bootstrap compiler work, at least.

Copy link

@joakim-noah joakim-noah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you tried running the druntime tests? ctest -R druntime-test-runner$; ./runtime/druntime-test-runner should show you what's working (check out the ldc-ltsmaster branch of druntime first and apply your patch there, so all the tests are run on a single invocation of the test runner).

src/core/sys/freebsd/execinfo.d Outdated Show resolved Hide resolved
enum _JBLEN = 31;
// __int128_t
struct _jmp_buf { long[2][_JBLEN + 1] _jb; };
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything after the first file should go upstream at dlang/druntime, submit this there instead.

@valpackett
Copy link
Author

druntime tests fail at CTFE stage:

/usr/home/greg/ldc/runtime/druntime/src/core/internal/hash.d(63): Error: "unable to compute hash of creal[]"
/usr/home/greg/ldc/runtime/druntime/src/core/internal/hash.d(288):        called from here: hashOf([(8.99L+86.0000Li), (3.12L+99.0000Li)
, (5.66L+12.0000Li)], 0LU)
/usr/home/greg/ldc/runtime/druntime/src/core/internal/convert.d(114): Error: shift by 112 is outside the range 0..63                   
/usr/home/greg/ldc/runtime/druntime/src/core/internal/convert.d(306): Error: template instance core.internal.convert.parse!(true, real)
error instantiating
/usr/home/greg/ldc/runtime/druntime/src/core/internal/convert.d(106):        instantiated from here: denormalizedMantissa!real         
/usr/home/greg/ldc/runtime/druntime/src/core/internal/convert.d(28):        instantiated from here: parse!(false, real)
/usr/home/greg/ldc/runtime/druntime/src/core/internal/convert.d(315):        instantiated from here: toUbyte!real
/usr/home/greg/ldc/runtime/druntime/src/core/internal/convert.d(326):        instantiated from here: toUbyte2!real
/usr/home/greg/ldc/runtime/druntime/src/core/internal/convert.d(351):        instantiated from here: testNumberConvert!"-real.infinity"
/usr/home/greg/ldc/runtime/druntime/src/core/internal/convert.d(114): Error: shift by 112 is outside the range 0..63
/usr/home/greg/ldc/runtime/druntime/src/core/internal/convert.d(326): Error: CTFE failed because of previous errors in toUbyte2
/usr/home/greg/ldc/runtime/druntime/src/core/internal/convert.d(326): Error: CTFE failed because of previous errors in toUbyte2
/usr/home/greg/ldc/runtime/druntime/src/core/internal/convert.d(352): Error: template instance core.internal.convert.testNumberConvert!"
real.infinity" error instantiating
/usr/home/greg/ldc/runtime/druntime/src/core/internal/convert.d(326): Error: CTFE failed because of previous errors in toUbyte2
[…]

(& same for many more of these conversions)

After removing/commenting out these, build-druntime-test-runner passes and ./runtime/druntime-test-runner exits successfully.

(I've been working on the revision referenced from ldc lts, looks like 1 commit behind ldc-ltsmaster now)

@valpackett
Copy link
Author

dmd-testsuite(-debug) fails with lots of object.Exception@/usr/home/greg/ldc/runtime/phobos/std/stdio.d(2428): Enforcement failed, that is enforce(f._p && f._p.handle) (and segfault if that enforce is commented out).

All other tests in ctest pass (after disabling the ctfe described in the previous comment)

@joakim-noah
Copy link

joakim-noah commented Aug 11, 2018

Use the patch from dlang#2257, that should fix the CTFE issue. Make sure you're on the ldc-ltsmaster branch, ie one commit ahead, or all tests won't be run without ctest.

Also, have you tried building LDC master and its druntime tests using ltsmaster? I'd like to know what happens then.

@valpackett
Copy link
Author

(Haven't tried with patched ltsmaster yet)

ldc master segfaulted when building phobos, with an entirely unhelpful core dump (frame #0: 0x0000000000000000)

Actually, before I got to that point, there were weird initialization issues (things not being initialized) for which I made some questionable workarounds:

--- i/dmd/identifier.d
+++ w/dmd/identifier.d
@@ -182,6 +182,7 @@ nothrow:

     static Identifier idPool(const(char)* s, uint len)
     {
+        initTable();
         StringValue* sv = stringtable.update(s, len);
         Identifier id = cast(Identifier)sv.ptrvalue;
         if (!id)
@@ -240,6 +241,7 @@ nothrow:

     static void initTable()
     {
-        stringtable._init(28000);
+        if (stringtable.table == null)
+            stringtable._init(28000);
     }
 }
--- i/dmd/root/stringtable.d
+++ w/dmd/root/stringtable.d
@@ -62,7 +62,6 @@ pure:
 struct StringTable
 {
 private:
-    StringEntry* table;
     size_t tabledim;
     ubyte** pools;
     size_t npools;
@@ -70,6 +69,7 @@ private:
     size_t count;

 public:
+    StringEntry* table;
     extern (C++) void _init(size_t size = 0) nothrow
     {
         size = nextpow2(cast(size_t)(size / loadFactor));
--- i/gen/target.cpp
+++ w/gen/target.cpp
@@ -25,6 +25,7 @@
 using llvm::APFloat;

 void Target::_init() {
+  CTFloat::_init();
   FloatProperties::_init();
   DoubleProperties::_init();
   RealProperties::_init();

@joakim-noah
Copy link

joakim-noah commented Aug 11, 2018

Yeah, same issues on other AArch64 platforms with a natively-built LDC master, may want to try this new ltsmaster pull, ldc-developers/ldc#2811, to see what difference it makes.

Regarding the DMD testsuite issues, how do the Phobos tests do first?

ctest -R phobos2-test-runner$
./runtime/phobos2-test-runner

@valpackett
Copy link
Author

Looks like I need to learn to actually read error messages! The CTFE error was @nogc function … cannot call non-@nogc … — I did not remove the @nogc when applying dlang#2257 to LTS :D

Now only dmd tests fail (that enforce in LockingTextWriter). druntime and phobos tests pass on LTS :)

@joakim-noah
Copy link

See if you can bootstrap LDC master and its tests pass now with the latest version of ldc-developers/ldc#2811 applied, as I noted for other platforms. Submit all your non-__asm druntime patches upstream, versioned out for AArch64, keeping only that first file change here.

Weird that you're getting std.stdio errors in the DMD testsuite but not in the Phobos test runner, you may need to look into that in a debugger.

@valpackett
Copy link
Author

The initialization bugs in ldc master are still there

* thread #1, name = 'ldc2', stop reason = signal SIGSEGV: invalid address (fault address: 0x6faa7af54)
  * frame #0: 0x00000000005a34c8 ldc2`_D3dmd4root11stringtable11StringTable8findSlotMxFNaNbmPxamZm + 92
    frame #1: 0x000000000051bcac ldc2`StringTable::update(char const*, unsigned long) + 68
    frame #2: 0x00000000003eb980 ldc2`Identifier::idPool(char const*, unsigned int) + 44
    frame #3: 0x00000000003d1f58 ldc2`_D3dmd10identifier10Identifier6idPoolFNbAxaZC3dmd10identifier10Identifier + 36
    frame #4: 0x00000000003edc34 ldc2`_D3dmd4cond16VersionCondition24addPredefinedGlobalIdentFAxaZv + 160
    frame #5: 0x00000000003edb60 ldc2`_D3dmd4cond16VersionCondition14addGlobalIdentFAxaZv + 60
    frame #6: 0x000000000054d664 ldc2`mars_mainBody(Array<char const*>&, Array<char const*>&) + 664
    frame #7: 0x00000000006acb34 ldc2`cppmain(argc=<unavailable>, argv=<unavailable>) at main.cpp:1060
    frame #8: 0x00000000005e6ff8 ldc2`_Dmain + 132
    frame #9: 0x00000000007eabd0 ldc2`_D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZ9__lambda1MFZv + 44
    frame #10: 0x00000000007eaa58 ldc2`_D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ7tryExecMFMDFZvZv + 52
    frame #11: 0x00000000007eab1c ldc2`_D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZv + 72
    frame #12: 0x00000000007eaa58 ldc2`_D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ7tryExecMFMDFZvZv + 52
    frame #13: 0x00000000007ea99c ldc2`_d_run_main + 1100
    frame #14: 0x00000000005e702c ldc2`main + 40
    frame #15: 0x00000000003c00b8 ldc2`__start(argc=232, argv=0x0000ffffffffcc88, env=0x0000ffffffffd3d0, cleanup=<unavailable>) at crt1.c:84

With the (bad) workarounds described above, I'm seeing super weird syntax errors that make zero sense, such as:

core/atomic.d(11): Error: semicolon expected, not `.`
core/atomic.d(11): Error: no identifier for declarator `.atomic`
core/atomic.d(13): Error: function declaration without return type. (Note that constructors are always named `this`)                                          
core/atomic.d(14): Error: no identifier for declarator `version(LDC)`
core/atomic.d(19): Error: found `{` when expecting `;` following statement
core/atomic.d(21): Error: found `enum` when expecting `;` following statement
core/atomic.d(23): Error: found `enum` when expecting `;` following statement
core/atomic.d(26): Error: semicolon expected, not `has128BitCAS`
core/atomic.d(26): Error: no identifier for declarator `has128BitCAS`
core/atomic.d(26): Error: declaration expected, not `=`
core/atomic.d(27): Error: unrecognized declaration
core/attribute.d(16): Error: semicolon expected, not `.`
core/attribute.d(16): Error: no identifier for declarator `.attribute`
core/attribute.d(54): Error: function declaration without return type. (Note that constructors are always named `this`)                                       
core/attribute.d(54): Error: no identifier for declarator `version(D_ObjectiveC)`                                                                             
core/attribute.d(54): Error: semicolon expected following function declaration
core/attribute.d(55): Error: semicolon expected, not `{`
core/attribute.d(55): Error: declaration expected, not `{`
core/attribute.d(57): Error: unrecognized declaration

(actually this was happening the last time as well, not segfault)

This is probably related to StringTable.

@joakim-noah
Copy link

Did you apply the changes to core.stdc.stdarg too, from that pull? I had to download that patch separately.

@valpackett
Copy link
Author

valpackett commented Aug 12, 2018

Oops I did not. Applying them results in an LLVM assertion failure:

Assertion failed: (Subtarget->isTargetDarwin() && "automatic va_arg instruction only works on Darwin"), function LowerVAARG, file /wrkdirs/usr/ports/devel/llvm60/work/llvm-6.0.1.src/lib/Target/AArch64/AArch64ISelLowering.cpp, line 4698.

Looks like that assertion is still there even in current dev llvm.

(currently building llvm without that assertion)

@joakim-noah
Copy link

Huh, guess it only worked for us since we used llvm with assertions disabled.

@valpackett
Copy link
Author

The va_list thing with assertions disabled didn't change anything. The initialization failure is not vararg related, as I expected…

@joakim-noah
Copy link

I'm skeptical that you're having some other non-va_list problem, as that pull got ldc master working for me on linux and Android/AArch64. I suppose it's possible that FreeBSD/AArch64 isn't using the AAPCS ABI or uses some APCS variant like iOS does, up to you to figure it out.

@kinke
Copy link
Member

kinke commented Aug 13, 2018

The initialization failure is not vararg related, as I expected…

Yep, it almost certainly isn't. By the looks of it, the module ctors aren't run; this might also cause your std.stdio:2428 issue. E.g., CTFloat::_init() is supposed to be called by the dmd.root.ctfloat module ctor by (the host compiler's) druntime (before main()), way before calling Target::_init() manually in dmd.mars.

[Changing a struct layout on one side only (D/C++), e.g., moving member StringEntry* table from first to last field, without adapting the C++ header too, makes things explode if the C++ code works with that struct and member too.]

@valpackett
Copy link
Author

Yeah, that's it:

import core.stdc.stdio;
shared static this() { printf("shared static\n"); }
shared static ~this() { printf("~shared static\n"); }
static this() { printf("static\n"); }
static ~this() { printf("~static\n"); }
void main() { printf("main\n"); }

(compiled with LTS) only prints "main".

Stepping through rt_moduleCtor in lldb finishes very quickly… (unfortunately LTSmaster doesn't seem to produce proper debug info)

@valpackett
Copy link
Author

valpackett commented Aug 13, 2018

So, there's no SectionGroups, but only when linking with LLD. Linking the above test with cc -fuse-ld=gold, the constructors/destructors run!

And there's Fatal error in EH code: _Unwind_RaiseException failed with reason code: 5 after ~shared static is printed:

* thread #1, name = 'ctortest', stop reason = signal SIGABRT
  * frame #0: 0x000000004066f464 libc.so.7`__sys_thr_kill + 8
    frame #1: 0x000000004066f430 libc.so.7`raise + 64
    frame #2: 0x000000004066f3a4 libc.so.7`abort + 84
    frame #3: 0x000000000041735c ctortest`fatalerror + 156
    frame #4: 0x000000000040d358 ctortest`onOutOfMemoryError + 32
    frame #5: 0x000000000040c784 ctortest`_D2rt4util9container6common8xreallocFNbPvmZPv + 76
    frame #6: 0x000000000040aa5c ctortest`_d_dso_registry + 164
    frame #7: 0x000000000042ff80 ctortest`ldc.dso_dtor.2rt7switch_ + 96
    frame #8: 0x000000004046b308 ld-elf.so.1
    frame #9: 0x0000000040465b50 ld-elf.so.1
    frame #10: 0x00000000406d7220 libc.so.7`__cxa_finalize + 172
    frame #11: 0x000000004066efe8 libc.so.7`exit + 44
    frame #12: 0x0000000000402414 ctortest`__start(argc=<unavailable>, argv=<unavailable>, env=<unavailable>, cleanup=<unavailable>) at crt1.c:84

Linking with cc -fuse-ld=bfd, everything prints and no error!

@kinke
Copy link
Member

kinke commented Aug 13, 2018

Nice findings. Seems to be related to problems with llvm.global_{c,d}tors (which we use to call the auto-generated ldc.register_dso function at startup/termination, per D module). These {c,d}tors are supposed to be called by the C runtime AFAIK (such as __cxa_finalize in your call stack after C main() returns). May be FreeBSD specific though (at least the issue with gold); Shippable CI is using gold (but bfd works too, but issues lots of TLS-related warnings with clang as C++ host compiler).

@valpackett
Copy link
Author

Yeah, I'm seeing TLS related warnings with bfd too.

Temporarily changed /usr/bin/ld to ld.bfd instead of the default ld.lld, discovered a new error, now in GC:

* thread #1, name = 'ldc2', stop reason = signal SIGSEGV: invalid address (fault address: 0x0)                                                                                             
  * frame #0: 0x0000000000d062c8 ldc2`_D2gc2gc3Gcx4markMFNbPvPvZv + 132                                                                                                                    
    frame #1: 0x0000000000cb87c4 ldc2`_D4core6thread14thread_scanAllUNbMDFNbPvPvZvZ43__T9__lambda2TE4core6thread8ScanTypeTPvTPvZ9__lambda2MFNbE4core6thread8ScanTypePvPvZv + 60            
    frame #2: 0x0000000000cb8748 ldc2`_D4core6thread15scanAllTypeImplFNbMDFNbE4core6thread8ScanTypePvPvZvPvZ20__T9__lambda3TPvTPvZ9__lambda3MFNbPvPvZv + 60                                
    frame #3: 0x0000000000ce4da8 ldc2`_D2rt19sections_elf_shared13scanTLSRangesFNbPS2rt4util9container5array13__T5ArrayTAvZ5ArrayMDFNbPvPvZvZv + 204                                       
    frame #4: 0x0000000000ce881c ldc2`_D2rt5tlsgc4scanFNbPvMDFNbPvPvZvZv + 40                                                                                                              
    frame #5: 0x0000000000cb86d0 ldc2`_D4core6thread15scanAllTypeImplFNbMDFNbE4core6thread8ScanTypePvPvZvPvZv + 380                                                                        
    frame #6: 0x0000000000cb8548 ldc2`_D4core6thread18thread_scanAllTypeUNbMDFNbE4core6thread8ScanTypePvPvZvZ17__T9__lambda2TPvZ9__lambda2MFNbPvZv + 48                                    
    frame #7: 0x0000000000cb55a4 ldc2`_D4core6thread18callWithStackShellFNbMDFNbPvZvZv + 112                                                                                               
    frame #8: 0x0000000000cb84f4 ldc2`thread_scanAllType + 56                                                                                                                              
    frame #9: 0x0000000000cb877c ldc2`thread_scanAll + 40                                                                                                                                  
    frame #10: 0x0000000000d071c8 ldc2`_D2gc2gc3Gcx7markAllMFNbbZv + 128                                                                                                                   
    frame #11: 0x0000000000d02944 ldc2`_D2gc2gc3Gcx11fullcollectMFNbbZm + 584                                                                                                              
    frame #12: 0x0000000000d04808 ldc2`_D2gc2gc3Gcx10smallAllocMFNbhKmkZPv + 516                                                                                                           
    frame #13: 0x0000000000cfff88 ldc2`_D2gc2gc3Gcx5allocMFNbmKmkZPv + 236                                                                                                                 
    frame #14: 0x0000000000cffe3c ldc2`_D2gc2gc2GC12mallocNoSyncMFNbmkKmxC8TypeInfoZPv + 184                                                                                               
    frame #15: 0x0000000000d0008c ldc2`_D2gc2gc2GC6callocMFNbmkPmxC8TypeInfoZPv + 224                                                                                                      
    frame #16: 0x0000000000ccfa3c ldc2`gc_calloc + 80                                                                                                                                      
    frame #17: 0x0000000000cb2eec ldc2`_D4core6memory2GC6callocFNaNbmkxC8TypeInfoZPv + 36                                                                                                  
    frame #18: 0x0000000000cd36a0 ldc2`_D2rt3aaA12allocBucketsFNaNbNemZAS2rt3aaA6Bucket + 48                                                                                               
    frame #19: 0x0000000000cd354c ldc2`_D2rt3aaA4Impl6__ctorMFNcxC25TypeInfo_AssociativeArraymZS2rt3aaA4Impl + 112                                                                         
    frame #20: 0x0000000000cd5794 ldc2`_d_assocarrayliteralTX + 252                                                                                                                        
      frame #21: 0x00000000008409e8 ldc2`_D3dmd7imphint19_sharedStaticCtor10FZv + 80
    frame #22: 0x0000000000ce1aa8 ldc2`_D2rt5minfo67__T14runModuleFuncsS442rt5minfo11ModuleGroup8runCtorsMFZ9__lambda2Z14runModuleFuncsMFAxPyS6object10ModuleInfoZv + 196                 
    frame #23: 0x0000000000ce18e4 ldc2`_D2rt5minfo11ModuleGroup8runCtorsMFZv + 128
    frame #24: 0x0000000000ce22a4 ldc2`_D2rt5minfo13rt_moduleCtorUZ14__foreachbody1MFKS2rt19sections_elf_shared3DSOZi + 48                                                                
    frame #25: 0x0000000000ce3ce0 ldc2`_D2rt19sections_elf_shared3DSO7opApplyFMDFKS2rt19sections_elf_shared3DSOZiZi + 184                                                                 
    frame #26: 0x0000000000ce2264 ldc2`rt_moduleCtor + 24
    frame #27: 0x0000000000cd8dd0 ldc2`rt_init + 192
    frame #28: 0x0000000000cd9928 ldc2`_D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZv + 36
    frame #29: 0x0000000000cd9888 ldc2`_D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ7tryExecMFMDFZvZv + 48
    frame #30: 0x0000000000cd97e8 ldc2`_d_run_main + 1696
    frame #31: 0x0000000000932db4 ldc2`main + 40
    frame #32: 0x000000000069d378 ldc2`__start(argc=232, argv=0x0000ffffffffcc90, env=0x0000ffffffffd3d8, cleanup=<unavailable>) at crt1.c:84

hmm — TLS is mentioned in the backtrace.

@joakim-noah
Copy link

The GC is running in your LDC? That doesn't make sense, LDC doesn't use the D GC internally.

@dnadlinger
Copy link
Member

Seems like the GC isn't disabled early enough…

@joakim-noah
Copy link

joakim-noah commented Aug 15, 2018

So just to be sure, all the same tests pass for ltsmaster once you started using ld.bfd? Also, you never saw test failures there with std.stream and std.numeric, among others listed in ldc-developers/ldc#2153? Those modules have not been fully ported to AArch64 yet, as noted there.

You can remove the changes from this pull that were merged upstream, I will just cherry-pick that commit.

@valpackett
Copy link
Author

Yeah, all the same tests pass on ltsmaster — only dmd fails. Never saw other failures.

@kinke
Copy link
Member

kinke commented Aug 15, 2018

The GC segfault above indicates invalid TLS ranges, which might depend on the linker again.

Seems like the GC isn't disabled early enough…

Yep indeed, but that looks like an upstream issue. https://github.com/ldc-developers/ldc/blob/master/dmd/imphint.d#L34-L43 leads to a _d_assocarrayliteralTX() call (for DMD too) in a module ctor, before the GC is disabled in D main() (for DMD too). There's no corresponding _d_assocarrayliteralTX override in dmd.root.rmem (again, neither for DMD).

@valpackett
Copy link
Author

Since bfd has emitted TLS warnings, it certainly might have screwed this up. I need to get LLD working (fix the section groups thing), but I don't really know what to look for. Can I do something with objdump/readelf to compare the binaries made by different linkers?

@kinke
Copy link
Member

kinke commented Aug 15, 2018

Not so sure about the TLS warnings; I quickly looked them up, and they are apparently safe to discard (and should be fixed with clang 7).

Can I do something with objdump/readelf to compare the binaries made by different linkers?

Sure. Use something minimal (with -betterC, add a extern(C) void main() {} for the executable) such as https://run.dlang.io/is/3DughW and make sure it doesn't work with LLD, but with bfd. Then check the IR, which should add the init function to the global static ctors:

@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @void onlineapp.init(), i8* null }] ; [#uses = 0]

Then check the asm of the object file, where you should find an init pointer in the special .init_array section:

.section	.init_array,"aw",@init_array
.p2align	3
.xword	void onlineapp.init() ; run.dlang.io automatically demangles...

Then finally compare the bfd/lld-linked binaries, sections, symbols etc. There might be missing (linker-magic) symbols bracketing a section and whatnot.

@valpackett
Copy link
Author

Looks like ltsmaster doesn't support betterC nor crt_constructor… Looking at IR from a non-betterC example, global_ctors references a generated function that does the ModuleInfo stuff. I'm pretty sure that gets called just fine — the problem was it not finding the ModuleInfos.

The various symbols with "moduleinfo" in the name don't seem to look different…

@joakim-noah
Copy link

I was just looking into this: no __minfo back in ltsmaster, but lld probably missing some magic symbols like you said.

@kinke
Copy link
Member

kinke commented Aug 16, 2018

I rather think it's wrongly stripping them out (llvm.used unused in ltsmaster?); we'd have linker errors if the magic symbols were missing.

@valpackett
Copy link
Author

comparing section sizes (.init_array and __minfo)

heh — that's what I just started doing… but wasn't aware of init_array — which turned out to have different size!

~/ldc % objdump -h testconstr-bfd | grep minfo
 27 .minfo_beg    000001d8  00000000004581e8  00000000004581e8  000481e8  2**3
 28 .minfo        000001d8  00000000004583c0  00000000004583c0  000483c0  2**3
 29 .minfo_end    000001d8  0000000000458598  0000000000458598  00048598  2**3
~/ldc % objdump -h testconstr-lld | grep minfo
 19 .minfo_beg    000001d8  0000000000064ca0  0000000000064ca0  00054ca0  2**3
 20 .minfo        000001d8  0000000000064e78  0000000000064e78  00054e78  2**3
 21 .minfo_end    000001d8  0000000000065050  0000000000065050  00055050  2**3
~/ldc % objdump -h testconstr-lld | grep init_array
 28 .init_array   00000008  00000000000703e0  00000000000703e0  000603e0  2**3
~/ldc % objdump -h testconstr-bfd | grep init_array
 18 .init_array   000001e0  0000000000452c58  0000000000452c58  00042c58  2**3

@valpackett
Copy link
Author

binaries: lld bfd

for this source:

import core.stdc.stdio;

shared static this() { printf("this\n"); }

void main() {}

@kinke
Copy link
Member

kinke commented Aug 16, 2018

As already mentioned, that .init_array section contains the pointers of the llvm.global_ctors functions, so 1 vs. 60 functions... Maybe try googling for known issues with .{init,fini}_array for lld/gold on AArch64 (and FreeBSD?). Are you using recent versions?

@joakim-noah
Copy link

joakim-noah commented Aug 16, 2018

What I mean is that ltsmaster predates generating a __minfo section altogether, used _Dmodule_ref linked list back then, maybe that symbol's getting stripped out?

Update: Never mind, I now see it was using explicitly generated .minfo_{beg,end} symbols on FreeBSD back then, not magic ones.

@valpackett
Copy link
Author

sections_ldc.d

I don't think that's used, sections_elf_shared.d is there and supports FreeBSD

@kinke
Copy link
Member

kinke commented Aug 16, 2018

What I mean is that ltsmaster predates generating a __minfo section altogether

[That file isn't used for Linux and FreeBSD (it really just seems to be used as fallback for unknown OS), sections_elf_shared.d is used. Seems like the section name is slightly different in ltsmaster (plus no magic linker symbols, manual .minfo_{beg,end} bracketing symbols instead?).]

@valpackett
Copy link
Author

googling for known issues with .{init,fini}_array for lld/gold on AArch64

I can only find relocation-related issues for that…

Are you using recent versions?

The default linker is lld 6. I also tried 5.0 and lld-devel (7.0.d20180523), same results. bfd is from binutils-2.30.

contains the pointers of the llvm.global_ctors functions, so 1 vs. 60 functions

I'm not sure where 60 would come from?

@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @ldc.dso_ctor.10testconstr, i8* null }] ; [#uses = 0]

@kinke
Copy link
Member

kinke commented Aug 16, 2018

I'm not sure where 60 would come from?

druntime (+ C libs possibly). There's one ctor/dtor per (linked-in) D object file. 60 ctors also more or less match the 59 (0x1d8 / 8) ModuleInfos. Note that LDC master uses --gc-sections for linking by default on Linux, so you may want to try -disable-linker-strip-dead in case you haven't tried disabling stripping yet. Ah, you're on FreeBSD. ;)

@valpackett
Copy link
Author

valpackett commented Oct 25, 2018

Huh, new FreeBSD commit: https://reviews.freebsd.org/D17587

"Implement a BSD licensed crtbegin/crtend" "These are needed for .ctors/.dtors and .jcr handling" "Perhaps put a comment here that arm64 does not use .ctors/.dtors or such?"

I'll ask about this…

UPD: facepalm, we were already talking about init_array here, not ctors

@valpackett
Copy link
Author

valpackett commented Oct 25, 2018

So looks like the object file from the compiler has the ctors as .ctors, bfd and gold linkers do convert that to init_array (apparently as an optimization!!!), but lld does not.

And why are there .ctors? Because ldc (at least ltsmaster) doesn't have anything like this piece of clang code:

https://github.com/llvm-mirror/clang/blob/5897428cd24e2deefbcc6f6744c0d7d233aa6747/lib/Driver/ToolChains/Gnu.cpp#L2598-L2620

@valpackett
Copy link
Author

So the GC issue is still present (when linking with lld).

@kinke
Copy link
Member

kinke commented Nov 4, 2018

Just with LLD?

@valpackett
Copy link
Author

bfd too (you can see above, I first discovered it with bfd, thought it might be bfd's fault, but no)

@kinke
Copy link
Member

kinke commented Nov 4, 2018

I suspect a FreeBSD-specific problem in section_elf_shared.d's getTLSRange() and/or scanSegments() in there, i.e., when trying to establish the TLS address range for the executable, based on the ELF header and __tls_get_addr().

I'd suggest using -link-debuglib (I think that's the old name for ltsmaster) to link against debug druntime (and -g obviously) and then debugging with appropriate breakpoints - a dummy executable should do, just perform a dummy allocation and then GC.collect(). If ltsmaster's debuginfos aren't sufficient, you can always add some printfs. You can also add a thread-local global in your dummy source file and print its address, so that you can verify druntime's TLS range.

@strejda
Copy link

strejda commented Dec 13, 2018

I hope that this problem was fixed by https://svnweb.freebsd.org/changeset/base/341512 But 'rust' itself needs additional patch, which is currently in review state. I hope that I will be able to commit it in next few days. (Bulk ports compile is still in progress to verify this patch, RTLD TLS handling is complicated from time to time).

@valpackett
Copy link
Author

valpackett commented Dec 13, 2018

Yes, looks like this was the same problem that was screwing up Rust. I'm not sure if D18417 is necessary for LDC or r341512 is enough, but I'm on a kernel with D18417 applied currently.

Thanks @strejda!


Now I have built ldc2, tests are mostly running out of memory (because I built ldc2 in debug mode :D), building dub failed with Assertion failed: ((!Node || !ResNo || ResNo < Node->getNumValues()) && "Invalid result number for the given node!"), function SDValue, file /wrkdirs/usr/ports/devel/llvm70/work/llvm-7.0.0.src/include/llvm/CodeGen/SelectionDAGNodes.h, line 1101 (BTW turns out that FreeBSD shipping LLVM with assertions was not intentional, it was a CMake accident), but simple examples like the one from the bottom of this page work fine! :)

Sooooo the changes I have in my repos are:

UPD: backtrace isn't actually working, I'm probably writing into the variable and not to where the variable points to, trying that fix. But why aren't we using libbacktrace?…

@kinke
Copy link
Member

kinke commented Dec 13, 2018

The -O -g dub issue is ldc-developers/ldc#1989.

@kinke
Copy link
Member

kinke commented Dec 13, 2018

I'm probably writing into the variable and not to where the variable points to

Yep edit: The other way around, you're currently writing into the void** value (which should be initialized with null). Use &p to set p instead.

@valpackett
Copy link
Author

Backtrace works now, thanks!

Updated this PR.

@kinke kinke merged commit 98321e0 into ldc-developers:ldc Dec 15, 2018
kinke pushed a commit that referenced this pull request Dec 15, 2018
@kinke
Copy link
Member

kinke commented Dec 15, 2018

I've also cherry-picked it to ltsmaster. - The other patches you cherry-picked for ltsmaster aren't required to build it and then use it for building master, right? They aren't for Linux/AArch64 and don't seem FreeBSD specific (dlang@ce863ec shouldn't be an issue, as LDC itself is usually linked against static druntime).

@valpackett
Copy link
Author

coming back to this:

and with that, we can build it in Ports for packaging :)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
5 participants