3

I'm writing my own operating system (static addresses) and I struggle to get the linker to always put my _start function at my desired location within the processes. I specify the location with -Ttext 0x10000 in my build file (Lets just say 0x10000 for this example).

Normally this works, but when i use -O2 the linker puts my main function on this address instead.

So how can i make sure that it is _start that ends up on this address? And is it possible without writing linker scripts?

The function _start is common for all processes and should enforce a nice exit for the scheduler in cases where the program returns instead of calling the exit(). I have a workaround solution in my head but I would preferred to get this working with the linker instead.

Espen Nilsen
  • 121
  • 1
  • 7
  • Thanks for the comment. The start function is in its own file.. And i realy would like to support main since it is its own process (compiled individually and included by the image builder). But - O2 messes this up. Anything i have missed. – Espen Nilsen Mar 19 '19 at 17:23
  • 1
    Is there a reason you can't use a linker script? When you use LD without a linker script it will use an internal linker script. That internal linker script (which you can see with `ld -V` places `.text.startup` before `.text` . At higher optimization levels `main` may be placed in the `.text.startup` section which is placed before `.text` in most (if not all) default linker scripts. Without a linker script one way to avoid this is to place `main` directly in `.text`.Declare `main`this way `int __attribute__((__section__(".text"))) main()` to force main into section `.text` – Michael Petch Mar 19 '19 at 18:00
  • Wow @MichaelPetch ! Thanks for that explanation, that attribute trick did work! No, there is no reason other than my own competence (to say it Dilbert terms). If I knew how to make variables from the make file propagate to a linker script that would also be a nice way of doing it. Right now just trying to educate myself on this issue, if the final verdict is that this can not be done by the way I'm doing it that also would be a valid answer. But how does this work for linux and the crt0? Is the linker aware that this is special? – Espen Nilsen Mar 19 '19 at 18:10
  • So just to be clear; when i disassemble I see that `_start` is now in the `.text` section and `main` is in the `.text.startup` section. Linking with `--entry=_start` has no effect. – Espen Nilsen Mar 19 '19 at 18:30
  • Can i build the process (file containing main) so it does not end up within `.text.startup` without doing it whit the `__attribute__` (etc.) statement ? Or is this the wrong way of looking at the problem? – Espen Nilsen Mar 19 '19 at 18:33
  • The right way would be a linker script that places things in the order you expect (you can also set the VMA in the linker script to 0x10000). I don't personally know of any command line option to force GCC to guarantee `main` is in `.text`. You can get the default linker script with `ld -V` and use it as a template to create your own. You can move`.text.startup` after `.text` – Michael Petch Mar 19 '19 at 18:42
  • Thank you for the comment. That's unfortunate :-) Do you think you could link to a pastebin with to your default? My ld -V (GNU ld (GNU Binutils for Ubuntu)) does not generate that output, it only prints the supported emulations. I have never tried to create my own linker script (although I have by now read a lot of the documentation). – Espen Nilsen Mar 19 '19 at 19:01
  • I should have corrected myself you should use `ld --verbose` instead of `ld -V` . The linker script is all the text **between** the lines with `=========================` – Michael Petch Mar 19 '19 at 19:05

2 Answers2

2

So i found 2 solutions.

  1. Set .section .text.startup in the file containing _start
  2. Set .section .text.mustbefirst (my own section name) in the file containing _start

In the first variant i just make sure that the start code also is included with the same order as the code containing main, although there are some ambiguity this did work in my case.

In the second variant i modified the default linker script to make sure my section symbol was first.

If the first is reliable (eg. depends on order of arguments or something) then this is OK. As an aside; does anybody know? If not then i would recommend a new section symbol and modified linker script.

Espen Nilsen
  • 121
  • 1
  • 7
-2

Add this in your linker script file (for instance if your startup file is crt0.o which contains _start)

STARTUP(crt0.o)

(found at https://wiki.osdev.org/Linker_Scripts#STARTUP)

now a (for me it's powerpc) disassembly of the start of the file yields:

main.elf:     file format elf32-powerpc

Disassembly of section .text:

01800154 <_start>:
 1800154:       94 21 ff e0     stwu    r1,-32(r1)
 1800158:       7c 08 02 a6     mflr    r0
 180015c:       93 61 00 0c     stw     r27,12(r1)
 1800160:       93 81 00 10     stw     r28,16(r1)

without that, the _start symbol was either absent (if entrypoint wasn't specified) or in the middle of the file (which can be an issue even if the entrypoint is defined because some loaders just ignore the entrypoint information and jump at the start of the file)

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219