Istnieją dwa sposoby, aby to zrobić dla konkretnego pliku obiektu:
- Opcja
gcc
-ffunction-sections
nakazuje mu, aby utworzyć sekcję oddzielny ELF dla każdej funkcji w SourceFile jest skompilowany.
- Tabela symboli zawiera nazwę sekcji, adres początkowy i rozmiar danej funkcji; które można wprowadzić do
objdump
za pośrednictwem argumentów --start-address
/--stop-address
.
Pierwszy przykład:
$ readelf -S t.o | grep ' .text.'
[ 1] .text PROGBITS 0000000000000000 00000040
[ 4] .text.foo PROGBITS 0000000000000000 00000040
[ 6] .text.bar PROGBITS 0000000000000000 00000060
[ 9] .text.foo2 PROGBITS 0000000000000000 000000c0
[11] .text.munch PROGBITS 0000000000000000 00000110
[14] .text.startup.mai PROGBITS 0000000000000000 00000180
ten został skompilowany z -ffunction-sections
i istnieją cztery funkcje, foo()
, bar()
, foo2()
i munch()
w moim pliku wynikowego. Mogę demontować je oddzielnie tak:
$ objdump -w -d --section=.text.foo t.o
t.o: file format elf64-x86-64
Disassembly of section .text.foo:
0000000000000000 <foo>:
0: 48 83 ec 08 sub $0x8,%rsp
4: 8b 3d 00 00 00 00 mov 0(%rip),%edi # a <foo+0xa>
a: 31 f6 xor %esi,%esi
c: 31 c0 xor %eax,%eax
e: e8 00 00 00 00 callq 13 <foo+0x13>
13: 85 c0 test %eax,%eax
15: 75 01 jne 18 <foo+0x18>
17: 90 nop
18: 48 83 c4 08 add $0x8,%rsp
1c: c3 retq
Inną opcją może być stosowany tak (nm
wysypisk wpisów w tabeli symbol):
$ nm -f sysv t.o | grep bar
bar |0000000000000020| T | FUNC|0000000000000026| |.text
$ objdump -w -d --start-address=0x20 --stop-address=0x46 t.o --section=.text
t.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000020 <bar>:
20: 48 83 ec 08 sub $0x8,%rsp
24: 8b 3d 00 00 00 00 mov 0(%rip),%edi # 2a <bar+0xa>
2a: 31 f6 xor %esi,%esi
2c: 31 c0 xor %eax,%eax
2e: e8 00 00 00 00 callq 33 <bar+0x13>
33: 85 c0 test %eax,%eax
35: 75 01 jne 38 <bar+0x18>
37: 90 nop
38: bf 3f 00 00 00 mov $0x3f,%edi
3d: 48 83 c4 08 add $0x8,%rsp
41: e9 00 00 00 00 jmpq 46 <bar+0x26>
w tym przypadku opcja -ffunction-sections
nie ma został użyty, dlatego początkowe przesunięcie funkcji nie jest równe zeru i nie ma go w osobnej sekcji (ale w .text
).
Uważaj jednak podczas demontażu plików obiektowych ...
To nie jest dokładnie co chcesz, ponieważ pliki obiektu, call
cele (jak również adresy zmiennych globalnych) nie zostały rozwiązane - nie widzisz tutaj, że foo
dzwoni printf
, ponieważ rozdzielczość tego na poziomie binarnym dzieje się tylko w czasie połączenia. Źródło zestawu miałoby tam jednak numer call printf
.Informacja, że ta callq
jest w rzeczywistości do printf
znajduje się w pliku obiektowym, ale oddzielona od kodu (jest to sekcja o nazwie relokacja, która wymienia lokalizacje w pliku obiektowym, które mają być "załatane" przez linker); dezasembler nie może tego rozwiązać.
Niektóre IDE umożliwiają ustawienie punktu przerwania i wyświetlenie kodu zespołu wygenerowanego przez tę funkcję. To się nazywa okno * demontażu *. To powinno zrobić to, czego szukasz - czy korzystasz z IDE? – Aaron
Wolę kompilować (z optymalizacją), a następnie dezasemblować, trzeba zrozumieć, że kompilator pozostawi kilka instrukcji niekompletnych dla adresów zewnętrznych i takich, ale łatwiej jest odczytać IMO niż przy użyciu -S. gcc -O2 -c hello.c -o hello.o, objdump -D hello.o –
Przejdź tutaj: http://gcc.godbolt.org/ wklej funkcję, wybierz kompilator, bardzo przydatny. – harold