summaryrefslogtreecommitdiff
path: root/base/loader/elf_object.cc
diff options
context:
space:
mode:
Diffstat (limited to 'base/loader/elf_object.cc')
-rw-r--r--base/loader/elf_object.cc94
1 files changed, 83 insertions, 11 deletions
diff --git a/base/loader/elf_object.cc b/base/loader/elf_object.cc
index 52f236fef..1136686f0 100644
--- a/base/loader/elf_object.cc
+++ b/base/loader/elf_object.cc
@@ -38,8 +38,8 @@
#define __LIBELF_NEED_LINK_H 0
#define __LIBELF_SYMBOL_VERSIONS 0
-#include <libelf/libelf.h>
-#include <libelf/gelf.h>
+#include "libelf/libelf.h"
+#include "libelf/gelf.h"
#include "base/loader/elf_object.hh"
@@ -55,6 +55,8 @@ ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
{
Elf *elf;
GElf_Ehdr ehdr;
+ Arch arch = UnknownArch;
+ OpSys opSys = UnknownOpSys;
// check that header matches library version
if (elf_version(EV_CURRENT) == EV_NONE)
@@ -72,17 +74,87 @@ ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
return NULL;
}
else {
- if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
- panic("32 bit ELF Binary, Not Supported");
- /* @todo this emachine value isn't offical yet.
- * so we probably shouldn't check it. */
-// if (ehdr.e_machine != EM_ALPHA)
-// panic("Non Alpha Binary, Not Supported");
+ //Detect the architecture
+ //Versioning issues in libelf need to be resolved to get the correct
+ //SPARC constants.
+ //If MIPS supports 32 bit executables, this may need to be changed.
+ //Also, there are other MIPS constants which may be used, like
+ //EM_MIPS_RS3_LE and EM_MIPS_X
+ //Since we don't know how to check for alpha right now, we'll
+ //just assume if it wasn't something else and it's 64 bit, that's
+ //what it must be.
+ if (ehdr.e_machine == EM_SPARC64 ||
+ ehdr.e_machine == EM_SPARC ||
+ ehdr.e_machine == EM_SPARCV9) {
+ arch = ObjectFile::SPARC;
+ } else if (ehdr.e_machine == EM_MIPS
+ && ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
+ arch = ObjectFile::MIPS;
+ } else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) {
+ arch = ObjectFile::Alpha;
+ } else {
+ arch = ObjectFile::UnknownArch;
+ }
- elf_end(elf);
+ //Detect the operating system
+ switch (ehdr.e_ident[EI_OSABI])
+ {
+
+ case ELFOSABI_LINUX:
+ opSys = ObjectFile::Linux;
+ break;
+ case ELFOSABI_SOLARIS:
+ opSys = ObjectFile::Solaris;
+ break;
+ case ELFOSABI_TRU64:
+ opSys = ObjectFile::Tru64;
+ break;
+ default:
+ opSys = ObjectFile::UnknownOpSys;
+ }
- return new ElfObject(fname, fd, len, data,
- ObjectFile::Alpha, ObjectFile::Linux);
+ //take a look at the .note.ABI section
+ //It can let us know what's what.
+ if (opSys == ObjectFile::UnknownOpSys)
+ {
+ Elf_Scn *section;
+ GElf_Shdr shdr;
+ Elf_Data *data;
+ uint32_t osAbi;;
+ int secIdx = 1;
+
+ // Get the first section
+ section = elf_getscn(elf, secIdx);
+
+ // While there are no more sections
+ while (section != NULL) {
+ gelf_getshdr(section, &shdr);
+ if (shdr.sh_type == SHT_NOTE && !strcmp(".note.ABI-tag",
+ elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name))) {
+ // we have found a ABI note section
+ // Check the 5th 32bit word for OS 0 == linux, 1 == hurd,
+ // 2 == solaris, 3 == freebsd
+ data = elf_rawdata(section, NULL);
+ assert(data->d_buf);
+ if(ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
+ osAbi = htole(((uint32_t*)data->d_buf)[4]);
+ else
+ osAbi = htobe(((uint32_t*)data->d_buf)[4]);
+
+ switch(osAbi) {
+ case 0:
+ opSys = ObjectFile::Linux;
+ break;
+ case 2:
+ opSys = ObjectFile::Solaris;
+ break;
+ }
+ } // if section found
+ section = elf_getscn(elf, ++secIdx);
+ } // while sections
+ }
+ elf_end(elf);
+ return new ElfObject(fname, fd, len, data, arch, opSys);
}
}