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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

cfile清空文件内容_编译-链接-加载 :ELF文件格式解析

發(fā)布時(shí)間:2024/9/30 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 cfile清空文件内容_编译-链接-加载 :ELF文件格式解析 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

摘要:對(duì)于C++的初學(xué)者,經(jīng)常在程序的編譯或者加載過(guò)程中遇到很多錯(cuò)誤,類似undefined reference to ... 和 GLIBCXX_3.4.20 not found 等。這些錯(cuò)誤都涉及到編譯器、連接器、加載器的相關(guān)知識(shí)。本系列文章,將通過(guò)一個(gè)實(shí)例程序,詳細(xì)介紹一個(gè)程序的編譯、鏈接、加載的過(guò)程。為了弄清這個(gè)過(guò)程,本文會(huì)簡(jiǎn)要介紹文本代碼到可執(zhí)行二進(jìn)制文件的大致過(guò)程,同時(shí)介紹x86平臺(tái)上linux系統(tǒng)下ELF文件格式,方便后續(xù)詳細(xì)探討編譯-鏈接-加載的詳細(xì)過(guò)程。

1. 程序的編譯與鏈接過(guò)程

對(duì)于編譯型的程序,代碼需要經(jīng)過(guò)編譯-鏈接的過(guò)程才會(huì)生成可執(zhí)行程序,具體過(guò)程如下

=====> COMPILATION PROCESS <======||----> Input is Source file(.c)|V+=================+| || C Preprocessor || |+=================+|| ---> Pure C file ( comd:cc -E <file.name> )|V+=================+| || Lexical Analyzer|| |+-----------------+| || Syntax Analyzer || |+-----------------+| || Semantic Analyze|| |+-----------------+| || Pre Optimization|| |+-----------------+| || Code generation || |+-----------------+| || Post Optimize || |+=================+||---> Assembly code (comd: cc -S <file.name> )|V+=================+| || Assembler || |+=================+||---> Object file (.obj) (comd: cc -c <file.name>)|V+=================+| Linker || and || loader |+=================+||---> Executable (.Exe/a.out) (com:cc <file.name> ) |VExecutable file(a.out)
  • 預(yù)處理:C語(yǔ)言預(yù)處理器展開 宏定義、#include、#deine 生成純C的代碼
  • 編譯
    • 詞法分析
    • 語(yǔ)法分析
    • 語(yǔ)義分析
    • 源代碼優(yōu)化:循環(huán)優(yōu)化、無(wú)用代碼刪除等
    • 代碼生成
      3. 鏈接:符號(hào)解析、重定位等。注意連接器和加載器的功能區(qū)分并不是那么清晰,對(duì)于loader而言,也會(huì)處理一些鏈接的工作。

    后文用到的main.cpp內(nèi)容如下,其他代碼都在這里 https://github.com/yukun89/draft/tree/master/hello_world/chapter1

    #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include "func.h" int global_b = 1; const int global_c = 1; int global_d[10]; static int global_e[10];int main(){static char *p = "Begin printf ";int *ip = (int *)malloc(4);*ip = 1;global_b = func(*ip);printf("%s the value of func is %dn", p, func(1));return global_b + global_c; }

    2.ELF文件格式

    與編譯-鏈接-加載相關(guān)的ELF文件主要有兩種格式:可重定位目標(biāo)文件(后綴名為.o) 與 可執(zhí)行目標(biāo)文件。(另外還有兩種是共享庫(kù)文件 和 coredump文件。)

    分析數(shù)據(jù)結(jié)構(gòu)之前,我們秉承一個(gè)基本原則:結(jié)構(gòu)決定功能;反過(guò)來(lái)說(shuō)也成立,設(shè)計(jì)ELF文件結(jié)構(gòu),是為了滿足特定的功能。這里我們先簡(jiǎn)要梳理一下,ELF文件應(yīng)該提供哪些功能?簡(jiǎn)單來(lái)說(shuō),ELF文件需要滿足可鏈接、可加載、可執(zhí)行三大類基本功能,具體來(lái)說(shuō),包含以下詳細(xì)功能。

    • 從可執(zhí)行的角度講,程序需要包含指令與數(shù)據(jù),也就是說(shuō)ELF文件中需要存儲(chǔ)程序?qū)?yīng)的指令和數(shù)據(jù)
    • 從可鏈接的角度講,需要處理不同編譯單元之間的引用問(wèn)題,所以需要符號(hào)解析與重定位相關(guān)信息
    • 從內(nèi)容組織的角度講,ELF文件中包含代碼、數(shù)據(jù)、重定位信息等多個(gè)section,同時(shí)包含這些數(shù)據(jù)的元數(shù)據(jù)信息(每個(gè)section在文件的起始地址是什么,有多大)。另外,ELF文件格式和其他的任何二進(jìn)制文件一樣,還應(yīng)該包含一個(gè)header,作為所有ELF文件中信息的元數(shù)據(jù)
    • 從可加載的角度講,ELF文件需要指定將那些代碼、數(shù)據(jù)映射到虛擬內(nèi)存的什么位置

    綜上,ELF的文件大致格式如圖所示

    注意:Section Headers并不在ELF文件的末尾;Program Header table并不存在于每一種ELF文件格式之中。下面我們用linux下的兩個(gè)命令工具readelf和objdump來(lái)詳細(xì)分析ELF文件中的各個(gè)部分。

    2.1 ELF文件頭

    ELF文件的相關(guān)定義在/usr/include/elf.h文件之中,具體ELF文件頭的信息如下

    typedef struct {unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */Elf64_Half e_type; /* Object file type */Elf64_Half e_machine; /* Architecture */Elf64_Word e_version; /* Object file version */Elf64_Addr e_entry; /* Entry point virtual address */Elf64_Off e_phoff; /* Program header table file offset */Elf64_Off e_shoff; /* Section header table file offset */Elf64_Word e_flags; /* Processor-specific flags */Elf64_Half e_ehsize; /* ELF header size in bytes */Elf64_Half e_phentsize; /* Program header table entry size */Elf64_Half e_phnum; /* Program header table entry count */Elf64_Half e_shentsize; /* Section header table entry size */Elf64_Half e_shnum; /* Section header table entry count */Elf64_Half e_shstrndx; /* Section header string table index */ } Elf64_Ehdr;

    這里,我們用readelf -h分別查看main.o和main兩種不同格式ELF文件的文件頭,得到的結(jié)果如下

    ykhuang@0062a6cb7e5e: readelf -h main.o ELF Header:Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00Class: ELF64Data: 2's complement, little endianVersion: 1 (current)OS/ABI: UNIX - System VABI Version: 0Type: REL (Relocatable file)Machine: Advanced Micro Devices X86-64Version: 0x1Entry point address: 0x0Start of program headers: 0 (bytes into file)Start of section headers: 1112 (bytes into file)Flags: 0x0Size of this header: 64 (bytes)Size of program headers: 0 (bytes)Number of program headers: 0Size of section headers: 64 (bytes)Number of section headers: 14Section header string table index: 1ykhuang@0062a6cb7e5e : readelf -h main ELF Header:Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00Class: ELF64Data: 2's complement, little endianVersion: 1 (current)OS/ABI: UNIX - System VABI Version: 0Type: EXEC (Executable file)Machine: Advanced Micro Devices X86-64Version: 0x1Entry point address: 0x400550Start of program headers: 64 (bytes into file)Start of section headers: 4536 (bytes into file)Flags: 0x0Size of this header: 64 (bytes)Size of program headers: 56 (bytes)Number of program headers: 9Size of section headers: 64 (bytes)Number of section headers: 30Section header string table index: 27

    通過(guò)以上的內(nèi)容,我們不難分析,header的主要作用是標(biāo)識(shí)ELF文件中section headers和program headers的位置與大小。header中各個(gè)其他字段的解釋,我們主要關(guān)注以下幾點(diǎn)

    • Type表示這個(gè)ELF文件屬于上文說(shuō)到的哪種(可重定位還是可執(zhí)行)ELF文件
    • 程序入口地址Entry point address這一項(xiàng)對(duì)于可執(zhí)行文件才有意義
    • 因?yàn)閘oader只會(huì)加載可執(zhí)行文件,將文件中的代碼和數(shù)據(jù)映射到虛擬MM,所以只有可執(zhí)行文件的program headers相關(guān)信息才有意義。

    2.2 ELF文件section

    ELF文件中的section主要包括:代碼段、數(shù)據(jù)段、重定位段等信息,section對(duì)應(yīng)的數(shù)據(jù)結(jié)構(gòu)如下

    typedef struct {Elf64_Word sh_name; /* Section name (string tbl index) */Elf64_Word sh_type; /* Section type */Elf64_Xword sh_flags; /* Section flags */Elf64_Addr sh_addr; /* Section virtual addr at execution */Elf64_Off sh_offset; /* Section file offset */Elf64_Xword sh_size; /* Section size in bytes */Elf64_Word sh_link; /* Link to another section */Elf64_Word sh_info; /* Additional section information */Elf64_Xword sh_addralign; /* Section alignment */Elf64_Xword sh_entsize; /* Entry size if section holds table */ } Elf64_Shdr;

    下面,讓我們來(lái)分別查看可重定位目標(biāo)文件與可執(zhí)行目標(biāo)文件的section信息

    ####可重定位目標(biāo)文件的信息ykhuang@0062a6cb7e5e  ~/project/draft/hello_world/chapter1   master ●  readelf -S -W main.o There are 14 section headers, starting at offset 0x1c0:Section Headers:[Nr] Name Type Address Off Size ES Flg Lk Inf Al[ 0] NULL 0000000000000000 000000 000000 00 0 0 0[ 1] .text PROGBITS 0000000000000000 000040 000063 00 AX 0 0 4[ 2] .rela.text RELA 0000000000000000 000750 0000c0 18 12 1 8[ 3] .data PROGBITS 0000000000000000 0000a8 000010 00 WA 0 0 8[ 4] .rela.data RELA 0000000000000000 000810 000018 18 12 3 8[ 5] .bss NOBITS 0000000000000000 0000c0 000068 00 WA 0 0 32[ 6] .rodata PROGBITS 0000000000000000 0000c0 00002e 00 A 0 0 4[ 7] .comment PROGBITS 0000000000000000 0000ee 00002d 01 MS 0 0 1[ 8] .note.GNU-stack PROGBITS 0000000000000000 00011b 000000 00 0 0 1[ 9] .eh_frame PROGBITS 0000000000000000 000120 000038 00 A 0 0 8[10] .rela.eh_frame RELA 0000000000000000 000828 000018 18 12 9 8[11] .shstrtab STRTAB 0000000000000000 000158 000066 00 0 0 1[12] .symtab SYMTAB 0000000000000000 000540 0001b0 18 13 11 8[13] .strtab STRTAB 0000000000000000 0006f0 00005a 00 0 0 1 Key to Flags:W (write), A (alloc), X (execute), M (merge), S (strings), l (large)I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)O (extra OS processing required) o (OS specific), p (processor specific)

    其中type字段的含義如下:

    • PROGBITS: 程序內(nèi)容,包含代碼、數(shù)據(jù)、調(diào)試相關(guān)信息
    • NOBITS:和PROGBITS類似,唯一不同的是在文件中不占空間,對(duì)應(yīng)的進(jìn)行內(nèi)存空間是加載的時(shí)候申請(qǐng)的
    • SYSTAM/DYNSYM: SYSTAM 表用于普通鏈接;DYNSYM用于動(dòng)態(tài)鏈接
    • STRTAB:string table,用于section名稱、普通的符號(hào)名稱、動(dòng)態(tài)鏈接的符號(hào)名稱。 據(jù)此,我們繪制出main.o文件的布局如下:

    可執(zhí)行文件的信息比較繁瑣,我們大致給出,后續(xù)再分析具體每個(gè)section的含義與作用。

    ####可執(zhí)行文件的section信息ykhuang@0062a6cb7e5e  ~/project/draft/hello_world/chapter1   master ●  readelf -S -W main There are 30 section headers, starting at offset 0x11b8:Section Headers:[Nr] Name Type Address Off Size ES Flg Lk Inf Al[ 0] NULL 0000000000000000 000000 000000 00 0 0 0[ 1] .interp PROGBITS 0000000000400238 000238 00001c 00 A 0 0 1[ 2] .note.ABI-tag NOTE 0000000000400254 000254 000020 00 A 0 0 4[ 3] .note.gnu.build-id NOTE 0000000000400274 000274 000024 00 A 0 0 4[ 4] .gnu.hash GNU_HASH 0000000000400298 000298 00001c 00 A 5 0 8[ 5] .dynsym DYNSYM 00000000004002b8 0002b8 0000c0 18 A 6 1 8[ 6] .dynstr STRTAB 0000000000400378 000378 0000b7 00 A 0 0 1[ 7] .gnu.version VERSYM 0000000000400430 000430 000010 02 A 5 0 2[ 8] .gnu.version_r VERNEED 0000000000400440 000440 000020 00 A 6 1 8[ 9] .rela.dyn RELA 0000000000400460 000460 000018 18 A 5 0 8[10] .rela.plt RELA 0000000000400478 000478 000060 18 A 5 12 8[11] .init PROGBITS 00000000004004d8 0004d8 00001a 00 AX 0 0 4[12] .plt PROGBITS 0000000000400500 000500 000050 10 AX 0 0 16[13] .text PROGBITS 0000000000400550 000550 000224 00 AX 0 0 16[14] .fini PROGBITS 0000000000400774 000774 000009 00 AX 0 0 4[15] .rodata PROGBITS 0000000000400780 000780 00003e 00 A 0 0 8[16] .eh_frame_hdr PROGBITS 00000000004007c0 0007c0 000044 00 A 0 0 4[17] .eh_frame PROGBITS 0000000000400808 000808 000134 00 A 0 0 8[18] .init_array INIT_ARRAY 0000000000600de0 000de0 000008 00 WA 0 0 8[19] .fini_array FINI_ARRAY 0000000000600de8 000de8 000008 00 WA 0 0 8[20] .jcr PROGBITS 0000000000600df0 000df0 000008 00 WA 0 0 8[21] .dynamic DYNAMIC 0000000000600df8 000df8 000200 10 WA 6 0 8[22] .got PROGBITS 0000000000600ff8 000ff8 000008 08 WA 0 0 8[23] .got.plt PROGBITS 0000000000601000 001000 000038 08 WA 0 0 8[24] .data PROGBITS 0000000000601038 001038 000018 00 WA 0 0 8[25] .bss NOBITS 0000000000601050 001050 000038 00 WA 0 0 16[26] .comment PROGBITS 0000000000000000 001050 000060 01 MS 0 0 1[27] .shstrtab STRTAB 0000000000000000 0010b0 000108 00 0 0 1[28] .symtab SYMTAB 0000000000000000 001938 0006d8 18 29 47 8[29] .strtab STRTAB 0000000000000000 002010 00028f 00 0 0 1 Key to Flags:W (write), A (alloc), X (execute), M (merge), S (strings), l (large)I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)O (extra OS processing required) o (OS specific), p (processor specific)

    2.2.1 代碼段(txt)-數(shù)據(jù)段-只讀數(shù)據(jù)段

    代碼段的信息,我們可以用objdump -s -d main.o具體查看代碼段的信息,此處不展開討論。

    數(shù)據(jù)段信息如下:

    ykhuang@0062a6cb7e5e  ~/project/draft/hello_world/chapter1   master ●  objdump -s -d main.omain.o: file format elf64-x86-64Contents of section .text:0000 554889e5 4883ec10 bf040000 00e80000 UH..H...........0010 00004889 45f8488b 45f8c700 01000000 ..H.E.H.E.......0020 488b45f8 8b0089c7 e8000000 00890500 H.E.............0030 000000bf 01000000 e8000000 0089c248 ...............H0040 8b050000 00004889 c6bf0000 0000b800 ......H.........0050 000000e8 00000000 8b050000 000083c0 ................0060 01c9c3 ... Contents of section .data:0000 01000000 00000000 00000000 00000000 ................ Contents of section .rodata:0000 01000000 25732074 68652076 616c7565 ....%s the value0010 206f6620 66756e63 20697320 25640a00 of func is %d..0020 42656769 6e207072 696e7466 2000 Begin printf .

    查看符號(hào)表信息如下 objdump -x main.o

    SYMBOL TABLE: 0000000000000000 g O .data 0000000000000004 global_b 0000000000000000 g O .rodata 0000000000000004 global_c 0000000000000000 g O .bss 0000000000000028 global_d 0000000000000000 g F .text 0000000000000063 main

    從這里我們可以看出,我們只有依賴符號(hào)表,才能知道某個(gè)變量存放的具體數(shù)值信息。

    3.其他

    需要指出的是,ELF文件格式之所以是現(xiàn)在這種結(jié)構(gòu),是由體系結(jié)構(gòu)和操作系統(tǒng)來(lái)決定的。在一些其他的系統(tǒng)上(例如MS-DOS或者IBM system V),編譯-鏈接的中間文件具有完全不同的結(jié)構(gòu)。總體來(lái)說(shuō),這些二進(jìn)制文件主要需要滿足可鏈接、可加載、可執(zhí)行。這里,我們簡(jiǎn)要列出了另外兩種編譯-鏈接-加載相關(guān)的文件結(jié)構(gòu):

    • COM(component object model)文件:MS-DOS系統(tǒng)上的可執(zhí)行文件。只有二進(jìn)制代碼,不包含其他任何信息,代碼會(huì)自動(dòng)load到0x100,只支持一個(gè)代碼段。
    • a.out 文件:unix上可執(zhí)行文件的一種,包含header、代碼段、數(shù)據(jù)段、其他段。程序執(zhí)行的過(guò)程主要是“讀取文件頭; map代碼段;map私有數(shù)據(jù)段; 創(chuàng)建進(jìn)行棧; 設(shè)置寄存器然后跳轉(zhuǎn)到程序開頭”

    ELF文件是目前l(fā)inux平臺(tái)上最通用的一種可鏈接-加載-執(zhí)行的文件結(jié)構(gòu),對(duì)于不同的語(yǔ)言,例如C/C++,他們對(duì)應(yīng)的ELF文件格式略微有所不同:C++相對(duì)于C編譯而成的ELF文件格式有自己獨(dú)特的section。了解ELF文件格式有利于我們后續(xù)詳細(xì)理解程序的鏈接-加載-執(zhí)行過(guò)程。

    最后放一下blog地址,歡迎來(lái)玩

    編譯-鏈接-加載:ELF文件格式解析 | 優(yōu)孚?www.uufool.com

    參考:

  • linker && loader
  • https://stackoverflow.com/questions/3996651/what-is-compiler-linker-loader
  • 總結(jié)

    以上是生活随笔為你收集整理的cfile清空文件内容_编译-链接-加载 :ELF文件格式解析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 91精品欧美一区二区三区 | 午夜在线播放 | 日本视频不卡 | 亚洲一区二区三区观看 | 欧美乱妇狂野欧美在线视频 | 欧美精品激情视频 | 激情久久网站 | 国产精品欧美一区二区三区 | 国产又黄又猛 | 麻豆av毛片 | 名人明星三级videos | 欧美a级片在线观看 | 天天性综合 | 成人免费看片'在线观看 | 免费中文字幕日韩 | 在线观看国产一区 | 草比视频在线观看 | 强开小嫩苞一区二区三区网站 | 爱爱精品视频 | 都市激情亚洲色图 | 怎么可能高潮了就结束漫画 | 国产一二精品 | 国产精品麻豆欧美日韩ww | 在线精品一区二区三区 | 毛片在线视频 | 成年人在线免费 | 欧美丝袜一区二区三区 | 偷拍第1页 | 亚洲视频一区二区三区 | 色婷婷av一区二区三区麻豆综合 | 久久国产剧情 | 香蕉视频网页版 | 欧美成人免费一级人片100 | 黄色在线网站 | 欧美性黄色 | 一起草在线视频 | 天堂精品久久 | 久久久全国免费视频 | 黄色在线播放视频 | 亚洲三页 | 野外性满足hd | 国产最新视频 | 成年人免费视频播放 | 日本一级片在线播放 | 综合xx网| 一区视频在线播放 | 四虎影城库 | 欧美成人小视频 | 手机看片日韩久久 | 亚洲拍拍| 欧美国产日韩一区二区三区 | 久久精品黄 | 日本免费黄网站 | 丰满少妇av | 日本美女全裸 | 九色porny自拍视频 | 色涩色| 国产麻豆成人 | 综合久久五月 | 99re只有精品 | 亚洲a人| 噜噜噜亚洲色成人网站 | 2018天天干天天操 | 欧美一区二区在线观看 | 欧美成人不卡视频 | 欧美一区二区三区系列电影 | 国产精品视频无码 | www.插插插 | 伊人久久精品一区二区三区 | 午夜影视网 | 久久久精品久久 | 婷婷综合国产 | 一级片手机在线观看 | 国产精品久久久久久久无码 | 奇米影视一区二区 | 操操操视频 | 国产性猛交╳xxx乱大交一区 | 久草免费在线视频观看 | 亚洲欧美日韩精品 | 秋霞在线视频 | 日韩精品免费一区 | 美女国产精品 | 古装做爰无遮挡三级聊斋艳谭 | 久久成人综合网 | www.超碰在线 | 一区二区中文字幕 | 在线va视频 | 裸体美女免费视频网站 | 日本精品免费在线观看 | 男人干女人视频 | 日韩有码中文字幕在线 | 秋霞av网 | 久久免费视频2 | 日韩精品在线免费视频 | 黄色成人在线 | 九九视频在线播放 | xxx日本黄色| 久久久精品一区 | 捆绑少妇玩各种sm调教 |