日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux如何调试elf程序,Linux应用程序elf描述

發布時間:2023/12/4 linux 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux如何调试elf程序,Linux应用程序elf描述 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

玩Linux的人應該明白ELF文件是一種文件格式,就好比.txt,.doc等一樣,只是這個文件是按照特定信息排列組成,同樣在windows上也存在一種格式,它叫PE,老的叫dos。下面我就來看看ELF文件里面到底有什么, 以hello.c為例子。

點擊(此處)折疊或打開

#include

int main (int argc, char *argv[])

{

printf ("Hello World\n");

return 0;

}

圖 1

執行:make hello? ?生成hello可執行文件(ELF格式).

首先,我們可以通過readelf -h hello,來獲取hello這個elf文件的頭部信息(該信息放置在hello文件的頭部,大小為64字節):

點擊(此處)折疊或打開

$ readelf -h hello

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: EXEC (Executable file)

Machine: Advanced Micro Devices X86-64

Version: 0x1

Entry point address: 0x400430

Start of program headers: 64(bytes into file)

Start of section headers: 6696(bytes into file)

Flags: 0x0

Size of this header: 64 (bytes)

Size of program headers: 56 (bytes)

Number of program headers: 9

Size of section headers: 64 (bytes)

Number of section headers: 31

Section header string table index: 28

圖 2

當我們在shell命令行敲擊./hello的時候,內核是怎么識別這是一個可執行文件(elf文件)的呢?其實,在shell進行運行的時候,busybox會將"./hello"當成execve系統函數參數進行傳參即:execve("./hello", ["./hello"]) 。當Linux發生系統調用并陷入內核后,Linux內核將這個hello文件的從0開始的前面幾個字節與.ELF(7f 45 4c 46)比較,如果一樣,則是elf文件,如果不一樣,則與"#!"進行比較,以此來查看是否為需要第三方解釋的腳本語言(#!后面跟的是解釋器的路徑),如#!/bin/sh或者#!/usr/bin/python。

上面提到的7f 45 4c 46就是一個elf文件的magic,一種固定elf標志即文件的識別碼,其對應的ascii碼是.ELF, 可以通過readelf -h hello獲取到,如圖2。

由圖2可知,這個ELF文件支持的平臺為X86-64,版本是0x1,入口地址是0x400430,段的起始地址是文件偏移6696字節處,Program Header在文件偏移64字節處即elf頭信息之后。當前elf header占大小64字節,有9個program header和31個段等等,具體elf header格式,可以參考elf.h頭文件。

溫馨小提示:這里我們普及一下什么是section。我們常聽說的section有代碼段(TEXT段),BSS段,數據段(DATA段),只讀數據段(RODATA段),HEAP, STACK等。在C語言中,.TEXT段主要用于存放函數對應的機器碼的(也就是可執行程序的可運行部分),BSS段主要存放全局未初始化變量的(數據部分),DATA段主要存放全局并且已經初始化過的變量的(注意:初始化成0/NULL的全局變量會被認為是未初始化而放置到BSS段,因為BSS段的數據默認就是0/NULL),RODATA段用于存放const類型的變量,HEAP主要是分配內存使用,而STACK主要是用于函數調用和函數局部變量使用。

在講ELF各個部分內容之前,我們先看看ELF文件的整體結構:

+-----------------------+?hello文件偏移 0bytes

|?? ? ? ? ? ? ? ? ? ? ? |

|? ? ? ? ELF Header? ? ?|

+-----------------------+ hello文件偏移64bytes

|?? ? ? ? ? ? ? ? ? ? ? |

|? ? ? ?Program Header? |

+-----------------------+ hello文件偏移568bytes (64+56 * 9)

|? ? ? ? interpreter? ? | (動態解釋器位置)

+-----------------------+

|? ? ? ? ? .......? ? ? |

+-----------------------+ hello文件偏移3600bytes

|? ? ? ? ? text? ? ? ? ?| (代碼段位置)

+-----------------------+

|? ? ? ? ?ro data? ? ? ?| (只讀數據段位置)

+-----------------------+

|? ? ? ? .......? ? ? ? | (其它段)

+-----------------------+

|? ? ? ? ? data? ? ? ? ?| (數據段)

+-----------------------+ hello文件偏移6696bytes

|? ? ?Section Header| (段表位置)

+-----------------------+?hello文件尾部8680 bytes

點擊(此處)折疊或打開

$ ls?-l hello

-rwxr-xr-x 1 cliu4 users?86809月 30 14:31 hello

圖 3

如圖3,圖為hello文件的整個布局圖,從圖中可以看出,hello可執行文件的大小為8680字節,其中0-64字節存放的是elf文件的頭部信息,即elf header(這個結構體可以通過查看elf.h獲取),64字節之后存放的是program header,在之后放的是動態解釋器(interpreter),而section header則是放到文件末尾的即6696字節處,中間放到程序段即section。而當我們知道了elf頭部信息的作用就是指明當前elf文件的版本號,運行環境和其他段的位置,個數以及大小后,那么緊接著elf header的program header到底又有什么用呢?首先我們看看program header里面到底有什么,如下圖:

點擊(此處)折疊或打開

$readelf -l hello

Elf file type is EXEC (Executable file)

Entry point 0x400430

There are 9 program headers, starting at offset 64

Program Headers:

Type? ? ? ? ? ? ? ?Offset? ? ? ? ? ?VirtAddrPhysAddrFileSizMemSiz? ? ? ? ? FlagsAlign

PHDR? ? ? ? ? 0x0000000000000040 0x0000000000400040 0x0000000000400040 0x00000000000001f8 0x00000000000001f8? ? RE? ? 8

INTERP? ? ? ?0x0000000000000238 0x0000000000400238 0x0000000000400238 0x000000000000001c 0x000000000000001c? ? R? ?? 1

[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]

LOAD? ? ? ? ?0x0000000000000000 0x00000000004000000x0000000000400000?0x00000000000007940x0000000000000794? ? RE? ?200000

LOAD? ? ? ? ?0x0000000000000e00 0x0000000000600e00 0x0000000000600e00 0x0000000000000238 0x0000000000000240? ??RW? ?200000

DYNAMIC? ? ? 0x0000000000000e28 0x0000000000600e28 0x0000000000600e28 0x00000000000001d0 0x00000000000001d0? ? RW? ? 8

NOTE? ? ? ? ?0x0000000000000254 0x0000000000400254 0x0000000000400254 0x0000000000000044 0x0000000000000044? ? R? ? ?4

GNU_EH_FRAME 0x0000000000000618 0x0000000000400618 0x0000000000400618?0x0000000000000044 0x0000000000000044? ??R? ? ?4

GNU_STACK? ? 0x0000000000000000 0x0000000000000000 0x0000000000000000?0x0000000000000000 0x0000000000000000? ? RW? ? 10

GNU_RELRO? ? 0x0000000000000e00 0x0000000000600e00 0x0000000000600e00 0x0000000000000200 0x0000000000000200? ? R? ? ? 1

Section to Segment mapping:

Segment Sections...

00

01? ? ?.interp

02? ? ?.interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame

03? ? ?.init_array .fini_array .jcr .dynamic .got .got.plt .data .bss

04? ? ?.dynamic

05? ? ?.note.ABI-tag .note.gnu.build-id

06? ? ?.eh_frame_hdr

07

08? ? ?.init_array .fini_array .jcr .dynamic .got

圖 4

如圖4,program headers包含:1、PHDR(program header起始位置0x40,大小0x1f8);2、INTERP(動態解釋器,其實就是一個字符串,記錄了動態解釋器的位置:/lib64/ld-linux-x86-64.so.2);3、LOAD;4、LOAD;5、DYNAMIC;6、NOTE等。從第20行"Section to Segment mapping"下面可以看到編號00,01,02,03....08,這些編號對應的是program header對應的表,例如:00對應的是PHDR,01對應的是INTERP,02對應的是LOAD等。因此,可以知道01對應的program header INTERP部分記錄的是.interp段信息;而其他的與運行相關的記錄在02/03對應的LOAD結構當中。那么這個program header到底有什么用呢?其實,這個program header仔細的朋友應該能夠發現每個program header都記錄了對應所在的文件偏移和內存的虛擬地址和物理地址,當系統調用execve陷入到內核,并且發現這個hello文件為elf文件的時候,Linux內核就會根據program header當中的提示信息來對hello進行內存映射,給hello開辟自己的虛擬地址空間(如LOAD部分虛擬地址是0x400000即圖4標紅部分),并且通過INTERP獲取到當前elf文件的動態解釋器路徑:/lib64/ld-linux-x86-64.so.2,還可以通過DYNAMIC部分獲取到當前hello文件依賴的動態庫信息,知道哪些動態庫需要引用(readelf -d hello)。因此,我可以簡單的理解為:program header信息 就是為Linux內核提供應用程序加載相關的信息,方便內核加載可執行程序。

如圖3,經過了program header,挨著它的便是動態解釋器(.interpreter)的位置了,這個地方比較簡單,就是一個字符串,指明了動態解釋器的路徑。這個動態解釋器/lib64/ld-linux-x86-64.so.2看起來是一個動態庫,其實不是,它是一個可用自我重定位的可執行程序,其主要作用就是幫助hello進行代碼重定位。

如圖3,在動態解釋器后的具體段,將在section headers之后描述。

如圖3,在文件的末尾,即6696偏移到8680偏移的位置處,存放的是section header。可用通過readelf -S hello獲取到。下圖是section headers結構的信息:

點擊(此處)折疊或打開

There are 31 section headers, starting at offset 0x1a28:

Section Headers:

[Nr]??Name Type Address Offset SizeEntSize Flags Link InfoAlign

[ 0]? NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0

[ 1] .interp PROGBITS 0000000000400238 00000238 000000000000001c 0000000000000000 A 0 0 1

[ 2] .note.ABI-tag NOTE 0000000000400254 00000254? 0000000000000020 0000000000000000 A 0 0 4

[ 3] .note.gnu.build-i NOTE 0000000000400274 00000274 0000000000000024 0000000000000000 A 0 0 4

[ 4] .gnu.hash GNU_HASH 0000000000400298 00000298? 000000000000001c 0000000000000000 A 5 0 8

[ 5] .dynsym DYNSYM 00000000004002b8 000002b8 0000000000000060 0000000000000018 A 6 1 8

[ 6] .dynstr STRTAB 0000000000400318 00000318 000000000000003d 0000000000000000 A 0 0 1

[ 7] .gnu.version VERSYM 0000000000400356 00000356 0000000000000008 0000000000000002 A 5 0 2

[ 8] .gnu.version_r VERNEED 0000000000400360 00000360 0000000000000020 0000000000000000 A 6 1 8

[ 9] .rela.dyn RELA 0000000000400380 00000380 0000000000000018 0000000000000018 A 5 0 8

[10] .rela.plt RELA 0000000000400398 00000398 0000000000000030 0000000000000018 AI 5 24 8

[11] .init PROGBITS 00000000004003c8 000003c8 000000000000001a 0000000000000000 AX0 0 4

[12] .plt PROGBITS 00000000004003f0 000003f0 0000000000000030 0000000000000010 AX0 0 16

[13] .plt.got PROGBITS 0000000000400420 00000420? 0000000000000008 0000000000000000 AX0 0 8

[14] .text PROGBITS 0000000000400430 00000430 00000000000001b2 0000000000000000 AX0 0 16

[15] .fini PROGBITS 00000000004005e4 000005e4? 0000000000000009 0000000000000000 AX0 0 4

[16] .rodata PROGBITS 00000000004005f0 000005f0 0000000000000027 0000000000000000 A 0 0 4

[17] .eh_frame_hdr PROGBITS 0000000000400618 00000618 0000000000000044 0000000000000000 A 0 0 4

[18] .eh_frame PROGBITS 0000000000400660 00000660 0000000000000134 0000000000000000 A 0 0 8

[19] .init_array INIT_ARRAY 0000000000600e00 00000e00 0000000000000010 0000000000000000 WA 0 0 8

[20] .fini_array FINI_ARRAY 0000000000600e10 00000e10? 0000000000000010 0000000000000000 WA 0 0 8

[21] .jcr PROGBITS 0000000000600e20 00000e20 0000000000000008 0000000000000000 WA 0 0 8

[22] .dynamic DYNAMIC 0000000000600e28 00000e28 00000000000001d0 0000000000000010 WA 6 0 8

[23] .got PROGBITS 0000000000600ff8 00000ff8 0000000000000008 0000000000000008 WA 0 0 8

[24] .got.plt PROGBITS 0000000000601000 00001000 0000000000000028 0000000000000008 WA 0 0 8

[25] .data PROGBITS 0000000000601028 00001028 0000000000000010 0000000000000000 WA 0 0 8

[26] .bss NOBITS 0000000000601038 00001038 0000000000000008 0000000000000000 WA 0 0 1

[27] .comment PROGBITS 0000000000000000 00001038 0000000000000035 0000000000000001 MS 0 0 1

[28] .shstrtab STRTAB 0000000000000000 00001915 000000000000010c 0000000000000000 0 0 1

[29] .symtab SYMTAB 0000000000000000 00001070 0000000000000678 0000000000000018 30 49 8

[30] .strtab STRTAB 0000000000000000 000016e8 000000000000022d 0000000000000000 0 0 1

圖 5

圖5是hello文件的section header, 這個信息描述了這個hello文件中到底存在有多少section,這里我將比較重要的section用紫色表示。其中,.interp, .text, .rodata, .data, .bss等幾個常用段,這里就不在進行介紹(通常.rodata,.data,和.text是挨著的,是為了節約存儲空間,因為.bss不會占用存儲空間)。.interp的具體實現將在以后的文章中加以描述。.note開頭和.gnu開頭的段基本上都是存放與調試相關的信息。

.dynsym和.dynstr: 這兩個段為動態符號段和動態字符串符號段,里面存放的是hello程序需要的外部符號信息,用于動態鏈接。

點擊(此處)折疊或打開

$readelf --dyn-syms hello

Symbol table '.dynsym' contains 4 entries:

Num: Value Size Type Bind Vis Ndx Name

0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND

1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.2.5 (2)

2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2)

3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__

.rela.dyn和.rela.plt:這兩個段是重定位符號表,主要用于指明需要動態解釋器(interpreter)幫忙重定位的符號。

點擊(此處)折疊或打開

$readelf -r hello

Relocation section '.rela.dyn' at offset 0x380 contains 1 entries:

Offset Info Type Sym. Value Sym. Name + Addend

000000600ff8 000300000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0

Relocation section '.rela.plt' at offset 0x398 contains 2 entries:

Offset Info Type Sym. Value Sym. Name + Addend

000000601018 000100000007 R_X86_64_JUMP_SLO 0000000000000000 puts@GLIBC_2.2.5 + 0

000000601020 000200000007 R_X86_64_JUMP_SLO 0000000000000000 __libc_start_main@GLIBC_2.2.5 + 0

注:在Linux當中,并不是所有符號需要在啟動的時候,由動態解釋器(interpreter)重定位。事實上,為了加快應用程序的啟動速度,Linux引入了延遲加載功能,即PLT。所謂的延遲加載是指在啟動的過程中,不需要對所有符號進行重定位,只有在需要該符號的時候,才對其進行重定位,通常Linux將函數作為PLT部分。

注:其中R_X86_64_GLOB_DAT 和R_X86_64_JUMP_SLO 為重定向類型,具體參考重定向。

.init: 與應用初始化相關,在進入main函數之前會涉及到,通常位于PLT代碼的前面。

點擊(此處)折疊或打開

Disassembly of section .init:? 只是一個過渡函數,由__libc_csu_init調用

00000000004003c8 <_init>:

4003c8: 48 83 ec 08 sub $0x8,%rsp

4003cc: 48 8b 05 25 0c 20 00 mov 0x200c25(%rip),%rax # 600ff8 <_dynamic>

4003d3: 48 85 c0 test %rax,%rax

4003d6: 74 05 je 4003dd <_init>

4003d8: e8 43 00 00 00 callq 400420 <__libc_start_main>

4003dd: 48 83 c4 08 add $0x8,%rsp

4003e1: c3 retq

.plt和.plt.got: .plt用于存放PLT跳板,如puts@GLIBC_2.2.5的實現(以后講解具體怎么跳);下圖為.plt段和.got.plt段的具體內容,其中.plt段內部是跳板函數的實現(匯編語句),.got.plt則只是數據的實現:

點擊(此處)折疊或打開

Contents of section .got.plt:? ? ? ? ? ? ?.got.plt的內容,601020->0x400416, 601018->0x400406(標紅部分,為數據,PLT第一次會訪問這里,之后這里會被覆蓋成真正的函數地址)

601000 280e6000 00000000 00000000 00000000? (.`.............

601010 00000000 00000000 0604400000000000? ..........@.....

601020 16044000 00000000

Disassembly of section .plt:

00000000004003f0 :

4003f0: ff 35 12 0c 20 00 pushq 0x200c12(%rip) # 601008 <_global_offset_table_>

4003f6: ff 25 14 0c 20 00 jmpq *0x200c14(%rip) # 601010 <_global_offset_table_>

4003fc: 0f 1f 40 00 nopl 0x0(%rax)

0000000000400400 :? ?這是一個跳板函數,當第一次調用的時候,GOT+0x8指向400406,然后進行函數重定位,第二次調用的時候,指向重定位后的地址

400400: ff 25 12 0c 20 00 jmpq *0x200c12(%rip) # 601018 <_global_offset_table_>

400406: 68 00 00 00 00 pushq $0x0

40040b: e9 e0 ff ff ff jmpq 4003f0 <_init>

0000000000400410 <__libc_start_main>:跳板函數:當第一次調用的時候,GOT+0x8指向400416,然后進行函數重定位,第二次調用的時候,指向重定位后的地址

400410: ff 25 0a 0c 20 00 jmpq *0x200c0a(%rip) # 601020 <_global_offset_table_>

400416: 68 01 00 00 00 pushq $0x1

40041b: e9 d0 ff ff ff jmpq 4003f0 <_init>

Disassembly of section .plt.got:

0000000000400420 <.plt.got>:

400420: ff 25 d2 0b 20 00 jmpq *0x200bd2(%rip) # 600ff8 <_dynamic>

400426: 66 90 xchg %ax,%ax

如上圖,如果我調用puts函數,則是通過callq? 400400 來調用的,即首先調用的是puts@plt函數,而這個函數就是在.plt段中實現的跳板函數,由它來完成最后的延遲重定向。

.fini: 與應用退出有關,在main函數退出可能會涉及到,通常為空。

.init_array和.fini_array: 類似于構造函數和析構函數,掛在.init_array段里面的函數,在main函數運行前運行;掛在.fini_array段里面的函數在main函數退出后運行。

.got和.got.plt: 又名全局偏移表,用于存放全局符號地址,其中plt屬于一種特殊的GOT表。.got.plt主要用于存放動態函數地址,此表和PLT搭配使用(以后會講解)。

.symtab和.strtab: hello程序內部能提供的符號表和一些符號信息,這個段通常用于動態庫需要,應用程序對此無用。

點擊(此處)折疊或打開

$readelf -s hello

Symbol table '.dynsym' contains 4 entries:

Num: Value Size Type Bind Vis Ndx Name

0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND

1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.2.5 (2)

2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2)

3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__

Symbol table '.symtab' contains 69 entries:

Num: Value Size Type Bind Vis Ndx Name

0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND

1: 0000000000400238 0 SECTION LOCAL DEFAULT 1

2: 0000000000400254 0 SECTION LOCAL DEFAULT 2

3: 0000000000400274 0 SECTION LOCAL DEFAULT 3

4: 0000000000400298 0 SECTION LOCAL DEFAULT 4

5: 00000000004002b8 0 SECTION LOCAL DEFAULT 5

限于篇幅,此處省略部分符號

55: 0000000000000000? ? ?0 FUNC? ? GLOBAL DEFAULT? UND __libc_start_main@@GLIBC

56: 0000000000601028? ? ?0 NOTYPE? GLOBAL DEFAULT? ?25 __data_start

57: 0000000000000000? ? ?0 NOTYPE? WEAK? ?DEFAULT? UND __gmon_start__

58: 0000000000601030? ? ?0 OBJECT? GLOBAL HIDDEN? ? 25 __dso_handle

59: 00000000004005f0? ? ?4 OBJECT? GLOBAL DEFAULT? ?16 _IO_stdin_used

60: 0000000000400570? ?101 FUNC? ? GLOBAL DEFAULT? ?14 __libc_csu_init

61: 0000000000601040? ? ?0 NOTYPE? GLOBAL DEFAULT? ?26 _end

62: 0000000000400430? ? 42 FUNC? ? GLOBAL DEFAULT? ?14 _start

63: 0000000000601038? ? ?0 NOTYPE? GLOBAL DEFAULT? ?26 __bss_start

64: 0000000000400548? ? 32 FUNC? ? GLOBAL DEFAULT? ?14 main

65: 0000000000000000? ? ?0 NOTYPE? WEAK? ?DEFAULT? UND _Jv_RegisterClasses

66: 0000000000601038? ? ?0 OBJECT? GLOBAL HIDDEN? ? 25 __TMC_END__

67: 0000000000000000? ? ?0 NOTYPE? WEAK? ?DEFAULT? UND _ITM_registerTMCloneTable

68: 00000000004003c8? ? ?0 FUNC? ? GLOBAL DEFAULT? ?11 _init

如上圖,符號表可以看出一個符號是否為全局符號,是否為弱符號,是否為局部符號,符號是函數還是變量等等。其中UND表示未定義,需要外部重定位的,GLOBAL為全局,LOCAL為局部,WEAK為弱符號,FUNC為函數,OBJECT為變量,NOTYPE為需要外部重定位的。例如:

64行:64: 0000000000400548? ? 32 FUNC? ? GLOBAL DEFAULT? ?14 main

函數名字main函數,全局符號,函數,地址0x400548等。

另外,我們可以通過objdump -s hello獲取整個hello文件各個section對應的內容,如下:

點擊(此處)折疊或打開

hello: file format elf64-x86-64 (下面的布局是按照program header提供的虛擬內存地址布局的,如.interp的起始地址0x400238)

Contents of section .interp:

4002382f6c6962 36342f6c 642d6c69 6e75782d /lib64/ld-linux-

400248 7838362d 36342e73 6f2e3200 x86-64.so.2.

Contents of section .note.ABI-tag:

400254 04000000 10000000 01000000 474e5500 ............GNU.

400264 00000000 02000000 06000000 20000000 ............ ...

Contents of section .note.gnu.build-id:

400274 04000000 14000000 03000000 474e5500 ............GNU.

400284 ce3c4f78 e2194357 f5296b53 6f39b5c2 .

400294 e4f14ee6 ..N.

Contents of section .gnu.hash:

400298 01000000 01000000 01000000 00000000 ................

4002a8 00000000 00000000 00000000 ............

Contents of section .dynsym:

4002b8 00000000 00000000 00000000 00000000 ................

4002c8 00000000 00000000 0b000000 12000000 ................

4002d8 00000000 00000000 00000000 00000000 ................

4002e8 10000000 12000000 00000000 00000000 ................

4002f8 00000000 00000000 22000000 20000000 ........"... ...

400308 00000000 00000000 00000000 00000000 ................

Contents of section .dynstr:

400318 006c6962 632e736f 2e360070 75747300 .libc.so.6.puts.

400328 5f5f6c69 62635f73 74617274 5f6d6169 __libc_start_mai

400338 6e005f5f 676d6f6e 5f737461 72745f5f n.__gmon_start__

400348 00474c49 42435f32 2e322e35 00 .GLIBC_2.2.5.

Contents of section .gnu.version:

400356 00000200 02000000 ........

Contents of section .gnu.version_r:

400360 01000100 01000000 10000000 00000000 ................

400370 751a6909 00000200 31000000 00000000 u.i.....1.......

Contents of section .rela.dyn:

400380 f80f6000 00000000 06000000 03000000 ..`.............

400390 00000000 00000000 ........

Contents of section .rela.plt:

400398 18106000 00000000 07000000 01000000 ..`.............

4003a8 00000000 00000000 20106000 00000000 ........ .`.....

4003b8 07000000 02000000 00000000 00000000 ................

Contents of section .init:

4003c8 4883ec08 488b0525 0c200048 85c07405 H...H..%. .H..t.

4003d8 e8430000 004883c4 08c3 .C...H....

Contents of section .plt:

4003f0 ff35120c 2000ff25 140c2000 0f1f4000 .5.. ..%.. ...@.

400400 ff25120c 20006800 000000e9 e0ffffff .%.. .h.........

400410 ff250a0c 20006801 000000e9 d0ffffff .%.. .h.........

Contents of section .plt.got:

400420 ff25d20b 20006690 .%.. .f.

Contents of section .text:

省略.text的具體內容

Contents of section .fini:

4005e4 4883ec08 4883c408 c3 H...H....

Contents of section .rodata:

4005f0 01000200 4265666f 7265206d 61696e00 ....Before main.

400600 41667465 72206d61 696e0048 656c6c6f After main.Hello

400610 20576f72 6c6400 World.

Contents of section .eh_frame_hdr:

400618 011b033b 44000000 07000000 d8fdffff ...;D...........

400628 90000000 18feffff 60000000 0effffff ........`.......

400638 b8000000 1fffffff d8000000 30ffffff ............0...

400648 f8000000 58ffffff 18010000 c8ffffff ....X...........

400658 60010000 `...

Contents of section .eh_frame:

400660 14000000 00000000 017a5200 01781001 .........zR..x..

400670 1b0c0708 90010710 14000000 1c000000 ................

400680 b0fdffff 2a000000 00000000 00000000 ....*...........

400690 14000000 00000000 017a5200 01781001 .........zR..x..

4006a0 1b0c0708 90010000 24000000 1c000000 ........$.......

4006b0 40fdffff 30000000 000e1046 0e184a0f @...0......F..J.

4006c0 0b770880 003f1a3b 2a332422 00000000 .w...?.;*3$"....

4006d0 1c000000 44000000 4efeffff 11000000 ....D...N.......

4006e0 00410e10 8602430d 064c0c07 08000000 .A....C..L......

4006f0 1c000000 64000000 3ffeffff 11000000 ....d...?.......

400700 00410e10 8602430d 064c0c07 08000000 .A....C..L......

400710 1c000000 84000000 30feffff 20000000 ........0... ...

400720 00410e10 8602430d 065b0c07 08000000 .A....C..[......

400730 44000000 a4000000 38feffff 65000000 D.......8...e...

400740 00420e10 8f02420e 188e0345 0e208d04 .B....B....E. ..

400750 420e288c 05480e30 8606480e 3883074d B.(..H.0..H.8..M

400760 0e40720e 38410e30 410e2842 0e20420e .@r.8A.0A.(B. B.

400770 18420e10 420e0800 14000000 ec000000 .B..B...........

400780 60feffff 02000000 00000000 00000000 `...............

400790 00000000 ....

Contents of section .init_array:

600e00 00054000 00000000 26054000 00000000 ..@.....&.@.....

Contents of section .fini_array:

600e10 e0044000 00000000 37054000 00000000 ..@.....7.@.....

Contents of section .jcr:

600e20 00000000 00000000 ........

Contents of section .dynamic:

省略.dynamic具體內容

Contents of section .got:

600ff8 00000000 00000000 ........

Contents of section .got.plt:

601000 280e6000 00000000 00000000 00000000 (.`.............

601010 00000000 00000000 06044000 00000000 ..........@.....

601020 16044000 00000000 ..@.....

Contents of section .data:

601028 00000000 00000000 00000000 00000000 ................

Contents of section .comment:

0000 4743433a 20285562 756e7475 20352e34 GCC: (Ubuntu 5.4

0010 2e302d36 7562756e 7475317e 31362e30 .0-6ubuntu1~16.0

0020 342e3131 2920352e 342e3020 32303136 4.11) 5.4.0 2016

0030 30363039 00 0609.

通過上圖,再結合各個段的具體信息,可以做進一步分析。上圖的具體格式為:

Contents of section 段名:

地址? 內容1? ?內容2 內容3 內容4? ? ? ASCII字符

地址? 內容1? ?內容2 內容3 內容4? ? ? ASCII字符

地址? 內容1? ?內容2 內容3 內容4? ? ? ASCII字符

...........................

elf文件的大致粗略信息就是如此,如果有需要可以進行更詳細的分析,這篇到這里為止,下一篇,主要分析execve系統調用里面到底完成了什么。

總結

以上是生活随笔為你收集整理的linux如何调试elf程序,Linux应用程序elf描述的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。