aboutsummaryrefslogtreecommitdiff
path: root/backends/plugins/elf/elf-loader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'backends/plugins/elf/elf-loader.cpp')
-rw-r--r--backends/plugins/elf/elf-loader.cpp72
1 files changed, 42 insertions, 30 deletions
diff --git a/backends/plugins/elf/elf-loader.cpp b/backends/plugins/elf/elf-loader.cpp
index 32e42daf7d..0503f81c42 100644
--- a/backends/plugins/elf/elf-loader.cpp
+++ b/backends/plugins/elf/elf-loader.cpp
@@ -66,9 +66,11 @@ void DLObject::unload() {
_segmentVMA = 0;
}
-bool DLObject::readElfHeader(Common::SeekableReadStream* DLFile, Elf32_Ehdr *ehdr) {
+bool DLObject::readElfHeader(Elf32_Ehdr *ehdr) {
+ assert(_file);
+
// Start reading the elf header. Check for errors and magic
- if (DLFile->read(ehdr, sizeof(*ehdr)) != sizeof(*ehdr) ||
+ if (_file->read(ehdr, sizeof(*ehdr)) != sizeof(*ehdr) ||
memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
warning("elfloader: No ELF file.");
return false;
@@ -127,10 +129,12 @@ bool DLObject::readElfHeader(Common::SeekableReadStream* DLFile, Elf32_Ehdr *ehd
return true;
}
-bool DLObject::readProgramHeaders(Common::SeekableReadStream* DLFile, Elf32_Ehdr *ehdr, Elf32_Phdr *phdr, Elf32_Half num) {
+bool DLObject::readProgramHeaders(Elf32_Ehdr *ehdr, Elf32_Phdr *phdr, Elf32_Half num) {
+ assert(_file);
+
// Read program header
- if (!DLFile->seek(ehdr->e_phoff + sizeof(*phdr) * num, SEEK_SET) ||
- DLFile->read(phdr, sizeof(*phdr)) != sizeof(*phdr)) {
+ if (!_file->seek(ehdr->e_phoff + sizeof(*phdr) * num, SEEK_SET) ||
+ _file->read(phdr, sizeof(*phdr)) != sizeof(*phdr)) {
warning("elfloader: Program header load failed.");
return false;
}
@@ -147,7 +151,7 @@ bool DLObject::readProgramHeaders(Common::SeekableReadStream* DLFile, Elf32_Ehdr
return true;
}
-bool DLObject::loadSegment(Common::SeekableReadStream* DLFile, Elf32_Phdr *phdr) {
+bool DLObject::loadSegment(Elf32_Phdr *phdr) {
// Attempt to allocate memory for segment
uint32 extra = phdr->p_vaddr % phdr->p_align; // Get extra length TODO: check logic here
debug(2, "elfloader: Extra mem is %x", extra);
@@ -174,8 +178,8 @@ bool DLObject::loadSegment(Common::SeekableReadStream* DLFile, Elf32_Phdr *phdr)
debug(2, "elfloader: Reading the segment into memory");
// Read the segment into memory
- if (!DLFile->seek(phdr->p_offset, SEEK_SET) ||
- DLFile->read(_segment, phdr->p_filesz) != phdr->p_filesz) {
+ if (!_file->seek(phdr->p_offset, SEEK_SET) ||
+ _file->read(_segment, phdr->p_filesz) != phdr->p_filesz) {
warning("elfloader: Segment load failed.");
return false;
}
@@ -185,7 +189,9 @@ bool DLObject::loadSegment(Common::SeekableReadStream* DLFile, Elf32_Phdr *phdr)
return true;
}
-Elf32_Shdr * DLObject::loadSectionHeaders(Common::SeekableReadStream* DLFile, Elf32_Ehdr *ehdr) {
+Elf32_Shdr * DLObject::loadSectionHeaders(Elf32_Ehdr *ehdr) {
+ assert(_file);
+
Elf32_Shdr *shdr = 0;
// Allocate memory for section headers
@@ -195,8 +201,8 @@ Elf32_Shdr * DLObject::loadSectionHeaders(Common::SeekableReadStream* DLFile, El
}
// Read from file into section headers
- if (!DLFile->seek(ehdr->e_shoff, SEEK_SET) ||
- DLFile->read(shdr, ehdr->e_shnum * sizeof(*shdr)) !=
+ if (!_file->seek(ehdr->e_shoff, SEEK_SET) ||
+ _file->read(shdr, ehdr->e_shnum * sizeof(*shdr)) !=
ehdr->e_shnum * sizeof(*shdr)) {
warning("elfloader: Section headers load failed.");
return 0;
@@ -205,7 +211,9 @@ Elf32_Shdr * DLObject::loadSectionHeaders(Common::SeekableReadStream* DLFile, El
return shdr;
}
-int DLObject::loadSymbolTable(Common::SeekableReadStream* DLFile, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) {
+int DLObject::loadSymbolTable(Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) {
+ assert(_file);
+
// Loop over sections, looking for symbol table linked to a string table
for (uint32 i = 0; i < ehdr->e_shnum; i++) {
if (shdr[i].sh_type == SHT_SYMTAB &&
@@ -232,8 +240,8 @@ int DLObject::loadSymbolTable(Common::SeekableReadStream* DLFile, Elf32_Ehdr *eh
}
// Read symbol table into memory
- if (!DLFile->seek(shdr[_symtab_sect].sh_offset, SEEK_SET) ||
- DLFile->read(_symtab, shdr[_symtab_sect].sh_size) !=
+ if (!_file->seek(shdr[_symtab_sect].sh_offset, SEEK_SET) ||
+ _file->read(_symtab, shdr[_symtab_sect].sh_size) !=
shdr[_symtab_sect].sh_size) {
warning("elfloader: Symbol table load failed.");
return -1;
@@ -246,7 +254,9 @@ int DLObject::loadSymbolTable(Common::SeekableReadStream* DLFile, Elf32_Ehdr *eh
return _symtab_sect;
}
-bool DLObject::loadStringTable(Common::SeekableReadStream* DLFile, Elf32_Shdr *shdr) {
+bool DLObject::loadStringTable(Elf32_Shdr *shdr) {
+ assert(_file);
+
uint32 string_sect = shdr[_symtab_sect].sh_link;
// Allocate memory for string table
@@ -256,8 +266,8 @@ bool DLObject::loadStringTable(Common::SeekableReadStream* DLFile, Elf32_Shdr *s
}
// Read string table into memory
- if (!DLFile->seek(shdr[string_sect].sh_offset, SEEK_SET) ||
- DLFile->read(_strtab, shdr[string_sect].sh_size) !=
+ if (!_file->seek(shdr[string_sect].sh_offset, SEEK_SET) ||
+ _file->read(_strtab, shdr[string_sect].sh_size) !=
shdr[string_sect].sh_size) {
warning("elfloader: Symbol table strings load failed.");
return false;
@@ -280,32 +290,32 @@ void DLObject::relocateSymbols(ptrdiff_t offset) {
}
}
-bool DLObject::load(Common::SeekableReadStream* DLFile) {
+bool DLObject::load() {
Elf32_Ehdr ehdr;
Elf32_Phdr phdr;
Elf32_Shdr *shdr;
bool ret = true;
- if (readElfHeader(DLFile, &ehdr) == false)
+ if (readElfHeader(&ehdr) == false)
return false;
for (uint32 i = 0; i < ehdr.e_phnum; i++) { //Load our segments
debug(2, "elfloader: Loading segment %d", i);
- if (readProgramHeaders(DLFile, &ehdr, &phdr, i) == false)
+ if (readProgramHeaders(&ehdr, &phdr, i) == false)
return false;
- if (!loadSegment(DLFile, &phdr))
+ if (!loadSegment(&phdr))
return false;
}
- if (!(shdr = loadSectionHeaders(DLFile, &ehdr)))
+ if (!(shdr = loadSectionHeaders(&ehdr)))
ret = false;
- if (ret && ((_symtab_sect = loadSymbolTable(DLFile, &ehdr, shdr)) < 0))
+ if (ret && ((_symtab_sect = loadSymbolTable(&ehdr, shdr)) < 0))
ret = false;
- if (ret && !loadStringTable(DLFile, shdr))
+ if (ret && !loadStringTable(shdr))
ret = false;
if (ret) {
@@ -314,7 +324,7 @@ bool DLObject::load(Common::SeekableReadStream* DLFile) {
relocateSymbols(_segmentOffset);
}
- if (ret && !relocateRels(DLFile, &ehdr, shdr))
+ if (ret && !relocateRels(&ehdr, shdr))
ret = false;
free(shdr);
@@ -323,28 +333,30 @@ bool DLObject::load(Common::SeekableReadStream* DLFile) {
}
bool DLObject::open(const char *path) {
- Common::SeekableReadStream* DLFile;
void *ctors_start, *ctors_end;
debug(2, "elfloader: open(\"%s\")", path);
- Common::FSNode file(path);
+ _file = Common::FSNode(path).createReadStream();
- if (!(DLFile = file.createReadStream())) {
- warning("elfloader: %s not found.", path);
+ if (!_file) {
+ warning("elfloader: File %s not found.", path);
return false;
}
debug(2, "elfloader: %s found!", path);
/*Try to load and relocate*/
- if (!load(DLFile)) {
+ if (!load()) {
unload();
return false;
}
debug(2, "elfloader: Loaded!");
+ delete _file;
+ _file = 0;
+
flushDataCache(_segment, _segmentSize);
ctors_start = symbol("___plugin_ctors");