<!-- /* Font Definitions */ @font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-alt:SimSun; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} @font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:-1610611985 1107304683 0 0 159 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:-1610611985 1073750139 0 0 159 0;} @font-face {font-family:"/@宋体"; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} @font-face {font-family:Verdana; panose-1:2 11 6 4 3 5 4 4 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:536871559 0 0 0 415 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; mso-pagination:none; font-size:10.5pt; mso-bidi-font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-fareast-font-family:宋体; mso-bidi-font-family:"Times New Roman"; mso-font-kerning:1.0pt;} span.EmailStyle15 {mso-style-type:personal; mso-style-noshow:yes; mso-style-unhide:no; mso-ansi-font-size:11.0pt; mso-bidi-font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-fareast-font-family:宋体; mso-hansi-font-family:Calibri; mso-bidi-font-family:"Times New Roman"; color:windowtext;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; mso-bidi-font-size:10.5pt; mso-ascii-font-family:Calibri; mso-fareast-font-family:宋体; mso-hansi-font-family:Calibri;} .MsoPapDefault {mso-style-type:export-only;} /* Page Definitions */ @page {mso-page-border-surround-header:no; mso-page-border-surround-footer:no;} @page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:36.0pt; mso-footer-margin:36.0pt; mso-paper-source:0;} div.Section1 {page:Section1;} -->
---------------objdump 是用查看目标文件或者可执行的目标文件的构成的 GCC 工具 ----------
以下 3 条命令足够那些喜欢探索目标文件与源代码之间的丝丝的关系的朋友。
objdump -x obj 以某种分类信息的形式把目标文件的数据组织(被分为几大块)输出
objdump -t obj 输出目标文件的符号表
objdump -h obj 输出目标文件的所有段概括
objdump -j .text/.data -S obj 输出指定段的信息,大概就是反汇编源代码把
自己的一个例子:
#include <stdio.h>
#define __sched __attribute__((__section__(".sched.text")))
void __sched my_sched(void)
{
printf("Hello me");
}
void __attribute__ ((constructor)) my_init(void)
{
printf("Hello ");
}
void __attribute__ ((destructor)) my_exit(void)
{
printf("bye2/n");
}
int main()
{
printf("World!/n");
printf("bye1/n");
return 0;
}
gcc attribute.c -o attribute -g3
[root@localhost objdump]# objdump attribute -x | grep .sched.text
13 .sched.text 00000015 080484ec 080484ec 000004ec 2**0
080484ec l d .sched.text 00000000 .sched.text
080484ec g F .sched.text 00000015 my_sched
上面先用-x找到.sched.text的地址和长度,下面用--start-address 和--stop-address 输入这个段的范围用-S -r -d等选项即可查看段中的内容
[root@localhost objdump]# objdump attribute --start-address=0x080484ec --stop-address=0x08048501 -S
attribute: file format elf32-i386
Disassembly of section .sched.text:
080484ec <my_sched>:
#include <stdio.h>
#define __sched __attribute__((__section__(".sched.text")))
void __sched my_sched(void)
{
80484ec: 55 push %ebp
80484ed: 89 e5 mov %esp,%ebp
80484ef: 83 ec 18 sub $0x18,%esp
printf("Hello me");
80484f2: b8 2c 85 04 08 mov $0x804852c,%eax
80484f7: 89 04 24 mov %eax,(%esp)
80484fa: e8 15 fe ff ff call 8048314 <printf@plt>
}
80484ff: c9 leave
8048500: c3 ret
先编译一个简单的 C 程序。
char* s = "Hello, World!";
char* x;
int i = 0x1234;
int main(int argc, char* argv[])
{
x = "Ubuntu";
printf("%s/n", s);
return 0;
}
编译后,使用 objdump 输出 ELF Section 信息。我们通常关心只有 .text, .rodata, .data, .bss 这几个段。
yuhen@yuhen-desktop:~/Learn.c$ objdump -h hello
Sections:
Idx Name Size VMA LMA File off Algn
12 .text 0000018c 08048310 08048310 00000310 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
14 .rodata 0000001d 080484b8 080484b8 000004b8 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
22 .data 00000010 0804a00c 0804a00c 0000100c 2**2
CONTENTS, ALLOC, LOAD, DATA
23 .bss 0000000c 0804a01c 0804a01c 0000101c 2**2
ALLOC
Section 说明:
- .text: 程序执行代码。
- .rodata: 代码中的字符串常量等。
- .data: 初始化的全局变量。
- .bss: 未初始化的全局变量。
我们反汇编看看 main 函数中的相关代码。
yuhen@yuhen-desktop:~/Learn.c$ objdump -d -M intel hello > hello.asm
yuhen@yuhen-desktop:~/Learn.c$ cat hello.asm | less # 我们只关心 main,其他代码省略
80483c4: 8d 4c 24 04 lea ecx,[esp+0x4]
80483c8: 83 e4 f0 and esp,0xfffffff0
80483cb: ff 71 fc push DWORD PTR [ecx-0x4]
80483ce: 55 push ebp
80483cf: 89 e5 mov ebp,esp
80483d1: 51 push ecx
80483d2: 83 ec 04 sub esp,0x4
80483d5: c7 05 24 a0 04 08 ce mov DWORD PTR ds:0x804a024,0x80484ce ; 注释: x = "Ubuntu"
80483dc: 84 04 08
80483df: a1 14 a0 04 08 mov eax,ds:0x804a014 ; 注释: s 地址
80483e4: 89 04 24 mov DWORD PTR [esp],eax
80483e7: e8 08 ff ff ff call 80482f4 <puts@plt>
80483ec: b8 00 00 00 00 mov eax,0x0
80483f1: 83 c4 04 add esp,0x4
80483f4: 59 pop ecx
80483f5: 5d pop ebp
80483f6: 8d 61 fc lea esp,[ecx-0x4]
80483f9: c3 ret
80483fa: 90 nop
80483fb: 90 nop
80483fc: 90 nop
80483fd: 90 nop
80483fe: 90 nop
80483ff: 90 nop
我们先关注全局变量 s,其地址是:
0x804a014 - 0x0804a00c (.data 基地址) + 0x0000100c (.data Offset) = 0x1014
我们看看二进制文件中对应位置的信息。
yuhen@yuhen-desktop:~/Learn.c$ xxd -g 1 -s 0x1014 -l 100 hello
0001024: 62 75 6e 74 75 20 34 2e 33 2e 33 2d 35 75 62 75 buntu 4.3.3-5ubu
0001034: 6e 74 75 34 29 20 34 2e 33 2e 33 00 00 47 43 43 ntu4) 4.3.3..GCC
指向 0x080484c0,我们计算一下该字符串的 offset。
0x080484c0 - 0x080484b8 (.rodata 基地址) + 0x000004b8 (.rodata Offset) = 0x04c0
看看数据。
yuhen@yuhen-desktop:~/Learn.c$ xxd -g 1 -s 0x04c0 -l 100 hello
00004d0: 75 6e 74 75 00 00 00 00 00 00 00 00 00 00 00 00 untu............
接下来看看未出化全局变量 x 的情况。
很显然,该变量地址 (0x804a024) 在 .bss 段 (0x0804a01c ~ 0x0804a028)。字符串 "Ubuntu" 地址是 0x80484ce,我们可以计算其 Offset。
0x80484ce - 0x080484b8 (.rodata 基地址) + 0x000004b8 (.rodata Offset) = 0x04ce
yuhen@yuhen-desktop:~/Learn.c$ xxd -g 1 -s 0x04ce -l 100 hello
00004de: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
全局变量和静态变量的地址在编译时就决定了的。我们还可以用 readelf 命令获取更详细的 ELF 文件信息。
yuhen@yuhen-desktop:~/Learn.c$ readelf -e hello
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x8048310
Start of program headers: 52 (bytes into file)
Start of section headers: 6004 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 8
Size of section headers: 40 (bytes)
Number of section headers: 36
Section header string table index: 33
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .interp PROGBITS 08048134 000134 000013 00 A 0 0 1
[ 2] .note.ABI-tag NOTE 08048148 000148 000020 00 A 0 0 4
[ 3] .hash HASH 08048168 000168 000028 04 A 5 0 4
[ 4] .gnu.hash GNU_HASH 08048190 000190 000020 04 A 5 0 4
[ 5] .dynsym DYNSYM 080481b0 0001b0 000050 10 A 6 1 4
[ 6] .dynstr STRTAB 08048200 000200 00004a 00 A 0 0 1
[ 7] .gnu.version VERSYM 0804824a 00024a 00000a 02 A 5 0 2
[ 8] .gnu.version_r VERNEED 08048254 000254 000020 00 A 6 1 4
[ 9] .rel.dyn REL 08048274 000274 000008 08 A 5 0 4
[10] .rel.plt REL 0804827c 00027c 000018 08 A 5 12 4
[11] .init PROGBITS 08048294 000294 000030 00 AX 0 0 4
[12] .plt PROGBITS 080482c4 0002c4 000040 04 AX 0 0 4
[13] .text PROGBITS 08048310 000310 00018c 00 AX 0 0 16
[14] .fini PROGBITS 0804849c 00049c 00001c 00 AX 0 0 4
[15] .rodata PROGBITS 080484b8 0004b8 00001d 00 A 0 0 4
[16] .eh_frame PROGBITS 080484d8 0004d8 000004 00 A 0 0 4
[17] .ctors PROGBITS 08049f0c 000f0c 000008 00 WA 0 0 4
[18] .dtors PROGBITS 08049f14 000f14 000008 00 WA 0 0 4
[19] .jcr PROGBITS 08049f1c 000f1c 000004 00 WA 0 0 4
[20] .dynamic DYNAMIC 08049f20 000f20 0000d0 08 WA 6 0 4
[21] .got PROGBITS 08049ff0 000ff0 000004 04 WA 0 0 4
[22] .got.plt PROGBITS 08049ff4 000ff4 000018 04 WA 0 0 4
[23] .data PROGBITS 0804a00c 00100c 000010 00 WA 0 0 4
[24] .bss NOBITS 0804a01c 00101c 00000c 00 WA 0 0 4
[25] .comment PROGBITS 00000000 00101c 0000fc 00 0 0 1
[26] .debug_aranges PROGBITS 00000000 001118 000070 00 0 0 8
[27] .debug_pubnames PROGBITS 00000000 001188 000025 00 0 0 1
[28] .debug_info PROGBITS 00000000 0011ad 0001b5 00 0 0 1
[29] .debug_abbrev PROGBITS 00000000 001362 000083 00 0 0 1
[30] .debug_line PROGBITS 00000000 0013e5 000180 00 0 0 1
[31] .debug_str PROGBITS 00000000 001565 00008e 01 MS 0 0 1
[32] .debug_ranges PROGBITS 00000000 0015f8 000040 00 0 0 8
[33] .shstrtab STRTAB 00000000 001638 000139 00 0 0 1
[34] .symtab SYMTAB 00000000 001d14 0004d0 10 35 54 4
[35] .strtab STRTAB 00000000 0021e4 000213 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x08048034 0x08048034 0x00100 0x00100 R E 0x4
INTERP 0x000134 0x08048134 0x08048134 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib/ld-linux.so.2]
LOAD 0x000000 0x08048000 0x08048000 0x004dc 0x004dc R E 0x1000
LOAD 0x000f0c 0x08049f0c 0x08049f0c 0x00110 0x0011c RW 0x1000
DYNAMIC 0x000f20 0x08049f20 0x08049f20 0x000d0 0x000d0 RW 0x4
NOTE 0x000148 0x08048148 0x08048148 0x00020 0x00020 R 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4
GNU_RELRO 0x000f0c 0x08049f0c 0x08049f0c 0x000f4 0x000f4 R 0x1
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.ABI-tag .hash ... .text .fini .rodata .eh_frame
03 .ctors .dtors .jcr .dynamic .got .got.plt .data .bss
04 .dynamic
05 .note.ABI-tag
06
07 .ctors .dtors .jcr .dynamic .got