Beispiel #1
0
void
Loader::initialise(ppcsize_t maxCodeSize)
{
   // Get the MEM2 Region
   be_val<uint32_t> mem2start, mem2size;
   OSGetMemBound(OSMemoryType::MEM2, &mem2start, &mem2size);

   // Allocate MEM2 Region
   gMemory.alloc(mem2start, mem2size);

   // Steal some space for code heap
   mCodeHeap = new TeenyHeap(gMemory.translate(mem2start), maxCodeSize);

   // Update MEM2 to ignore the code heap region
   OSSetMemBound(OSMemoryType::MEM2, mem2start + maxCodeSize, mem2size - maxCodeSize);
}
Beispiel #2
0
bool
Loader::loadRPL(UserModule &module, const char *buffer, size_t size)
{
   auto in = BigEndianView { buffer, size };
   auto header = elf::Header { };
   auto info = elf::FileInfo { };
   auto sections = std::vector<elf::Section> { };

   // Read header
   if (!elf::readHeader(in, header)) {
      gLog->error("Failed elf::readHeader");
      return false;
   }

   // Check it is a CAFE abi rpl
   if (header.abi != elf::EABI_CAFE) {
      gLog->error("Unexpected elf abi found {:02x} expected {:02x}", header.abi, elf::EABI_CAFE);
      return false;
   }

   // Read sections
   if (!elf::readSections(in, header, sections)) {
      gLog->error("Failed elf::readSections");
      return false;
   }

   // Process sections, find our data and code sections
   processSections(module, sections, sections[header.shstrndx].data.data());

   // Update EntryInfo
   loadFileInfo(info, sections);
   module.entryPoint = header.entry;
   module.defaultStackSize = info.stackSize;

   // Allocate code & data sections in memory
   auto codeStart = module.codeAddressRange.first;
   auto codeSize = module.maxCodeSize;
   gMemory.alloc(codeStart, codeSize); // TODO: Append code to end of other loaded code sections

   auto dataStart = alignUp(codeStart + codeSize, 4096);
   auto dataSize = alignUp(module.dataAddressRange.second - module.dataAddressRange.first, 4096);
   auto dataEnd = dataStart + dataSize;
   gMemory.alloc(dataStart, dataSize); // TODO: Use OSDynLoad_MemAlloc for data section allocation

   // Update MEM2 memory bounds
   be_val<uint32_t> mem2start, mem2size;
   OSGetMemBound(OSMemoryType::MEM2, &mem2start, &mem2size);
   OSSetMemBound(OSMemoryType::MEM2, dataEnd, mem2size - (dataEnd - mem2start));

   // Relocate sections
   relocateSections(sections, module.codeAddressRange.first, codeStart, module.dataAddressRange.first, dataStart);

   module.codeAddressRange.first = codeStart;
   module.codeAddressRange.second = codeStart + codeSize;

   module.dataAddressRange.first = dataStart;
   module.dataAddressRange.second = dataStart + dataSize;

   // Relocate entry point
   for (auto i = 0u; i < sections.size(); ++i) {
      auto &section = sections[i];

      if (section.header.addr <= header.entry && section.header.addr + section.data.size() > header.entry) {
         auto offset = section.section->address - section.header.addr;
         module.entryPoint = header.entry + offset;
         break;
      }
   }

   // Load sections into memory
   loadSections(sections);

   // Process small data sections
   processSmallDataSections(module);

   // Process symbols
   // TODO: Support more than one symbol section?
   for (auto i = 0u; i < sections.size(); ++i) {
      auto &section = sections[i];

      if (section.header.type != elf::SHT_SYMTAB) {
         continue;
      }

      processSymbols(module, section, sections);
   }

   // Process relocations
   for (auto i = 0u; i < sections.size(); ++i) {
      auto &section = sections[i];

      if (section.header.type != elf::SHT_RELA) {
         continue;
      }

      processRelocations(module, section, sections);
   }
   
   if (0) {
      // Print address ranges
      gLog->debug("Loaded module!");
      gLog->debug("Code {:08x} -> {:08x}", module.codeAddressRange.first, module.codeAddressRange.second);
      gLog->debug("Data {:08x} -> {:08x}", module.dataAddressRange.first, module.dataAddressRange.second);

      // Print all sections
      gLog->debug("Sections:");

      for (auto i = 0u; i < module.sections.size(); ++i) {
         auto section = module.sections[i];
         gLog->debug("{:08x} {} {:x}", section->address, section->name, section->size);
      }
      
      // Print all symbols
      gLog->debug("Symbols:");

      for (auto i = 0u; i < module.symbols.size(); ++i) {
         auto symbol = module.symbols[i];

         if (symbol && symbol->name.size()) {
            gLog->debug("{:08x} {}", symbol->address, symbol->name);
         }
      }
   }

   return true;
}