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

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

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > linux >内容正文

linux

Linux elf文件分析

發(fā)布時(shí)間:2023/12/20 linux 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux elf文件分析 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

目錄

      • 前言
      • elf文件格式
          • 1、大致結(jié)構(gòu)
          • 2、ELF header(Ehdr)
          • 3、Program Header Table(Phdr)
          • 4、section header table(Shdr)
      • 查看elf文件信息


前言

elf文件是儲(chǔ)存linux下可重定位文件(.o,.ko),可執(zhí)行文件,共享目標(biāo)文件(.so)的一種文件。


elf文件格式

1、大致結(jié)構(gòu)

2、ELF header(Ehdr)
  • ELF header的定義可以在 /usr/include/elf.h 中找到。Elf32_Ehdr是32位 ELF header的結(jié)構(gòu)體。Elf64_Ehdr是64位ELF header的結(jié)構(gòu)體,兩者主要區(qū)別在于某些成員的長(zhǎng)度不一樣;

  • Ehdr 各個(gè)成員的說(shuō)明

    e_ident[**] //elf標(biāo)識(shí) e_type; //elf類(lèi)型(重定位文件rel(.o,.ko),可執(zhí)行文件,共享目標(biāo)文件dyn(.so)) e_ machine; //目標(biāo)文件體系類(lèi)型,即運(yùn)行架構(gòu),如x86、riscv、arm等 e_version; //目標(biāo)文件版本 e_entry; //elf入口地址 e_ phoff; //程序頭部偏移 e_shoff; //節(jié)區(qū)頭部偏移 e_flags; //處理器的特定標(biāo)志,32位和64位Intel架構(gòu)都沒(méi)有定義標(biāo)志,因此eflags的值是0 e_ehsize; //ELF格式頭部大小 e_phentsize; //程序頭部表項(xiàng)大小 e_phnum; //程序頭表項(xiàng)個(gè)數(shù),即segment數(shù)(各個(gè)segment連續(xù)存放) e_shentsize; //節(jié)區(qū)頭部表項(xiàng)大小 e_shnum; //節(jié)區(qū)表項(xiàng)個(gè)數(shù),即section數(shù)(各個(gè)section連續(xù)存放) e_shstrndx; //str節(jié)區(qū)(symbol的名字)在節(jié)區(qū)中位置(inedx)//可以使用命令 readelf 文件名,幫助理解

    ELF header(Ehdr)
    ELF文件解析(二):ELF header詳解 - JollyWing - 博客園 (cnblogs.com)

3、Program Header Table(Phdr)
  • 將多個(gè)section 再包一層,各個(gè)成員說(shuō)明

    p_type; //segment類(lèi)型,segment就是一些段信息(.text,.rodata..),//一個(gè)segment包含多個(gè)section p_offset; //segment在文件中的偏移 p_vaddr; //segment虛地址 p_paddr; //物理地址 p_filesz; //文件中segment字節(jié)數(shù) p_memsz; //內(nèi)存中segment字節(jié)數(shù) p_flags; p_align;

注意:一般只有可執(zhí)行文件才有(有錯(cuò)請(qǐng)指出)

4、section header table(Shdr)
  • section header結(jié)構(gòu)體的定義可以在 /usr/include/elf.h

  • Shdr 各成員說(shuō)明

    sh_name; //一個(gè)索引值,在shstrtable(section header string table,包含section name的字符串表,也是一個(gè)section)中的索引 sh_type; //節(jié)區(qū)種類(lèi),如rel* sh_flags; //可寫(xiě),可分配,可執(zhí)行等屬性 sh_addr; //如果section會(huì)出現(xiàn)在進(jìn)程的內(nèi)存映像中,給出了section第一字節(jié)的虛擬地址;Relocatable file 的虛存地址都為0。Executable file 和 Shared object file 才會(huì)為有需要的 Section 計(jì)算虛存地址 sh_offset; //給出節(jié)區(qū)第一個(gè)字節(jié)在elf文件中的偏移 sh_size; //節(jié)區(qū)大小 sh_link; //給出字節(jié)頭部表索引鏈接 sh_info; //給出節(jié)區(qū)附加信息 sh_addralign; //地址對(duì)齊約束 sh_entsize; //給出對(duì)于某些有固定項(xiàng)目的大小,如符號(hào)表,這個(gè)值給出了每個(gè)記錄大小。//一個(gè)可執(zhí)行文件中包含多個(gè)section段(對(duì)應(yīng)源文件中使用section定義的段,鏈接腳本會(huì)定義哪些段為代碼),一個(gè)section中有可能有多個(gè)函數(shù)(多段代碼使用一個(gè)section定義) //可以使用命令 objdump -s -d 文件名,查看文件的的section信息,幫助理解
  • .symtab(符號(hào)表,section的一種),符號(hào)表中每個(gè)entry 的結(jié)構(gòu)如下:

    st_name; //一個(gè)索引值,在shstrtable(section header string table,包含section name的字符串表,也是一個(gè)section)中的索引 st_value; //可重定向文件(.ko):相對(duì)于節(jié)起始地址的偏移。//可執(zhí)行文件(vmlinux):絕對(duì)地址。 st_size; //符號(hào)所指內(nèi)容占據(jù)空間的大小(變量的大小,函數(shù)的大小) st_info; //它的高4位表示 Symbol Binding,低4位表示 Symbol Type st_other; st_shndx; //可重定向文件(.ko):對(duì)應(yīng)節(jié)區(qū)的在節(jié)區(qū)組中的下標(biāo),和st_value組合使用
  • 重定位節(jié)(rela section)

  • 為需要重新計(jì)算地址的地方提供定位信息
    一般體現(xiàn)為引用外部函數(shù)時(shí),加載到內(nèi)存時(shí)需要重新定位外部函數(shù)的地址
    .text 的重定位信息在 .rela_text, 以此類(lèi)推

  • 每個(gè)entry的結(jié)構(gòu);

    typedef struct { Elf64_Addr r_offset; /* 重定位文件 表示要重定位的地方,相對(duì)于對(duì)應(yīng)節(jié)區(qū)的起始地址的相對(duì)地址;可執(zhí)行文件 表示要重定位的地方的地址*/ Elf64_Xword r_info; /* 低32位表示重定向的類(lèi)型,高32位表示符號(hào)在符號(hào)表中的下標(biāo) */ Elf64_Sxword r_addend; } Elf64_Rela# 計(jì)算公式: # R_386_64(1) result = S + A + r_addend(64位才有); # R_386_PC64(2) result = S - P + A + r_addend(64位才有); # result: 重定向后填入P指向位置的值,即替換result的值 # P:要被重定位地方的地址偏移,即 r_offset + 相應(yīng)節(jié)區(qū)的起始地址 # A:要被重定位地方記錄的數(shù)值 # S:r_info找到的符號(hào)的地址,.o st_value + section_baseaddr, 可執(zhí)行文件 st_value root:~$ readelf -x 20 ./crc32c-intel.koHex dump of section '__jump_table':NOTE: This section has relocations against it, but these have NOT been applied to this dump.0x00000000 00000000 00000000 00000000 00000000 ................0x00000010 00000000 00000000 ........root:~$ readelf -x 21 ./crc32c-intel.koHex dump of section '.rela__jump_table':0x00000000 00000000 00000000 01000000 02000000 ................0x00000010 77030000 00000000 08000000 00000000 w...............0x00000020 01000000 02000000 7e030000 00000000 ........~.......0x00000030 10000000 00000000 01000000 d7000000 ................0x00000040 00000000 00000000 ........root:~$ readelf -r ./crc32c-intel.ko ... Relocation section '.rela__jump_table' at offset 0x2bd8 contains 3 entries:Offset Info Type Sym. Value Sym. Name + Addend 000000000000 000200000001 R_X86_64_64 0000000000000000 .text + 377 000000000008 000200000001 R_X86_64_64 0000000000000000 .text + 37e 000000000010 00d700000001 R_X86_64_64 0000000000000000 retp_enabled_key + 0 ...
  • 重定位的大致過(guò)程

    section header table(Shdr)
    ELF格式探析之三:sections - JollyWing - 博客園 (cnblogs.com)
    .symtab(符號(hào)表,section的一種)
    重定位信息
    (37條消息) Linux系統(tǒng)–ELF文件之可重定位文件(Relocatable file)解析_Barry-CSDN博客

  • 理解例子



  • 查看elf文件信息

    readelf 依賴(lài) binutils:http://ftp.gnu.org/gnu/binutils/

    • ELF header的信息:readelf -h

      jingl@JingL$ readelf -h ./crc32c-intel.ko 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: 19784 (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: 29Section header string table index: 28
    • program header信息: readelf -l

    • Section 信息:readelf -S

      jingl@JingL$ readelf -S ./crc32c-intel.ko There are 29 section headers, starting at offset 0x4d48:Section Headers:[Nr] Name Type Address OffsetSize EntSize Flags Link Info Align[ 0] NULL 0000000000000000 000000000000000000000000 0000000000000000 0 0 0[ 1] .note.gnu.build-i NOTE 0000000000000000 000000400000000000000024 0000000000000000 A 0 0 4 ...[28] .shstrtab STRTAB 0000000000000000 00004c200000000000000121 0000000000000000 0 0 1 Key to Flags:W (write), A (alloc), X (execute), M (merge), S (strings), I (info),L (link order), O (extra OS processing required), G (group), T (TLS),C (compressed), x (unknown), o (OS specific), E (exclude),l (large), p (processor specific)
    • 查看某一段的數(shù)據(jù):readelf -x num

      jingl@JingL$ readelf -x 8 ./crc32c-intel.koHex dump of section '.altinstr_replacement':0x00000000 0faee8ff e7 .....jingl@JingL$ readelf -x 11 ./crc32c-intel.koHex dump of section '.altinstructions':NOTE: This section has relocations against it, but these have NOT been applied to this dump.0x00000000 00000000 00000000 7d000200 00000000 ........}.......0x00000010 00000000 ed001105 ........jingl@JingL$ readelf -x 12 ./crc32c-intel.koHex dump of section '.rela.altinstructions':0x00000000 00000000 00000000 02000000 03000000 ................0x00000010 41000000 00000000 0c000000 00000000 A...............0x00000020 02000000 02000000 7e030000 00000000 ........~.......0x00000030 10000000 00000000 02000000 05000000 ................0x00000040 00000000 00000000 ........jingl@JingL$ readelf -x 20 ./crc32c-intel.koHex dump of section '__jump_table':NOTE: This section has relocations against it, but these have NOT been applied to this dump.0x00000000 00000000 00000000 00000000 00000000 ................0x00000010 00000000 00000000 ........jingl@JingL$ readelf -x 21 ./crc32c-intel.koHex dump of section '.rela__jump_table':0x00000000 00000000 00000000 01000000 02000000 ................0x00000010 77030000 00000000 08000000 00000000 w...............0x00000020 01000000 02000000 7e030000 00000000 ........~.......0x00000030 10000000 00000000 01000000 d7000000 ................0x00000040 00000000 00000000 ........
    • Symbol table 信息:readelf -s

      jingl@JingL$ readelf -s./crc32c-intel.koSymbol table '.symtab' contains 222 entries:Num: Value Size Type Bind Vis Ndx Name0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND1: 0000000000000000 0 SECTION LOCAL DEFAULT 1 ...220: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND boot_cpu_data221: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND __kernel_fpu_end
    • 重定位信息:readelf -r

      root:~$ readelf -r ./crc32c-intel.ko ... Relocation section '.rela__jump_table' at offset 0x2bd8 contains 3 entries:Offset Info Type Sym. Value Sym. Name + Addend 000000000000 000200000001 R_X86_64_64 0000000000000000 .text + 377 000000000008 000200000001 R_X86_64_64 0000000000000000 .text + 37e 000000000010 00d700000001 R_X86_64_64 0000000000000000 retp_enabled_key + 0 ...
    • 反匯編 代碼段:objdum -d

    • 刪除elf文件中的段:strip <option[s]> <in-file[s]>
      常用選項(xiàng)如下:

      -s --strip-allRemove all symbol and relocation information注: 刪除其他符號(hào)表段和調(diào)試信息段,但不刪除 .shstrtab 段-g -S -d --strip-debugRemove all debugging symbols & sections這幾個(gè)選項(xiàng)的功能是一樣,即移除上述5個(gè)".debug_"開(kāi)頭的調(diào)試信息段,仍會(huì)保留符號(hào)表--only-keep-debugStrip everything but the debug information注:段的總數(shù)量沒(méi)有減少,但文件大小減少了;對(duì)比了"readelf -S"輸出中的"offset"段,發(fā)現(xiàn)其中前面若干段的offset都沒(méi)有變化,即size為0了。-R --remove-section=<name>Also remove section <name> from the output移除指定段,比如 strip --remove-section=.symtab a.outstrip --remove-section=.strtab a.out

      驅(qū)動(dòng)文件(.ko)可能包含調(diào)試信息(.debug_info,依賴(lài)config中的CONFIG_DEBUG_INFO配置),可以使用strip --strip-debug ./xxx.ko去除;

      使用strip, eu-strip, objcopy等剝離與導(dǎo)回符號(hào)表及調(diào)試信息
      compile kernel with debug info

    總結(jié)

    以上是生活随笔為你收集整理的Linux elf文件分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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