OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 9:25 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 16 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Purpose of eh_frame section?
PostPosted: Mon Jan 28, 2019 3:00 pm 
Offline
Member
Member

Joined: Mon May 15, 2017 11:04 am
Posts: 50
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 = .;
}


Top
 Profile  
 
 Post subject: Re: Purpose of eh_frame section?
PostPosted: Tue Jan 29, 2019 1:51 pm 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 1593
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.

_________________
Carpe diem!


Top
 Profile  
 
 Post subject: Re: Purpose of eh_frame section?
PostPosted: Tue Jan 29, 2019 3:05 pm 
Offline
Member
Member

Joined: Mon May 15, 2017 11:04 am
Posts: 50
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?


Last edited by DevNoteHQ on Wed Jan 30, 2019 6:23 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Purpose of eh_frame section?
PostPosted: Wed Jan 30, 2019 3:23 am 
Offline
Member
Member

Joined: Fri Apr 20, 2018 9:15 am
Posts: 35
Location: Cambridge, UK
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.


Top
 Profile  
 
 Post subject: Re: Purpose of eh_frame section?
PostPosted: Wed Jan 30, 2019 8:28 am 
Offline
Member
Member

Joined: Mon May 15, 2017 11:04 am
Posts: 50
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?


Top
 Profile  
 
 Post subject: Re: Purpose of eh_frame section?
PostPosted: Wed Jan 30, 2019 12:05 pm 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 1593
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.

_________________
Carpe diem!


Top
 Profile  
 
 Post subject: Re: Purpose of eh_frame section?
PostPosted: Wed Jan 30, 2019 12:16 pm 
Offline
Member
Member

Joined: Mon May 15, 2017 11:04 am
Posts: 50
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?


Top
 Profile  
 
 Post subject: Re: Purpose of eh_frame section?
PostPosted: Wed Jan 30, 2019 12:47 pm 
Offline
Member
Member

Joined: Thu May 17, 2007 1:27 pm
Posts: 999
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).

_________________
managarm: Microkernel-based OS capable of running a Wayland desktop (Discord: https://discord.gg/7WB6Ur3). My OS-dev projects: [mlibc: Portable C library for managarm, qword, Linux, Sigma, ...] [LAI: AML interpreter] [xbstrap: Build system for OS distributions].


Top
 Profile  
 
 Post subject: Re: Purpose of eh_frame section?
PostPosted: Wed Jan 30, 2019 1:28 pm 
Offline
Member
Member

Joined: Fri Apr 20, 2018 9:15 am
Posts: 35
Location: Cambridge, UK
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.


Top
 Profile  
 
 Post subject: Re: Purpose of eh_frame section?
PostPosted: Wed Jan 30, 2019 2:53 pm 
Offline
Member
Member

Joined: Mon May 15, 2017 11:04 am
Posts: 50
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?


Top
 Profile  
 
 Post subject: Re: Purpose of eh_frame section?
PostPosted: Thu Jan 31, 2019 9:22 am 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 1593
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.

_________________
Carpe diem!


Top
 Profile  
 
 Post subject: Re: Purpose of eh_frame section?
PostPosted: Thu Jan 31, 2019 12:35 pm 
Offline
Member
Member

Joined: Mon May 15, 2017 11:04 am
Posts: 50
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...


Top
 Profile  
 
 Post subject: Re: Purpose of eh_frame section?
PostPosted: Thu Jan 31, 2019 2:09 pm 
Offline
Member
Member

Joined: Mon Feb 02, 2015 7:11 pm
Posts: 898
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.

_________________
https://github.com/kiznit/rainbow-os


Top
 Profile  
 
 Post subject: Re: Purpose of eh_frame section?
PostPosted: Fri Feb 01, 2019 4:16 am 
Offline
Member
Member

Joined: Mon May 15, 2017 11:04 am
Posts: 50
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...


Top
 Profile  
 
 Post subject: Re: Purpose of eh_frame section?
PostPosted: Fri Feb 01, 2019 4:48 am 
Offline
Member
Member
User avatar

Joined: Thu Aug 11, 2005 11:00 pm
Posts: 1110
Location: Tartu, Estonia
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?

_________________
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 16 posts ]  Go to page 1, 2  Next

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot], SemrushBot [Bot] and 55 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group