我必须编写一个打印ELF文件的C程序。我无法弄清楚节标题字符串表的位置。
假设我有一个文件,它给了我以下输出:
readelf -h
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 17636 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 40 (bytes)
Number of section headers: 23
Section header string table index: 20
和:
readelf -S:
There are 23 section headers, starting at offset 0x44e4:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00000000 000034 000028 00 AX 0 0 4
[ 2] .rel.text REL 00000000 0049d0 000018 08 21 1 4
[ 3] .data PROGBITS 00000000 00005c 000000 00 WA 0 0 4
[ 4] .bss NOBITS 00000000 00005c 000000 00 WA 0 0 4
[ 5] .rodata PROGBITS 00000000 00005c 00000a 00 A 0 0 1
[ 6] .debug_info PROGBITS 00000000 000066 00008f 00 0 0 1
[ 7] .rel.debug_info REL 00000000 0049e8 0000b0 08 21 6 4
[ 8] .debug_abbrev PROGBITS 00000000 0000f5 000041 00 0 0 1
[ 9] .debug_loc PROGBITS 00000000 000136 000038 00 0 0 1
[10] .debug_aranges PROGBITS 00000000 00016e 000020 00 0 0 1
[11] .rel.debug_arange REL 00000000 004a98 000010 08 21 10 4
[12] .debug_line PROGBITS 00000000 00018e 0001b3 00 0 0 1
[13] .rel.debug_line REL 00000000 004aa8 000008 08 21 12 4
[14] .debug_macinfo PROGBITS 00000000 000341 003fb9 00 0 0 1
[15] .debug_str PROGBITS 00000000 0042fa 0000bf 01 MS 0 0 1
[16] .comment PROGBITS 00000000 0043b9 00002b 01 MS 0 0 1
[17] .note.GNU-stack PROGBITS 00000000 0043e4 000000 00 0 0 1
[18] .eh_frame PROGBITS 00000000 0043e4 000038 00 A 0 0 4
[19] .rel.eh_frame REL 00000000 004ab0 000008 08 21 18 4
[20] .shstrtab STRTAB 00000000 00441c 0000c5 00 0 0 1
[21] .symtab SYMTAB 00000000 00487c 000130 10 22 16 4
[22] .strtab STRTAB 00000000 0049ac 000021 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
我如何计算节标题字符串表的位置?
答案 0 :(得分:13)
这就是我的所作所为:
#pragma pack(push,1)
typedef struct
{
uint8 e_ident[16];
uint16 e_type;
uint16 e_machine;
uint32 e_version;
uint32 e_entry;
uint32 e_phoff;
uint32 e_shoff;
uint32 e_flags;
uint16 e_ehsize;
uint16 e_phentsize;
uint16 e_phnum;
uint16 e_shentsize;
uint16 e_shnum;
uint16 e_shstrndx;
} Elf32Hdr;
typedef struct
{
uint32 sh_name;
uint32 sh_type;
uint32 sh_flags;
uint32 sh_addr;
uint32 sh_offset;
uint32 sh_size;
uint32 sh_link;
uint32 sh_info;
uint32 sh_addralign;
uint32 sh_entsize;
} Elf32SectHdr;
#pragma pack(pop)
{
FILE* ElfFile = NULL;
char* SectNames = NULL;
Elf32Hdr elfHdr;
Elf32SectHdr sectHdr;
uint idx;
// ...
// read ELF header
fread(&elfHdr, 1, sizeof elfHdr, ElfFile);
// read section name string table
// first, read its header
fseek(ElfFile, elfHdr.e_shoff + elfHdr.e_shstrndx * sizeof sectHdr, SEEK_SET);
fread(§Hdr, 1, sizeof sectHdr, ElfFile);
// next, read the section, string data
SectNames = malloc(sectHdr.sh_size);
fseek(ElfFile, sectHdr.sh_offset, SEEK_SET);
fread(SectNames, 1, sectHdr.sh_size, ElfFile);
// read all section headers
for (idx = 0; idx < elfHdr.e_shnum; idx++)
{
const char* name = "";
fseek(ElfFile, elfHdr.e_shoff + idx * sizeof sectHdr, SEEK_SET);
fread(§Hdr, 1, sizeof sectHdr, ElfFile);
// print section name
if (sectHdr.sh_name);
name = SectNames + sectHdr.sh_name;
printf("%2u %s\n", idx, name);
}
// ...
}
答案 1 :(得分:4)
以下是如何获取部分名称字符串表:
e_shstrndx
字段指定描述包含节名称的字符串表的节头表条目的索引。e_shentsize
字段指定每个节标题表条目的大小(以字节为单位)。e_shoff
字段指定文件偏移到部分标题表的开头。因此,字符串表的标题条目将位于文件偏移量:
header_table_entry_offset = (e_shentsize * e_shstrndx) + e_shoff
根据对象的ELF类,此标头表条目可以是Elf32_Shdr
或Elf64_Shdr
。请注意,标头表条目的文件表示可能与运行程序的主机上的内存中表示不同。
标题条目中的sh_offset
字段将指定字符串表的起始文件偏移量,而sh_size
字段将指定其大小。
进一步阅读:“libelf by Example”教程更深入地介绍了ELF可执行文件头和ELF剖面标题表。
答案 2 :(得分:2)
似乎你想要的是STRTAB,其偏移量为0x441c(第[20]行)。标头在文件中开始17636个字节(根据
Start of section headers: 17636 (bytes into file)
所以我猜你的字符串表从文件的开头起始于17636 + 17436 = 35072字节。
我可能完全错了,但那就是我要开始的地方。您知道如何使用od
或某些此类实用程序来执行文件字节转储吗?
答案 3 :(得分:0)
节头表始于starting point of your file
+ e_shoff
。 elf.h
文件已经具有Elfxx_Shdr
结构和Elfxx_Ehdr
结构,其中上面的xx分别是32位或64位的32
或64
。>
您可以使用e_shentsize
中的Elfxx_Ehdr
获取节头字符串表索引,然后使用sh_name
中的sh_offset
和Elfxx_Shdr
。 sh_name
将为您提供strtab
的索引,如果您添加sh_offset
。这将为您提供该部分的全名。使用sh_type
,sh_flag
等对类型,标记和其他标记相同。
我建议您跳过executable and linkable format wikipedia article 和efl.h file man page。