Несогласие инструментов для анализа размера раздела.bss файла ELF
Анализируя раздел.bss программы на C++, скомпилированной в виде файла ELF для платформы ARM, я наткнулся на несколько способов определения размера. Четыре способа, которые я протестировал, также упоминаются в инструменте вопросов для анализа размера секций ELF и символа.
Однако результаты были совсем другие:
bss size according to nm: 35380
bss size according to readelf: 37632
bss size according to size: 37888
bss size according to objdump: 37594
В чем может быть причина этого?
Скрипт Python, используемый для генерации вывода
#!/usr/bin/env python
import re
import subprocess
import sys
fname = sys.argv[1]
# nm
output = subprocess.check_output(['arm-none-eabi-nm','-l','-S','-C',fname])
size = 0
for line in output.splitlines():
m = re.search('[0-9a-f]* ([0-9a-f]*) ([a-zA-Z]) ([^/]*)\s*([^\s]*)',line)
if m:
stype = m.group(2).strip()
if stype in ['B','b']:
size += int(m.group(1),16)
print "bss size according to nm: \t%i" % size
# readelf
output = subprocess.check_output(['arm-none-eabi-readelf','-S',fname])
for line in output.splitlines():
m = re.search('bss\s+[A-Z]+\s+[0-9a-f]+ [0-9a-f]+ ([0-9a-f]+)',line)
if m:
print "bss size according to readelf: \t%i" % int(m.group(1),16)
break
# size
output = subprocess.check_output(['arm-none-eabi-size',fname])
for line in output.splitlines():
m = re.search('[0-9]+\s+[0-9]+\s+([0-9]+)',line)
if m:
print "bss size according to size: \t%i" % int(m.group(1))
break
# objdump
output = subprocess.check_output(['arm-none-eabi-objdump','-C','-t','-j','.bss',fname])
size = 0
for line in output.splitlines():
m = re.search('bss\s+([0-9a-f]*)\s+',line)
if m:
size += int(m.group(1),16)
print "bss size according to objdump: \t%i" % size
Редактировать: Одна вещь, которую я обнаружил, это то, что nm классифицирует статические переменные внутри функций (правильно) как слабые (V), хотя они могут быть частью.bss. Однако не все разделы, классифицируемые как V, являются частью.bss, поэтому я не могу просто добавить все V разделы к размеру. Так неужели эта задача невозможна с помощью nm?
1 ответ
Вот пример файла ассемблера, который производит исполняемый файл, который показывает некоторые вещи, которые могут произойти:
.section .bss
.globl var1
.size var1, 1
var1:
.skip 1
.align 16777216
.globl var2
.size var2, 1048576
.globl var3
.size var3, 1048576
.globl var4
.size var4, 1048576
var2:
var3:
var4:
.skip 1048576
.text
.globl main
main:
xor %eax, %eax
ret
size -x
дает этот вывод:
text data bss dec hex filename
0x5c9 0x220 0x2100000 34605033 21007e9 a.out
eu-readelf -S
показывает по существу ту же информацию:
[25] .bss NOBITS 0000000001000000 01000000 02100000 0 WA 0 0 16777216
Тем не менее, размеры символов, как показано eu-readelf -s
, совсем разные:
32: 0000000001000001 1 OBJECT LOCAL DEFAULT 25 completed.6963
48: 0000000003000000 1048576 NOTYPE GLOBAL DEFAULT 25 var2
49: 0000000003000000 1048576 NOTYPE GLOBAL DEFAULT 25 var4
59: 0000000002000000 1 NOTYPE GLOBAL DEFAULT 25 var1
61: 0000000003000000 1048576 NOTYPE GLOBAL DEFAULT 25 var3
Сумма их размеров 0x300002, а не 0x2100000. Этому способствуют два фактора:
- Существует разрыв около 16 МиБ после
var1
который не используется. Необходимо осуществить выравниваниеvar2
, в связи с порядком, в котором определены переменные. Часть пространства используется повторноcompleted.6963
, var2
,var3
,var4
являются псевдонимами: значения символов одинаковы, поэтому существует только один объект, поддерживающий переменную.
Кроме того, между концом .data
раздел и .bss
раздел, вызванный .bss
Требование выравнивания. При обычном динамическом загрузчике это просто приведет к не отображенной области памяти:
LOAD 0x000e08 0x0000000000200e08 0x0000000000200e08 0x000220 0x000220 RW 0x200000
LOAD 0x1000000 0x0000000001000000 0x0000000001000000 0x000000 0x2100000 RW 0x200000
Так size
предположительно правильно, когда не учитывается этот пробел.
Числа в этом примере, конечно, чрезмерны, но эти эффекты видны даже с обычными двоичными файлами, только в меньшей степени.
readelf
/size
а также objdump
/nm
различия могут быть особенностью ARM; они, вероятно, вызваны определенными типами символов, которых нет в моем примере.