{
Process::initState();
- argsInit<uint32_t>(PageBytes);
+ if (objFile->getArch() == ::Loader::Power)
+ argsInit<uint32_t>(PageBytes);
+ else
+ argsInit<uint64_t>(PageBytes);
+
+ // Fix up entry point and symbol table for 64-bit ELF ABI v1
+ if (objFile->getOpSys() != ::Loader::LinuxPower64ABIv1)
+ return;
+
+ // Fix entry point address and the base TOC pointer by looking the
+ // the function descriptor in the .opd section
+ Addr entryPoint, tocBase;
+ ByteOrder byteOrder = objFile->getByteOrder();
+ ThreadContext *tc = system->threads[contextIds[0]];
+
+ // The first doubleword of the descriptor contains the address of the
+ // entry point of the function
+ initVirtMem->readBlob(getStartPC(), &entryPoint, sizeof(Addr));
+
+ // Update the PC state
+ auto pc = tc->pcState();
+ pc.byteOrder(byteOrder);
+ pc.set(gtoh(entryPoint, byteOrder));
+ tc->pcState(pc);
+
+ // The second doubleword of the descriptor contains the TOC base
+ // address for the function
+ initVirtMem->readBlob(getStartPC() + 8, &tocBase, sizeof(Addr));
+ tc->setIntReg(TOCPointerReg, gtoh(tocBase, byteOrder));
+
+ // Fix symbol table entries as they would otherwise point to the
+ // function descriptor rather than the actual entry point address
+ auto *symbolTable = new ::Loader::SymbolTable;
+
+ for (auto sym : ::Loader::debugSymbolTable) {
+ Addr entry;
+ ::Loader::Symbol symbol = sym;
+
+ // Try to read entry point from function descriptor
+ if (initVirtMem->tryReadBlob(sym.address, &entry, sizeof(Addr)))
+ symbol.address = gtoh(entry, byteOrder);
+
+ symbolTable->insert(symbol);
+ }
+
+ // Replace the current debug symbol table
+ ::Loader::debugSymbolTable.clear();
+ ::Loader::debugSymbolTable.insert(*symbolTable);
+ delete symbolTable;
}
template <typename IntType>
{
int intSize = sizeof(IntType);
ByteOrder byteOrder = objFile->getByteOrder();
+ bool is64bit = (objFile->getArch() == ::Loader::Power64);
+ bool isLittleEndian = (byteOrder == ByteOrder::little);
std::vector<AuxVector<IntType>> auxv;
std::string filename;
//Auxilliary vectors are loaded only for elf formatted executables.
auto *elfObject = dynamic_cast<::Loader::ElfObject *>(objFile);
if (elfObject) {
- IntType features = 0;
+ IntType features = PPC_FEATURE_32;
+
+ // Check if running in 64-bit mode
+ if (is64bit)
+ features |= PPC_FEATURE_64;
+
+ // Check if running in little endian mode
+ if (isLittleEndian)
+ features |= PPC_FEATURE_PPC_LE | PPC_FEATURE_TRUE_LE;
//Bits which describe the system hardware capabilities
//XXX Figure out what these should be
auxv.emplace_back(M5_AT_HWCAP, features);
//The system page size
- auxv.emplace_back(M5_AT_PAGESZ, PowerISA::PageBytes);
+ auxv.emplace_back(M5_AT_PAGESZ, pageSize);
//Frequency at which times() increments
auxv.emplace_back(M5_AT_CLKTCK, 0x64);
// For statically linked executables, this is the virtual address of
//Set the machine status for a typical userspace
Msr msr = 0;
- msr.sf = (intSize == 8);
+ msr.sf = is64bit;
msr.hv = 1;
msr.ee = 1;
msr.pr = 1;
msr.ir = 1;
msr.dr = 1;
msr.ri = 1;
- msr.le = (byteOrder == ByteOrder::little);
+ msr.le = isLittleEndian;
tc->setMiscReg(MISCREG_MSR, msr);
- tc->pcState(getStartPC());
+ auto pc = tc->pcState();
+ pc.set(getStartPC());
+ pc.byteOrder(byteOrder);
+ tc->pcState(pc);
//Align the "stack_min" to a page boundary.
memState->setStackMin(roundDown(stack_min, pageSize));
arch = (eclass == ELFCLASS64) ? Riscv64 : Riscv32;
} else if (emach == EM_PPC && eclass == ELFCLASS32) {
arch = Power;
- if (edata != ELFDATA2MSB) {
- fatal("The binary you're trying to load is compiled for "
- "little endian Power.\ngem5 only supports big "
- "endian Power. Please recompile your binary.\n");
- }
- } else if (emach == EM_PPC64) {
- fatal("The binary you're trying to load is compiled for 64-bit "
- "Power. M5\n only supports 32-bit Power. Please "
- "recompile your binary.\n");
+ } else if (emach == EM_PPC64 && eclass == ELFCLASS64) {
+ arch = Power64;
} else {
warn("Unknown architecture: %d\n", emach);
}
void
ElfObject::determineOpSys()
{
+ // For 64-bit Power, EI_OSABI and EI_ABIVERSION cannot be used to
+ // determine the ABI version used by the ELF object
+ if (ehdr.e_machine == EM_PPC64) {
+ switch (ehdr.e_flags & 0x3) {
+ case 0x1: opSys = LinuxPower64ABIv1; return;
+ case 0x2: opSys = LinuxPower64ABIv2; return;
+ default:
+ if (ehdr.e_ident[EI_DATA] == ELFDATA2MSB)
+ opSys = LinuxPower64ABIv1;
+ if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
+ opSys = LinuxPower64ABIv2;
+ return;
+ }
+ }
+
// Detect the operating system
switch (ehdr.e_ident[EI_OSABI]) {
case ELFOSABI_LINUX: