LinuxC目标文件


宗旨:技术的学习是有限的,分享的精神是无限的。


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

编译器编译源代码后生成的文件叫做目标文件。目标文件是已经编译后的可执行文件,只是还没有经过链接的过程。

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

动态链接库和静态链接库也是按照可执行文件存储的。

1、ELF文件归于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;——大端机

3、BSS段

.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文件结构

         提取重要的结构:ELFHeader(ELF文件头)、.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文件的符号表,readelf,objdump,nm等;

1、ELF符号表结构

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目标文件相关推荐

  1. linux 反汇编目标文件,用于查看目标文件或可执行文件的组成信息的命令:objdump命令...

    1.功能简介 objdump 命令是 GNU Binutils 二进制工具集的一员,用于查看目标文件或可执行文件的组成信息,以可读的形式打印二进制文件的内容. 2.命令格式 objdump[OPTIO ...

  2. linux下目标文件的类型6,Linux下文件类型

    Linux下文件的类型是不依赖于其后缀名的,但一般来讲: .o,是目标文件,相当于windows中的.obj文件 .so 为共享库,是shared object,用于动态连接的,和dll差不多 .a为 ...

  3. linux目标文件,Linux下目标文件分析

    作者:冯老师, 1. 程序源码如下: 2.命令 gcc –E simple_section.c –o simple_section.i gcc –S simple_section.i –o simpl ...

  4. Linux 处理目标文件的工具(指令)

  5. linux 内核重定位,Linux 内核学习笔记:预备知识之“目标文件”

    8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? 本文主要阐述 Linux 的目标文件(有可重定位目标文件.可执行目标文件和共享目标文件三种形式),并把重点放在其格式和案 ...

  6. linux 中查找文件,并且将目标文件按时间顺序排序

    From: http://blog.csdn.net/linhx/article/details/5440288 linux 中,在redhat中检测过了,查找文件,并且将目标文件按时间顺序排序,这里 ...

  7. linux/windows下查看目标文件.a/.lib的函数符号名称

    1.linux下 (1). objdump -t 查看对象文件所有的符号列表:例如 objdump -t libtest.o (2).nm列出目标文件(.o)的符号清单:例如 nm -s filena ...

  8. linux下几种目标文件的分析

    本文中用到的命令: gcc -c addvec.c  生成可重定位目标文件addvec.o readelf addvec.o -a 读取可重定位目标文件addvec.o gcc -O2 -c main ...

  9. 如何分析linux下的几种目标文件

    为什么80%的码农都做不了架构师?>>>    作者:snsn1984 本文中用到的命令: gcc -c addvec.c 生成可重定位目标文件addvec.o readelf ad ...

最新文章

  1. 数据结构Stack:关系以及方法
  2. Keil代码整体偏移和查找功能
  3. 六、配置Oracle数据库的网络环境
  4. java list clear 垃圾回收_list.clear()vs list = new ArrayList Integer(); [重复]
  5. Random Forest 实用经验(转)
  6. html get请求_99% 的人都理解错了 HTTP 中 GET 与 POST 的区别【面试必问】
  7. linux procs单位m,Linux
  8. python post参数传递不成功_Python中的API构建指南:在Flask中进行API开发
  9. 通过linux内核如何读取pmbus总线上的数据,linux PMBus总线驱动设计分析(示例代码)...
  10. 地图上导出坐标html文件,如何将标签的坐标、海拔等属性导出到TXT文本中
  11. r语言如何下载carzip包本地安装_R语言安装程序包
  12. python语言程序设计二级教程pdf_二级python语言程序设计教程
  13. 我的第一本社会心理学(part2)--社会心理学的理论与方法
  14. 设置google浏览器为黑色底色
  15. chrome弹出2345网址导航删除方法之一
  16. 常用PLC学习资料下载地址
  17. 华为鸿蒙系统界面清新,华为鸿蒙系统:全新UI界面
  18. 深度学习笔记----计算机视觉的任务及对应的网络模型
  19. 2.3 从外部置入图片 [Ps教程]
  20. PC电脑安装苹果操作系统MAC OS X【图文教程】

热门文章

  1. .net remoting 技术
  2. PowerDesigner 把Comment写到name中 和把name写到Comment中 pd7以后版本可用
  3. Android 编程下的四大组件之服务(Service)
  4. 不同技术团队的配合问题及DevOps
  5. 学成在线--0.项目概述
  6. Flask项目--发送短信验证码
  7. 趣解 XSS和CSRF的原理
  8. python初中必背语法_一些python语法的合集
  9. 用matlab简单电路模型,基于MATLAB的电路模型仿真应用
  10. java如何限制输入值_[限制input输入类型]常用限制input方法