0

I am trying to port an OS development tutorial from NASM Intel syntax, to GAS (gcc/as).

There is one file that only has one section (.multiboot_header) that's suposed to only contain data for the bootloader. I have that file both on Intel and AT&T syntax, but when I compile them, the one compiled with GAS produces sections that werent asked for in the source file:

Nasm:

~$ objdump -h multiboot_header.asm.o 

multiboot_header.asm.o:     file format elf64-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .multiboot_header 0000000c  0000000000000000  0000000000000000  00000180  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA

Gcc:

$ objdump -h multiboot_header.S.o

multiboot_header.S.o:     file format elf64-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .text         00000000  0000000000000000  0000000000000000  00000040  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .data         00000000  0000000000000000  0000000000000000  00000040  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000000  0000000000000000  0000000000000000  00000040  2**0
                  ALLOC
  3 .multiboot_header 0000000c  0000000000000000  0000000000000000  00000040  2**0
                  CONTENTS, READONLY

As you can see gcc generates extra sections, and the file offset is not quite the same too. Why is this happening, and how can i solve it?

Edit:

Tutorial i am following: https://os.phil-opp.com/multiboot-kernel/

Here's the linker script im using:

ENTRY(start)

SECTIONS {
    . = 1M;
    
    .boot :
    {
        /* ensure that the multiboot header is at the beginning */
        *(.multiboot_header)
    }
    
    .text :
    {
        *(.text)
    }
}

Also, here's the multiboot_header.S file:

.section .multiboot_header
header_start:
    .long 0xe85250d6        # magic number (multiboot 2)
    .long 0             # architecture 0 (protected mode x86)
    .long header_end - header_start # header lenght
    # checksum
    .long 0x100000000 - (0xe85250d6 + 0 + (header_end - header_start))
    
    # insert optional multiboot tags here
    
    # required end tag
    .word 0 # type
        .word 0 # flags
        .long 8 # size
header_end:

Output of readelf -S build/kernel-x86_64.bin with GAS:

There are 6 section headers, starting at offset 0x1d8:

Section Headers:
  [Nr] Name              Type             Address           Offset         Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000       0000000000000000  0000000000000000           0     0     0
  [ 1] .boot             PROGBITS         0000000000100000  000000ee       0000000000000018  0000000000000000           0     0     1
  [ 2] .text             PROGBITS         0000000000100000  00000078       0000000000000076  0000000000000000  AX       0     0     1
  [ 3] .symtab           SYMTAB           0000000000000000  00000108       0000000000000078  0000000000000018           4     4     8
  [ 4] .strtab           STRTAB           0000000000000000  00000180       000000000000002c  0000000000000000           0     0     1
  [ 5] .shstrtab         STRTAB           0000000000000000  000001ac       0000000000000027  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  D (mbind), l (large), p (processor specific)

and with NASM:

There are 6 section headers, starting at offset 0x228:

Section Headers:
  [Nr] Name              Type             Address           Offset         Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000       0000000000000000  0000000000000000           0     0     0
  [ 1] .boot             PROGBITS         0000000000100000  00000080       0000000000000018  0000000000000000   A       0     0     1
  [ 2] .text             PROGBITS         0000000000100020  000000a0       0000000000000076  0000000000000000  AX       0     0     16
  [ 3] .symtab           SYMTAB           0000000000000000  00000118       0000000000000090  0000000000000018           4     5     8
  [ 4] .strtab           STRTAB           0000000000000000  000001a8       0000000000000059  0000000000000000           0     0     1
  [ 5] .shstrtab         STRTAB           0000000000000000  00000201       0000000000000027  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  D (mbind), l (large), p (processor specific)
SamFF
  • 203
  • 1
  • 7
  • 1
    What `gcc` command did you use to make `multiboot_header.S.o`? I assume `gcc` with `-c` so it didn't link it into an executable? What difference are you seeing in file offset? They all have `00000040` in that column. The .text/.data/.bss sections all have zero size, so hopefully it won't create any problem when linking. A linker script should still work to get things laid out as necessary. – Peter Cordes Jul 06 '22 at 09:46
  • @PeterCordes For assembling multiboot_header.S.o, indeed I used ```gcc -c```. Afout file offsets I'm talking about it being ```00000180``` in ```multiboot_header.asm.o``` and ```00000040``` in ```multiboot_header.S.o```. You are saying that because they have size 0 those sections shouldn't affect anything, but GRUB isn't detecting the multiboot header, so I suppose it has something to do either with the file offset or these sections. – SamFF Jul 06 '22 at 12:40
  • 1
    GRUB isn't detecting the multiboot header in what? You haven't shown a [mcve] of your actual problem with *linking* this object file into an ELF executable with `ld` (presumably with a linker script). You're looking at un-linked `.o` files, and the file-position of sections there shouldn't affect where the linker ends up putting them in an executable. It's not surprising or problematic that NASM and GAS put different stuff in their `.o` files, perhaps different metadata or just different ordering of the same stuff. I don't expect an empty .data etc. to be a problem for a linker script. – Peter Cordes Jul 06 '22 at 12:45
  • @PeterCordes I've added the linker script and multiboot_header.S files, that might help. But I am making an OS, using GRUB as the bootloader, using multiboot 2 standart, which asks for a magic number and some extra info on te beggining of the kernel binary (sorry if I'm not using the correct terminology), which we put on multiboot_header.S. When I did it with NASM it worked fine, but now with gcc, grub just prints: ```error: no multiboot header found``` ```error: you need to load the kernel first``` – SamFF Jul 06 '22 at 13:00
  • 1
    Ok sure, but what does `objdump -h` or better `readelf` say when you use it on the output of `ld`? Your `.o` is an *input* to `ld`. That's why the virtual addresses are all zero, and why it has a `.o` name. If you're trying to boot that, *there's your problem*. – Peter Cordes Jul 06 '22 at 13:01
  • 1
    Also, how is your multiboot header size only `0xc` bytes? NASM on my system assembles the file in the tutorial to have a size for that section of `0x18` bytes, which looks about right for the amount of `.long` and `.word` directives. But you're showing a `0xc`-sized output from NASM, which I can't reproduce. If you left out the stuff earlier in the file, like the actual multiboot magic number, then that would be another showstopper. – Peter Cordes Jul 06 '22 at 13:08
  • Thats because I used a smaller file for testing about the sections, my bad! But that wasn't interfeering with the build. – SamFF Jul 06 '22 at 13:33
  • @PeterCordes I added the output of readelf to the post, as it's too long to fit in a comment. – SamFF Jul 06 '22 at 16:29

0 Answers0