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

liobjc2 does not detect C++ runtine on NetBSD #203

Closed
rmottola opened this issue Apr 1, 2021 · 17 comments · Fixed by #205
Closed

liobjc2 does not detect C++ runtine on NetBSD #203

rmottola opened this issue Apr 1, 2021 · 17 comments · Fixed by #205

Comments

@rmottola
Copy link
Member

rmottola commented Apr 1, 2021

If I run cmake without sourcing GNUstep.sh first (=gnustep config not found)

-- The C compiler identification is Clang 10.0.1
-- The ASM compiler identification is Clang
-- Found assembler: /usr/pkg/bin/clang
-- The CXX compiler identification is Clang 10.0.1
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/pkg/bin/clang - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/pkg/bin/clang++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Testing C++ interop
-- Testing C++ standard library
-- Using /usr/pkg/bin/clang
-- libobjc will depend on C++ standard library
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Failed
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE  
-- GNUstep install type set to NONE
-- Performing Test CXA_ALLOCATE_EXCEPTION_NOEXCEPT_COMPILES
-- Performing Test CXA_ALLOCATE_EXCEPTION_NOEXCEPT_COMPILES - Success
-- Configuring done
-- Generating done
-- Build files have been written to: /home/multix/code/libobjc2/Build

then I get:
CXX_RUNTIME_LIB CXX_RUNTIME_LIB-NOTFOUND

@davidchisnall
Copy link
Member

What does NetBSD install? If it doesn't install a separate .so for the C++ runtime then this is the correct behaviour (to link the C++ standard library instead).

@rmottola
Copy link
Member Author

rmottola commented Apr 2, 2021

If it is the correct behaviour, fine. libobjc2 actually compiles
However 39% tests passed, 116 tests failed out of 190 does means it doesn't almost work.

this is what ldd shows:

libobjc.so.4.6:
        -lpthread.1 => /usr/lib/libpthread.so.1
        -lc.12 => /usr/lib/libc.so.12
        -lm.0 => /usr/lib/libm.so.0
        -lstdc++.9 => /usr/lib/libstdc++.so.9
        -lgcc_s.1 => /usr/lib/libgcc_s.so.1

It should also answer your question, it uses libstdc++.so.

lrwxr-xr-x  1 root  wheel       16 Oct 18 19:24 /usr/lib/libstdc++.so -> libstdc++.so.9.0
lrwxr-xr-x  1 root  wheel       16 Oct 18 19:24 /usr/lib/libstdc++.so.9 -> libstdc++.so.9.0
-r--r--r--  1 root  wheel  1964752 Oct 18 19:24 /usr/lib/libstdc++.so.9.0
-r--r--r--  1 root  wheel  3810506 Oct 18 19:24 /usr/lib/libstdc++_p.a
-r--r--r--  1 root  wheel   291284 Oct 18 19:24 /usr/lib/libsupc++.a

It appears the only available as shared object, since libsupc++ is static and no .so is available

@davidchisnall
Copy link
Member

It would be helpful if you could list the tests that aren't failing, their output, and your full CMake invocation. The linkage for libobjc2.so looks correct but 116 failing tests is surprising.

@rmottola
Copy link
Member Author

rmottola commented Apr 8, 2021

Running tests...
Test project /home/multix/code/libobjc2/Build
        Start   1: alias
  1/190 Test   #1: alias .............................................Child aborted***Exception:   0.02 sec
        Start   2: alias_optimised
  2/190 Test   #2: alias_optimised ...................................Child aborted***Exception:   0.01 sec
        Start   3: alias_legacy
  3/190 Test   #3: alias_legacy ......................................   Passed    0.04 sec
        Start   4: alias_legacy_optimised
  4/190 Test   #4: alias_legacy_optimised ............................   Passed    0.01 sec
        Start   5: alignTest
  5/190 Test   #5: alignTest .........................................Child aborted***Exception:   0.00 sec
        Start   6: alignTest_optimised
  6/190 Test   #6: alignTest_optimised ...............................Child aborted***Exception:   0.01 sec
        Start   7: alignTest_legacy
  7/190 Test   #7: alignTest_legacy ..................................   Passed    0.02 sec
        Start   8: alignTest_legacy_optimised
  8/190 Test   #8: alignTest_legacy_optimised ........................   Passed    0.02 sec
        Start   9: AllocatePair
  9/190 Test   #9: AllocatePair ......................................Child aborted***Exception:   0.02 sec
        Start  10: AllocatePair_optimised
 10/190 Test  #10: AllocatePair_optimised ............................Child aborted***Exception:   0.02 sec
        Start  11: AllocatePair_legacy
 11/190 Test  #11: AllocatePair_legacy ...............................   Passed    0.02 sec
        Start  12: AllocatePair_legacy_optimised
 12/190 Test  #12: AllocatePair_legacy_optimised .....................   Passed    0.01 sec
        Start  13: ARCTest_arc
 13/190 Test  #13: ARCTest_arc .......................................Child aborted***Exception:   0.00 sec
        Start  14: ARCTest_arc_optimised
 14/190 Test  #14: ARCTest_arc_optimised .............................Child aborted***Exception:   0.00 sec
        Start  15: ARCTest_arc_legacy
 15/190 Test  #15: ARCTest_arc_legacy ................................   Passed    0.03 sec
        Start  16: ARCTest_arc_legacy_optimised
 16/190 Test  #16: ARCTest_arc_legacy_optimised ......................   Passed    0.01 sec
        Start  17: AssociatedObject
 17/190 Test  #17: AssociatedObject ..................................Child aborted***Exception:   0.00 sec
        Start  18: AssociatedObject_optimised
 18/190 Test  #18: AssociatedObject_optimised ........................Child aborted***Exception:   0.03 sec
        Start  19: AssociatedObject_legacy
 19/190 Test  #19: AssociatedObject_legacy ...........................   Passed    0.01 sec
        Start  20: AssociatedObject_legacy_optimised
 20/190 Test  #20: AssociatedObject_legacy_optimised .................   Passed    0.01 sec
        Start  21: AssociatedObject2
 21/190 Test  #21: AssociatedObject2 .................................Child aborted***Exception:   0.00 sec
        Start  22: AssociatedObject2_optimised
 22/190 Test  #22: AssociatedObject2_optimised .......................Child aborted***Exception:   0.00 sec
        Start  23: AssociatedObject2_legacy
 23/190 Test  #23: AssociatedObject2_legacy ..........................   Passed    0.01 sec
        Start  24: AssociatedObject2_legacy_optimised
 24/190 Test  #24: AssociatedObject2_legacy_optimised ................   Passed    0.02 sec
        Start  25: BlockImpTest
 25/190 Test  #25: BlockImpTest ......................................Child aborted***Exception:   0.00 sec
        Start  26: BlockImpTest_optimised
 26/190 Test  #26: BlockImpTest_optimised ............................Child aborted***Exception:   0.00 sec
        Start  27: BlockImpTest_legacy
 27/190 Test  #27: BlockImpTest_legacy ...............................   Passed    0.01 sec
        Start  28: BlockImpTest_legacy_optimised
 28/190 Test  #28: BlockImpTest_legacy_optimised .....................   Passed    0.01 sec
        Start  29: BlockTest_arc
 29/190 Test  #29: BlockTest_arc .....................................Child aborted***Exception:   0.00 sec
        Start  30: BlockTest_arc_optimised
 30/190 Test  #30: BlockTest_arc_optimised ...........................Child aborted***Exception:   0.01 sec
        Start  31: BlockTest_arc_legacy
 31/190 Test  #31: BlockTest_arc_legacy ..............................   Passed    0.01 sec
        Start  32: BlockTest_arc_legacy_optimised
 32/190 Test  #32: BlockTest_arc_legacy_optimised ....................   Passed    0.01 sec
        Start  33: ConstantString
 33/190 Test  #33: ConstantString ....................................Child aborted***Exception:   0.00 sec
        Start  34: ConstantString_optimised
 34/190 Test  #34: ConstantString_optimised ..........................Child aborted***Exception:   0.00 sec
        Start  35: ConstantString_legacy
 35/190 Test  #35: ConstantString_legacy .............................   Passed    0.01 sec
        Start  36: ConstantString_legacy_optimised
 36/190 Test  #36: ConstantString_legacy_optimised ...................   Passed    0.01 sec
        Start  37: Category
 37/190 Test  #37: Category ..........................................Child aborted***Exception:   0.01 sec
        Start  38: Category_optimised
 38/190 Test  #38: Category_optimised ................................Child aborted***Exception:   0.00 sec
        Start  39: Category_legacy
 39/190 Test  #39: Category_legacy ...................................   Passed    0.01 sec
        Start  40: Category_legacy_optimised
 40/190 Test  #40: Category_legacy_optimised .........................   Passed    0.01 sec
        Start  41: ExceptionTest
 41/190 Test  #41: ExceptionTest .....................................Child aborted***Exception:   0.01 sec
        Start  42: ExceptionTest_optimised
 42/190 Test  #42: ExceptionTest_optimised ...........................Child aborted***Exception:   0.00 sec
        Start  43: ExceptionTest_legacy
 43/190 Test  #43: ExceptionTest_legacy ..............................Child aborted***Exception:   0.04 sec
        Start  44: ExceptionTest_legacy_optimised
 44/190 Test  #44: ExceptionTest_legacy_optimised ....................Child aborted***Exception:   0.02 sec
        Start  45: FastARC
 45/190 Test  #45: FastARC ...........................................Child aborted***Exception:   0.01 sec
        Start  46: FastARC_optimised
 46/190 Test  #46: FastARC_optimised .................................Child aborted***Exception:   0.01 sec
        Start  47: FastARC_legacy
 47/190 Test  #47: FastARC_legacy ....................................   Passed    0.01 sec
        Start  48: FastARC_legacy_optimised
 48/190 Test  #48: FastARC_legacy_optimised ..........................   Passed    0.01 sec
        Start  49: FastRefCount
 49/190 Test  #49: FastRefCount ......................................Child aborted***Exception:   0.03 sec
        Start  50: FastRefCount_optimised
 50/190 Test  #50: FastRefCount_optimised ............................Child aborted***Exception:   0.00 sec
        Start  51: FastRefCount_legacy
 51/190 Test  #51: FastRefCount_legacy ...............................   Passed    0.02 sec
        Start  52: FastRefCount_legacy_optimised
 52/190 Test  #52: FastRefCount_legacy_optimised .....................   Passed    0.01 sec
        Start  53: Forward
 53/190 Test  #53: Forward ...........................................Child aborted***Exception:   0.00 sec

If I manually run the first 4 tests I see:

isengard$ ./alias
[1]   Abort trap              ./alias
isengard$ ./alias
[1]   Abort trap              ./alias
isengard$ ./alias_optimised 
[1]   Abort trap              ./alias_optimised
isengard$ ./alias_legacy
isengard$ ./alias_legacy_optimised 

However, compare the result of ldd:

isengard$ ldd alias
ldd: alias: wrong number of segments (1 != 2)
isengard$ ldd alias_legacy
alias_legacy:
        -lobjc.4.6 => /home/multix/code/libobjc2/Build/libobjc.so.4.6
        -lpthread.1 => /usr/lib/libpthread.so.1
        -lc.12 => /usr/lib/libc.so.12
        -lm.0 => /usr/lib/libm.so.0
        -lstdc++.9 => /usr/lib/libstdc++.so.9
        -lgcc_s.1 => /usr/lib/libgcc_s.so.1

wrong number of segments doesn't look promising. I checked that for other tests... apparently the legacy versions are fine, the other versions give this ldd issue.

I invoke cmake with only your suggested parameters of setting -DCMAKE_C_COMPILER=clang
-DCMAKE_CXX_COMPILER=clang++. However I then tweak in ccmake:

CMAKE_CXX_FLAGS -march=i686
CMAKE_C_FLAGS -march=i686

so to avoid issues withlinking with libatomic.

@davidchisnall
Copy link
Member

This looks like it's caused by bugs in NetBSD's run-time linker. Most of these tests don't generate any output, but if you run them in a debugger then you may find something interesting.

@rmottola
Copy link
Member Author

rmottola commented Apr 9, 2021

Some tests run in the debugger show absolutely nothing, however, this one looks bad objc_msgSend and which is surely an essential functionality:

0xacc268f7 in _lwp_kill () from /usr/lib/libc.so.12
(gdb) bt
#0  0xacc268f7 in _lwp_kill () from /usr/lib/libc.so.12
#1  0xacc26811 in raise () from /usr/lib/libc.so.12
#2  0xacc25e70 in abort () from /usr/lib/libc.so.12
#3  0xaccf4955 in test_eh_personality () from /home/multix/code/libobjc2/Build/libobjc.so.4.6
#4  0xaccf6cec in _Unwind_RaiseException () from /home/multix/code/libobjc2/Build/libobjc.so.4.6
#5  0xac9d5423 in __cxa_throw () from /usr/lib/libstdc++.so.9
#6  0xaccf47f6 in cxx_throw() () from /home/multix/code/libobjc2/Build/libobjc.so.4.6
#7  0xacce8bd1 in eh_trampoline() () from /home/multix/code/libobjc2/Build/libobjc.so.4.6
#8  0xaccf4bcb in test_cxx_eh_implementation () from /home/multix/code/libobjc2/Build/libobjc.so.4.6
#9  0xacce4d2a in internal_objc_personality () from /home/multix/code/libobjc2/Build/libobjc.so.4.6
#10 0xacce5587 in __gnustep_objc_personality_v0 () from /home/multix/code/libobjc2/Build/libobjc.so.4.6
#11 0xaccf6cec in _Unwind_RaiseException () from /home/multix/code/libobjc2/Build/libobjc.so.4.6
#12 0xacce4ae3 in objc_exception_throw () from /home/multix/code/libobjc2/Build/libobjc.so.4.6
#13 0x08049305 in +[MsgTest initialize] ()
#14 0xaccd6bf3 in objc_send_initialize () from /home/multix/code/libobjc2/Build/libobjc.so.4.6
#15 0xacce2798 in slowMsgLookup () from /home/multix/code/libobjc2/Build/libobjc.so.4.6
#16 0xacce8b13 in objc_msgSend () from /home/multix/code/libobjc2/Build/libobjc.so.4.6
#17 0x08049b9e in main ()


@davidchisnall
Copy link
Member

This is crashing trying to understand the C++ exception layout, which happens the first time that an exception is thrown. For some reason, NetBSD's layout doesn't correspond to anything that we test. This abort is assert failure so you could look at the code in test_eh_personality and try to fix it. I don't know what NetBSD is doing that's odd here - the code works with multiple versions of libcxxrt, libsupc++ and libc++abi, on FreeBSD and Linux, so I've no idea what NetBSD is doing.

Note: It's probably easier to debug if you do a debug build.

@rmottola
Copy link
Member Author

rmottola commented Apr 9, 2021

#0  0xb5f6d8f7 in _lwp_kill () from /usr/lib/libc.so.12
#1  0xb5f6d811 in raise () from /usr/lib/libc.so.12
#2  0xb5f6ce70 in abort () from /usr/lib/libc.so.12
#3  0xb603b955 in test_eh_personality (version=1, actions=1, exceptionClass=5138137972254386944, exceptionObject=0xb5be7040, 
    context=0xbfb6dc94) at /home/multix/code/libobjc2/objcxx_eh.cc:485
#4  0xb603dcec in _Unwind_RaiseException () from /home/multix/code/libobjc2/Build/libobjc.so.4.6
#5  0xb5d1c423 in __cxa_throw () from /usr/lib/libstdc++.so.9
#6  0xb603b7f6 in cxx_throw () at /home/multix/code/libobjc2/objcxx_eh.cc:445
#7  0xb602fbd1 in eh_trampoline() () at eh_trampoline.s:30
#8  0xb603bbcb in test_cxx_eh_implementation () at /home/multix/code/libobjc2/objcxx_eh.cc:510
#9  0xb602bd2a in internal_objc_personality (version=1, actions=1, exceptionClass=5138137972457228867, 
    exceptionObject=0xb5bef010, context=0xbfb6e0cc, isNew=1 '\001') at /home/multix/code/libobjc2/eh_personality.c:394
#10 0xb602c587 in __gnustep_objc_personality_v0 (version=1, actions=1, exceptionClass=5138137972457228867, 
    exceptionObject=0xb5bef010, context=0xbfb6e0cc) at /home/multix/code/libobjc2/eh_personality.c:553
#11 0xb603dcec in _Unwind_RaiseException () from /home/multix/code/libobjc2/Build/libobjc.so.4.6
#12 0xb602bae3 in objc_exception_throw (object=0x804c608 <._OBJC_CLASS_MsgTest>)
    at /home/multix/code/libobjc2/eh_personality.c:239
#13 0x08049305 in +[MsgTest initialize] (self=0x804c608 <._OBJC_CLASS_MsgTest>, _cmd=0xb5c03e70)
    at /home/multix/code/libobjc2/Test/objc_msgSend.m:94
#14 0xb601dbf3 in objc_send_initialize (object=0x804c608 <._OBJC_CLASS_MsgTest>) at /home/multix/code/libobjc2/dtable.c:788
#15 0xb6029798 in objc_msg_lookup_internal (receiver=0xbfb6e3d8, selector=0x804ca7c <objc_selector_foo_>, version=0x0)
    at /home/multix/code/libobjc2/sendmsg2.c:107
#16 slowMsgLookup (receiver=0xbfb6e3d8, cmd=0x804ca7c <objc_selector_foo_>) at /home/multix/code/libobjc2/sendmsg2.c:161
#17 0xb602fb13 in objc_msgSend () at /home/multix/code/libobjc2/objc_msgSend.x86-32.S:121
#18 0x08049b9e in main () at /home/multix/code/libobjc2/Test/objc_msgSend.m:183

Any specific details you would like to be printed out?

@davidchisnall
Copy link
Member

It's crashing here. It's failing to find the exception object in the thrown exception. If you poke memory around there, you may be able to find what needs to be changed for NetBSD.

@rmottola
Copy link
Member Author

rmottola commented Apr 9, 2021

Well I don't know what I should do with "poke memory around there", I tried to inspet the exception class:

#3  0xb9d1e955 in test_eh_personality (version=1, actions=1, exceptionClass=5138137972254386944, exceptionObject=0xb98ca040, 
    context=0xbfbab1ec) at /home/multix/code/libobjc2/objcxx_eh.cc:485
485                             abort()

(gdb) p exceptionObject
$4 = (_Unwind_Exception *) 0xb98ca040
(gdb) p refcount_backwards_offset
$5 = -52

I tried to print out the value and maybe "poke" by changing the -52, but I can't:

(gdb) p read_offset(exceptionObject,-52)
Invalid data type for function to be called.

I tried this:

(gdb) p *reinterpret_cast<uintptr_t>(reinterpret_cast<char*>(exceptionObject) - 52)
$11 = 0
(gdb) p *reinterpret_cast<uintptr_t>(reinterpret_cast<char*>(exceptionObject) - 53)
$12 = 0
(gdb) p *reinterpret_cast<uintptr_t>(reinterpret_cast<char*>(exceptionObject) - 54)
$13 = 0
(gdb) p *reinterpret_cast<uintptr_t>(reinterpret_cast<char*>(exceptionObject) - 55)
$14 = 0
(gdb) p *reinterpret_cast<uintptr_t>(reinterpret_cast<char*>(exceptionObject) - 56)
$15 = 0
(gdb) p *reinterpret_cast<uintptr_t>(reinterpret_cast<char*>(exceptionObject) - 57)
$16 = 0
(gdb) p *reinterpret_cast<uintptr_t>(reinterpret_cast<char*>(exceptionObject) - 58)
$17 = 0
(gdb) p *reinterpret_cast<uintptr_t>(reinterpret_cast<char*>(exceptionObject) - 59)
$18 = 0
(gdb) p *reinterpret_cast<uintptr_t>(reinterpret_cast<char*>(exceptionObject) - 60)
$19 = 0
(gdb) p *reinterpret_cast<uintptr_t>(reinterpret_cast<char*>(exceptionObject) - 51)
$20 = 1543503872
(gdb) p *reinterpret_cast<uintptr_t>(reinterpret_cast<char*>(exceptionObject) - 50)
$21 = 761004032
(gdb) p *reinterpret_cast<uintptr_t>(reinterpret_cast<char*>(exceptionObject) - 49)
$22 = -752002048
(gdb) p *reinterpret_cast<uintptr_t>(reinterpret_cast<char*>(exceptionObject) - 48)
$23 = -1177342628

Looks almost as if it is off-by-one? I don't know exactly what to look for, but 51 has data.

@davidchisnall
Copy link
Member

Can you also print the expected value? I can't tell if any of the dumped values are the right one.

@rmottola
Copy link
Member Author

Where is the expected value? From the code it looks like searching for 1. Please tell me which variable to printout or how to print you the expected value.

$2 = {<std::__atomic_base<int>> = {static _S_alignment = 4, _M_i = -48}, <No data fields>}
(gdb) p sizeof(uintptr_t)
$3 = 4

@rmottola
Copy link
Member Author

Please let me know if the above is useful or how to print the expected value you need.

@davidchisnall
Copy link
Member

It's looking for the offset of the refcount, so it expects to find a value of 1 somewhere. I don't know why it isn't in any of the expected places with NetBSD, you'll have to look at the source code for the NetBSD C++ runtime and try to find where it puts it in the __cxa_exception structure.

@rmottola
Copy link
Member Author

rmottola commented Apr 21, 2021

I found a reference of the __cxa_exception here unwind-cxx.h#L62, is this structure what you are referring to? but I find the refcount you need. Please help me to help you.

@davidchisnall
Copy link
Member

It looks as if the refcount is here.

It may be that this line is wrong (are you doing this on a 32-bit platform?) if uintptr_t is not the same size as word.

That said, we don't actually use the result of this scanning anywhere anymore, so the right fix is probably to just delete the code. See #205.

@rmottola
Copy link
Member Author

Yes, this is on a 32bit platform.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging a pull request may close this issue.

2 participants