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

歡迎訪問 生活随笔!

生活随笔

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

linux

Linux C目标文件

發布時間:2023/12/20 linux 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux C目标文件 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

LinuxC目標文件


宗旨:技術的學習是有限的,分享的精神是無限的。


一、目標文件格式(ELF格式)

編譯器編譯源代碼后生成的文件叫做目標文件。目標文件是已經編譯后的可執行文件,只是還沒有經過鏈接的過程。

PC平臺流行的可執行文件格式:windows下的PE和Linux下的ELF。

動態鏈接庫和靜態鏈接庫也是按照可執行文件存儲的。

1ELF文件歸于4類:

ELF文講類型

說明

舉例

可重定位文件

目標文件.o

Linux的.o, windows下的.obj

可執行文件

直接可執行的文件

/bin/bash ??windows的.exe

共享目標文件

?

.so?? DLL

核心轉儲文件

進程意外終止

core dump

Linux下的file命令查看相應的文件格式:



2、目標文件

編譯后的機器指令代碼、數據、符號表、調試信息、字符串等。

一般目標文件將這些文件信息按不同的屬性,以“節”的形式存儲。

機器指令放在代碼段.text,已初始化全局變量和靜態變量放在數據段里.data,未初始化全局變量和靜態變量放在數據段里.bss。.bss只是為變量預留的位置而已,并沒有內容,不占據空間。

??

二、剖析目標文件section.o

// section.c: #include<stdio.h>int init_var = 84; int uninit_var;void fun(int i) {printf(" %d \n", i); }int main(void) {static int static_var = 85;static int static_var2;int a = 1;int b;fun(init_var + uninit_var + a + b);return 0; }

gcc? -c ?section.c生成section.o——只編譯不鏈接?

objdump? -h? section.o// ELF文件的各個段的基本信息打印出來。


除了最基本的代碼段、數據段、BSS段,還有三個段:只讀數據段(.rodata)、注釋信息段(.comment)和堆棧提示段(.note.GNU-stack)。

段的屬性:最容易理解的就是段的長度Size和段所在的位置File off(偏移量)。每個段第二行的“CONTENTS”表示該段在文件中存在——BSS段沒有“CONTENTS “,實際上在ELF中不存在;”note.GNU-stack“有“CONTENTS”但大小為0,奇怪。

?

size命令查看ELF文件中的代碼段、數據段和BSS段長度。

root@colinux:~/mystudy# size section.o

?? text??? data????bss???? dec???? hex filename

? ?88??????8?????? 4???? 100?????64 section.o

?

1、代碼段

???????? objdump的“-s”十六進制方式打印,“-d”反匯編。提取出代碼段的內容:

?

“Contents of section.text”就是.text的數據以十六進制方式打印出來的內容,0x58字節,與size命令的長度符合。對照反匯編結果,.text包含兩個函數,fun()和main()。.text的第一個字節就是”0x55”就是fun()函數的第一條“push?? %ebp”指令,而最后一個字節0xc3正是main()函數的最后一條指令“ret”。


2、數據段和只讀數據段

???????? .data段保存的是初始化的全局變量和靜態變量,section.c中有這樣兩個變量init_var和static_var,都是int型,剛好8字節。所以.data的大小是8字節。

Contents of section .data:

?0000 54000000 55000000??????????????????? T...U...???????

Contents of section .rodata:

?0000 20256420 0a00???????????????????????? %d ..??

.data前四個字節,0x54、0x00、0x00、0x00 —— 0x54 = 84;——大端機

?

3BSS

???????? .bss段保存的是未化的全局變量和靜態變量,section.c中有這樣兩個變量uninit_var和static_var2。但是通過size命令看到.bss只有4字節。通過符號表(后面說)看到,只有static_var2被放入了.bss段,uninit_var沒有。與不同的語言和不同的編譯器有關。

?

4、其他段? ? ? ??

常用段名

說明

.rodata

只讀數據,如字符串常量,const只讀變量

.comment

編譯器版本信息,

.debug

調試信息

.dynamic

動態鏈接信息

.hash

符號哈希表

.line

行號表

.note

額外的編譯器信息:公司名,發布版本號等

.strtab

字符串表

.symtab

符號表

.shstrtab

段名表

.plt?? .got

動態鏈接的跳轉表和全局入口表

.init? .fini

程序初始化與終結代碼段

?

三、ELF文件結構

???????? 提取重要的結構:ELFHeaderELF文件頭)、.text.data.bss、其他段、段表、字符串表、符號表等。

ELF文件頭——描述了整個文件的文件屬性:是否可執行、是靜態還是動態連接及入口地址、目標硬件、目標操作系統等信息。

段表——所有段的信息:段名、段的長度、在文件中的偏移、讀寫權限及段的其他屬性。

?

1、文件頭(readelf命令)?


ELF文件頭定義:ELF魔數、文件機器字節長度、文件存儲方式、版本、運行平臺、ABI版本、ELF重定位類型、硬件平臺、硬件平臺版本、入口地址、程序頭入口地址和長度、段表的位置和長度及段的數量等。

ELF文件頭結構及相關常數被定義在”/usr/include/elf.h”,32位“ELF32_Ehdr

#define EI_NIDENT(16)typedef struct {unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */Elf32_Half e_type; /* Objectfile type */Elf32_Half e_machine; /*Architecture */Elf32_Word e_version; /* Object file version */Elf32_Addr e_entry; /* Entrypoint virtual address */Elf32_Off e_phoff; /* Programheader table file offset */Elf32_Off e_shoff; /* Sectionheader table file offset */Elf32_Word e_flags; /*Processor-specific flags */Elf32_Half e_ehsize; /* ELFheader size in bytes */Elf32_Half e_phentsize; /* Programheader table entry size */Elf32_Half e_phnum; /* Program header table entrycount */Elf32_Half e_shentsize; /* Sectionheader table entry size */Elf32_Half e_shnum; /* Sectionheader table entry count */Elf32_Half e_shstrndx; /* Sectionheader string table index */ } Elf32_Ehdr;

結構與readelf輸出的ELF文件頭信息相比:只有e_ident對應了readelf輸出中的“Class ?Data? Version?OS/ABI? ABI Version”5個參數,剩下的參數一一對應。

ELF魔數:Magic:??7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 ?

16字節對應了Elf32_Ehdr的e_ident這個16字節成員。這16字節被ELF標準規定來標識ELF文件的平臺屬性:如字長、字節序、版本等。16字節含義:

前4字節是所有ELF文件都必須相同的標識碼:0x7F、0X45、0X4C、0X46(這四個字節就是ELF文件的魔數)。幾乎所有的可執行文件的開始的幾個字節都是魔數,如a.out最開始兩個字節是0x01、0x07;PE最開始兩個字節是0x4d、0x5a。這個魔數用來確認文件類型。第5個字節用來標識ELF文件類的,0x01表示是32位的,0x02表示64位的。第6字節是字節序,規定ELF文件是大端的還是小端的。第7字節規定ELF文件的主版本號,一般是1.后面的九個字節ELF標準沒有定義,一般寫0。

e_type文件類型:ET_REL—— 1 ——可重定位文件,一般是.o文件;ET_EXEC—— 2 —— 可執行文件; ET_DYN —— 2 ——共享目標文件,一般是.so文件。

e_machine機器類型:ELF文件的平臺屬性,EM_386 —— 3 —— x86

?

2、段表

ELF的段結構就是由段表決定的,編譯器、連接器和裝載器都是靠段表來定位和訪問各個段的屬性的。段表在ELF文件中的位置由ELF文件頭Elf32_Ehdr結構中的” e_shoff” 成員決定。section.o中,段表位于偏移0x104(260字節)處。

前面用”objdump -h”查看ELF文件中的段,此命令只是把ELF文件中的關鍵段顯示出來了,省略了其他輔助性的段:符號表、字符串表、重定位表等。

readelf -S命令


段表是以“Elf32_Shdr”結構體為元素的數組,數組元素的個數等于段的個數,每個“Elf32_Shdr”結構體對應一個段。section.o:11個元素的數組。/usr/include/elf.h:

typedef struct {Elf32_Word sh_name; /* Section name (string tblindex) */Elf32_Word sh_type; /* Section type */Elf32_Word sh_flags; /* Section flags */Elf32_Addr sh_addr; /* Section virtual addr atexecution */Elf32_Off sh_offset; /* Section file offset */Elf32_Word sh_size; /* Section size in bytes */Elf32_Word sh_link; /* Link to another section */Elf32_Word sh_info; /* Additional sectioninformation */Elf32_Word sh_addralign; /* Section alignment */Elf32_Word sh_entsize; /* Entry size if section holdstable */ } Elf32_Shdr;

總結section.o段表的位置

?

起始地址

大小

ELF Header? e_shoff = 0x104

0

0x34

.text

0x34

0x52

.data

0x88

0x08

.rodata

0x90

0x06

.comment

0x96

0x1d

.shstrtab

0xB3

0x51

Section Table

0x104

0x1b8

.symtab

0x2bc

0xf0

.rel.text

0x3fc

0x28

長度為0x424 = 1060,這個長度正好是section.o文件的大小。

段的類型(sh_type):段的名字只有在編譯和鏈接的過程中有意義。SHT_NULL – 0 – 無效段, SHT_PROGBITS– 1 – 程序段, SHT_SYMTAB – 2 – 表示該段的內容為符號表, SHT_STRTAB – 3 – 字符串表, SHT_RELA –4 – 重定位表, SHT_HASH – 5 – 符號表的哈希表,SHT_DYNAMIC – 6 – 動態鏈接信息, SHT_NOTE – 7 – 提示性信息, SHT_NOBITS– 8 –該段在文件中沒內容, SHT_REL – 9 –該段包含了重定位信息,SHT_SHLIB – 10 – 保留,SHT_DNYSYM – 11 – 動態鏈接的符號表。

段的標志位(sh_flag):表示該段在進程虛擬地址空間中的屬性,可寫可執行等。SHF_WRITE – 1 – 該段在進程空間中可寫; SHF_ALLOC– 2 – 在進程空間中要分配空間; SHF_EXECINSTR– 4 –該段在進程空間中可以被執行,一般指代碼段。

???????? 段的鏈接信息(sh_link、sh_info):

sh_type

sh_link

sh_info

SHT_DYNAMIC

字符串表在段表的下標

0

SHT_HASH

符號表在段表中的下標

0

SHT_REL

相應符號表在段表中的下標

該重定位表所作用的段在段表中的下標

SHT_RELA

SHT_SYMTAB

操作系統相關

操作系統相關

SHTDYNSYM

other

SHN_UNDEF

0

?

3、重定位表

???????? section.o中有一個“rel.text”的段,類型是“SHT_REL”——重定位表。

代碼段和數據段中那些對絕對地址的引用的位置——相應的重定位表。section.o中的“rel.text”就是對“.text”段的重定位表——printf函數的調用;而“.data”段沒有對絕對地址的引用,只包含了幾個常量,故沒有“.rel.data”。

?

4、字符串表——段名,變量名等

?

四、鏈接的接口——符號

???????? 可以使用很多工具查看ELF文件的符號表,readelfobjdumpnm等;

1ELF符號表結構

???????? ELF符號表是文件中的一個段“.symtab”

/* Symbol table entry. */ typedef struct {Elf32_Word st_name; /* Symbol name (string tblindex) */Elf32_Addr st_value; /* Symbol value */Elf32_Word st_size; /* Symbol size */unsigned char st_info; /* Symbol type and binding */unsigned char st_other; /* Symbol visibility */Elf32_Section st_shndx; /* Section index */ } Elf32_Sym;


總結

以上是生活随笔為你收集整理的Linux C目标文件的全部內容,希望文章能夠幫你解決所遇到的問題。

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