57#include "debug/Loader.hh"
71 if (elf_version(EV_CURRENT) == EV_NONE)
72 panic(
"wrong elf version number!");
79 elf_memory((
char *)
const_cast<uint8_t *
>(ifd->data()), ifd->len());
83 if (gelf_getehdr(elf, &ehdr) == 0)
105 "Error: setInterpDir has already been called once\n");
112 elf = elf_memory((
char *)
const_cast<uint8_t *
>(
imageData->data()),
126 for (
int i = 0;
i <
ehdr.e_phnum; ++
i) {
128 if (gelf_getphdr(
elf,
i, &phdr) == 0) {
129 panic(
"gelf_getphdr failed for segment %d.",
i);
132 if (phdr.p_type == PT_LOAD)
134 if (phdr.p_type == PT_INTERP) {
146 "No loadable segments in '%s'. ELF file corrupted?\n",
155 if (elf_version(EV_CURRENT) == EV_NONE)
156 panic(
"wrong elf version number!");
160 Elf_Scn *section = elf_getscn(
elf, sec_idx);
165 gelf_getshdr(section, &shdr);
167 if (shdr.sh_type == SHT_SYMTAB) {
168 Elf_Data *
data = elf_getdata(section,
nullptr);
169 int count = shdr.sh_size / shdr.sh_entsize;
170 DPRINTF(Loader,
"Found Symbol Table, %d symbols present.",
count);
175 gelf_getsym(
data,
i, &sym);
177 char *sym_name = elf_strptr(
elf, shdr.sh_link, sym.st_name);
178 if (!sym_name || sym_name[0] ==
'$')
183 switch (GELF_ST_BIND(sym.st_info)) {
199 switch (GELF_ST_TYPE(sym.st_info)) {
221 binding, symbol_type, sym_name, sym.st_value,
225 DPRINTF(Loader,
"Symbol: %-40s value %#x.\n",
231 section = elf_getscn(
elf, sec_idx);
239 const std::string elf_path = (
char *)
imageData->data() + phdr.p_offset;
240 if (!interpDir.empty())
241 return interpDir + elf_path;
249 auto &emach =
ehdr.e_machine;
250 auto &eclass =
ehdr.e_ident[EI_CLASS];
251 auto &edata =
ehdr.e_ident[EI_DATA];
254 if (emach == EM_SPARC64 || (emach == EM_SPARC && eclass == ELFCLASS64) ||
255 emach == EM_SPARCV9) {
257 }
else if (emach == EM_SPARC32PLUS ||
258 (emach == EM_SPARC && eclass == ELFCLASS32)) {
260 }
else if (emach == EM_MIPS && eclass == ELFCLASS32) {
262 if (edata != ELFDATA2LSB) {
263 fatal(
"The binary you're trying to load is compiled for big "
264 "endian MIPS. gem5\nonly supports little endian MIPS. "
265 "Please recompile your binary.\n");
267 }
else if (emach == EM_X86_64 && eclass == ELFCLASS64) {
269 }
else if (emach == EM_386 && eclass == ELFCLASS32) {
271 }
else if (emach == EM_ARM && eclass == ELFCLASS32) {
273 }
else if (emach == EM_AARCH64 && eclass == ELFCLASS64) {
275 }
else if (emach == EM_RISCV) {
277 }
else if (emach == EM_PPC && eclass == ELFCLASS32) {
279 }
else if (emach == EM_PPC64 && eclass == ELFCLASS64) {
282 warn(
"Unknown architecture: %d\n", emach);
291 if (
ehdr.e_machine == EM_PPC64) {
292 switch (
ehdr.e_flags & 0x3) {
296 if (
ehdr.e_ident[EI_DATA] == ELFDATA2MSB)
298 if (
ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
305 switch (
ehdr.e_ident[EI_OSABI]) {
309 case ELFOSABI_SOLARIS:
318 case ELFOSABI_FREEBSD:
325 Elf_Scn *section = elf_getscn(
elf, 1);
326 for (
int sec_idx = 1; section; section = elf_getscn(
elf, ++sec_idx)) {
328 gelf_getshdr(section, &shdr);
330 char *e_str = elf_strptr(
elf,
ehdr.e_shstrndx, shdr.sh_name);
331 if (shdr.sh_type == SHT_NOTE && !strcmp(
".note.ABI-tag", e_str)) {
335 Elf_Data *raw_data = elf_rawdata(section,
nullptr);
336 assert(raw_data && raw_data->d_buf);
338 uint32_t raw_abi = ((uint32_t *)raw_data->d_buf)[4];
339 bool is_le =
ehdr.e_ident[EI_DATA] == ELFDATA2LSB;
340 uint32_t os_abi = is_le ?
htole(raw_abi) :
htobe(raw_abi);
347 fatal(
"gem5 does not support the HURD ABI.\n");
357 if (!strcmp(
".SUNW_version", e_str) || !strcmp(
".stab.index", e_str)) {
367 auto edata =
ehdr.e_ident[EI_DATA];
368 if (edata == ELFDATANONE)
369 panic(
"invalid ELF data encoding");
370 byteOrder = (edata == ELFDATA2MSB) ? ByteOrder::big : ByteOrder::little;
376 auto name = std::to_string(seg_num);
378 if (phdr.p_memsz == 0) {
379 warn(
"Ignoring empty loadable segment %s",
name);
384 phdr.p_offset, phdr.p_filesz });
385 Addr uninitialized = phdr.p_memsz - phdr.p_filesz;
392 phdr.p_paddr + phdr.p_filesz, uninitialized });
395 const Addr file_start = phdr.p_offset;
396 const Addr file_end = file_start + phdr.p_filesz;
402 if (file_start <= ehdr.e_phoff && file_end >
ehdr.e_phoff)
417 if (elf_version(EV_CURRENT) == EV_NONE)
418 panic(
"wrong elf version number!");
422 elf_memory((
char *)
const_cast<uint8_t *
>(
imageData->data()),
428 if (gelf_getehdr(
elf, &
ehdr) ==0) {
429 panic(
"Not ELF, shouldn't be here");
434 Elf_Scn *section = elf_getscn(
elf, sec_idx);
439 gelf_getshdr(section, &shdr);
441 section = elf_getscn(
elf, ++sec_idx);
std::string getInterpPath(const GElf_Phdr &phdr) const
std::set< std::string > sectionNames
void handleLoadableSegment(GElf_Phdr phdr, int seg_num)
uint16_t _programHeaderSize
bool sectionExists(std::string sec)
void determineByteOrder()
uint16_t _programHeaderCount
void updateBias(Addr bias_addr) override
ElfObject(ImageFileDataPtr ifd)
ImageFileDataPtr imageData
const std::vector< Segment > & segments() const
MemoryImage & offset(Addr by)
void addSegment(const Segment &seg)
const SymbolTable & symtab() const
bool insert(const Symbol &symbol)
Insert a new symbol in the table if it does not already exist.
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
#define panic(...)
This implements a cprintf based panic() function.
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
#define fatal(...)
This implements a cprintf based fatal() function.
#define warn_if(cond,...)
Conditional warning macro that checks the supplied condition and only prints a warning if the conditi...
void setInterpDir(const std::string &dirname)
This is the interface for setting up a base path for the elf interpreter.
ObjectFile * createObjectFile(const std::string &fname, bool raw)
std::shared_ptr< ImageFileData > ImageFileDataPtr
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
const std::string & name()