49 #include <sys/types.h>
59 #include "debug/Loader.hh"
65 bool skip_interp_check)
68 if (elf_version(EV_CURRENT) == EV_NONE)
69 panic(
"wrong elf version number!");
73 Elf *elf = elf_memory((
char*)data, len);
77 if (gelf_getehdr(elf, &ehdr) == 0) {
85 if (ehdr.e_machine == EM_SPARC64 ||
86 (ehdr.e_machine == EM_SPARC &&
87 ehdr.e_ident[EI_CLASS] == ELFCLASS64) ||
88 ehdr.e_machine == EM_SPARCV9) {
90 }
else if (ehdr.e_machine == EM_SPARC32PLUS ||
91 (ehdr.e_machine == EM_SPARC &&
92 ehdr.e_ident[EI_CLASS] == ELFCLASS32)) {
94 }
else if (ehdr.e_machine == EM_MIPS &&
95 ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
97 if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB) {
98 fatal(
"The binary you're trying to load is compiled for big "
99 "endian MIPS. gem5\nonly supports little endian MIPS. "
100 "Please recompile your binary.\n");
102 }
else if (ehdr.e_machine == EM_X86_64 &&
103 ehdr.e_ident[EI_CLASS] == ELFCLASS64) {
105 }
else if (ehdr.e_machine == EM_386 &&
106 ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
108 }
else if (ehdr.e_machine == EM_ARM &&
109 ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
111 }
else if (ehdr.e_machine == EM_AARCH64 &&
112 ehdr.e_ident[EI_CLASS] == ELFCLASS64) {
114 }
else if (ehdr.e_machine == EM_RISCV) {
116 }
else if (ehdr.e_machine == EM_PPC &&
117 ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
119 if (ehdr.e_ident[EI_DATA] != ELFDATA2MSB) {
120 fatal(
"The binary you're trying to load is compiled for "
121 "little endian Power.\ngem5 only supports big "
122 "endian Power. Please recompile your binary.\n");
124 }
else if (ehdr.e_machine == EM_PPC64) {
125 fatal(
"The binary you're trying to load is compiled for 64-bit "
126 "Power. M5\n only supports 32-bit Power. Please "
127 "recompile your binary.\n");
128 }
else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) {
134 warn(
"Unknown architecture: %d\n", ehdr.e_machine);
140 switch (ehdr.e_ident[EI_OSABI]) {
144 case ELFOSABI_SOLARIS:
153 case ELFOSABI_FREEBSD:
166 Elf_Scn *section = elf_getscn(elf, sec_idx);
171 gelf_getshdr(section, &shdr);
173 char *e_str = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name);
174 if (shdr.sh_type == SHT_NOTE &&
175 !strcmp(
".note.ABI-tag", e_str)) {
179 Elf_Data *raw_data = elf_rawdata(section, NULL);
180 assert(raw_data && raw_data->d_buf);
182 uint32_t raw_abi = ((uint32_t*)raw_data->d_buf)[4];
183 bool is_le = ehdr.e_ident[EI_DATA] == ELFDATA2LSB;
184 uint32_t os_abi = is_le ?
htole(raw_abi) :
htobe(raw_abi);
191 fatal(
"gem5 does not support the HURD ABI.\n");
201 if (!strcmp(
".SUNW_version", e_str) ||
202 !strcmp(
".stab.index", e_str))
205 section = elf_getscn(elf, ++sec_idx);
221 uint64_t e_phoff = ehdr.e_phoff;
224 gelf_getphdr(elf,
i, &phdr);
226 if (phdr.p_offset <= e_phoff &&
227 phdr.p_offset + phdr.p_filesz > e_phoff) {
229 phdr.p_paddr + (e_phoff - phdr.p_offset);
235 if (!skip_interp_check) {
236 for (
int i = 0;
i < ehdr.e_phnum;
i++) {
238 M5_VAR_USED void *check_p = gelf_getphdr(elf,
i, &phdr);
239 assert(check_p !=
nullptr);
241 if (phdr.p_type != PT_INTERP)
244 char *interp_path = (
char*)data + phdr.p_offset;
245 int fd = open(interp_path, O_RDONLY);
247 fatal(
"Unable to open dynamic executable's interpreter.\n");
251 assert(check_i == 0);
253 void *
mm = mmap(
nullptr, sb.st_size, PROT_READ,
255 assert(mm != MAP_FAILED);
258 uint8_t *interp_image = (uint8_t*)mm;
261 assert(obj !=
nullptr);
273 uint8_t *_data,
Arch _arch,
OpSys _op_sys)
274 :
ObjectFile(_filename, _len, _data, _arch, _op_sys),
275 _programHeaderTable(0), _programHeaderSize(0), _programHeaderCount(0),
276 interpreter(nullptr), ldBias(0), relocate(true),
277 ldMin(std::numeric_limits<
Addr>::max()),
278 ldMax(std::numeric_limits<
Addr>::min())
281 if (elf_version(EV_CURRENT) == EV_NONE)
282 panic(
"wrong elf version number!");
290 if (gelf_getehdr(elf, &ehdr) ==0) {
291 panic(
"Not ELF, shouldn't be here");
294 entry = ehdr.e_entry;
303 Addr text_sec_start = 0;
304 Addr data_sec_start = 0;
305 Addr bss_sec_start = 0;
308 Elf_Scn *section = elf_getscn(elf, sec_idx);
313 gelf_getshdr(section, &shdr);
314 char *sec_name = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name);
317 if (!strcmp(
".text", sec_name)) {
318 text_sec_start = shdr.sh_addr;
319 }
else if (!strcmp(
".data", sec_name)) {
320 data_sec_start = shdr.sh_addr;
321 }
else if (!strcmp(
".bss", sec_name)) {
322 bss_sec_start = shdr.sh_addr;
325 Elf_Error errorNum = (Elf_Error)elf_errno();
326 if (errorNum != ELF_E_NONE) {
327 const char *errorMessage = elf_errmsg(errorNum);
328 fatal(
"Error from libelf: %s.\n", errorMessage);
332 section = elf_getscn(elf, ++sec_idx);
338 for (
int i = 0;
i < ehdr.e_phnum; ++
i) {
340 if (gelf_getphdr(elf,
i, &phdr) == 0) {
341 panic(
"gelf_getphdr failed for segment %d.",
i);
345 if (!(phdr.p_type & PT_LOAD))
349 ldMax = std::max(
ldMax, phdr.p_vaddr + phdr.p_memsz);
352 if (phdr.p_paddr <= bss_sec_start &&
353 phdr.p_paddr + phdr.p_memsz > bss_sec_start &&
354 phdr.p_memsz - phdr.p_filesz > 0) {
356 bss.
size = phdr.p_memsz - phdr.p_filesz;
361 if (phdr.p_vaddr <= text_sec_start &&
362 phdr.p_vaddr + phdr.p_filesz > text_sec_start) {
365 if (phdr.p_vaddr != 0)
371 }
else if (phdr.p_vaddr <= data_sec_start &&
372 phdr.p_vaddr + phdr.p_filesz > data_sec_start) {
381 extra.
size = phdr.p_filesz;
389 "Empty .text segment in '%s'. ELF file corrupted?\n",
392 DPRINTFR(Loader,
"text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n",
410 if (elf_version(EV_CURRENT) == EV_NONE)
411 panic(
"wrong elf version number!");
419 Elf_Scn *section = elf_getscn(elf, sec_idx);
423 while (section != NULL) {
425 gelf_getshdr(section, &shdr);
427 if (shdr.sh_type == SHT_SYMTAB) {
429 Elf_Data *
data = elf_getdata(section, NULL);
430 int count = shdr.sh_size / shdr.sh_entsize;
431 DPRINTF(Loader,
"Found Symbol Table, %d symbols present\n", count);
436 gelf_getsym(data,
i, &sym);
437 if (GELF_ST_BIND(sym.st_info) == binding) {
438 char *sym_name = elf_strptr(elf, shdr.sh_link, sym.st_name);
439 if (sym_name && sym_name[0] !=
'$') {
441 if (symtab->
insert(value & mask, sym_name)) {
442 DPRINTF(Loader,
"Symbol: %-40s value %#x\n",
450 section = elf_getscn(elf, sec_idx);
524 if (elf_version(EV_CURRENT) == EV_NONE)
525 panic(
"wrong elf version number!");
533 if (gelf_getehdr(elf, &ehdr) ==0) {
534 panic(
"Not ELF, shouldn't be here");
539 Elf_Scn *section = elf_getscn(elf, sec_idx);
544 gelf_getshdr(section, &shdr);
545 sectionNames.insert(elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name));
546 section = elf_getscn(elf, ++sec_idx);
576 segment.baseAddr += bias_addr;
virtual bool loadWeakSymbols(SymbolTable *symtab, Addr base=0, Addr offset=0, Addr addr_mask=maxAddr) override
bool loadSections(PortProxy &mem_proxy, Addr addr_mask=maxAddr, Addr offset=0) override
ElfObject(const std::string &_filename, size_t _len, uint8_t *_data, Arch _arch, OpSys _opSys)
bool sectionExists(std::string sec)
virtual bool loadAllSymbols(SymbolTable *symtab, Addr base=0, Addr offset=0, Addr addr_mask=maxAddr) override
virtual bool loadGlobalSymbols(SymbolTable *symtab, Addr base=0, Addr offset=0, Addr addr_mask=maxAddr) override
virtual void updateBias(Addr bias_addr) override
const std::string filename
bool insert(Addr address, std::string symbol)
#define warn_if(cond,...)
Conditional warning macro that checks the supplied condition and only prints a warning if the conditi...
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
uint16_t _programHeaderCount
virtual bool loadSections(PortProxy &mem_proxy, Addr mask=maxAddr, Addr offset=0)
static const int NumArgumentRegs M5_VAR_USED
This object is a proxy for a structural port, to be used for debug accesses.
static ObjectFile * tryFile(const std::string &fname, size_t len, uint8_t *data, bool skip_interp_check=false)
bool loadSomeSymbols(SymbolTable *symtab, int binding, Addr mask, Addr base, Addr offset)
Helper functions for loadGlobalSymbols() and loadLocalSymbols().
std::vector< Segment > extraSegments
uint16_t _programHeaderSize
std::set< std::string > sectionNames
virtual bool loadLocalSymbols(SymbolTable *symtab, Addr base=0, Addr offset=0, Addr addr_mask=maxAddr) override
bool loadSection(Section *sec, PortProxy &mem_proxy, Addr mask, Addr offset=0)
T bits(T val, int first, int last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it...