tft每日頭條

 > 科技

 > c語言f的用法

c語言f的用法

科技 更新时间:2024-12-20 07:38:44

gcc生成執行文件過程為:

  1. 源文件(*.c文件)編譯成對象文件(*.o文件);
  2. 鍊接程序ld,把對象文件(*.o文件)鍊接成可執行程序。

因此要透徹鍊接的過程, 需要先了解對象文件(*.o文件)是怎樣構成的?


下面用個簡單的例子來說明:

#include<stdio.h> int global_var=5; extern int other_file_var; int main() { int a=1; int b=a other_file_var; return 0; }

  1. gcc -c test.c -o test.o 生成test.o;
  2. 查看test.o内容(vim test.o):

c語言f的用法(講透C語言靜态鍊接)1

圖1

看到的是一堆亂碼,因為查看方式不對, 就像mp3格式的文件需要用音樂播放器才能播放一樣,對象文件(*.o)是elf格式的, 需要用objdump, readelf 工具來查看。

elf格式的官方文檔,可以了解到elf格式文件的結構如下圖所示:

c語言f的用法(講透C語言靜态鍊接)2

圖2

下面将一個個部分來分析。

1. ELF文件頭(Header)分析

readelf -h test.o 查看elf文件頭部信息

c語言f的用法(講透C語言靜态鍊接)3

圖3

  1. 主要字段的含義已在圖中标識;
  2. Size of this headers可知,頭部占用了64字節;
  3. hexdump -n 64 test.o 查看頭部64字節數據内容(16進制格式);

c語言f的用法(講透C語言靜态鍊接)4

圖4

圖中紅框裡的數據就是test.o文件的前64字節,也就是elf頭部,對比上面兩圖,(圖3)中的魔數7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 剛好與(圖4)中的前16字節(小段編碼)對應,後面每個字段的含義也是一一對應的。

  1. 頭部信息結構可以參考/usr/include/elf.hELf64_Ehdr, 32位的可以參考ELf32_Ehdr結構

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;

  1. 由字段Start Of Section Header可知,在test.o文件的656字節處有一個"段的頭部表"。
2. ELF段頭部表(Section Header)分析

readelf -S test.o查看"段的頭部表",在這個表裡保存了文件裡所有段的屬性信息,如段的名字,段在文件的開始位置, 段的長度等:

c語言f的用法(講透C語言靜态鍊接)5

圖4

由圖可知

  • 主要字段的含義已從圖中标識;
  • 段表的數據在偏離文件開始的0x290處,跟ELF Header Start Of Section Header字段保持一緻;
  • 這個段表裡總共有12項,不同的項描述了不同段的屬性;
  • 2.1 text段

    text段在偏離test.o文件開頭0x40字節處,長度為0x20字節,用hexdump -s 0x40 -n 0x20 test.o,查看text段的16進制内容。

    c語言f的用法(講透C語言靜态鍊接)6

    圖5

    然後objdump -d test.o 打印出程序的反彙編代碼,

    c語言f的用法(講透C語言靜态鍊接)7

    圖6

    由上面兩圖可知,text部分的數據恰好是main函數的機器碼,也就是text段裡保存的是代碼段。

    2.2 data段

    data段在偏離test.o文件開頭0x60字節處,長度為0x4字節,用hexdump -s 0x60 -n 0x4 test.o,查看data段的16進制内容,

    c語言f的用法(講透C語言靜态鍊接)8

    圖7

    4個字節剛好是個int的長度,裡面保存的數值是5,也就是全局變量global_var的值,驗證了已初始化的全局變量保存在data段。

    2.3 bss段

    詳細講解見:融會貫通C與彙編,以彙編的視角庖丁解牛C語言:變量篇

    2.4 .rela.text (text的重定位段)

    main函數裡的global_var定義在别的文件,後面鍊接需要根據别的文件來确定它的虛拟内存地址,由于text中有需要重定位的變量,所以就有了.rela.text段。readelf -r test.o

    c語言f的用法(講透C語言靜态鍊接)9

    圖8

  • offset列表示需要重定位的符号在該段中的偏移,這裡表示偏離text段0xd處;
  • info列高4個字節是該符号在.symtab中的索引,見下圖;
  • c語言f的用法(講透C語言靜态鍊接)10

    圖9

    2.5 .symtab 符号表

    c語言f的用法(講透C語言靜态鍊接)11

    圖9

  • ndx列是該符号在段表中的索引:(1)比如global_var的索引為3,圖4中索引3表示data段,
  • 也就是說global_var這個符号在data段;(2)如果是“UND“則表示該符号定義在别的文件,需要重定位,重定位信息見“2.4 .rela.text”。

    c語言f的用法(講透C語言靜态鍊接)12

    圖10


    站在C語言的肩膀上學彙編(1):棧

    站在C語言的肩膀上學彙編(2):棧

    站在C語言的肩膀上學彙編(3):棧

    融會貫通C與彙編,以彙編的視角庖丁解牛C語言:變量篇

    創造不易,如果幫助到了您,求點贊。謝謝!

    ,

    更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

    查看全部

    相关科技资讯推荐

    热门科技资讯推荐

    网友关注

    Copyright 2023-2024 - www.tftnews.com All Rights Reserved