-
Notifications
You must be signed in to change notification settings - Fork 82
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
Fix C++ exceptions / threads #103
Comments
I ran into a strange issue regarding C++ exceptions. I am leaving this here in case it helps someone... In a moderately sized app (~7k SLOC), I didn't have any issue with exceptions for quite some time. Then I added a simple code that would throw and catch an exception at the beginning of The crash happens in 00102ad6 <__gnu_Unwind_RaiseException+0x26>:
102ad6: 000f movs r7, r1
102ad8: f8cd c000 str.w ip, [sp]
102adc: e006 b.n 102aec <__gnu_Unwind_RaiseException+0x3c>
102ade: 6933 ldr r3, [r6, #16]
102ae0: 466a mov r2, sp
102ae2: 4631 mov r1, r6
102ae4: 4798 blx r3
!!! 2808 cmp r0, #8 !!!
102ae8: 4604 mov r4, r0
102aea: d108 bne.n 102afe <__gnu_Unwind_RaiseException+0x4e>
102aec: 4630 mov r0, r6
102aee: 9910 ldr r1, [sp, #64] ; 0x40
102af0: f7ff feca bl 102888 <get_eit_entry>
102af4: 2800 cmp r0, #0 The real issue is at the instruction before, the I found a workaround for the moment, but I can't say for sure that it fixes the issue or just hides it until it reappears in another way. Compiling in Release instead of RelWithDebInfo seems to fix the problem. AFAIK, the only difference there is the absence of the -g flag when compiling. I am thinking that maybe when the relocation tables are getting too big, the ELF/SCE headers generated by the vita toolchain are broken and the vita fails to relocate some things? The vita does do some dynamic relocation when doing ASLR, right? Is there some code that assumes that there are less than some number of relocations? or that sections are not bigger than some size? |
This remind me of someone who ported ScummVM (IIRC) and exporting all of it functions, making the exports (or the relocs ? or the symtable ?) unbearable for the ModuleMgr.
Could you double check if this comment is really responsible for the crash/working state ? Maybe the diff will highlight some kind of sections limits that you just hit. |
I've checked it once more to be sure, probably the 5th time ^^ Here's the diff of the velf files:
Nothing strange about section sizes... or I may have missed something. Another strange thing is that the exception tables in ARM are supposed to contain relative addresses, so they shouldn't need to be relocated. If you want to see what it looks like, the following commit is the one that makes the app crash: blastrock/pkgj@724ec4c . As I said, this is unrelated code, the The commit before should work, it shows "fatal error: test" but the app does not crash. If you want to compile the code, run |
I have dug deeper, but still haven't found a fix... The issue (in my case at least) is with the entry for __cxa_throw in the unwind table (among others), which means that all exceptions will make the program crash. Entries in the unwind table look like __cxa_throw's entry in the unwind table uses the personality routine 0 (__aeabi_unwind_cpp_pr0) to handle unwinding, and as such I dumped the eboot.bin with an hexadecimal editor, and there's clearly a I have no idea why it gets replaced, and since it's done by the vita's elf loader I have no idea how to investigate further. If anyone has any idea as to why it behaves like that, it would be much appreciated. |
I have spent some more time on this... The faulty relocation is actually there, in the ELF output from ld. I tried removing just that one manually and it fixed my bug. Then I tried to understand why I get that relocation in the first place. I used readelf on eh_throw.o from libsupc++ in libstdc++, there are two relocations on __cxa_throw's unwind table, but they are not on the content field, so everything is fine there. I tried writing a custom linker script (from the default one) with this:
I've put out the problematic part in its own section. Of course this will never work as the exidx table must be ordered, but it allows me analyzing the final binary and check ld's behavior. I can see that there are several relocations in .rel.ARM.exidx that change addresses before .ARM.exidx, including in the section I have extracted. That's why I think the bug is in ld. I tried reading the code of ld, but it's a mass of chaos coming straight from hell, can't do anything in there. I tried using llvm's lld to link the binary, I had to change the linker script to add some padding for vita-elf-create for the module info structure. I managed to get an eboot, and the problematic relocation is not in there, but it won't run on my psvita giving me a generic error :( |
I think I found the root of my issue and worked around it in a patch on ld. Reported here: https://sourceware.org/bugzilla/show_bug.cgi?id=23839 Workaround here: https://sourceware.org/bugzilla/show_bug.cgi?id=20595#c1 Here is my fork of vitasdk (a bit old), with the ld patch: https://github.com/blastrock/autobuilds/releases/tag/master-linux-v8 Hope this gets fixed... |
This is really cool, thanks for investigating and reporting the bug upstream. |
@blastrock gcc 7.4 & 8.2 was applied that patch except |
The NO_IMPLICIT_EXTERN_C was merged here vitasdk/buildscripts@d27627d so you don't need it anymore if you compile master. The backported patch doesn't seem that important actually, but I didn't double check. You will need however the binutils patch blastrock/autobuilds@b2f8cd5#diff-3b86632c44a047a317357da4d98eaf0a if you have issues with exceptions. The ld bug report didn't get any answer, I guess it won't get any for a long time. |
okay, I made the patch for that. |
I got the report from @xerpi that this issue is still alive.
this test code will occur the crash. |
I'm not sure what this snippet should do. Division by zero is not an exception in c++, programs usually crash because of that (depending on the platform). On linux, you get a SIGFPE I believe.
Btw, the crash that I worked around was fixed upstream, it seems: https://sourceware.org/bugzilla/show_bug.cgi?id=23839 |
I test it with various conditions. version up binutils or apply the patch have been occurred segfault on vita-elf-create catch exception would be normal on the main thread. but when we make the thread with idk main reason, it could be problem of the ps. div 0 isn't an important part(the main issue is the crash when we use the pthread on c++). |
Then I don't think this is related to the exidx section. That section is read when the stack is unwound, which happens when you throw an exception. Since there is no throw in that program, that binutil patch shouldn't change anything. That's only my understanding however, I could be wrong. You should remove that division by 0 for your tests if it isn't important. It is undefined behavior, a crash is a valid result for that. |
sorry I'm late. |
@blastrock do you still have an example to reproduce it? Binutils issues have been closed and merged so I wan't to remove the patch |
I haven't worked on psvita in a while, so I can't be sure, but I had a branch for that. You can try to build blastrock/pkgj@724ec4c . This used to crash pkgj right after it starts with the psvita C-whatever error. The correct behavior is no crash, but a black screen with an error. Building it might prove a little hard. You need to install a bunch of tools and run |
Throwing an exception on the Vita and catching it crashes the program.
Temporary workaround by @DaveeFTW:
Add this before
main()
:Add the following to
target_link_libraries()
:The text was updated successfully, but these errors were encountered: