Неопределенная ссылка в пользовательском файле ELF, но символ определен в таблице символов файлов - PullRequest
1 голос
/ 21 июня 2020

Я пытался узнать о машинном коде x86-64 и файлах ELF. Для этой цели я написал код для создания файла ELF с некоторым машинным кодом в нем. Я использую некоторый машинный код, который я собрал с помощью nasm (он просто печатает сообщение и вызывает системный вызов exit, затем я учусь самостоятельно собирать машинный код) и написал программу C для написания правильного заголовка ELF / Заголовки разделов / Таблица символов и т. Д. c. вручную в файл.

Теперь я пытаюсь связать свой файл (с одной функцией в нем) с другим файлом elf, который я генерирую через gcc из C кода (test.c):

// does not work with or without "extern"
extern void hello();

void _start()
{
  hello();

  // exit system call
  asm(
    "movl $60,%eax;"
    "xorl %ebx,%ebx;"
    "syscall");
}

Результат readelf -a в моем ELF-файле (hello.o):

ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              REL (Relocatable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          64 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0
  Size of section headers:           64 (bytes)
  Number of section headers:         9
  Section header string table index: 8

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .text             PROGBITS         0000000000000000  00000280
       0000000000000044  0000000000000000  AX       0     0     16
  [ 2] .rela.text        RELA             0000000000000000  000002c8
       0000000000000030  0000000000000018   I       6     1     8
  [ 3] .data             PROGBITS         0000000000000000  00000300
       0000000000000005  0000000000000000  WA       0     0     16
  [ 4] .bss              NOBITS           0000000000000000  00000310
       0000000000000080  0000000000000000   A       0     0     16
  [ 5] .rodata           PROGBITS         0000000000000000  00000310
       000000000000000d  0000000000000000   A       0     0     16
  [ 6] .symtab           SYMTAB           0000000000000000  00000320
       0000000000000150  0000000000000018           7    14     8
  [ 7] .strtab           STRTAB           0000000000000000  00000470
       0000000000000028  0000000000000000           0     0     1
  [ 8] .shstrtab         STRTAB           0000000000000000  00000498
       000000000000003f  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),
  l (large), p (processor specific)

There are no section groups in this file.

There are no program headers in this file.

There is no dynamic section in this file.

Relocation section '.rela.text' at offset 0x2c8 contains 2 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
00000000001a  000500000001 R_X86_64_64       0000000000000000 .rodata + 0
000000000024  00050000000a R_X86_64_32       0000000000000000 .rodata + d

The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported.

Symbol table '.symtab' contains 14 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    2 
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    3 
     4: 0000000000000000     0 SECTION LOCAL  DEFAULT    4 
     5: 0000000000000000     0 SECTION LOCAL  DEFAULT    5 
     6: 0000000000000000     0 SECTION LOCAL  DEFAULT    6 
     7: 0000000000000000     0 SECTION LOCAL  DEFAULT    7 
     8: 0000000000000000     0 SECTION LOCAL  DEFAULT    8 
     9: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS hello.c
    10: 0000000000000000    68 FUNC    GLOBAL DEFAULT    1 hello
    11: 0000000000000060    13 OBJECT  LOCAL  DEFAULT    5 msg
    12: 000000000000000d     8 NOTYPE  LOCAL  DEFAULT  ABS len
    13: 0000000000000050     5 OBJECT  GLOBAL DEFAULT    3 _test

No version information found in this file.

Я скомпилировал test.c с

gcc -c -nostdlib -fno-asynchronous-unwind-tables test.c -o test.o

чтобы затем связать с ld test.o hello.o, что, к сожалению, дает

ld: test.o: in function `_start':
test.c:(.text+0xa): undefined reference to `hello'

, хотя функция hello определена в hello.o (обратите внимание на запись в таблице символов с именем hello, которая находится в разделе 1, раздел .text и, кажется, имеет правильный размер / тип / значение / привязку).

Если я скомпилирую файл только с void hello(){} так же, как я скомпилировал test.c, эти два объектных файла, очевидно, могут быть связаны. Кроме того, если я сгенерирую свой собственный файл ELF hello.o как исполняемый файл, переименовав функцию hello в _start, она будет работать нормально. Я уже некоторое время бьюсь головой о стену, и есть две вещи, которые я хотел бы знать: Очевидно, я хотел бы знать свою проблему с файлом ELF. Но также я хотел бы знать, как я могу отлаживать такие проблемы в будущем. Я попытался собрать ld из исходного кода (клонирование репозитория GNU binutils) с отладочными символами, но я не очень далеко продвинулся в отладке самого ld.

Изменить: я загрузил свой эльфийский файл сюда: https://drive.google.com/file/d/1cRNr0VPAjkEbueuWFYwLYbpijVnLySqq/view?usp=sharing

1 Ответ

1 голос
/ 22 июня 2020

Это было довольно сложно отладить.

Вот результат readelf -WSs hello.o для файла, который вы загрузили на диск Google (он не соответствует информации в вашем вопросе):

There are 9 section headers, starting at offset 0x40:

Section Headers:
  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            0000000000000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        0000000000000000 000280 000044 00  AX  0   0 16
  [ 2] .rela.text        RELA            0000000000000000 0002c8 000030 18   I  6   1  8
  [ 3] .data             PROGBITS        0000000000000000 000300 000005 00  WA  0   0 16
  [ 4] .bss              NOBITS          0000000000000000 000310 000080 00   A  0   0 16
  [ 5] .rodata           PROGBITS        0000000000000000 000310 00000d 00   A  0   0 16
  [ 6] .symtab           SYMTAB          0000000000000000 000320 000150 18      7  14  8
  [ 7] .strtab           STRTAB          0000000000000000 000470 000028 00      0   0  1
  [ 8] .shstrtab         STRTAB          0000000000000000 000498 00003f 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),
  l (large), p (processor specific)

Symbol table '.symtab' contains 14 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000000000     0 SECTION LOCAL  DEFAULT    1
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    2
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    3
     4: 0000000000000000     0 SECTION LOCAL  DEFAULT    4
     5: 0000000000000000     0 SECTION LOCAL  DEFAULT    5
     6: 0000000000000000     0 SECTION LOCAL  DEFAULT    6
     7: 0000000000000000     0 SECTION LOCAL  DEFAULT    7
     8: 0000000000000000     0 SECTION LOCAL  DEFAULT    8
     9: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS hello.c
    10: 0000000000000000    68 FUNC    GLOBAL DEFAULT    1 hello
    11: 0000000000000060    13 OBJECT  LOCAL  DEFAULT    5 msg
    12: 000000000000000d     8 NOTYPE  LOCAL  DEFAULT  ABS len
    13: 0000000000000050     5 OBJECT  GLOBAL DEFAULT    3 _test

Проблема связана со значением .sh_info (14) раздела .symtab.

Согласно документации , .sh_info для SYMTAB раздела предполагается содержат «на единицу больше, чем индекс таблицы символов последнего локального символа (привязка STB_LOCAL)».

Таким образом, значение 14 сообщает компоновщику, что все символы в этом файле являются локальными, и поэтому невозможно использовать для разрешения каких-либо внешних ссылок на них.

Вам нужно переместить все LOCAL символы перед GLOBAL (здесь msg и len нужно будет переместить перед hello), чтобы таблица символов выглядела так:

...
     9: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS hello.c
    10: 0000000000000060    13 OBJECT  LOCAL  DEFAULT    5 msg
    11: 000000000000000d     8 NOTYPE  LOCAL  DEFAULT  ABS len
    12: 0000000000000000    68 FUNC    GLOBAL DEFAULT    1 hello
    13: 0000000000000050     5 OBJECT  GLOBAL DEFAULT    3 _test

, а затем установите .sh_info для раздела .symtab на 12.

Но я бы тоже хотел бы знать, как я могу отлаживать такие проблемы в будущем.

Как вы обнаружили, отладка bi nutils ld очень сложен, отчасти потому, что он использует libbfd, который переполнен макросами и сам по себе очень сложен для отладки.

Я отлаживал это, создавая Gold из источник, который, к счастью, произвел точно такой же отказ.

...