通常在 ELF 文件中,已初始化的数据变量会保留在目标文件中。如果数据变量很大,并且仅包含少量的已初始化(非零)元素,则整个变量仍会保留在目标文件中。
包含大型部分初始化数据变量(如 FORTRAN COMMON 块)的目标文件可能会产生较大的磁盘空间开销。SHT_SUNW_move 节提供了一种压缩这些数据变量的机制。此压缩机制可减小关联目标文件的磁盘空间大小。
SHT_SUNW_move 节包含多个类型为 ELF32_Move 或 Elf64_Move 的项。使用这些项,可以将数据变量定义为暂定项目 (.bss)。这些项目在目标文件中不占用任何空间,但在运行时会构成目标文件的内存映像。移动记录可确定如何初始化内存映像的数据,从而构造完整的数据变量。
ELF32_Move 和 Elf64_Move 项的定义如下:
typedef struct { Elf32_Lword m_value; Elf32_Word m_info; Elf32_Word m_poffset; Elf32_Half m_repeat; Elf32_Half m_stride; } Elf32_Move; #define ELF32_M_SYM(info) ((info)>>8) #define ELF32_M_SIZE(info) ((unsigned char)(info)) #define ELF32_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size)) typedef struct { Elf64_Lword m_value; Elf64_Xword m_info; Elf64_Xword m_poffset; Elf64_Half m_repeat; Elf64_Half m_stride; } Elf64_Move; #define ELF64_M_SYM(info) ((info)>>8) #define ELF64_M_SIZE(info) ((unsigned char)(info)) #define ELF64_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size))
这些结构的元素如下:
初始化值,即移到内存映像中的值。
符号表索引(与应用初始化相关)以及初始化的偏移的大小(以字节为单位)。成员的低 8 位定义大小,该大小可以是 1、2、4 或 8。高位字节定义符号索引。
相对于应用初始化的关联符号的偏移。
重复计数。
幅度计数。该值表示在执行重复初始化时应跳过的单元数。单元是由 m_info 定义的初始化目标文件的大小。m_stride 值为零表示连续对单元执行初始化。
以下数据定义以前在目标文件中会占用 0x8000 个字节:
typedef struct { int one; char two; } Data; Data move[0x1000] = { {0, 0}, {1, '1'}, {0, 0}, {0xf, 'F'}, {0xf, 'F'}, {0, 0}, {0xe, 'E'}, {0, 0}, {0xe, 'E'} };
SHT_SUNW_move 节可用于说明此数据。数据项在 .bss 节中定义。使用相应的移动项初始化数据项中的非零元素。
$ elfdump -s data | fgrep move [17] 0x00020868 0x00008000 OBJT GLOB 0 .bss move $ elfdump -m data Move Section: .SUNW_move symndx offset size repeat stride value with respect to [17] 0x44 4 1 1 0x45000000 move [17] 0x40 4 1 1 0xe move [17] 0x34 4 1 1 0x45000000 move [17] 0x30 4 1 1 0xe move [17] 0x1c 4 2 1 0x46000000 move [17] 0x18 4 2 1 0xf move [17] 0xc 4 1 1 0x31000000 move [17] 0x8 4 1 1 0x1 move
可重定位目标文件提供的移动节可串联并在链接编辑器所创建的目标文件中输出。但是,在以下条件下链接编辑器将处理移动项,并将其内容扩展到传统的数据项中。