aboutsummaryrefslogtreecommitdiff
path: root/fesvr
diff options
context:
space:
mode:
authorMarcus Comstedt <marcus@mc.pp.se>2019-08-18 16:03:43 +0200
committerMarcus Comstedt <marcus@mc.pp.se>2019-10-28 09:23:32 +0100
commitf437e6a4e9983be0583ee1bf34512f80f3cc0162 (patch)
treef3ac0efc442019566f31aa5ba26c78915e80a0b6 /fesvr
parent5652b9dd6298c7b61fe80bc2a508bbd3c9e5c5ef (diff)
downloadspike-f437e6a4e9983be0583ee1bf34512f80f3cc0162.zip
spike-f437e6a4e9983be0583ee1bf34512f80f3cc0162.tar.gz
spike-f437e6a4e9983be0583ee1bf34512f80f3cc0162.tar.bz2
Implement support for big-endian hosts
Diffstat (limited to 'fesvr')
-rw-r--r--fesvr/elf.h2
-rw-r--r--fesvr/elfloader.cc74
-rw-r--r--fesvr/htif.cc5
-rw-r--r--fesvr/syscall.cc11
4 files changed, 52 insertions, 40 deletions
diff --git a/fesvr/elf.h b/fesvr/elf.h
index b66038d..b4b0add 100644
--- a/fesvr/elf.h
+++ b/fesvr/elf.h
@@ -11,6 +11,8 @@
#define IS_ELF32(hdr) (IS_ELF(hdr) && (hdr).e_ident[4] == 1)
#define IS_ELF64(hdr) (IS_ELF(hdr) && (hdr).e_ident[4] == 2)
+#define IS_ELFLE(hdr) (IS_ELF(hdr) && (hdr).e_ident[5] == 1)
+#define IS_ELFBE(hdr) (IS_ELF(hdr) && (hdr).e_ident[5] == 2)
#define PT_LOAD 1
diff --git a/fesvr/elfloader.cc b/fesvr/elfloader.cc
index 3042f54..6e764ef 100644
--- a/fesvr/elfloader.cc
+++ b/fesvr/elfloader.cc
@@ -2,6 +2,7 @@
#include "elf.h"
#include "memif.h"
+#include "byteorder.h"
#include <cstring>
#include <string>
#include <sys/stat.h>
@@ -30,58 +31,65 @@ std::map<std::string, uint64_t> load_elf(const char* fn, memif_t* memif, reg_t*
assert(size >= sizeof(Elf64_Ehdr));
const Elf64_Ehdr* eh64 = (const Elf64_Ehdr*)buf;
assert(IS_ELF32(*eh64) || IS_ELF64(*eh64));
+ assert(IS_ELFLE(*eh64) || IS_ELFBE(*eh64));
std::vector<uint8_t> zeros;
std::map<std::string, uint64_t> symbols;
- #define LOAD_ELF(ehdr_t, phdr_t, shdr_t, sym_t) do { \
+ #define LOAD_ELF(ehdr_t, phdr_t, shdr_t, sym_t, bswap) do { \
ehdr_t* eh = (ehdr_t*)buf; \
- phdr_t* ph = (phdr_t*)(buf + eh->e_phoff); \
- *entry = eh->e_entry; \
- assert(size >= eh->e_phoff + eh->e_phnum*sizeof(*ph)); \
- for (unsigned i = 0; i < eh->e_phnum; i++) { \
- if(ph[i].p_type == PT_LOAD && ph[i].p_memsz) { \
- if (ph[i].p_filesz) { \
- assert(size >= ph[i].p_offset + ph[i].p_filesz); \
- memif->write(ph[i].p_paddr, ph[i].p_filesz, (uint8_t*)buf + ph[i].p_offset); \
+ phdr_t* ph = (phdr_t*)(buf + bswap(eh->e_phoff)); \
+ *entry = bswap(eh->e_entry); \
+ assert(size >= bswap(eh->e_phoff) + bswap(eh->e_phnum)*sizeof(*ph)); \
+ for (unsigned i = 0; i < bswap(eh->e_phnum); i++) { \
+ if(bswap(ph[i].p_type) == PT_LOAD && bswap(ph[i].p_memsz)) { \
+ if (bswap(ph[i].p_filesz)) { \
+ assert(size >= bswap(ph[i].p_offset) + bswap(ph[i].p_filesz)); \
+ memif->write(bswap(ph[i].p_paddr), bswap(ph[i].p_filesz), (uint8_t*)buf + bswap(ph[i].p_offset)); \
} \
- zeros.resize(ph[i].p_memsz - ph[i].p_filesz); \
- memif->write(ph[i].p_paddr + ph[i].p_filesz, ph[i].p_memsz - ph[i].p_filesz, &zeros[0]); \
+ zeros.resize(bswap(ph[i].p_memsz) - bswap(ph[i].p_filesz)); \
+ memif->write(bswap(ph[i].p_paddr) + bswap(ph[i].p_filesz), bswap(ph[i].p_memsz) - bswap(ph[i].p_filesz), &zeros[0]); \
} \
} \
- shdr_t* sh = (shdr_t*)(buf + eh->e_shoff); \
- assert(size >= eh->e_shoff + eh->e_shnum*sizeof(*sh)); \
- assert(eh->e_shstrndx < eh->e_shnum); \
- assert(size >= sh[eh->e_shstrndx].sh_offset + sh[eh->e_shstrndx].sh_size); \
- char *shstrtab = buf + sh[eh->e_shstrndx].sh_offset; \
+ shdr_t* sh = (shdr_t*)(buf + bswap(eh->e_shoff)); \
+ assert(size >= bswap(eh->e_shoff) + bswap(eh->e_shnum)*sizeof(*sh)); \
+ assert(bswap(eh->e_shstrndx) < bswap(eh->e_shnum)); \
+ assert(size >= bswap(sh[bswap(eh->e_shstrndx)].sh_offset) + bswap(sh[bswap(eh->e_shstrndx)].sh_size)); \
+ char *shstrtab = buf + bswap(sh[bswap(eh->e_shstrndx)].sh_offset); \
unsigned strtabidx = 0, symtabidx = 0; \
- for (unsigned i = 0; i < eh->e_shnum; i++) { \
- unsigned max_len = sh[eh->e_shstrndx].sh_size - sh[i].sh_name; \
- assert(sh[i].sh_name < sh[eh->e_shstrndx].sh_size); \
- assert(strnlen(shstrtab + sh[i].sh_name, max_len) < max_len); \
- if (sh[i].sh_type & SHT_NOBITS) continue; \
- assert(size >= sh[i].sh_offset + sh[i].sh_size); \
- if (strcmp(shstrtab + sh[i].sh_name, ".strtab") == 0) \
+ for (unsigned i = 0; i < bswap(eh->e_shnum); i++) { \
+ unsigned max_len = bswap(sh[bswap(eh->e_shstrndx)].sh_size) - bswap(sh[i].sh_name); \
+ assert(bswap(sh[i].sh_name) < bswap(sh[bswap(eh->e_shstrndx)].sh_size)); \
+ assert(strnlen(shstrtab + bswap(sh[i].sh_name), max_len) < max_len); \
+ if (bswap(sh[i].sh_type) & SHT_NOBITS) continue; \
+ assert(size >= bswap(sh[i].sh_offset) + bswap(sh[i].sh_size)); \
+ if (strcmp(shstrtab + bswap(sh[i].sh_name), ".strtab") == 0) \
strtabidx = i; \
- if (strcmp(shstrtab + sh[i].sh_name, ".symtab") == 0) \
+ if (strcmp(shstrtab + bswap(sh[i].sh_name), ".symtab") == 0) \
symtabidx = i; \
} \
if (strtabidx && symtabidx) { \
- char* strtab = buf + sh[strtabidx].sh_offset; \
- sym_t* sym = (sym_t*)(buf + sh[symtabidx].sh_offset); \
- for (unsigned i = 0; i < sh[symtabidx].sh_size/sizeof(sym_t); i++) { \
- unsigned max_len = sh[strtabidx].sh_size - sym[i].st_name; \
- assert(sym[i].st_name < sh[strtabidx].sh_size); \
- assert(strnlen(strtab + sym[i].st_name, max_len) < max_len); \
- symbols[strtab + sym[i].st_name] = sym[i].st_value; \
+ char* strtab = buf + bswap(sh[strtabidx].sh_offset); \
+ sym_t* sym = (sym_t*)(buf + bswap(sh[symtabidx].sh_offset)); \
+ for (unsigned i = 0; i < bswap(sh[symtabidx].sh_size)/sizeof(sym_t); i++) { \
+ unsigned max_len = bswap(sh[strtabidx].sh_size) - bswap(sym[i].st_name); \
+ assert(bswap(sym[i].st_name) < bswap(sh[strtabidx].sh_size)); \
+ assert(strnlen(strtab + bswap(sym[i].st_name), max_len) < max_len); \
+ symbols[strtab + bswap(sym[i].st_name)] = bswap(sym[i].st_value); \
} \
} \
} while(0)
if (IS_ELF32(*eh64))
- LOAD_ELF(Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Sym);
+ if (IS_ELFLE(*eh64))
+ LOAD_ELF(Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Sym, from_le);
+ else
+ LOAD_ELF(Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Sym, from_be);
else
- LOAD_ELF(Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Sym);
+ if (IS_ELFLE(*eh64))
+ LOAD_ELF(Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Sym, from_le);
+ else
+ LOAD_ELF(Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Sym, from_be);
munmap(buf, size);
diff --git a/fesvr/htif.cc b/fesvr/htif.cc
index d9ff341..d9e884f 100644
--- a/fesvr/htif.cc
+++ b/fesvr/htif.cc
@@ -4,6 +4,7 @@
#include "rfb.h"
#include "elfloader.h"
#include "encoding.h"
+#include "byteorder.h"
#include <algorithm>
#include <assert.h>
#include <vector>
@@ -183,7 +184,7 @@ int htif_t::run()
while (!signal_exit && exitcode == 0)
{
- if (auto tohost = mem.read_uint64(tohost_addr)) {
+ if (auto tohost = from_le(mem.read_uint64(tohost_addr))) {
mem.write_uint64(tohost_addr, 0);
command_t cmd(mem, tohost, fromhost_callback);
device_list.handle_command(cmd);
@@ -194,7 +195,7 @@ int htif_t::run()
device_list.tick();
if (!fromhost_queue.empty() && mem.read_uint64(fromhost_addr) == 0) {
- mem.write_uint64(fromhost_addr, fromhost_queue.front());
+ mem.write_uint64(fromhost_addr, to_le(fromhost_queue.front()));
fromhost_queue.pop();
}
}
diff --git a/fesvr/syscall.cc b/fesvr/syscall.cc
index 6e8baf6..f0bdd25 100644
--- a/fesvr/syscall.cc
+++ b/fesvr/syscall.cc
@@ -2,6 +2,7 @@
#include "syscall.h"
#include "htif.h"
+#include "byteorder.h"
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
@@ -299,21 +300,21 @@ reg_t syscall_t::sys_getmainvars(reg_t pbuf, reg_t limit, reg_t a2, reg_t a3, re
{
std::vector<std::string> args = htif->target_args();
std::vector<uint64_t> words(args.size() + 3);
- words[0] = args.size();
+ words[0] = to_le(args.size());
words[args.size()+1] = 0; // argv[argc] = NULL
words[args.size()+2] = 0; // envp[0] = NULL
size_t sz = (args.size() + 3) * sizeof(words[0]);
for (size_t i = 0; i < args.size(); i++)
{
- words[i+1] = sz + pbuf;
+ words[i+1] = to_le(sz + pbuf);
sz += args[i].length() + 1;
}
std::vector<char> bytes(sz);
memcpy(&bytes[0], &words[0], sizeof(words[0]) * words.size());
for (size_t i = 0; i < args.size(); i++)
- strcpy(&bytes[words[i+1] - pbuf], args[i].c_str());
+ strcpy(&bytes[from_le(words[i+1]) - pbuf], args[i].c_str());
if (bytes.size() > limit)
return -ENOMEM;
@@ -342,11 +343,11 @@ void syscall_t::dispatch(reg_t mm)
reg_t magicmem[8];
memif->read(mm, sizeof(magicmem), magicmem);
- reg_t n = magicmem[0];
+ reg_t n = from_le(magicmem[0]);
if (n >= table.size() || !table[n])
throw std::runtime_error("bad syscall #" + std::to_string(n));
- magicmem[0] = (this->*table[n])(magicmem[1], magicmem[2], magicmem[3], magicmem[4], magicmem[5], magicmem[6], magicmem[7]);
+ magicmem[0] = to_le((this->*table[n])(from_le(magicmem[1]), from_le(magicmem[2]), from_le(magicmem[3]), from_le(magicmem[4]), from_le(magicmem[5]), from_le(magicmem[6]), from_le(magicmem[7])));
memif->write(mm, sizeof(magicmem), magicmem);
}