-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathloadelf.cpp
More file actions
94 lines (84 loc) · 3 KB
/
loadelf.cpp
File metadata and controls
94 lines (84 loc) · 3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include "loadelf.hpp"
#include <cstdio>
#include <cstdlib>
#include <fcntl.h>
#include <gelf.h>
#include <libelf.h>
#include <memory>
#include <spdlog/spdlog.h>
#include <unistd.h>
// 分析 ELF 文件,返回所有加载到内存中的段信息
std::vector<MemBlock> get_data_from_elf(const char *filename, std::shared_ptr<spdlog::logger> logger) {
std::vector<MemBlock> blocks;
// 初始化 libelf 库
if (elf_version(EV_CURRENT) == EV_NONE) {
logger->error("ELF: cannot initialize libelf");
return std::vector<MemBlock>();
}
// 打开 ELF 文件
int fd = open(filename, O_RDONLY);
if (fd < 0) {
const char *errstr = strerrordesc_np(errno);
logger->error("ELF: cannot open file '{}': {}", filename, errstr);
return std::vector<MemBlock>();
}
// 开始 ELF 处理
Elf *e = elf_begin(fd, ELF_C_READ, nullptr);
if (!e) {
logger->error("ELF: elf_begin failed: {}", elf_errmsg(-1));
close(fd);
return std::vector<MemBlock>();
}
// 读取 ELF 头部
GElf_Ehdr ehdr;
if (gelf_getehdr(e, &ehdr) == nullptr) {
logger->error("ELF: gelf_getehdr failed: {}", elf_errmsg(-1));
elf_end(e);
close(fd);
return std::vector<MemBlock>();
}
// 获取程序头表中的段数量
size_t phnum = 0;
if (elf_getphdrnum(e, &phnum) != 0) {
logger->error("ELF: elf_getphdrnum failed: {}", elf_errmsg(-1));
elf_end(e);
close(fd);
return std::vector<MemBlock>();
}
// 遍历所有程序头
for (size_t i = 0; i < phnum; ++i) {
GElf_Phdr phdr;
if (gelf_getphdr(e, i, &phdr) != &phdr) {
logger->error("ELF: gelf_getphdr header {} failed: {}", i, elf_errmsg(-1));
return std::vector<MemBlock>();
}
// 只考虑加载段
if (phdr.p_type == PT_LOAD) {
MemBlock block;
block.vaddr = phdr.p_vaddr;
block.memsz = phdr.p_memsz;
// 如果段在文件中有初始化数据,则读取数据
if (phdr.p_filesz > 0) {
block.data.resize(phdr.p_filesz);
if (lseek(fd, phdr.p_offset, SEEK_SET) == -1) {
const char *errstr = strerrordesc_np(errno);
logger->error("ELF: failed seeking to offset {}: {}", phdr.p_offset, errstr);
return std::vector<MemBlock>();
} else {
ssize_t bytesRead = read(fd, block.data.data(), phdr.p_filesz);
if (bytesRead != (ssize_t)phdr.p_filesz) {
const char *errstr = strerrordesc_np(errno);
logger->error(
"ELF: failed reading {} bytes data: {}", phdr.p_filesz, errstr
);
return std::vector<MemBlock>();
}
}
}
blocks.push_back(block);
}
}
elf_end(e);
close(fd);
return blocks;
}