
221220000 张三 Linux zzy 5.15.146.1-microsoft-standard-WSL2 #1 SMP Thu Jan 11 04:09:03 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux 00:02:31 up 5 days, 12:10, 3 users, load average: 0.47, 0.44, 0.48
120 lines
3.4 KiB
C
120 lines
3.4 KiB
C
#include <common.h>
|
|
#include <elf.h>
|
|
|
|
typedef MUXDEF(CONFIG_ISA64, Elf64_Ehdr, Elf32_Ehdr) Elf_Ehdr;
|
|
typedef MUXDEF(CONFIG_ISA64, Elf64_Phdr, Elf32_Phdr) Elf_Phdr;
|
|
typedef MUXDEF(CONFIG_ISA64, Elf64_Shdr, Elf32_Shdr) Elf_Shdr;
|
|
typedef MUXDEF(CONFIG_ISA64, Elf64_Sym , Elf32_Sym ) Elf_Sym;
|
|
#define ELF_ST_TYPE \
|
|
MUXDEF(CONFIG_ISA64, ELF64_ST_TYPE, ELF32_ST_TYPE)
|
|
|
|
typedef struct {
|
|
word_t start;
|
|
word_t end;
|
|
word_t size;
|
|
char fname[32];
|
|
} Elf_Ftrace;
|
|
// [start, start + size) == [start, end]
|
|
static int elf_ftrace_size = 0;
|
|
static Elf_Ftrace elf_ftrace[128];
|
|
|
|
#ifdef CONFIG_FTRACE_DISPLAY
|
|
void ftrace_display() {
|
|
for (int i = 0; i < elf_ftrace_size; i ++) {
|
|
log_write("ftrace %d: ["FMT_WORD", "FMT_WORD"] %s\n", i, elf_ftrace[i].start, elf_ftrace[i].end, elf_ftrace[i].fname);
|
|
}
|
|
}
|
|
#else
|
|
void ftrace_display() {}
|
|
#endif
|
|
|
|
void init_elf(const char* elf_file) {
|
|
// open elf
|
|
if (elf_file == NULL) {
|
|
Log("No elf is given.");
|
|
return;
|
|
}
|
|
|
|
FILE *fp = fopen(elf_file, "rb");
|
|
Assert(fp, "Can not open '%s'", elf_file);
|
|
|
|
fseek(fp, 0, SEEK_END);
|
|
long size = ftell(fp);
|
|
int ret;
|
|
|
|
Log("The elf is %s, size = %ld", elf_file, size);
|
|
|
|
// read elf header
|
|
unsigned char e_ident[EI_NIDENT];
|
|
fseek(fp, 0, SEEK_SET);
|
|
ret = fread(e_ident, sizeof(e_ident), 1, fp);
|
|
assert(ret == 1);
|
|
switch (e_ident[EI_CLASS]) {
|
|
case ELFCLASS32:
|
|
Log("ELF class: ELF32");
|
|
break;
|
|
case ELFCLASS64:
|
|
Log("ELF class: ELF64");
|
|
break;
|
|
default:
|
|
Assert(false, "Error: unknown or unsupported ELF class.");
|
|
return;
|
|
}
|
|
|
|
// get elf header
|
|
Elf_Ehdr ehdr;
|
|
fseek(fp, 0, SEEK_SET);
|
|
ret = fread(&ehdr, sizeof(Elf_Ehdr), 1, fp);
|
|
assert(ret == 1);
|
|
|
|
// get section header
|
|
assert(ehdr.e_shoff != 0);
|
|
Elf_Shdr shdr[ehdr.e_shnum];
|
|
ret = fseek(fp, ehdr.e_shoff, SEEK_SET);
|
|
ret = fread(&shdr, sizeof(shdr), 1, fp);
|
|
assert(ret == 1);
|
|
|
|
// get symbol table and string table
|
|
Elf_Sym *psymt = NULL;
|
|
char* pstrt = NULL;
|
|
size_t symt_len = 0, strt_sz = 0;
|
|
for (int i = 0; i < ehdr.e_shnum; i++) {
|
|
if (shdr[i].sh_type == SHT_SYMTAB) {
|
|
fseek(fp, shdr[i].sh_offset, SEEK_SET);
|
|
assert(shdr[i].sh_size % sizeof(Elf_Sym) == 0);
|
|
symt_len = shdr[i].sh_entsize;
|
|
Elf_Sym sym[symt_len];
|
|
ret = fread(sym, shdr[i].sh_size, 1, fp);
|
|
assert(ret == 1);
|
|
psymt = sym;
|
|
Log("SYMTAB %08x %06x %06x", shdr[i].sh_addr, shdr[i].sh_offset, shdr[i].sh_size);
|
|
} else if (shdr[i].sh_type == SHT_STRTAB) {
|
|
strt_sz = shdr[i].sh_size;
|
|
fseek(fp, shdr[i].sh_offset, SEEK_SET);
|
|
char buffer[strt_sz];
|
|
ret = fread(buffer, strt_sz, 1, fp);
|
|
assert(ret == 1);
|
|
pstrt = buffer;
|
|
Log("SHT_STRTAB %08x %06x %06x", shdr[i].sh_addr, shdr[i].sh_offset, shdr[i].sh_size);
|
|
}
|
|
}
|
|
|
|
// filling ftrace
|
|
assert(pstrt != NULL && pstrt != NULL);
|
|
for (int i = 0; i < symt_len; i ++) {
|
|
Log("---LOG: %3d: %08x %5u %x", i, psymt[i].st_value, psymt[i].st_size, psymt[i].st_name);
|
|
if (ELF_ST_TYPE(psymt[i].st_info) == STT_FUNC) {
|
|
// Warning due to elf_ftrace is global variable so you don't need to set '\0' in the end
|
|
// strncpy(elf_ftrace[elf_ftrace_size].fname, pstrt + psymt[i].st_name,
|
|
// sizeof(elf_ftrace[0].fname) - 1);
|
|
elf_ftrace[elf_ftrace_size].start = psymt[i].st_value;
|
|
elf_ftrace[elf_ftrace_size].size = psymt[i].st_size;
|
|
elf_ftrace[elf_ftrace_size].end = psymt[i].st_value + psymt[i].st_size - 1;
|
|
elf_ftrace_size ++;
|
|
}
|
|
}
|
|
|
|
fclose(fp);
|
|
return;
|
|
}
|