OSDev.org https://forum.osdev.org/ |
|
_Unwind_RaiseException() calls abort() https://forum.osdev.org/viewtopic.php?f=1&t=31366 |
Page 1 of 1 |
Author: | robbiedobbie [ Tue Feb 14, 2017 12:24 pm ] |
Post subject: | _Unwind_RaiseException() calls abort() |
Currently, I'm implementing the C++ ABI (as described on http://mentorembedded.github.io/cxx-abi/) to get RTTI and Exceptions working. RTTI is working fine already, however I'm experiencing some difficulties while getting Exceptions to work. I made a simple testcase in which I throw an integer and catch it in the function below. Compiling works just fine, and when running, allocating my exception structure + exception body works fine too. The __cxa_throw method is called correctly as well. However, in this method, **** hits the fan. To start unwinding the stack, I call _Unwind_RaiseException() with my unwindHeader as an argument. This however calls my abort function (Which is required since libgcc needs it as soon as exceptions are not disabled). After some debugging, I think the libgcc unwinder can't find the stack frames and relating info. I read in the wiki before that when using libsupc++ (Which I'm not using), you would have to call "__register_frame(address_of_eh_frames);" to set the correct eh_frame location so that it can find the info in those frames. I'm not setting the address of the eh_frames anywhere currently, and haven't seen anything in the ABI describing this. I also went through the sourcecode of libsupc++ to see what the __register_frame function does, but I didn't see anything interacting with the libgcc unwinder. I also checked my compiled elf to see whether the sections are set correctly, which they seem to be: Code: ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: Advanced Micro Devices X86-64 Version: 0x1 Entry point address: 0xffffffff8000dfdc Start of program headers: 64 (bytes into file) Start of section headers: 2627112 (bytes into file) Flags: 0x0 Size of this header: 64 (bytes) Size of program headers: 56 (bytes) Number of program headers: 4 Size of section headers: 64 (bytes) Number of section headers: 20 Section header string table index: 17 Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 [ 1] .text PROGBITS ffffffff80000000 00001000 000000000001ba04 0000000000000000 AX 0 0 4096 [ 2] .data PROGBITS ffffffff8001c000 0001d000 00000000002135b8 0000000000000000 WA 0 0 4096 [ 3] .bss NOBITS ffffffff80230000 002305b8 00000000000027f8 0000000000000000 WA 0 0 4096 [ 4] .eh_frame PROGBITS ffffffff80233000 00231000 00000000000031a8 0000000000000000 A 0 0 4096 [ 5] .gcc_except_table PROGBITS ffffffff80237000 00235000 0000000000000040 0000000000000000 A 0 0 4096 [ 6] .init PROGBITS ffffffff80238000 00236000 0000000000000010 0000000000000000 AX 0 0 4096 [ 7] .fini PROGBITS ffffffff80239000 00237000 000000000000000b 0000000000000000 AX 0 0 4096 [ 8] .jcr PROGBITS ffffffff8023a000 00238000 0000000000000008 0000000000000000 WA 0 0 4096 [ 9] .comment PROGBITS 0000000000000000 00238008 0000000000000011 0000000000000001 MS 0 0 1 [10] .debug_info PROGBITS 0000000000000000 00238019 000000000001df48 0000000000000000 0 0 1 [11] .debug_abbrev PROGBITS 0000000000000000 00255f61 0000000000004c2d 0000000000000000 0 0 1 [12] .debug_aranges PROGBITS 0000000000000000 0025ab8e 0000000000000a50 0000000000000000 0 0 1 [13] .debug_ranges PROGBITS 0000000000000000 0025b5de 0000000000001c10 0000000000000000 0 0 1 [14] .debug_line PROGBITS 0000000000000000 0025d1ee 00000000000056c7 0000000000000000 0 0 1 [15] .debug_str PROGBITS 0000000000000000 002628b5 0000000000009387 0000000000000001 MS 0 0 1 [16] .debug_loc PROGBITS 0000000000000000 0026bc3c 000000000000bb1f 0000000000000000 0 0 1 [17] .shstrtab STRTAB 0000000000000000 0028156c 00000000000000bb 0000000000000000 0 0 1 [18] .symtab SYMTAB 0000000000000000 00277760 0000000000005b50 0000000000000018 19 398 8 [19] .strtab STRTAB 0000000000000000 0027d2b0 00000000000042bc 0000000000000000 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings), I (info), L (link order), O (extra OS processing required), G (group), T (TLS), C (compressed), x (unknown), o (OS specific), E (exclude), l (large), p (processor specific) There are no section groups in this file. Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align LOAD 0x0000000000001000 0xffffffff80000000 0xffffffff80000000 0x000000000001ba04 0x000000000001ba04 R E 1000 LOAD 0x000000000001d000 0xffffffff8001c000 0xffffffff8001c000 0x00000000002135b8 0x00000000002167f8 RW 1000 LOAD 0x0000000000231000 0xffffffff80233000 0xffffffff80233000 0x000000000000600b 0x000000000000600b R E 1000 LOAD 0x0000000000238000 0xffffffff8023a000 0xffffffff8023a000 0x0000000000000008 0x0000000000000008 RW 1000 Section to Segment mapping: Segment Sections... 00 .text 01 .data .bss 02 .eh_frame .gcc_except_table .init .fini 03 .jcr There is no dynamic section in this file. There are no relocations in this file. Am I overlooking something in the ABI? Or is something missing in there? Any clues on how to get _Unwind_RaiseException() to work and start unwinding the stack (After which my personality function can take over...)? |
Author: | dchapiesky [ Tue Feb 14, 2017 6:41 pm ] |
Post subject: | Re: _Unwind_RaiseException() calls abort() |
In libgcc the eh_frame registration hokus-pokus is contained in https://github.com/gcc-mirror/gcc/blob/ ... crtstuff.c as well as https://github.com/gcc-mirror/gcc/blob/ ... bl-ctors.h and is intimately related to the compiler emitting proper entries in .init/.fini sections. So just as a test I would check that things like c constructors actually work first.... Code: char *teststring = 0; __attribute__((constructor)) void TestMe (void) { teststring = "Worked!"; } int main(int argc, char **argv) { printf("Message [%s]\n", teststring); } I did not print in the TestMe() constructor as stdout will not have been setup yet by crt0.c If you get "Worked!" then your .init/.fini is playing nice with the compiler and likewise - with libgcc at least - the eh_frame will have been registered. I know you said you don't use libgcc, but the control flow in the libgcc files above should give you a heads up as to how to go about it. Good luck and cheers |
Author: | robbiedobbie [ Wed Feb 15, 2017 2:57 am ] |
Post subject: | Re: _Unwind_RaiseException() calls abort() |
Thank you for responding dchapiesky wrote: In libgcc the eh_frame registration hokus-pokus is contained in https://github.com/gcc-mirror/gcc/blob/ ... crtstuff.c as well as https://github.com/gcc-mirror/gcc/blob/ ... bl-ctors.h I've been looking into the source and I first thought that __register_frame_info was something defined in libsupc++, but I now tried calling it as an external symbol anyway, and it seems to link just fine. So I will be experimenting with it, to see if this fixes my issues. dchapiesky wrote: and is intimately related to the compiler emitting proper entries in .init/.fini sections. So just as a test I would check that things like c constructors actually work first.... Constructors are working fine (both C and static C++ objects, not that it makes a difference to the compiler). dchapiesky wrote: If you get "Worked!" then your .init/.fini is playing nice with the compiler and likewise - with libgcc at least - the eh_frame will have been registered. I know you said you don't use libgcc, but the control flow in the libgcc files above should give you a heads up as to how to go about it. I am using libgcc, I'm not using libsupc++. So you're saying that the registering of eh_frame should work just fine if the .init/.fini sections are linked and run correctly? |
Author: | dchapiesky [ Wed Feb 15, 2017 6:22 am ] |
Post subject: | Re: _Unwind_RaiseException() calls abort() |
Well.... after looking at those two files I posted and remembering the pain.... Please let me ramble about this for a few moments and then hopefully I will have something to contribute... Basically it goes like this... 1) elf loader loads your program 2) elf loader finds ENTRY() point - usually _start 3) _start() being in crt0.c iterates .init and calls each function pointer in the list 4) one of those entries in .init is called frame_dummy() - line 459 in crtstuff.c from libgcc - injected into .init section simply by linking attributes 5) frame_dummy() - and this is the important part - calls register_frame_info in a fashion that was configured at build time of the host gcc compiler... note the USE_EH_FRAME_REGISTRY, etc... so libgcc, and how the frame information is *generated* by the compiler are closely intertwined - thus hokus-pokus 6) in unwind_dw2-fde.c of libgcc we see __register_frame() defined at line 110 - it checks to see if eh_frame exists and does an allocation using malloc() and then calls register_frame_info() on the eh_frame pointer. __register_frame() seems to be bone thrown to non-glibc libraries since if you grep the source code of gcc you find that the ONLY place __register_frame() is used is in its definition. Ramble over... In gcc.c at around 1740 we see that register_frame_info() is referenced and more hokus pokus based on compiler configuration. So... in gcc.c at 1763 - we see Code: #ifdef USE_LIBUNWIND_EXCEPTIONS and so I would ask is your compiler configured for this? But I worry that I am simply sending you on a wild goose chase.... So the best I think I can recommend at this point is examining the llvm project and how they do it.. https://github.com/llvm-mirror?tab=repositories llvm.org specifically their libunwind, libcxx, and libcxxabi libraries.... I do note that their libunwind looks for an .eh_frame_hdr section which is not shown in your first post. See https://github.com/llvm-mirror/libunwin ... Parser.hpp Sorry I couldn't be of much better help. |
Author: | robbiedobbie [ Wed Feb 15, 2017 8:27 am ] |
Post subject: | Re: _Unwind_RaiseException() calls abort() |
dchapiesky wrote: 1) elf loader loads your program 2) elf loader finds ENTRY() point - usually _start 3) _start() being in crt0.c iterates .init and calls each function pointer in the list 4) one of those entries in .init is called frame_dummy() - line 459 in crtstuff.c from libgcc - injected into .init section simply by linking attributes 5) frame_dummy() - and this is the important part - calls register_frame_info in a fashion that was configured at build time of the host gcc compiler... note the USE_EH_FRAME_REGISTRY, etc... so libgcc, and how the frame information is *generated* by the compiler are closely intertwined - thus hokus-pokus 6) in unwind_dw2-fde.c of libgcc we see __register_frame() defined at line 110 - it checks to see if eh_frame exists and does an allocation using malloc() and then calls register_frame_info() on the eh_frame pointer. __register_frame() seems to be bone thrown to non-glibc libraries since if you grep the source code of gcc you find that the ONLY place __register_frame() is used is in its definition. After some more examining of libgcc and libsupc++ I arrived at the same conclusions. I still tried manually registering the frame, but this didn't change anything. dchapiesky wrote: In gcc.c at around 1740 we see that register_frame_info() is referenced and more hokus pokus based on compiler configuration. So... in gcc.c at 1763 - we see Code: #ifdef USE_LIBUNWIND_EXCEPTIONS and so I would ask is your compiler configured for this? As far as I can see this is used when actually using libunwind (Which differs from the basic libgcc unwinding). It might be that I'm incorrect on this point though, I'm just touching the source of gcc for the very first time with this project. dchapiesky wrote: I do note that their libunwind looks for an .eh_frame_hdr section which is not shown in your first post. See https://github.com/llvm-mirror/libunwin ... Parser.hpp Sorry I couldn't be of much better help. That's actually a good one. I have seen the section before, but can't remember when. I'll go check whether this might be an issue. Also, I want to thank you because you have already given me quite some pointers on what might be wrong, so don't be sorry, it's actually very usefull |
Page 1 of 1 | All times are UTC - 6 hours |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |