IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> (GCC)STM32进阶修炼之ELF文件剖析 -> 正文阅读

[嵌入式](GCC)STM32进阶修炼之ELF文件剖析

本文拟通过分析一个普通的32位elf文件去剖析32位elf文件结构。(System V ABI基于2013版)

一、32位数据格式

NameSizeAlignmentPurpose
Elf32_Addr44Unsigned program address
Elf32_Off44Unsigned file offset
Elf32_Half22Unsigned medium integer
Elf32_Word44Unsigned integer
Elf32_Sword44Signed integer
unsigned char11Unsigned small integer

上图表示:

比如Elf32_Addr表示无符号程序地址,其大小为4bytes,字节对齐为4。对于STM32来说,其地址是32位,这个毋庸置疑。在Linux下/usr/include/elf.h中也有定义:

typedef uint16_t Elf32_Half;
typedef uint16_t Elf64_Half;

typedef uint32_t Elf32_Word;
typedef	int32_t  Elf32_Sword;
typedef uint32_t Elf64_Word;
typedef	int32_t  Elf64_Sword;

typedef uint64_t Elf32_Xword;
typedef	int64_t  Elf32_Sxword;
typedef uint64_t Elf64_Xword;
typedef	int64_t  Elf64_Sxword;

typedef uint32_t Elf32_Addr;
typedef uint64_t Elf64_Addr;

typedef uint32_t Elf32_Off;
typedef uint64_t Elf64_Off;

typedef uint16_t Elf32_Section;
typedef uint16_t Elf64_Section;

typedef Elf32_Half Elf32_Versym;
typedef Elf64_Half Elf64_Versym;

可以看到就是一些重定义,这个主要是为了不同平台的兼容性。在平台确定的情况下把它们带入的看做uint32_t或uint16_t等是完全没问题的。 如果是在Windows下使用gcc工具链开发,也可在工具链的?include 文件夹下找到elf.h ,本文所有宏与结构体定义均可在elf.h里找到。

二、ELF Header

这个结构体即为所有elf文件的文件头,是一个固定格式。文件起始对应结构体首地址。

2.1?e_ident[EI_NIDENT]

首先可以看到这是一个unsigned?char类型的数组,大小为16。

这个数组内容标志着这是一个object文件,而且里面包含了和架构等无关的信息(也就是每个字节顺序和含义都是被定义死的,不会受比如大小端等的影响)。数组所存信息如下:

NameValuePurpose
EI_MAG00File identification
EI_MAG11File identification
EI_MAG22File identification
EI_MAG33File identification
EI_CLASS4File class
EI_DATA5Data encoding
EI_VERSION6File version
EI_OSABI7Operating system/ABI identification
EI_ABIVERSION8ABI version
EI_PAD9Start of padding bytes
EI_NIDENT16Size of?e_ident[]

其中每个部分代表:

2.1.1 EI_MAG0~EI_MAG3

很明显,前四个字节是固定的,分别是0x7F和E、L、F的ASCII值。

2.1.2 EI_CLASS

它表示该文件是一个什么类型的文件,可选:无效、32位、64位

?2.1.3 EI_DATA

它表示该文件字节序是大端还是小端,可选:无效、小端、大端

LSB:Least Significant Bit

MSB:Most Significant Bit

2.1.4 EI_VERSION

当前版本,此字节必须为EV_CURRENT,在elf.h里可以看到:

2.1.5?EI_OSABI

此字节用于标识当前文件使用特定的操作系统或者ABI。相关内容如下:

NameValueMeaning
ELFOSABI_NONE0No extensions or unspecified
ELFOSABI_HPUX1Hewlett-Packard HP-UX
ELFOSABI_NETBSD2NetBSD
ELFOSABI_GNU3GNU
ELFOSABI_LINUX
?
3
?
Linux
???historical - alias for ELFOSABI_GNU
ELFOSABI_SOLARIS6Sun Solaris
ELFOSABI_AIX7AIX
ELFOSABI_IRIX8IRIX
ELFOSABI_FREEBSD9FreeBSD
ELFOSABI_TRU6410Compaq TRU64 UNIX
ELFOSABI_MODESTO11Novell Modesto
ELFOSABI_OPENBSD12Open BSD
ELFOSABI_OPENVMS13Open VMS
ELFOSABI_NSK14Hewlett-Packard Non-Stop Kernel
ELFOSABI_AROS15Amiga Research OS
ELFOSABI_FENIXOS16The FenixOS highly scalable multi-core OS
ELFOSABI_CLOUDABI17Nuxi CloudABI
ELFOSABI_OPENVOS18Stratus Technologies OpenVOS
64-255Architecture-specific value range

2.1.6?EI_ABIVERSION

此字节用于标识目标文件的ABI版本,从而用来区别那些不相互兼容的ABI版本。

2.1.7?EI_PAD

这些字节未使用,可以看到上面一共用了从0到8字节,所以剩下的从9到15字节都为0。

2.2?e_type

NameValueMeaning
ET_NONE0No file type
ET_REL1Relocatable file
ET_EXEC2Executable file
ET_DYN3Shared object file
ET_CORE4Core file
ET_LOOS0xfe00Operating system-specific
ET_HIOS0xfeffOperating system-specific
ET_LOPROC0xff00Processor-specific
ET_HIPROC0xffffProcessor-specific

这两个字节表示文件类型,可以看到上图中Systerm V ABI中就有:

无类型、可重定位文件、可执行文件、共享目标文件、核心文件、用以特定操作系统、用以特定处理器等

2.3?e_machine

这两个字节表示目标文件属于哪种的芯片架构类型:

NameValueMeaning
EM_NONE0No machine
EM_M321AT&T WE 32100
EM_SPARC2SPARC
EM_3863Intel 80386
EM_68K4Motorola 68000
EM_88K5Motorola 88000
EM_IAMCU6Intel MCU
EM_8607Intel 80860
EM_MIPS8MIPS I Architecture
EM_S3709IBM System/370 Processor
EM_MIPS_RS3_LE10MIPS RS3000 Little-endian
reserved11-14Reserved for future use
EM_PARISC15Hewlett-Packard PA-RISC
reserved16Reserved for future use
EM_VPP50017Fujitsu VPP500
EM_SPARC32PLUS18Enhanced instruction set SPARC
EM_96019Intel 80960
EM_PPC20PowerPC
EM_PPC642164-bit PowerPC
EM_S39022IBM System/390 Processor
EM_SPU23IBM SPU/SPC
reserved24-35Reserved for future use
EM_V80036NEC V800
EM_FR2037Fujitsu FR20
EM_RH3238TRW RH-32
EM_RCE39Motorola RCE
EM_ARM40ARM 32-bit architecture (AARCH32)
EM_ALPHA41Digital Alpha
EM_SH42Hitachi SH
EM_SPARCV943SPARC Version 9
EM_TRICORE44Siemens TriCore embedded processor
EM_ARC45Argonaut RISC Core, Argonaut Technologies Inc.
EM_H8_30046Hitachi H8/300
EM_H8_300H47Hitachi H8/300H
EM_H8S48Hitachi H8S
EM_H8_50049Hitachi H8/500
EM_IA_6450Intel IA-64 processor architecture
EM_MIPS_X51Stanford MIPS-X
EM_COLDFIRE52Motorola ColdFire
EM_68HC1253Motorola M68HC12
EM_MMA54Fujitsu MMA Multimedia Accelerator
EM_PCP55Siemens PCP
EM_NCPU56Sony nCPU embedded RISC processor
EM_NDR157Denso NDR1 microprocessor
EM_STARCORE58Motorola Star*Core processor
EM_ME1659Toyota ME16 processor
EM_ST10060STMicroelectronics ST100 processor
EM_TINYJ61Advanced Logic Corp. TinyJ embedded processor family
EM_X86_6462AMD x86-64 architecture
EM_PDSP63Sony DSP Processor
EM_PDP1064Digital Equipment Corp. PDP-10
EM_PDP1165Digital Equipment Corp. PDP-11
EM_FX6666Siemens FX66 microcontroller
EM_ST9PLUS67STMicroelectronics ST9+ 8/16 bit microcontroller
EM_ST768STMicroelectronics ST7 8-bit microcontroller
EM_68HC1669Motorola MC68HC16 Microcontroller
EM_68HC1170Motorola MC68HC11 Microcontroller
EM_68HC0871Motorola MC68HC08 Microcontroller
EM_68HC0572Motorola MC68HC05 Microcontroller
EM_SVX73Silicon Graphics SVx
EM_ST1974STMicroelectronics ST19 8-bit microcontroller
EM_VAX75Digital VAX
EM_CRIS76Axis Communications 32-bit embedded processor
EM_JAVELIN77Infineon Technologies 32-bit embedded processor
EM_FIREPATH78Element 14 64-bit DSP Processor
EM_ZSP79LSI Logic 16-bit DSP Processor
EM_MMIX80Donald Knuth's educational 64-bit processor
EM_HUANY81Harvard University machine-independent object files
EM_PRISM82SiTera Prism
EM_AVR83Atmel AVR 8-bit microcontroller
EM_FR3084Fujitsu FR30
EM_D10V85Mitsubishi D10V
EM_D30V86Mitsubishi D30V
EM_V85087NEC v850
EM_M32R88Mitsubishi M32R
EM_MN1030089Matsushita MN10300
EM_MN1020090Matsushita MN10200
EM_PJ91picoJava
EM_OPENRISC92OpenRISC 32-bit embedded processor
EM_ARC_COMPACT93ARC International ARCompact processor (old spelling/synonym: EM_ARC_A5)
EM_XTENSA94Tensilica Xtensa Architecture
EM_VIDEOCORE95Alphamosaic VideoCore processor
EM_TMM_GPP96Thompson Multimedia General Purpose Processor
EM_NS32K97National Semiconductor 32000 series
EM_TPC98Tenor Network TPC processor
EM_SNP1K99Trebia SNP 1000 processor
EM_ST200100STMicroelectronics (www.st.com) ST200 microcontroller
EM_IP2K101Ubicom IP2xxx microcontroller family
EM_MAX102MAX Processor
EM_CR103National Semiconductor CompactRISC microprocessor
EM_F2MC16104Fujitsu F2MC16
EM_MSP430105Texas Instruments embedded microcontroller msp430
EM_BLACKFIN106Analog Devices Blackfin (DSP) processor
EM_SE_C33107S1C33 Family of Seiko Epson processors
EM_SEP108Sharp embedded microprocessor
EM_ARCA109Arca RISC Microprocessor
EM_UNICORE110Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University
EM_EXCESS111eXcess: 16/32/64-bit configurable embedded CPU
EM_DXP112Icera Semiconductor Inc. Deep Execution Processor
EM_ALTERA_NIOS2113Altera Nios II soft-core processor
EM_CRX114National Semiconductor CompactRISC CRX microprocessor
EM_XGATE115Motorola XGATE embedded processor
EM_C166116Infineon C16x/XC16x processor
EM_M16C117Renesas M16C series microprocessors
EM_DSPIC30F118Microchip Technology dsPIC30F Digital Signal Controller
EM_CE119Freescale Communication Engine RISC core
EM_M32C120Renesas M32C series microprocessors
reserved121-130Reserved for future use
EM_TSK3000131Altium TSK3000 core
EM_RS08132Freescale RS08 embedded processor
EM_SHARC133Analog Devices SHARC family of 32-bit DSP processors
EM_ECOG2134Cyan Technology eCOG2 microprocessor
EM_SCORE7135Sunplus S+core7 RISC processor
EM_DSP24136New Japan Radio (NJR) 24-bit DSP Processor
EM_VIDEOCORE3137Broadcom VideoCore III processor
EM_LATTICEMICO32138RISC processor for Lattice FPGA architecture
EM_SE_C17139Seiko Epson C17 family
EM_TI_C6000140The Texas Instruments TMS320C6000 DSP family
EM_TI_C2000141The Texas Instruments TMS320C2000 DSP family
EM_TI_C5500142The Texas Instruments TMS320C55x DSP family
EM_TI_ARP32143Texas Instruments Application Specific RISC Processor, 32bit fetch
EM_TI_PRU144Texas Instruments Programmable Realtime Unit
reserved145-159Reserved for future use
EM_MMDSP_PLUS160
reserved145-159Reserved for future use
EM_MMDSP_PLUS160STMicroelectronics 64bit VLIW Data Signal Processor
EM_CYPRESS_M8C161Cypress M8C microprocessor
EM_R32C162Renesas R32C series microprocessors
EM_TRIMEDIA163NXP Semiconductors TriMedia architecture family
EM_QDSP6164QUALCOMM DSP6 Processor
EM_8051165Intel 8051 and variants
EM_STXP7X166STMicroelectronics STxP7x family of configurable and extensible RISC processors
EM_NDS32167Andes Technology compact code size embedded RISC processor family
EM_ECOG1168Cyan Technology eCOG1X family
EM_ECOG1X168Cyan Technology eCOG1X family
EM_MAXQ30169Dallas Semiconductor MAXQ30 Core Micro-controllers
EM_XIMO16170New Japan Radio (NJR) 16-bit DSP Processor
EM_MANIK171M2000 Reconfigurable RISC Microprocessor
EM_CRAYNV2172Cray Inc. NV2 vector architecture
EM_RX173Renesas RX family
EM_METAG174Imagination Technologies META processor architecture
EM_MCST_ELBRUS175MCST Elbrus general purpose hardware architecture
EM_ECOG16176Cyan Technology eCOG16 family
EM_CR16177National Semiconductor CompactRISC CR16 16-bit microprocessor
EM_ETPU178Freescale Extended Time Processing Unit
EM_SLE9X179Infineon Technologies SLE9X core
EM_L10M180Intel L10M
EM_K10M181Intel K10M
reserved182Reserved for future Intel use
EM_AARCH64183ARM 64-bit architecture (AARCH64)
reserved184Reserved for future ARM use
EM_AVR32185Atmel Corporation 32-bit microprocessor family
EM_STM8186STMicroeletronics STM8 8-bit microcontroller
EM_TILE64187Tilera TILE64 multicore architecture family
EM_TILEPRO188Tilera TILEPro multicore architecture family
EM_MICROBLAZE189Xilinx MicroBlaze 32-bit RISC soft processor core
EM_CUDA190NVIDIA CUDA architecture
EM_TILEGX191Tilera TILE-Gx multicore architecture family
EM_CLOUDSHIELD192CloudShield architecture family
EM_COREA_1ST193KIPO-KAIST Core-A 1st generation processor family
EM_COREA_2ND194KIPO-KAIST Core-A 2nd generation processor family
EM_ARC_COMPACT2195Synopsys ARCompact V2
EM_OPEN8196Open8 8-bit RISC soft processor core
EM_RL78197Renesas RL78 family
EM_VIDEOCORE5198Broadcom VideoCore V processor
EM_78KOR199Renesas 78KOR family
EM_56800EX200Freescale 56800EX Digital Signal Controller (DSC)
EM_BA1201Beyond BA1 CPU architecture
EM_BA2202Beyond BA2 CPU architecture
EM_XCORE203XMOS xCORE processor family
EM_MCHP_PIC204Microchip 8-bit PIC(r) family
EM_INTEL205205Reserved by Intel
EM_INTEL206206Reserved by Intel
EM_INTEL207207Reserved by Intel
EM_INTEL208208Reserved by Intel
EM_INTEL209209Reserved by Intel
EM_KM32210KM211 KM32 32-bit processor
EM_KMX32211KM211 KMX32 32-bit processor
EM_KMX16212KM211 KMX16 16-bit processor
EM_KMX8213KM211 KMX8 8-bit processor
EM_KVARC214KM211 KVARC processor
EM_CDP215Paneve CDP architecture family
EM_COGE216Cognitive Smart Memory Processor
EM_COOL217Bluechip Systems CoolEngine
EM_NORC218Nanoradio Optimized RISC
EM_CSR_KALIMBA219CSR Kalimba architecture family
EM_Z80220Zilog Z80
EM_VISIUM221Controls and Data Services VISIUMcore processor
EM_FT32222FTDI Chip FT32 high performance 32-bit RISC architecture
EM_MOXIE223Moxie processor family
EM_AMDGPU224AMD GPU architecture
225 - 242
EM_RISCV243RISC-V

我们也可以到elf.h里查看:

也就是ARM架构是40来表示。

2.4?e_version

这四个字节表示目标文件版本,只有0和1分别表示无效版本、当前版本:

2.5?e_entry

这四个字节表示程序入口的虚拟地址,如果是可执行文件,则程序指令从这个地址开始执行。但是像可重定位文件这些没有入口地址的,一般都为0。

2.6?e_phoff

这四个字节表示文件程序头表的相对偏移,单位字节。如果没有程序头表,则为0。

2.7?e_shoff

这四个字节表示文件段头表的相对偏移,单位字节。如果没有段头表,则为0。

关于程序头表和段头表在下面会有更加详细的解释。

2.8?e_flags

这四个字节表示ELF文件平台相关属性,一般格式为EF_machine_flag。其中ARM架构相关flag有:

2.9?e_ehsize

这两个字节表示ELF文件头的大小,单位字节。

2.10?e_phentsize

这两个字节表示程序头表中一个条目大小,单位字节,每个条目大小相同。

2.11?e_phnum

这两个字节表示程序头表中的条目数。没有程序头表,则为0。

2.12?e_shentsize

这两个字节表示段表描述符大小,单位字节。

2.13?e_shnum

这两个字节表示段表描述符数量。

2.14 e_shstrndx

这两个字节表示段表字符串表所在的段在段表中的下标。

2.15 实际文件分析

上图是笔者某个工程的elf文件,把它放在excel里分析如下:

然后使用readelf -a读取elf文件信息:

?*?section有段和节的意思,但是通常站在链接的角度,我们把section译作 “节” ,而站在执行角度我们把它的近义词segment译作 “段” 。此处分析借鉴了《程序员的自我修养-链接、装载与库》,所以叫做段表。

三、section?header

以上是一个section header的标准结构,而段表就是一个包含一个或多个这样相同结构体的列表。

3.1?sh_name

这四个字节表示一个段的名字的偏移。由上文知道在elf的header里面专门有描述字符串段的索引,就是因为所有段的名字都存在这个段内(.shstrtab),而这个偏移就是在这个段里面的偏移。

3.2 sh_type

这四个字节表示段的类型。如下图:

NameValue
SHT_NULL0
SHT_PROGBITS1
SHT_SYMTAB2
SHT_STRTAB3
SHT_RELA4
SHT_HASH5
SHT_DYNAMIC6
SHT_NOTE7
SHT_NOBITS8
SHT_REL9
SHT_SHLIB10
SHT_DYNSYM11
SHT_INIT_ARRAY14
SHT_FINI_ARRAY15
SHT_PREINIT_ARRAY16
SHT_GROUP17
SHT_SYMTAB_SHNDX18
SHT_LOOS0x60000000
SHT_HIOS0x6fffffff
SHT_LOPROC0x70000000
SHT_HIPROC0x7fffffff
SHT_LOUSER0x80000000
SHT_HIUSER0xffffffff

3.2.1?SHT_NULL

此类型表示该段为非活跃的,它不关联任何有用的信息,也可以理解为无意义。

3.2.2 SHT_PROGBITS

该段所持有的所有信息都是由程序定义,比如代码段、数据段、程序段等都是这种,它们的意义是由程序决定的。

3.2.3 SHT_SYMTAB

该段的内容为完整的符号表。

3.2.4 SHT_STRTAB

该段的内容为字符串表。

3.2.5 SHT_RELA

该段内容为重定位表。

3.2.6 SHT_HASH

该段内容为符号表的哈希表。

3.2.7 SHT_DYNAMIC

该段包含动态链接的相关信息。

3.2.8 SHT_NOTE

该段内容为提示性信息。

3.2.9 SHT_NOBITS

该段在文件中不占用空间,其他同?SHT_PROGBITS 。

3.2.10 SHT_REL

该段内容为重定位信息。

3.2.11 SHT_SHLIB

保留。

3.2.12 SHT_DYNSYM

该段内容为动态链接的符号表。相当于把完整符号表?SHT_SYMTAB?里面关于动态链接的符号全部放在一个段内。

3.2.13 SHT_INIT_ARRAY

该段包含一个指向初始化函数的指针数组。

3.2.14 SHT_FINI_ARRAY

该段包含一个指向终止函数的指针数组。

3.2.15 SHT_PREINIT_ARRAY

本段包含一个指向函数的指针数组,这些函数在所有其他初始化函数之前被调用。

3.2.16 SHT_GROUP

该段定义了一个段组,即一组相关的段。

3.2.17 SHT_SYMTAB_SHNDX

该段与一个符号表部分相关联,如果该符号表引用的任何部分头索引包含转义值SHN_XINDEX,则需要这个段。

3.2.18 SHT_LOOS~SHT_HIOS

这个范围内的值留给特定的操作系统使用。

3.2.19?SHT_LOPROC~SHT_HIPROC

这个范围内的值留给特定的处理器使用。

3.2.20?SHT_LOUSER~SHT_HIUSER

用户可以使用该范围表示自定义段类型,而不用担心和标准段类型冲突。

3.3?sh_flags

这四个字节表示段的标志:

NameValue
SHF_WRITE0x1
SHF_ALLOC0x2
SHF_EXECINSTR0x4
SHF_MERGE0x10
SHF_STRINGS0x20
SHF_INFO_LINK0x40
SHF_LINK_ORDER0x80
SHF_OS_NONCONFORMING0x100
SHF_GROUP0x200
SHF_TLS0x400
SHF_COMPRESSED0x800
SHF_MASKOS0x0ff00000
SHF_MASKPROC0xf0000000

它们分别表示:

3.3.1 SHF_WRITE

该段包含在程序执行时可写的数据。

3.3.2 SHF_ALLOC

该段在进程空间中必须要被分配空间。

3.3.3 SHF_EXECINSTR

该段包含可以被执行的机器码。

3.3.4 SHF_MERGE

该段的数据可以被合并以消除重复。除非SHF_STRINGS标志也被设置,否则段中的数据元素是统一大小的。每个元素的大小在段头表的sh_entsize字段中指定。如果SHF_STRINGS标志也被设置,数据元素由空尾的字符串组成。每个字符的大小在段头表的sh_entsize字段中指定。

3.3.5 SHF_STRINGS

该段中的数据元素由以空字符结尾的字符串组成。每个字符的大小在段头表的?sh_entsize?字段中指定。

3.3.6 SHF_INFO_LINK

该段的?sh_info?字段保存一个段头表索引。

3.3.7 SHF_LINK_ORDER

这个标志为链接编辑增加了特殊的排序要求。这些要求适用于本段头的sh_link字段引用另一段(被链接的段)的情况。如果这个部分与输出文件中的其他部分结合在一起,它必须以与这些部分相同的相对顺序出现,因为被链接的部分与被链接的部分结合在一起。

3.3.8 SHF_OS_NONCONFORMING

这一部分需要特殊的操作系统处理(超出标准的链接规则)以避免不正确的行为。如果这部分有一个sh_type值或者包含在操作系统特定范围内的sh_flags位,而处理这部分的链接编辑器不能识别这些值,那么链接编辑器应该以一个错误拒绝包含这部分的对象文件。

3.3.9 SHF_GROUP

这个部分是一个部分组的成员(可能是唯一的一个)。

3.3.10 SHF_TLS

该部分持有线程本地存储,这意味着每个独立的执行流程都有自己的该数据的不同实例。

3.3.11 SHF_COMPRESSED

这个标志标识了一个包含压缩数据的部分。SHF_COMPRESSED只适用于不可分配的部分,并且不能与SHF_ALLOC一起使用。此外,SHF_COMPRESSED不能应用于SHT_NOBITS类型的部分。
所有对压缩区的重定位都指定了对未压缩区数据的偏移量。因此,在应用重定位之前,有必要对部分数据进行解压。每个压缩部分都独立地指定了算法。允许在一个给定的ELF对象中的不同部分采用不同的压缩算法。

被压缩的部分以一个描述压缩相关信息的结构体开始,该结构体标识了压缩算法。压缩信息结构体如下:

typedef struct {
	Elf32_Word	ch_type;//压缩算法类型
	Elf32_Word	ch_size;//未压缩数据大小
	Elf32_Word	ch_addralign;//未压缩数据所需对齐方式
} Elf32_Chdr;

而压缩算法类型包含:

NameValue
ELFCOMPRESS_ZLIB1
ELFCOMPRESS_LOOS0x60000000
ELFCOMPRESS_HIOS0x6fffffff
ELFCOMPRESS_LOPROC0x70000000
ELFCOMPRESS_HIPROC0x7fffffff

可以看到只有 1 是被指定为 ZLIB,其他?0x60000000 ~?0x6fffffff?都保留给了操作系统去指定,而?0x7000000 ~ 0x7fffffff都保留给了处理器去指定。

3.3.12 SHF_MASKOS

保留给操作系统去指定。

3.3.13 SHF_MASKPROC

保留给处理器去指定。

更多信息请查看资料引用。

3.3.14 一些标准段的类型及其属性

3.4?sh_addr

段的虚拟地址,如果该段可以被加载,则次字段为该段被加载后在进程空间中的虚拟地址,否则为0 。

3.5?sh_offset

如果该段在文件中,表示该段在文件中的相对偏移。比如 SHT_NOBITS 类型的段该字段就没有意义。

3.6?sh_size

该段的长度。单位:字节。

3.7?sh_link

该字段保存一个段头表的索引链接,具体解释取决于段的类型。

3.8?sh_info

该字段包含额外的信息,具体解释取决于段的类型。

sh_link 和 sh_info 具体信息在下表:

sh_typesh_linksh_info
SHT_DYNAMICThe section header index of the string table used by entries in the section.0
SHT_HASHThe section header index of the symbol table to which the hash table applies.0
SHT_REL
SHT_RELA
The section header index of the associated symbol table.The section header index of the section to which the relocation applies.
SHT_SYMTAB
SHT_DYNSYM
The section header index of the associated string table.One greater than the symbol table index of the last local symbol (binding?STB_LOCAL).
SHT_GROUPThe section header index of the associated symbol table.The symbol table index of an entry in the associated symbol table. The name of the specified symbol table entry provides a signature for the section group.
SHT_SYMTAB_SHNDXThe section header index of the associated symbol table section.0

3.9?sh_addralign

段地址对齐,此值是2的指数。比如8字节对齐,则sh_addralign = 3 。

3.10?sh_entsize

该字段在某些包含固定长度条目的段中,表示单个条目的大小,比如符号表。如果为0表示不包含固定长度条目的表。

3.11?实际文件分析

还使用上一节的elf文件,从ELF文件头可以看到Section headers的偏移是 0x00021824 ,单个项目大小是 40 字节,共有 22 个项目。我们找到段头表起始地址:

可以看到22个项目中第一个也就是索引0的项目40个字节全是0,但与标准规定相符:

段头表之【索引0】:

NameValueNote
sh_name0No name
sh_typeSHT_NULLInactive
sh_flags0No flags
sh_addr0No address
sh_offset0No offset
sh_sizeUnspecifiedIf non-zero, the actual number of section header entries
sh_linkUnspecifiedIf non-zero, the index of the section header string table section
sh_info0No auxiliary information
sh_addralign0No alignment
sh_entsize0No entries

使用readelf -S也可以看到:

我们继续看第二个项目:

我们实际分析一下:

首先我们如果想知道名称,必须要先找到包含段名的字符串表,这也是为什么ELF文件头里面要把包含段名的字符串表的索引单独列出来的原因,由上一节我们知道段名字符串表索引是 21?,注意索引是从 0?开始的。所以字符串表在段表里面的起始地址应该是?0x00021824 + 21?* 40 = 0x21B6C?,查看该地址处数据:

同样对它进行分析:

由该段在文件中的偏移我们可以找到该段内容的首地址:

注意,字符串表的查表方式为从索引开始,到0x00结束的字符串内容。可以看到从第9个字节开始到0x00用字符串表示刚好是 .shstrtab?,而从第27个字节开始到0x00为止字符串内容刚好是 .isr_vector ,与预期相符。

回到刚才段表中索引1的项,通过段名我们知道索引1的段表项保存的是向量表。它的类型是?SHT_PROGBITS ,所以它的内容被程序所定义,而且它需要被分配空间,它被加载时的虚拟地址是0x0800 0000,这个地址在STM32里就是0x0000 0000,这与向量表在运行时存放地址不谋而合。其次该段在文件中的相对偏移是0x010000,我们找到它的内容:

这与bin文件中地址相同:

四、program?header?

以上是一个program?header的标准结构,程序头表就是包含一个或多个program?header的列表。

4.1?p_type

段类型。仔细看会发现和段表很多类型有点类似。

NameValue
PT_NULL0
PT_LOAD1
PT_DYNAMIC2
PT_INTERP3
PT_NOTE4
PT_SHLIB5
PT_PHDR6
PT_TLS7
PT_LOOS0x60000000
PT_HIOS0x6fffffff
PT_LOPROC0x70000000
PT_HIPROC0x7fffffff

4.1.1 PT_NULL

数组元素未使用。

4.1.2 PT_LOAD

数组元素指定一个可加载段,由p_filesz和p_memsz描述。

4.1.3 PT_DYNAMIC

数组元素指定动态链接信息。

4.1.4 PT_INTERP

数组元素指定一个以null结尾的路径名的位置与大小,被解释器调用。只对可执行文件有意义。

4.1.5 PT_NOTE

数组元素指定辅助信息的位置和大小。

4.1.6 PT_SHLIB

保留。

4.1.7 PT_PHDR

数组元素指定程序头表本身在文件和程序程序运行空间中的位置和大小。

4.1.8 PT_TLS

数组元素指定TLS模版。(Thread-Local Storage)

4.1.9 PT_LOOS~PT_HIOS

此范围内类型由操作系统指定。

4.1.10 PT_LOPROC~PT_HIPROC

此范围内类型由处理器指定。

4.2?p_offset

段在文件中的相对偏移。

4.3?p_vaddr

段在内存中的虚拟地址。

4.4?p_paddr

段的物理地址。

4.5?p_filesz

段在镜像文件中的大小,单位:字节。

4.6?p_memsz

段在运行运行空间中的大小,单位:字节。

4.7?p_flags

段的相关标志。如下图:

FlagsValueExactAllowable
none0All access deniedAll access denied
PF_X1Execute onlyRead, execute
PF_W2Write onlyRead, write, execute
PF_W+PF_X3Write, executeRead, write, execute
PF_R4Read onlyRead, execute
PF_R+PF_X5Read, executeRead, execute
PF_R+PF_W6Read, writeRead, write, execute
PF_R+PF_W+PF_X7Read, write, executeRead, write, execute

4.8?p_align

该字段指定段的对齐字节。

4.9?实际文件分析

还是由之前的elf文件分析,由ELF文件头可知,程序头表单个项大小为32字节,一共有3个项,程序头表起始位置为 0x34 。我们看索引0的?program?header:

实际分析如下:

使用readelf -l 查看程序头表可以看到:

查看3个段的划分:?

资料引用:

SYSTEM V ABI 4.1

System V Application Binary Interface - DRAFT - 10 June 2013

《程序员的自我修养——链接、装载与库》

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-04-09 18:36:52  更:2022-04-09 18:38:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 4:45:37-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码