OSDev.org

The Place to Start for Operating System Developers
It is currently Tue Mar 19, 2024 7:59 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 7 posts ] 
Author Message
 Post subject: C code and Linkier script: calculate jump locations
PostPosted: Wed Nov 07, 2018 10:25 am 
Offline

Joined: Wed Nov 07, 2018 10:15 am
Posts: 23
I have a problem, with I resolve in simple way. The problem was I creating my own kernel, which cannot use multi cores, etc. It handles modules. Modules is a binary blob loaded by Grub2 bootloader. Because I don't know the exactly address module is loaded, I use variable at fixed address. In both kernel and module address I use extern directive to have access to this variable and write linker script to put this variable into specific place of memory. Before accessing module code, I simply set these variable to beginning of my module in memory.

Only modules without forks works. I cannot use jumps, so if, while, do... while, for and goto isn't usable. Either I cannot use function call in my module code.

Question is: How to tell linker or compiler to calculate each jump by value placed in some place of memory?


Top
 Profile  
 
 Post subject: Re: C code and Linkier script: calculate jump locations
PostPosted: Wed Nov 07, 2018 11:16 am 
Offline
Member
Member
User avatar

Joined: Thu Nov 16, 2006 12:01 pm
Posts: 7612
Location: Germany
What you are looking for is "position independent code" (PIC).

_________________
Every good solution is obvious once you've found it.


Top
 Profile  
 
 Post subject: Re: C code and Linkier script: calculate jump locations
PostPosted: Wed Nov 07, 2018 1:18 pm 
Offline

Joined: Wed Nov 07, 2018 10:15 am
Posts: 23
Thank you.

I created shared objects previously for GNU/Linux, but I don't know how to use this flag, when programming an kernel. How to use this flag with conjunction giving address to read start of my kernel module?

That's a my linker script:
Code:
OUTPUT_FORMAT("binary")
ENTRY("init")
PROVIDE(__module_load_addr = 0x1000);
SECTIONS {
  . = 0;
  .text : {
    *(.text)
  }
 
  .rodata : {
    *(.rodata)
  }
 
  .data  : {
    *(.data)
  }
 
  .bss : {
    *(.bss)
  }

}


Module_load_addr is a void * to variable keeping address whereas my kernel module is loaded.
So the format is binary, not elf. It is possible to change this linker script without changing output format? My OS will probably support elf in future, but in another time.


Top
 Profile  
 
 Post subject: Re: C code and Linkier script: calculate jump locations
PostPosted: Wed Nov 07, 2018 11:07 pm 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 1590
You should probably investigate why loops and conditionals don't work right now. Because those typically are position independent (short and near jumps use a relative offset).

I would suggest compiling your modules with load address 0, and in PIC mode. I don't know how you locate a specific function in the module right now, but I would add an offset table to the start. Then the kernel can just calculate a function pointer when the module is loaded by adding the base address to the offsets, and then call the function pointers. I don't know how the module would call back into the kernel. You might want to hand it a couple of function pointers as well.

_________________
Carpe diem!


Top
 Profile  
 
 Post subject: Re: C code and Linkier script: calculate jump locations
PostPosted: Thu Nov 08, 2018 12:10 pm 
Offline

Joined: Wed Nov 07, 2018 10:15 am
Posts: 23
I discovered the problem. Linker puts my print function (module is called text_console) at the beginning of binary output file. My kernel jump to the beginning of module to initialize it. That's my linker script:
Code:
OUTPUT_FORMAT("binary")
ENTRY("init")
PROVIDE(__module_load_addr = 0x1000);
SECTIONS {
 
 
  .text : {
    *(init)
    *(.text)
  }
 
  .rodata : {
    *(.rodata)
  }
 
  .data  : {
    *(.data)
  }
 
  .bss : {
    *(.bss)
  }

}

That's a part of definition of my init function:
Code:
__attribute__ ((section ("entry"))) char init(struct drivers*dr, int driver_count) {
...
}

I must tell that gcc internals are not known for me, so I can do mistakes in many places. Be polite. Is there a way to force linker/compiler to put my init function on top of output file? I think creating one pointer to init function at the beginning of file (as nullplan suggested) is a waste of space.


Top
 Profile  
 
 Post subject: Re: C code and Linkier script: calculate jump locations
PostPosted: Fri Nov 09, 2018 9:07 am 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 670
If you put function init in the section entry in the code then don't you mean to use:

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


Top
 Profile  
 
 Post subject: Re: C code and Linkier script: calculate jump locations
PostPosted: Sun Nov 11, 2018 2:49 am 
Offline

Joined: Wed Nov 07, 2018 10:15 am
Posts: 23
Ok. Nothing works, but solution given by Employed Russian on https://stackoverflow.com/questions/661 ... -toolchain worked.
You need to use --ffunction-sections and similar linker script to this bellow:
Code:
OUTPUT_FORMAT("binary")
SECTIONS {
 
  . = 0;
  .text : {

    *(.text.init);
    *(.text.*)
  }
 
  .rodata : {
    *(.rodata)
  }
 
  .data  : {
    *(.data)
  }
 
  .bss : {
    *(.bss)
  }

}


Then init will be at beginning of output file. Thanks for help!


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 7 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: DotBot [Bot] and 8 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