我想要编写一段代码来存储原始.elf文件中的符号表和字符串表.我的代码可以做到这一点,但它缺少地址和名称:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
// ELF header structure
typedef struct {
uint8_t e_ident[16];
uint16_t e_type;
uint16_t e_machine;
uint32_t e_version;
uint64_t e_entry;
uint64_t e_phoff;
uint64_t e_shoff;
uint32_t e_flags;
uint16_t e_ehsize;
uint16_t e_phentsize;
uint16_t e_phnum;
uint16_t e_shentsize;
uint16_t e_shnum;
uint16_t e_shstrndx;
} Elf64_Ehdr;
// Section header structure
typedef struct {
uint32_t sh_name;
uint32_t sh_type;
uint64_t sh_flags;
uint64_t sh_addr;
uint64_t sh_offset;
uint64_t sh_size;
uint32_t sh_link;
uint32_t sh_info;
uint64_t sh_addralign;
uint64_t sh_entsize;
} Elf64_Shdr;
// Symbol table entry structure
typedef struct {
uint32_t st_name;
uint8_t st_info;
uint8_t st_other;
uint16_t st_shndx;
uint32_t st_value; // normally it was uint64_t
uint64_t st_size;
uint32_t st_name2; // Extended name field
} Elf64_Sym;
Elf64_Sym* symbol_table;
char* string_table;
uint64_t stringSize;
size_t num_symbols;
struct SymbolEntry {
char name[256];
unsigned long address;
};
// Comparison function for sorting symbols based on their addresses
int compare_symbols(const void* a, const void* b) {
const Elf64_Sym* symbol_a = (const Elf64_Sym*)a;
const Elf64_Sym* symbol_b = (const Elf64_Sym*)b;
if (symbol_a->st_value < symbol_b->st_value) return -1;
if (symbol_a->st_value > symbol_b->st_value) return 1;
return 0;
}
int findTables(){
FILE* file = fopen("trace.elf", "rb");
if (!file) {
printf("Error opening file\n");
return 1;
}
// Read the ELF header
Elf64_Ehdr elf_header;
if (fread(&elf_header, sizeof(Elf64_Ehdr), 1, file) != 1) {
printf("Error reading ELF header\n");
fclose(file);
return 1;
}
// Get the section header table offset from the ELF header
fseek(file, elf_header.e_shoff, SEEK_SET);
// Read the section header table
Elf64_Shdr section_headers[elf_header.e_shnum];
if (fread(section_headers, sizeof(Elf64_Shdr), elf_header.e_shnum, file) != elf_header.e_shnum) {
printf("Error reading section headers\n");
fclose(file);
return 1;
}
// Find the symbol table and the associated string table (for symbol names)
Elf64_Shdr* symbol_table_header = NULL;
Elf64_Shdr* string_table_header = NULL;
for (int i = 0; i < elf_header.e_shnum; i++) {
if (section_headers[i].sh_type == 0x2) { // SHT_SYMTAB
symbol_table_header = §ion_headers[i];
} else if (section_headers[i].sh_type == 0x3) { // SHT_STRTAB
string_table_header = §ion_headers[i];
}
if (symbol_table_header && string_table_header) {
break; // Both tables found, exit the loop
}
}
if (!symbol_table_header || !string_table_header) {
printf("Symbol table or string table not found\n");
fclose(file);
return 1;
}
// Calculate the number of symbols in the symbol table
num_symbols = symbol_table_header->sh_size / sizeof(Elf64_Sym);
// Read the symbol table
symbol_table = (Elf64_Sym*)malloc(symbol_table_header->sh_size);
if (!symbol_table) {
printf("Error allocating memory for symbol table\n");
fclose(file);
return 1;
}
fseek(file, symbol_table_header->sh_offset, SEEK_SET);
if (fread(symbol_table, sizeof(Elf64_Sym), num_symbols, file) != num_symbols) {
printf("Error reading symbol table\n");
free(symbol_table);
fclose(file);
return 1;
}
// Read the string table
string_table = (char*)malloc(string_table_header->sh_size);
if (!string_table) {
printf("Error allocating memory for string table\n");
free(symbol_table);
fclose(file);
return 1;
}
fseek(file, string_table_header->sh_offset, SEEK_SET);
if (fread(string_table, 1, string_table_header->sh_size, file) != string_table_header->sh_size) {
printf("Error reading string table\n");
free(symbol_table);
free(string_table);
fclose(file);
return 1;
}
stringSize = string_table_header->sh_size;
fclose(file);
}
void printTables(){
printf("Address\t\tName\n");
printf("-------\t\t----\n");
// Print all symbols with their addresses and names
for (size_t j = 0; j < num_symbols; j++) {
// Check if the symbol name is valid (inside the string table)
if (symbol_table[j].st_name < stringSize) {
char* symbol_name = &string_table[symbol_table[j].st_name];
printf("0x%08x\t%s\n", symbol_table[j].st_value, symbol_name);
}
}
}
void freeSpaces(){
free(symbol_table);
free(string_table);
}
int main() {
if(findTables() == 1){
printf("Exiting...");
return 0;
}
// Sort the symbol table based on addresses
qsort(symbol_table, num_symbols, sizeof(Elf64_Sym), compare_symbols);
printTables();
freeSpaces();
return 0;
}
以下是trace.self的一些代码输出:
0x004016d0 __do_global_dtors_aux
0x00401ac1 trace_return_values
0x00401b0c foo
0x00401b36 main
0x00401b50 handle_zhaoxin
0x00401fb0 get_common_indices.constprop.0
0x00402df0 __libc_start_main_impl
但是,当使用"nm-n trace.self"命令并以这种方式获取符号表时,相同的部分是:
00000000004016d0 t __do_global_dtors_aux
0000000000401710 t frame_dummy
0000000000401745 T get_address
0000000000401ac1 T trace_return_values
0000000000401b0c T foo
0000000000401b21 T bar
0000000000401b36 T main
0000000000401b50 t handle_zhaoxin
0000000000401d20 t handle_amd
0000000000401ed0 t call_fini
0000000000401f10 t __libc_start_call_main
如您所见,第一个输出中缺少一些地址和名称.尤其是"wine 吧".是我的代码错误还是有其他问题?