Неверный размер функции внутри объекта ARM ELF

readelf вывод объектного файла:

Symbol table '.symtab' contains 15 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 00000000     0 FILE    LOCAL  DEFAULT  ABS fp16.c
     2: 00000000     0 SECTION LOCAL  DEFAULT    1 
     3: 00000000     0 SECTION LOCAL  DEFAULT    3 
     4: 00000000     0 SECTION LOCAL  DEFAULT    4 
     5: 00000000     0 NOTYPE  LOCAL  DEFAULT    1 $t
     6: 00000001   194 FUNC    LOCAL  DEFAULT    1 __gnu_f2h_internal
     7: 00000010     0 NOTYPE  LOCAL  DEFAULT    5 $d
     8: 00000000     0 SECTION LOCAL  DEFAULT    5 
     9: 00000000     0 SECTION LOCAL  DEFAULT    7 
    10: 000000c5    78 FUNC    GLOBAL HIDDEN     1 __gnu_h2f_internal
    11: 00000115     4 FUNC    GLOBAL HIDDEN     1 __gnu_f2h_ieee
    12: 00000119     4 FUNC    GLOBAL HIDDEN     1 __gnu_h2f_ieee
    13: 0000011d     4 FUNC    GLOBAL HIDDEN     1 __gnu_f2h_alternative
    14: 00000121     4 FUNC    GLOBAL HIDDEN     1 __gnu_h2f_alternative

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        00000000 000034 000124 00  AX  0   0  4
  [ 2] .rel.text         REL             00000000 00058c 000010 08      9   1  4
  [ 3] .data             PROGBITS        00000000 000158 000000 00  WA  0   0  1
  [ 4] .bss              NOBITS          00000000 000158 000000 00  WA  0   0  1
  [ 5] .debug_frame      PROGBITS        00000000 000158 00008c 00      0   0  4
  [ 6] .rel.debug_frame  REL             00000000 00059c 000060 08      9   5  4
  [ 7] .ARM.attributes   ARM_ATTRIBUTES  00000000 0001e4 00002f 00      0   0  1
  [ 8] .shstrtab         STRTAB          00000000 000213 000051 00      0   0  1
  [ 9] .symtab           SYMTAB          00000000 00041c 0000f0 10     10  10  4
  [10] .strtab           STRTAB          00000000 00050c 00007e 00      0   0  1

Relocation section '.rel.text' at offset 0x58c contains 2 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
0000011a  00000a66 R_ARM_THM_JUMP11  000000c5   __gnu_h2f_internal
00000122  00000a66 R_ARM_THM_JUMP11  000000c5   __gnu_h2f_internal

Relocation section '.rel.debug_frame' at offset 0x59c contains 12 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
00000014  00000802 R_ARM_ABS32       00000000   .debug_frame
00000018  00000202 R_ARM_ABS32       00000000   .text
00000040  00000802 R_ARM_ABS32       00000000   .debug_frame
00000044  00000202 R_ARM_ABS32       00000000   .text
00000050  00000802 R_ARM_ABS32       00000000   .debug_frame
00000054  00000202 R_ARM_ABS32       00000000   .text
00000060  00000802 R_ARM_ABS32       00000000   .debug_frame
00000064  00000202 R_ARM_ABS32       00000000   .text
00000070  00000802 R_ARM_ABS32       00000000   .debug_frame
00000074  00000202 R_ARM_ABS32       00000000   .text
00000080  00000802 R_ARM_ABS32       00000000   .debug_frame
00000084  00000202 R_ARM_ABS32       00000000   .text

Структура раздела .text, как я понимаю:

Раздел .text имеет размер 0x124

0x0: unknown byte
0x1-0xC3: __gnu_f2h_internal
0xC3-0xC5: two unknown bytes between those functions (btw what are those?)
0xC5-0x113: __gnu_h2f_internal
0x113-0x115: two unknown bytes between those functions
0x115-0x119: __gnu_f2h_ieee
0x119-0x11D: __gnu_h2f_ieee
0x11D-0x121: __gnu_f2h_alternative
0x121-0x125: __gnu_h2f_alternative // section is only 0x124, what happened to the missing byte?

Обратите внимание, что размер раздела составляет 0x124, а последняя функция заканчивается на 0x125, что случилось с отсутствующим байтом?

Спасибо.


person Koten    schedule 19.10.2015    source источник


Ответы (1)


Технически ваш «недостающий байт» - это тот самый байт, который находится прямо там, в 0x0.

Обратите внимание, что вы смотрите на значение символа, то есть на адрес функции времени выполнения (это было бы намного яснее, если бы VMA вашего .text-раздела не было 0). Поскольку они являются функциями Thumb, для адресов установлен бит 0, так что процессор переключается в режим Thumb при их вызове; фактические местоположения этих инструкций по-прежнему выровнены наполовину, то есть 0x0, 0xc4, 0x114 и т. д., поскольку в противном случае они не могли бы быть выполнены (вы бы сочли ошибкой неправильно выровненный ПК). Уберите бит 0 в соответствии с спецификацией ARM ELF говорит о символах STT_FUNC, чтобы получить фактический VMA инструкции, соответствующей этому символу, затем вычесть начало раздела, и у вас должно быть то же относительное смещение, что и внутри самого объектного файла.

<offset in section> = (<symbol value> & ~1) - <section VMA>

Дополнительное заполнение полуслова после некоторых функций просто гарантирует, что каждый символ выровнен по словам - вероятно, для этого есть разные причины, но первая, которая приходит на ум, заключается в том, что инструкция adr не работала бы должным образом, если бы они не были.

person Notlikethat    schedule 19.10.2015
comment
адрес загрузки раздела вы имеете ввиду виртуальный адрес раздела при исполнении? можете ли вы привести пример, как вернуть смещение секции? и как получить верные данные последней функции (__gnu_h2f_alternative) - person Koten; 02.11.2015
comment
Да, извините, освежившись в точной терминологии, я вижу, что адрес загрузки мог двусмысленно предлагать LMA, когда я действительно имел в виду VMA. В вашем примере __gnu_h2f_alternative, по-видимому, состоит из 4 байтов (1 или 2 инструкции Thumb) со смещениями от 0x120 до 0x123 в .text, которые предположительно будут занимать от 0x154 до 0x157 в фактическом файле. - person Notlikethat; 03.11.2015
comment
Спасибо за полезное объяснение. Правильно ли это делать для каждой функции, чтобы получать правильные необработанные данные? std::vector<unsigned char> vec; vec.insert(vec.begin(), section_offset + symbol[i].st_value & ~1, section_offset + symbol[i].st_size); - person Koten; 07.11.2015