Page 1 of 1

How do you solve the order problem when you link the .o file

Posted: Mon Oct 11, 2021 12:03 am
by benjixu
I often have linking problems, when I build a project with multiple static libraries. When I am going to link the .o files. Then, I found this problem that is if I change the .o files' order, I won't correctly run this kernel. Later, I searched a lot of materials, and I found this:
On Unix-like systems, the traditional behavior of compilers and linkers
is to search for external functions from left to right in the object files
specified on the command line. This means that the object file which
contains the definition of a function should appear after any files which
call that function.

Most current compilers and linkers will search all object files, regardless
of order, but since not all compilers do this it is best to follow the
convention of ordering object files from left to right.
The link instruction are:

Code: Select all

1. ld -nostdlib -T link.lds -o kernel.elf print_amd64.o main.o kernel.o trapa.o trap.o 
2. ld -nostdlib -T link.lds -o kernel.elf kernel.o main.o trapa.o trap.o print_amd64.o

objcopy -O binary kernel.elf kernel.bin

dd if=kernel.bin of=boot.img bs=512 count=100 seek=6 conv=notrunc

qemu-system-x86_64 -cpu Skylake-Server -m 512 -hda boot.img -boot d
The first ld instruction is the right and the second one is wrong. In this case, I can certainly change this order of the .o files to make it link correctly. But I use the makefile to compile the huge system containing a lot of files. It is pretty hard to command the makefile to compile each file in order. Do you have any idea to solve this problem?

Re: How do you solve the order problem when you link the .o

Posted: Mon Oct 11, 2021 11:25 am
by nullplan
So what is the problem with the second command line? You have not actually said what happens when you use it, only that it doesn't work, which isn't a problem report. But you do use objcopy to remove the ELF headers, so I am going to assume the problem is the multiboot header not getting to the right place. That's what dedicated sections are for.

The linker treats object files and static libraries specified on command line differently from each other. Object files are always linked in, object files in static libraries are only linked in if referenced by the current set of undefined symbols. The upshot is that you may have to specify the same library multiple times to resolve all dependencies, and that order of libraries matters.

Re: How do you solve the order problem when you link the .o

Posted: Mon Oct 11, 2021 11:50 am
by iansjack
The multiboot header or is it that the program doesn't know it's start address as the headers have been removed?

Re: How do you solve the order problem when you link the .o

Posted: Mon Oct 11, 2021 2:36 pm
by benjixu
nullplan wrote:So what is the problem with the second command line? You have not actually said what happens when you use it, only that it doesn't work, which isn't a problem report. But you do use objcopy to remove the ELF headers, so I am going to assume the problem is the multiboot header not getting to the right place. That's what dedicated sections are for.

The linker treats object files and static libraries specified on command line differently from each other. Object files are always linked in, object files in static libraries are only linked in if referenced by the current set of undefined symbols. The upshot is that you may have to specify the same library multiple times to resolve all dependencies, and that order of libraries matters.
I am so glad that got your response. I am sorry I didn't describe it clearly. Actually, the ld can link the .o files as well, and I can got the .bin file. But after that, when I use qemu to boot the kernel, I found that I can't start it. I searched a lot of materials last night, and at this time, I end up found that this problem occurred by the enter function: start. as long as I put the kernel.o at the first, I can correctly run it in the qemu. I attached all project files here, so that you can test them by yourself. And Plus, If I use the makefile to compile all projects I can't adjust the order when I use the ld to link the files. Since it is the simplest project, When we build a big and complicated kernel, we have to compile a lot of files in each directory. So we hardly are able to arrange the order manually. Do you have an idea to solve this program?

Re: How do you solve the order problem when you link the .o

Posted: Mon Oct 11, 2021 2:43 pm
by benjixu
iansjack wrote:The multiboot header or is it that the program doesn't know it's start address as the headers have been removed?
I guess that the CPU can't find the entrance of kernel.asm. I attach all project files here, you can test by yourself. and Plus, If I use the makefile to compile all projects I can't adjust the order when I use the ld to link the files. Since it is the simplest project, When we build a big kernel, we have to make a lot of files in each directory. So we hardly are able to arrange the order manually. Do you have an idea to solve this program?

Re: How do you solve the order problem when you link the .o

Posted: Mon Oct 11, 2021 3:09 pm
by Octocontrabass
Your loader jumps to address 0x200000, but you actually want it to jump to the start of the .text section from kernel.o. When you link your object files in a different order, the .text section from a different object file might end up at that address.

You can change your linker script to always put the .text section from kernel.o first, or you can come up with a new section name for the entry point in kernel.asm and change your linker script to always put that new section first.

Re: How do you solve the order problem when you link the .o

Posted: Mon Oct 11, 2021 3:53 pm
by benjixu
Octocontrabass wrote:Your loader jumps to address 0x200000, but you actually want it to jump to the start of the .text section from kernel.o. When you link your object files in a different order, the .text section from a different object file might end up at that address.

You can change your linker script to always put the .text section from kernel.o first, or you can come up with a new section name for the entry point in kernel.asm and change your linker script to always put that new section first.
How can I alter the link script? I have no sense in link script?

Re: How do you solve the order problem when you link the .o

Posted: Mon Oct 11, 2021 5:26 pm
by Octocontrabass
benjixu wrote:How can I alter the link script?
Here is one way you could do it:

Code: Select all

...
SECTIONS
{
    . = 0x200000;
    /* make sure the .text section from kernel.o ends up at 0x200000 */
    .text.entry : {
        kernel.o(.text)
    }

    .text : {
        *(.text)
...
(I haven't tested this so it may not be entirely correct.)

Re: How do you solve the order problem when you link the .o

Posted: Tue Oct 12, 2021 3:09 pm
by benjixu
Octocontrabass wrote:
benjixu wrote:How can I alter the link script?
Here is one way you could do it:

Code: Select all

...
SECTIONS
{
    . = 0x200000;
    /* make sure the .text section from kernel.o ends up at 0x200000 */
    .text.entry : {
        kernel.o(.text)
    }

    .text : {
        *(.text)
...
(I haven't tested this so it may not be entirely correct.)
Yes, you are correct. And plus, if I want to put the main.o in the second one. How can I do?

Re: How do you solve the order problem when you link the .o

Posted: Tue Oct 12, 2021 3:19 pm
by Octocontrabass
Why do you want to change how main.o is linked?

Re: How do you solve the order problem when you link the .o

Posted: Tue Oct 12, 2021 9:15 pm
by benjixu
Octocontrabass wrote:Why do you want to change how main.o is linked?
I just want to know how do you write the link script.

Re: How do you solve the order problem when you link the .o

Posted: Wed Oct 13, 2021 2:22 am
by iansjack