OSDev.org
https://forum.osdev.org/

Purpose of eh_frame section?
https://forum.osdev.org/viewtopic.php?f=1&t=33469
Page 1 of 2

Author:  DevNoteHQ [ Mon Jan 28, 2019 3:00 pm ]
Post subject:  Purpose of eh_frame section?

Hi guys!

I had a problem switching from mapping the whole memory to mapping the sections that i provide by linker-symboles.
When calling some functions under certain circumstances, i got a triple-fault.
Then i looked through my section-sizes and found that there were like 0x2000 missing between .rodata and .bss.
So i did an objdump -h of my kernel and found three extra sections: .eh_frame, .rodata.str1.1 and .rodata.str1.8
I added them to .rodata like so:
Code:
.rodata ALIGN(0x1000) : AT(ADDR(.rodata) - HVMA)
{
   _rodata_start = .;
   *(.rodata)
   *(.eh_frame)
   *(.rodata.str1.1)
   *(.rodata.str1.8)
   _rodata_end = .;
}

Now i read online that .eh_frame contains stuff like C++ Exception-Handling. So .eh_frame needs to go to .text?
And what are the other two .rodata-sections?

Thanks for your help!


EDIT: And why do i get a triple-fault when adding the NX-Bit to .data and .bss?
EDIT2: I think i found the problem for .data... I'm calling start_dtors in the .data-section, aren't i?


For reference, the whole linker-file:
Code:
OUTPUT_FORMAT(elf64-x86-64)
ENTRY(start)

HVMA = 0xFFFFFF0000000000;

SECTIONS
{
   . = 1M;
   _start = . + HVMA;
   _bin_start = . + HVMA;

   .init :
   {
      *(.initl)
   }

   . += HVMA;

   .text ALIGN(0x1000) : AT(ADDR(.text) - HVMA)
   {
      *(.inith)
      *(.text)
   }

   _bin_end = .;

   .data ALIGN(0x1000) : AT(ADDR(.data) - HVMA)
   {
      _data_start = .;
      start_ctors = .;
      *(.ctor*)
      end_ctors = .;
      start_dtors = .;
      *(.dtor*)
      end_dtors = .;
      *(.data)
      _data_end = .;
   }

   .rodata ALIGN(0x1000) : AT(ADDR(.rodata) - HVMA)
   {
      _rodata_start = .;
      *(.rodata)
      *(.eh_frame)
      *(.rodata.str1.1)
      *(.rodata.str1.8)
      _rodata_end = .;
   }

   .bss ALIGN(0x1000) : AT(ADDR(.bss) - HVMA)
   {
      _bss_start = .;
      *(COMMON)
      *(.bss)
      _bss_end = .;
   }

   _end = .;
}

Author:  nullplan [ Tue Jan 29, 2019 1:51 pm ]
Post subject:  Re: Purpose of eh_frame section?

First of all, might I suggest moving the .rodata section behind the .text section? This would allow the linker to create a single non-writable segment in the output file (and then a single non-executable one). Makes for easier loading, is all.

Second, compilers sometimes add things to the ends of section names. Which you took care of in the ctors sections but not anywhere else.
So, your linker script needs stuff like

Code:
.text : {
  *(.inith)
  *(.text)
  *(.text.*)
}


Why do you always go for page alignment? That's unnecessary except for the break between code and data.

And finally, .eh_frame is indeed for exception handling. However, unless you are using C++, and have a lib capable of handling exceptions, you can just discard it. It is data, and usually read-only as well. Basically contains an exception table.

Author:  DevNoteHQ [ Tue Jan 29, 2019 3:05 pm ]
Post subject:  Re: Purpose of eh_frame section?

Yeah i saw that on the "Creating a 64-bit kernel"-Tutorial. In the "Bare Bones"-Tutorial they put .rodata in a seperate section, which is probably why i did that too. Is that because of the old section-system in the gdt?
I thought it would be a security-issue to put .rodata into .text because you could then execute stuff in .rodata, but i mean what would execute some random non-writable data do for a potential hacker? :mrgreen:

Is it also enough to just add the * after each section without the dot? I did something like this for everything and it seems to work just fine:
Code:
.text ALIGN(0x1000) : AT(ADDR(.text) - HVMA)
   {
      *(.inith)
      *(.text*)
      *(.eh_frame)
      *(.rodata*)
   }

That would make sence, will do :mrgreen:
Well my current issue is that i can add the NX-Bit to .data, but not to .bss; Does .bss also contain function-pointers? Because i do call function-pointers sometimes...
So i could just put .bss and COMMON into .data if i get the NX-Bit to work?

Yeah I'm writing in C++, but i don't have a lib for exception-handling (yet). Would those be the unwind-libs?

To further simplify my linker-script: Can i put . += HVMA into .text between .initl and .inith? So that i could delete the seperate .init-section?

EDIT: Or do assembly-portions end up in .bss if you don't specify a section?

Author:  tabz [ Wed Jan 30, 2019 3:23 am ]
Post subject:  Re: Purpose of eh_frame section?

DevNoteHQ wrote:
Yeah I'm writing in C++, but i don't have a lib for exception-handling (yet). Would those be the unwind-libs?


Yeah the unwinder is the part of your runtime that finds the appropriate exception handler for an exception when it's thrown.

Author:  DevNoteHQ [ Wed Jan 30, 2019 8:28 am ]
Post subject:  Re: Purpose of eh_frame section?

tabz wrote:
Yeah the unwinder is the part of your runtime that finds the appropriate exception handler for an exception when it's thrown.


But i would need to support C++-Exceptions in my ISRs too, don't I?

Author:  nullplan [ Wed Jan 30, 2019 12:05 pm ]
Post subject:  Re: Purpose of eh_frame section?

DevNoteHQ wrote:
But i would need to support C++-Exceptions in my ISRs too, don't I?


If you were to use exceptions, take good care not to throw anything into the assembly code. I mean, what would be the meaning of throwing an exception out of an ISR? That would be an error. And while throwing out of a syscall arguably has a meaning, there is no ABI for exception unwinding through a context switch. Nor is one simple to create.

So, no, your assembly stubs to enter the C++ code would not need to support exceptions, as long as that C++ code ensures no exceptions ever reach the assembly code.

Alternatively, you can study the Itanium ABI to generate an exception trampoline for all your assembly stubs. Which seems a lot of work for something so easily prevented.

Author:  DevNoteHQ [ Wed Jan 30, 2019 12:16 pm ]
Post subject:  Re: Purpose of eh_frame section?

nullplan wrote:
If you were to use exceptions, take good care not to throw anything into the assembly code. I mean, what would be the meaning of throwing an exception out of an ISR? That would be an error. And while throwing out of a syscall arguably has a meaning, there is no ABI for exception unwinding through a context switch. Nor is one simple to create.

So, no, your assembly stubs to enter the C++ code would not need to support exceptions, as long as that C++ code ensures no exceptions ever reach the assembly code.

Alternatively, you can study the Itanium ABI to generate an exception trampoline for all your assembly stubs. Which seems a lot of work for something so easily prevented.


No i meant for example that when i cause a "divide-by-zero" fault i need to forward it from the ISR to the exception-handler, don't i?

Author:  Korona [ Wed Jan 30, 2019 12:47 pm ]
Post subject:  Re: Purpose of eh_frame section?

nullplan wrote:
DevNoteHQ wrote:
But i would need to support C++-Exceptions in my ISRs too, don't I?


If you were to use exceptions, take good care not to throw anything into the assembly code. I mean, what would be the meaning of throwing an exception out of an ISR? That would be an error. And while throwing out of a syscall arguably has a meaning, there is no ABI for exception unwinding through a context switch. Nor is one simple to create.

That is not quite true - you can add CFI directives to allow throwing exceptions through stack switches (e.g. iret, if you know that the interrupted stack also belongs to the kernel). Not that it's a good idea, but it is certainly possible. I considered doing this to generate EFAULT in the kernel (together with -fnon-call-exceptions). This method works but has other problems (like producing a lot of bloat in the exception tables).

Author:  tabz [ Wed Jan 30, 2019 1:28 pm ]
Post subject:  Re: Purpose of eh_frame section?

DevNoteHQ wrote:
nullplan wrote:
If you were to use exceptions, take good care not to throw anything into the assembly code. I mean, what would be the meaning of throwing an exception out of an ISR? That would be an error. And while throwing out of a syscall arguably has a meaning, there is no ABI for exception unwinding through a context switch. Nor is one simple to create.

So, no, your assembly stubs to enter the C++ code would not need to support exceptions, as long as that C++ code ensures no exceptions ever reach the assembly code.

Alternatively, you can study the Itanium ABI to generate an exception trampoline for all your assembly stubs. Which seems a lot of work for something so easily prevented.


No i meant for example that when i cause a "divide-by-zero" fault i need to forward it from the ISR to the exception-handler, don't i?


I think we're a bit confused by the term exception. By "exception", I mean a C++ exception that is thrown with a "throw" statement and caught in a "try { ... } catch(...) { ... }". These (AFAIK) are entirely managed by the C++ runtime and don't touch your ISRs. Your ISRs receive CPU exceptions which are different to C++ exceptions. Someone can correct me if I'm wrong.

Author:  DevNoteHQ [ Wed Jan 30, 2019 2:53 pm ]
Post subject:  Re: Purpose of eh_frame section?

tabz wrote:
I think we're a bit confused by the term exception. By "exception", I mean a C++ exception that is thrown with a "throw" statement and caught in a "try { ... } catch(...) { ... }". These (AFAIK) are entirely managed by the C++ runtime and don't touch your ISRs. Your ISRs receive CPU exceptions which are different to C++ exceptions. Someone can correct me if I'm wrong.


Well I thought that they would be handled through the ISRs. So what kind of exceptions are handled by the C++ runtime? Coming from C# I find it difficult to differentiate language features. So for example if you declare a new object in C#, but don't give it a address through 'new', you would get an exception by the .net-Framework if you try to use it. But that seems impossible in C++ without ISR-Support?

EDIT: But my most important question remains: Why can't i disable execution of instructions in my .bss-Section?

Author:  nullplan [ Thu Jan 31, 2019 9:22 am ]
Post subject:  Re: Purpose of eh_frame section?

DevNoteHQ wrote:
Well I thought that they would be handled through the ISRs. So what kind of exceptions are handled by the C++ runtime? Coming from C# I find it difficult to differentiate language features. So for example if you declare a new object in C#, but don't give it a address through 'new', you would get an exception by the .net-Framework if you try to use it. But that seems impossible in C++ without ISR-Support?

I presume this is because C# initializes all uninitialized variables to NULL, and accessing that causes a fault.

C++ exception handling is, as has been stated, about C++ exceptions, i.e. whatever happens if a function notices it cannot deliver on its promises and executes a throw statement. CPU exceptions are something entirely different. You could try to throw out of an exception handler, sure, but I'm not sure if the ABI allows that. Alternatively you could try to bend the return IP to a function that throws, but I'm not sure if that works, either. Frankly, I don't use C++ in kernel space. If I have a fault in kernel space, I have my own exception tables to handle them. If that doesn't work, there is only the panic() function.

Quote:
EDIT: But my most important question remains: Why can't i disable execution of instructions in my .bss-Section?

What are you trying to execute there? If it is the ctors list, then you are probably doing it wrong. Inspect those sections yourself, but aren't those usually just lists of pointers to functions? In that case you should execute the pointed-to functions, not the list.

Author:  DevNoteHQ [ Thu Jan 31, 2019 12:35 pm ]
Post subject:  Re: Purpose of eh_frame section?

nullplan wrote:
I presume this is because C# initializes all uninitialized variables to NULL, and accessing that causes a fault.

C++ exception handling is, as has been stated, about C++ exceptions, i.e. whatever happens if a function notices it cannot deliver on its promises and executes a throw statement. CPU exceptions are something entirely different. You could try to throw out of an exception handler, sure, but I'm not sure if the ABI allows that. Alternatively you could try to bend the return IP to a function that throws, but I'm not sure if that works, either. Frankly, I don't use C++ in kernel space. If I have a fault in kernel space, I have my own exception tables to handle them. If that doesn't work, there is only the panic() function.

Oh okay. Was just a bit confused by languages :mrgreen:

nullplan wrote:
What are you trying to execute there? If it is the ctors list, then you are probably doing it wrong. Inspect those sections yourself, but aren't those usually just lists of pointers to functions? In that case you should execute the pointed-to functions, not the list.


Well the ctors list is in .data, which works just fine with the NX-Bit. As far as I'm aware, I don't use any function pointers except in my simple keyboard-driver. But i guess debugging it with the NX-Bit set would probably answer some questions...

Author:  kzinti [ Thu Jan 31, 2019 2:09 pm ]
Post subject:  Re: Purpose of eh_frame section?

DevNoteHQ wrote:
Well the ctors list is in .data, which works just fine with the NX-Bit. As far as I'm aware, I don't use any function pointers except in my simple keyboard-driver. But i guess debugging it with the NX-Bit set would probably answer some questions...


It doesn't matter if the function pointers are in an NX-protected page in the data section. Pointers are not executed, the functions that they point to are. The functions themselves need to be in non-NX pages.

Author:  DevNoteHQ [ Fri Feb 01, 2019 4:16 am ]
Post subject:  Re: Purpose of eh_frame section?

kzinti wrote:
It doesn't matter if the function pointers are in an NX-protected page in the data section. Pointers are not executed, the functions that they point to are. The functions themselves need to be in non-NX pages.

Yeah thats clear, but how would i put a function into the .bss section in C/C++? Because I'm pretty sure i don't have a assembly file with section .bss except the bootup-code, where I create the stack in .bss... So there shouldn't be a single function outside .text...

Author:  XenOS [ Fri Feb 01, 2019 4:48 am ]
Post subject:  Re: Purpose of eh_frame section?

Have you had a look at running objdump on your output file? What does your .bss section contain? What is at the address from which you get the fault when NX is enabled? Is that address in the .bss section?

Page 1 of 2 All times are UTC - 6 hours
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/