Работа компоновщика при создании 32-битного ядра - PullRequest
1 голос
/ 09 февраля 2020

Ну, у меня есть 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

Это не вопрос, связанный с разработчиком ОС, но связанный с компоновщиками. Когда я делаю 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 просматривает таблицу заголовков программы и затем выводит соответствующий необработанный двоичный файл?

Я просто, вероятно, не слишком хорошо понимаю компоновщики: (

1 Ответ

0 голосов
/ 09 февраля 2020

Чтобы понять ситуацию - вам нужно знать разницу между разделами и сегментами.

Вы указываете в команде 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.

Для более тесной работы с компоновщиками Вы можете написать собственный скрипт [ссылка] , чтобы избежать дефолта, что может быть неприемлемо для разработки ядра в некоторых ситуациях. Вы можете посмотреть на linux x86 kernel [link] .

objcopy, поскольку ваша ситуация используется для упрощения системы сборки и замены скрипта компоновщика. Но это не очень хороший способ. Он анализирует obj структуру и преобразует ее в двоичный файл, где обычно располагаются только код и данные, указывающие c разделы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...