链接器在创建32位内核中的工作

问题描述 投票:1回答:1

嗯,我有一个32位c内核代码,我按如下方式链接:

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

这不是与OS开发人员有关的问题,而是与链接程序有关的问题。当我执行readelf -s kernel.elf时,我得到:

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

[当我执行readelf -S kernel.elf时我得到:

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)

对我来说这似乎是标准的...这是问题,当我执行readelf -l kernel.elf时,得到以下信息:


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 

此0xff000来自哪里??我不明白这个价值是如何产生的?另外,objcopy是否会查看程序头表,然后输出相应的原始二进制文件?

我可能不太了解链接器:(

c linker osdev binutils
1个回答
0
投票

要了解这种情况-您需要了解各节和各节之间的区别。

您在命令中为Addr部分指定.text,默认情况下offset = 0x1000

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不是您的目标标志,但显示0x1000是预期的默认值。

0x100000-0x1000 = 0xff000

如果需要使用段,则可以使用-Ttext-segment=org标志。

为了更紧密地使用链接器,您可以编写自己的脚本 [link],以避免出现默认值,在某些情况下,这对于内核开发是不可接受的。您可以查看一个适用于linux x86内核的文件 [link]

objcopy根据您的情况用于简化构建系统,并替换链接描述文件。但这不是一个好方法。它解析obj结构并将其转换为二进制文件,通常只在其中放置代码和数据特定的部分。

© www.soinside.com 2019 - 2024. All rights reserved.