1

Well, I have a 32 bit c kernel code that I link as follows:

i686-elf-ld  entry.o kernel.o cursor.o -Ttext 0x100000 -e kmain -o kernel.elf
objcopy -O binary kernel.elf kernel.o

This is not a question related to OS dev, but related to linkers. When I do readelf -s kernel.elf I get:

Symbol table '.symtab' contains 29 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 00100000     0 SECTION LOCAL  DEFAULT    1 
     2: 001002f4     0 SECTION LOCAL  DEFAULT    2 
     3: 0010035c     0 SECTION LOCAL  DEFAULT    3 
     4: 00101454     0 SECTION LOCAL  DEFAULT    4 
     5: 00000000     0 SECTION LOCAL  DEFAULT    5 
     6: 00000000     0 SECTION LOCAL  DEFAULT    6 
     7: 00000000     0 SECTION LOCAL  DEFAULT    7 
     8: 00000000     0 SECTION LOCAL  DEFAULT    8 
     9: 00000000     0 SECTION LOCAL  DEFAULT    9 
    10: 00000000     0 SECTION LOCAL  DEFAULT   10 
    11: 00000000     0 FILE    LOCAL  DEFAULT  ABS kernel/entry.asm
    12: 00000000     0 FILE    LOCAL  DEFAULT  ABS dadio.c
    13: 00000000     0 FILE    LOCAL  DEFAULT  ABS kernel.c
    14: 0010022d    11 FUNC    LOCAL  DEFAULT    1 block_number
    15: 00100238    69 FUNC    LOCAL  DEFAULT    1 pmmngr_free_block
    16: 00000000     0 FILE    LOCAL  DEFAULT  ABS kernel/src/asm/cursor.asm
    17: 0010005d   251 FUNC    GLOBAL DEFAULT    1 printf
    18: 0010027d    48 FUNC    GLOBAL DEFAULT    1 pmmgr_free_range
    19: 001002b0     0 NOTYPE  GLOBAL DEFAULT    1 set_cursor
    20: 001002d1     0 NOTYPE  GLOBAL DEFAULT    1 get_cursor
    21: 00100007    86 FUNC    GLOBAL DEFAULT    1 clear
    22: 00101458     0 NOTYPE  GLOBAL DEFAULT    4 __bss_start
    23: 00101454     4 OBJECT  GLOBAL DEFAULT    4 _physical_memory_table
    24: 00100195   152 FUNC    GLOBAL DEFAULT    1 pmmngr_init
    25: 00101458     0 NOTYPE  GLOBAL DEFAULT    4 _edata
    26: 00101458     0 NOTYPE  GLOBAL DEFAULT    4 _end
    27: 00100000     0 NOTYPE  GLOBAL DEFAULT    1 start
    28: 00100158    61 FUNC    GLOBAL DEFAULT    1 kmain

When I do readelf -S kernel.elf I get:

There are 14 section headers, starting at offset 0x2044:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        00100000 001000 0002f1 00  AX  0   0 16
  [ 2] .rodata           PROGBITS        001002f4 0012f4 000066 00   A  0   0  4
  [ 3] .eh_frame         PROGBITS        0010035c 00135c 0000f8 00   A  0   0  4
  [ 4] .data             PROGBITS        00101454 001454 000004 00  WA  0   0  4
  [ 5] .comment          PROGBITS        00000000 001458 000011 01  MS  0   0  1
  [ 6] .debug_aranges    PROGBITS        00000000 001469 000040 00      0   0  1
  [ 7] .debug_info       PROGBITS        00000000 0014a9 00032c 00      0   0  1
  [ 8] .debug_abbrev     PROGBITS        00000000 0017d5 0001c9 00      0   0  1
  [ 9] .debug_line       PROGBITS        00000000 00199e 000195 00      0   0  1
  [10] .debug_str        PROGBITS        00000000 001b33 0001ed 01  MS  0   0  1
  [11] .symtab           SYMTAB          00000000 001d20 0001d0 10     12  17  4
  [12] .strtab           STRTAB          00000000 001ef0 0000d1 00      0   0  1
  [13] .shstrtab         STRTAB          00000000 001fc1 000082 00      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),
  p (processor specific)

This seems standard to me... Here's the issue, when I do readelf -l kernel.elf, I get the following:


Elf file type is EXEC (Executable file)
Entry point 0x100158
There are 2 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000000 0x000ff000 0x000ff000 0x01454 0x01454 R E 0x1000
  LOAD           0x001454 0x00101454 0x00101454 0x00004 0x00004 RW  0x1000

 Section to Segment mapping:
  Segment Sections...
   00     .text .rodata .eh_frame 
   01     .data 

Where does this 0xff000 come from?? I can't understand how this value arose? Also, does objcopy take a look at the program header table and then output a corresponding raw binary?

I just probably don't understand linkers too well :(

Suraaj K S
  • 600
  • 3
  • 21
  • Probably a result of using `-Ttext=0x100000` . I suppose it may be an artifact of the default linker script that `i686-elf-ld` uses. If you use your own linker script rather than `-Ttext=0x100000` (and the default script) I would expect you wouldn't see this. As it is 0xff000` is 4k below 0x100000. – Michael Petch Feb 09 '20 at 19:21
  • Is there a particular problem you are trying to solve? – Michael Petch Feb 09 '20 at 19:38
  • There is a linker script in this answer I created https://stackoverflow.com/questions/55085455/how-to-convert-ld-ttext-option-to-a-linker-script . Copy it to a file called link.ld (or whatever file you wish), change 0x1000 to 0x100000 and then link with `-Tlink.ld` rather than `-Ttext=0x100000` . Using your own linker script will override the default the compiler was using. – Michael Petch Feb 09 '20 at 21:37
  • @MichaelPetch The problem I'm trying to solve is this: https://stackoverflow.com/questions/60097907/viewing-the-exact-memory-range-that-a-linker-uses-for-a-executable-binary/60099165#60099165 . I was trying to experiment with my linker – Suraaj K S Feb 10 '20 at 03:13

1 Answers1

0

To understand the situation - you need to know the difference between sections and segments.

You specify in the command the Addr for your .text section, which offset=0x1000 by default.

Manual for ld:

   --section-alignment
       Sets the section alignment.  Sections in memory will always begin at addresses which are a multiple of this number.  Defaults to
       0x1000.  [This option is specific to the i386 PE targeted port of the linker]

section-alignment isn't your target flag, but shows that 0x1000 is expected default value.

0x100000 - 0x1000 = 0xff000

If you need to work with segment, you can use -Ttext-segment=org flag.

For closer work with linkers, you can write an own script [link], to avoid default, which could be not acceptable for kernel development in some situations. You can look at one for linux x86 kernel [link].

objcopy for your situation is used to simplify build system, and replace linker script. But it's not a good way in common. It parses obj structure and transform it to binary, where usually located only code and data specific sections.

Maneevao
  • 331
  • 2
  • 6
  • Since the OP is using an i686-elf cross compiler and tool chain, the LD they are running won't target PE so `--section-alignment` doesn't apply. – Michael Petch Feb 09 '20 at 22:25