diff options
34 files changed, 426 insertions, 340 deletions
diff --git a/src/arch/alpha/process.cc b/src/arch/alpha/process.cc index e266b92b2..9311a6415 100644 --- a/src/arch/alpha/process.cc +++ b/src/arch/alpha/process.cc @@ -54,10 +54,10 @@ AlphaProcess::AlphaProcess(ProcessParams *params, ObjectFile *objFile) objFile) { fatal_if(params->useArchPT, "Arch page tables not implemented."); - Addr brk_point = roundUp(objFile->maxSegmentAddr(), PageBytes); + Addr brk_point = roundUp(image.maxAddr(), PageBytes); // Set up stack. On Alpha, stack goes below the image. - Addr stack_base = objFile->minSegmentAddr() - (409600 + 4096); + Addr stack_base = image.minAddr() - (409600 + 4096); // Set up region for mmaps. Addr mmap_end = 0x10000; @@ -74,13 +74,6 @@ AlphaProcess::AlphaProcess(ProcessParams *params, ObjectFile *objFile) void AlphaProcess::argsInit(int intSize, int pageSize) { - // Patch the ld_bias for dynamic executables. - updateBias(); - - objFile->loadSegments(initVirtMem); - if (objFile->getInterpreter()) - objFile->getInterpreter()->loadSegments(initVirtMem); - std::vector<AuxVector<uint64_t>> auxv; ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile); diff --git a/src/arch/alpha/system.cc b/src/arch/alpha/system.cc index 31e7aa062..a7a47036a 100644 --- a/src/arch/alpha/system.cc +++ b/src/arch/alpha/system.cc @@ -57,13 +57,11 @@ AlphaSystem::AlphaSystem(Params *p) */ // Load Console Code console = createObjectFile(params()->console); - console->setLoadMask(loadAddrMask); if (console == NULL) fatal("Could not load console file %s", params()->console); // Load pal file pal = createObjectFile(params()->pal); - pal->setLoadMask(loadAddrMask); if (pal == NULL) fatal("Could not load PALcode file %s", params()->pal); @@ -111,8 +109,8 @@ AlphaSystem::initState() System::initState(); // Load program sections into memory - pal->loadSegments(physProxy); - console->loadSegments(physProxy); + pal->buildImage().mask(loadAddrMask).write(physProxy); + console->buildImage().mask(loadAddrMask).write(physProxy); /** * Copy the osflags (kernel arguments) into the consoles diff --git a/src/arch/arm/freebsd/system.cc b/src/arch/arm/freebsd/system.cc index 764f036b4..106c8e432 100644 --- a/src/arch/arm/freebsd/system.cc +++ b/src/arch/arm/freebsd/system.cc @@ -132,8 +132,8 @@ FreebsdArmSystem::initState() if (ra) bootReleaseAddr = ra & ~ULL(0x7F); - dtb_file->setLoadOffset(params()->atags_addr + loadAddrOffset); - dtb_file->loadSegments(physProxy); + dtb_file->buildImage(). + offset(params()->atags_addr + loadAddrOffset).write(physProxy); delete dtb_file; // Kernel boot requirements to set up r0, r1 and r2 in ARMv7 diff --git a/src/arch/arm/linux/system.cc b/src/arch/arm/linux/system.cc index a0869b46a..740d2e0e6 100644 --- a/src/arch/arm/linux/system.cc +++ b/src/arch/arm/linux/system.cc @@ -151,8 +151,8 @@ LinuxArmSystem::initState() "to DTB file: %s\n", params()->dtb_filename); } - dtb_file->setLoadOffset(params()->atags_addr + loadAddrOffset); - dtb_file->loadSegments(physProxy); + dtb_file->buildImage(). + offset(params()->atags_addr + loadAddrOffset).write(physProxy); delete dtb_file; } else { // Using ATAGS diff --git a/src/arch/arm/process.cc b/src/arch/arm/process.cc index ff3b92f48..d9b714c44 100644 --- a/src/arch/arm/process.cc +++ b/src/arch/arm/process.cc @@ -75,7 +75,7 @@ ArmProcess32::ArmProcess32(ProcessParams *params, ObjectFile *objFile, ObjectFile::Arch _arch) : ArmProcess(params, objFile, _arch) { - Addr brk_point = roundUp(objFile->maxSegmentAddr(), PageBytes); + Addr brk_point = roundUp(image.maxAddr(), PageBytes); Addr stack_base = 0xbf000000L; Addr max_stack_size = 8 * 1024 * 1024; Addr next_thread_stack_base = stack_base - max_stack_size; @@ -89,7 +89,7 @@ ArmProcess64::ArmProcess64(ProcessParams *params, ObjectFile *objFile, ObjectFile::Arch _arch) : ArmProcess(params, objFile, _arch) { - Addr brk_point = roundUp(objFile->maxSegmentAddr(), PageBytes); + Addr brk_point = roundUp(image.maxAddr(), PageBytes); Addr stack_base = 0x7fffff0000L; Addr max_stack_size = 8 * 1024 * 1024; Addr next_thread_stack_base = stack_base - max_stack_size; @@ -266,14 +266,6 @@ ArmProcess::argsInit(int pageSize, IntRegIndex spIndex) //We want 16 byte alignment uint64_t align = 16; - // Patch the ld_bias for dynamic executables. - updateBias(); - - // load object file into target memory - objFile->loadSegments(initVirtMem); - if (objFile->getInterpreter()) - objFile->getInterpreter()->loadSegments(initVirtMem); - //Setup the auxilliary vectors. These will already have endian conversion. //Auxilliary vectors are loaded only for elf formatted executables. ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile); diff --git a/src/arch/arm/system.cc b/src/arch/arm/system.cc index efc347d9d..bf2881026 100644 --- a/src/arch/arm/system.cc +++ b/src/arch/arm/system.cc @@ -143,7 +143,7 @@ ArmSystem::initState() if (bootldr) { bool isGICv3System = dynamic_cast<Gicv3 *>(getGIC()) != nullptr; - bootldr->loadSegments(physProxy); + bootldr->buildImage().write(physProxy); inform("Using bootloader at address %#x\n", bootldr->entryPoint()); diff --git a/src/arch/mips/process.cc b/src/arch/mips/process.cc index 4c4b0e414..8e1e22b66 100644 --- a/src/arch/mips/process.cc +++ b/src/arch/mips/process.cc @@ -65,7 +65,7 @@ MipsProcess::MipsProcess(ProcessParams *params, ObjectFile *objFile) Addr next_thread_stack_base = stack_base - max_stack_size; // Set up break point (Top of Heap) - Addr brk_point = objFile->maxSegmentAddr(); + Addr brk_point = image.maxAddr(); brk_point = roundUp(brk_point, PageBytes); // Set up region for mmaps. Start it 1GB above the top of the heap. @@ -89,14 +89,6 @@ MipsProcess::argsInit(int pageSize) { int intSize = sizeof(IntType); - // Patch the ld_bias for dynamic executables. - updateBias(); - - // load object file into target memory - objFile->loadSegments(initVirtMem); - if (objFile->getInterpreter()) - objFile->getInterpreter()->loadSegments(initVirtMem); - std::vector<AuxVector<IntType>> auxv; ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile); diff --git a/src/arch/power/process.cc b/src/arch/power/process.cc index 89b94b21f..7b53d7038 100644 --- a/src/arch/power/process.cc +++ b/src/arch/power/process.cc @@ -56,7 +56,7 @@ PowerProcess::PowerProcess(ProcessParams *params, ObjectFile *objFile) { fatal_if(params->useArchPT, "Arch page tables not implemented."); // Set up break point (Top of Heap) - Addr brk_point = objFile->maxSegmentAddr(); + Addr brk_point = image.maxAddr(); brk_point = roundUp(brk_point, PageBytes); Addr stack_base = 0xbf000000L; @@ -95,13 +95,9 @@ PowerProcess::argsInit(int intSize, int pageSize) //We want 16 byte alignment uint64_t align = 16; - // Patch the ld_bias for dynamic executables. - updateBias(); - // load object file into target memory - objFile->loadSegments(initVirtMem); - if (objFile->getInterpreter()) - objFile->getInterpreter()->loadSegments(initVirtMem); + image.write(initVirtMem); + interpImage.write(initVirtMem); //Setup the auxilliary vectors. These will already have endian conversion. //Auxilliary vectors are loaded only for elf formatted executables. diff --git a/src/arch/riscv/bare_metal/system.cc b/src/arch/riscv/bare_metal/system.cc index 3fb07a489..44e14e5ce 100644 --- a/src/arch/riscv/bare_metal/system.cc +++ b/src/arch/riscv/bare_metal/system.cc @@ -55,7 +55,7 @@ BareMetalRiscvSystem::initState() RiscvSystem::initState(); // load program sections into memory - if (!bootloader->loadSegments(physProxy)) { + if (!bootloader->buildImage().write(physProxy)) { warn("could not load sections to memory"); } } diff --git a/src/arch/riscv/process.cc b/src/arch/riscv/process.cc index 35dde7600..617efa0ee 100644 --- a/src/arch/riscv/process.cc +++ b/src/arch/riscv/process.cc @@ -75,7 +75,7 @@ RiscvProcess64::RiscvProcess64(ProcessParams *params, ObjectFile *objFile) : const Addr stack_base = 0x7FFFFFFFFFFFFFFFL; const Addr max_stack_size = 8 * 1024 * 1024; const Addr next_thread_stack_base = stack_base - max_stack_size; - const Addr brk_point = roundUp(objFile->maxSegmentAddr(), PageBytes); + const Addr brk_point = roundUp(image.maxAddr(), PageBytes); const Addr mmap_end = 0x4000000000000000L; memState = make_shared<MemState>(brk_point, stack_base, max_stack_size, next_thread_stack_base, mmap_end); @@ -87,7 +87,7 @@ RiscvProcess32::RiscvProcess32(ProcessParams *params, ObjectFile *objFile) : const Addr stack_base = 0x7FFFFFFF; const Addr max_stack_size = 8 * 1024 * 1024; const Addr next_thread_stack_base = stack_base - max_stack_size; - const Addr brk_point = roundUp(objFile->maxSegmentAddr(), PageBytes); + const Addr brk_point = roundUp(image.maxAddr(), PageBytes); const Addr mmap_end = 0x40000000L; memState = make_shared<MemState>(brk_point, stack_base, max_stack_size, next_thread_stack_base, mmap_end); @@ -123,10 +123,6 @@ RiscvProcess::argsInit(int pageSize) const int RandomBytes = 16; const int addrSize = sizeof(IntType); - updateBias(); - objFile->loadSegments(initVirtMem); - if (objFile->getInterpreter()) - objFile->getInterpreter()->loadSegments(initVirtMem); ElfObject* elfObject = dynamic_cast<ElfObject*>(objFile); memState->setStackMin(memState->getStackBase()); diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc index 1c020c6b1..048c7e957 100644 --- a/src/arch/sparc/process.cc +++ b/src/arch/sparc/process.cc @@ -204,14 +204,6 @@ SparcProcess::argsInit(int pageSize) // maintain double word alignment of the stack pointer. uint64_t align = 16; - // Patch the ld_bias for dynamic executables. - updateBias(); - - // load object file into target memory - objFile->loadSegments(initVirtMem); - if (objFile->getInterpreter()) - objFile->getInterpreter()->loadSegments(initVirtMem); - enum hardwareCaps { M5_HWCAP_SPARC_FLUSH = 1, diff --git a/src/arch/sparc/process.hh b/src/arch/sparc/process.hh index f8f19f290..0ef34352b 100644 --- a/src/arch/sparc/process.hh +++ b/src/arch/sparc/process.hh @@ -78,7 +78,7 @@ class Sparc32Process : public SparcProcess Sparc32Process(ProcessParams * params, ObjectFile *objFile) : SparcProcess(params, objFile, 0) { - Addr brk_point = objFile->maxSegmentAddr(); + Addr brk_point = image.maxAddr(); brk_point = roundUp(brk_point, SparcISA::PageBytes); // Reserve 8M for main stack. @@ -122,7 +122,7 @@ class Sparc64Process : public SparcProcess Sparc64Process(ProcessParams * params, ObjectFile *objFile) : SparcProcess(params, objFile, 2047) { - Addr brk_point = objFile->maxSegmentAddr(); + Addr brk_point = image.maxAddr(); brk_point = roundUp(brk_point, SparcISA::PageBytes); Addr max_stack_size = 8 * 1024 * 1024; diff --git a/src/arch/sparc/system.cc b/src/arch/sparc/system.cc index e9615b00c..255cc1453 100644 --- a/src/arch/sparc/system.cc +++ b/src/arch/sparc/system.cc @@ -136,25 +136,15 @@ SparcSystem::initState() // Call the initialisation of the super class System::initState(); - // Load reset binary into memory - reset->setLoadOffset(params()->reset_addr); - reset->loadSegments(physProxy); - // Load the openboot binary - openboot->setLoadOffset(params()->openboot_addr); - openboot->loadSegments(physProxy); - // Load the hypervisor binary - hypervisor->setLoadOffset(params()->hypervisor_addr); - hypervisor->loadSegments(physProxy); - // Load the nvram image - nvram->setLoadOffset(params()->nvram_addr); - nvram->loadSegments(physProxy); - // Load the hypervisor description image - hypervisor_desc->setLoadOffset(params()->hypervisor_desc_addr); - hypervisor_desc->loadSegments(physProxy); - // Load the partition description image - partition_desc->setLoadOffset(params()->partition_desc_addr); - partition_desc->loadSegments(physProxy); - + reset->buildImage().offset(params()->reset_addr).write(physProxy); + openboot->buildImage().offset(params()->openboot_addr).write(physProxy); + hypervisor->buildImage(). + offset(params()->hypervisor_addr).write(physProxy); + nvram->buildImage().offset(params()->nvram_addr).write(physProxy); + hypervisor_desc->buildImage(). + offset(params()->hypervisor_desc_addr).write(physProxy); + partition_desc->buildImage(). + offset(params()->partition_desc_addr).write(physProxy); // @todo any fixup code over writing data in binaries on setting break // events on functions should happen here. diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc index 546474138..11b46c824 100644 --- a/src/arch/x86/process.cc +++ b/src/arch/x86/process.cc @@ -136,7 +136,7 @@ X86_64Process::X86_64Process(ProcessParams *params, ObjectFile *objFile, vsyscallPage.vtimeOffset = 0x400; vsyscallPage.vgettimeofdayOffset = 0x0; - Addr brk_point = roundUp(objFile->maxSegmentAddr(), PageBytes); + Addr brk_point = roundUp(image.maxAddr(), PageBytes); Addr stack_base = 0x7FFFFFFFF000ULL; Addr max_stack_size = 8 * 1024 * 1024; Addr next_thread_stack_base = stack_base - max_stack_size; @@ -175,7 +175,7 @@ I386Process::I386Process(ProcessParams *params, ObjectFile *objFile, vsyscallPage.vsyscallOffset = 0x400; vsyscallPage.vsysexitOffset = 0x410; - Addr brk_point = roundUp(objFile->maxSegmentAddr(), PageBytes); + Addr brk_point = roundUp(image.maxAddr(), PageBytes); Addr stack_base = _gdtStart; Addr max_stack_size = 8 * 1024 * 1024; Addr next_thread_stack_base = stack_base - max_stack_size; @@ -770,14 +770,6 @@ X86Process::argsInit(int pageSize, // We want 16 byte alignment uint64_t align = 16; - // Patch the ld_bias for dynamic executables. - updateBias(); - - // load object file into target memory - objFile->loadSegments(initVirtMem); - if (objFile->getInterpreter()) - objFile->getInterpreter()->loadSegments(initVirtMem); - enum X86CpuFeature { X86_OnboardFPU = 1 << 0, X86_VirtualModeExtensions = 1 << 1, diff --git a/src/base/SConscript b/src/base/SConscript index 0c7558d09..efa7df700 100644 --- a/src/base/SConscript +++ b/src/base/SConscript @@ -76,6 +76,7 @@ Source('loader/aout_object.cc') Source('loader/dtb_object.cc') Source('loader/ecoff_object.cc') Source('loader/elf_object.cc') +Source('loader/memory_image.cc') Source('loader/object_file.cc') Source('loader/raw_object.cc') Source('loader/symtab.cc') diff --git a/src/base/loader/aout_object.cc b/src/base/loader/aout_object.cc index 97651586f..eb633c1ce 100644 --- a/src/base/loader/aout_object.cc +++ b/src/base/loader/aout_object.cc @@ -58,17 +58,23 @@ AoutObject::AoutObject(const string &_filename, : ObjectFile(_filename, _len, _data, _arch, _opSys) { execHdr = (aout_exechdr *)fileData; - entry = execHdr->entry; +} - addSegment("text", N_TXTADDR(*execHdr), fileData + N_TXTOFF(*execHdr), - execHdr->tsize); - addSegment("data", N_DATADDR(*execHdr), fileData + N_DATOFF(*execHdr), - execHdr->dsize); - addSegment("bss", N_BSSADDR(*execHdr), nullptr, execHdr->bsize); +MemoryImage +AoutObject::buildImage() const +{ + MemoryImage image({ + { "text", N_TXTADDR(*execHdr), + fileData + N_TXTOFF(*execHdr), execHdr->tsize }, + { "data", N_DATADDR(*execHdr), + fileData + N_DATOFF(*execHdr), execHdr->dsize }, + { "bss", N_BSSADDR(*execHdr), nullptr, execHdr->bsize} + }); - for (auto &seg: segments) - DPRINTFR(Loader, "%s\n", *seg); + for (auto &seg: image.segments()) + DPRINTFR(Loader, "%s\n", seg); + return image; } diff --git a/src/base/loader/aout_object.hh b/src/base/loader/aout_object.hh index 65ed7ca0f..4f8c86fcd 100644 --- a/src/base/loader/aout_object.hh +++ b/src/base/loader/aout_object.hh @@ -48,13 +48,14 @@ class AoutObject : public ObjectFile public: virtual ~AoutObject() {} - virtual bool loadAllSymbols(SymbolTable *symtab, Addr base = 0, - Addr offset = 0, Addr addr_mask = maxAddr); - virtual bool loadGlobalSymbols(SymbolTable *symtab, Addr base = 0, - Addr offset = 0, - Addr addr_mask = maxAddr); - virtual bool loadLocalSymbols(SymbolTable *symtab, Addr base = 0, - Addr offset = 0, Addr addr_mask = maxAddr); + MemoryImage buildImage() const override; + + bool loadAllSymbols(SymbolTable *symtab, Addr base=0, + Addr offset=0, Addr addr_mask = MaxAddr) override; + bool loadGlobalSymbols(SymbolTable *symtab, Addr base=0, + Addr offset=0, Addr addr_mask=MaxAddr) override; + bool loadLocalSymbols(SymbolTable *symtab, Addr base=0, + Addr offset=0, Addr addr_mask=MaxAddr) override; static ObjectFile *tryFile(const std::string &fname, size_t len, uint8_t *data); diff --git a/src/base/loader/dtb_object.cc b/src/base/loader/dtb_object.cc index 275139a8c..f5b206a74 100644 --- a/src/base/loader/dtb_object.cc +++ b/src/base/loader/dtb_object.cc @@ -53,10 +53,8 @@ DtbObject::tryFile(const std::string &fname, size_t len, uint8_t *data) DtbObject::DtbObject(const std::string &_filename, size_t _len, uint8_t *_data, Arch _arch, OpSys _opSys) - : ObjectFile(_filename, _len, _data, _arch, _opSys), - data(new Segment{ "data", 0, fileData, len }) + : ObjectFile(_filename, _len, _data, _arch, _opSys) { - segments.emplace_back(data); fileDataMmapped = true; } @@ -131,9 +129,6 @@ DtbObject::addBootCmdLine(const char* _args, size_t len) return false; } - data->size = newLen; - data->data = fdt_buf_w_space; - // clean up old buffer and set to new fdt blob munmap(fileData, this->len); fileData = fdt_buf_w_space; @@ -164,6 +159,12 @@ DtbObject::findReleaseAddr() return rel_addr; } +MemoryImage +DtbObject::buildImage() const +{ + return {{"data", 0, fileData, len}}; +} + bool DtbObject::loadAllSymbols(SymbolTable *symtab, Addr base, Addr offset, Addr addr_mask) diff --git a/src/base/loader/dtb_object.hh b/src/base/loader/dtb_object.hh index 7cb842e43..1284025ff 100644 --- a/src/base/loader/dtb_object.hh +++ b/src/base/loader/dtb_object.hh @@ -40,50 +40,50 @@ */ class DtbObject : public ObjectFile { - protected: - DtbObject(const std::string &_filename, size_t _len, uint8_t *_data, - Arch _arch, OpSys _opSys); + protected: + DtbObject(const std::string &_filename, size_t _len, uint8_t *_data, + Arch _arch, OpSys _opSys); - /** Bool marking if this dtb file has replaced the original - * read in DTB file with a new modified buffer - */ - bool fileDataMmapped; + /** Bool marking if this dtb file has replaced the original + * read in DTB file with a new modified buffer + */ + bool fileDataMmapped; - Segment *data; + public: + virtual ~DtbObject(); - public: - virtual ~DtbObject(); + /** Adds the passed in Command Line options for the kernel + * to the proper location in the device tree. + * @param _args command line to append + * @param len length of the command line string + * @return returns true on success, false otherwise + */ + bool addBootCmdLine(const char* _args, size_t len); - /** Adds the passed in Command Line options for the kernel - * to the proper location in the device tree. - * @param _args command line to append - * @param len length of the command line string - * @return returns true on success, false otherwise - */ - bool addBootCmdLine(const char* _args, size_t len); + /** Parse the DTB file enough to find the provided release + * address and return it. + * @return release address for SMP boot + */ + Addr findReleaseAddr(); - /** Parse the DTB file enough to find the provided release - * address and return it. - * @return release address for SMP boot - */ - Addr findReleaseAddr(); + MemoryImage buildImage() const override; - bool loadAllSymbols(SymbolTable *symtab, Addr base = 0, - Addr offset = 0, Addr addrMask = maxAddr); - bool loadGlobalSymbols(SymbolTable *symtab, Addr base = 0, - Addr offset = 0, Addr addrMask = maxAddr); - bool loadLocalSymbols(SymbolTable *symtab, Addr base = 0, - Addr offset = 0, Addr addrMask = maxAddr); + bool loadAllSymbols(SymbolTable *symtab, Addr base=0, + Addr offset=0, Addr addrMask=MaxAddr) override; + bool loadGlobalSymbols(SymbolTable *symtab, Addr base=0, + Addr offset=0, Addr addrMask=MaxAddr) override; + bool loadLocalSymbols(SymbolTable *symtab, Addr base=0, + Addr offset=0, Addr addrMask=MaxAddr) override; - /** Static function that tries to load file as a - * flattened device tree blob. - * @param fname path to file - * @param len length of file - * @param data mmap'ed data buffer containing file contents - * @return ObjectFile representing closest match of file type - */ - static ObjectFile *tryFile(const std::string &fname, - size_t len, uint8_t *data); + /** Static function that tries to load file as a + * flattened device tree blob. + * @param fname path to file + * @param len length of file + * @param data mmap'ed data buffer containing file contents + * @return ObjectFile representing closest match of file type + */ + static ObjectFile *tryFile(const std::string &fname, + size_t len, uint8_t *data); }; #endif //__DTB_OBJECT_HH__ diff --git a/src/base/loader/ecoff_object.cc b/src/base/loader/ecoff_object.cc index 56f9b35fc..cecc68dc1 100644 --- a/src/base/loader/ecoff_object.cc +++ b/src/base/loader/ecoff_object.cc @@ -72,15 +72,23 @@ EcoffObject::EcoffObject(const string &_filename, size_t _len, uint8_t *_data, aoutHdr = &(execHdr->a); entry = aoutHdr->entry; +} - addSegment("text", aoutHdr->text_start, fileData + ECOFF_TXTOFF(execHdr), - aoutHdr->tsize); - addSegment("data", aoutHdr->data_start, fileData + ECOFF_DATOFF(execHdr), - aoutHdr->dsize); - addSegment("bss", aoutHdr->bss_start, nullptr, aoutHdr->bsize); - - for (auto &seg: segments) - DPRINTFR(Loader, "%s\n", *seg); +MemoryImage +EcoffObject::buildImage() const +{ + MemoryImage image({ + { "text", aoutHdr->text_start, + fileData + ECOFF_TXTOFF(execHdr), aoutHdr->tsize }, + { "data", aoutHdr->data_start, + fileData + ECOFF_DATOFF(execHdr), aoutHdr->dsize }, + { "bss", aoutHdr->bss_start, nullptr, aoutHdr->bsize } + }); + + for (auto &seg: image.segments()) + DPRINTFR(Loader, "%s\n", seg); + + return image; } bool diff --git a/src/base/loader/ecoff_object.hh b/src/base/loader/ecoff_object.hh index b1ae91107..94811158e 100644 --- a/src/base/loader/ecoff_object.hh +++ b/src/base/loader/ecoff_object.hh @@ -51,12 +51,14 @@ class EcoffObject : public ObjectFile public: virtual ~EcoffObject() {} - virtual bool loadAllSymbols(SymbolTable *symtab, Addr base = 0, - Addr offset = 0, Addr addr_mask = maxAddr); - virtual bool loadGlobalSymbols(SymbolTable *symtab, Addr base = 0, - Addr offset = 0, Addr addr_mask = maxAddr); - virtual bool loadLocalSymbols(SymbolTable *symtab, Addr base = 0, - Addr offset = 0, Addr addr_mask = maxAddr); + MemoryImage buildImage() const override; + + bool loadAllSymbols(SymbolTable *symtab, Addr base=0, + Addr offset=0, Addr addr_mask=MaxAddr) override; + bool loadGlobalSymbols(SymbolTable *symtab, Addr base=0, + Addr offset=0, Addr addr_mask=MaxAddr) override; + bool loadLocalSymbols(SymbolTable *symtab, Addr base=0, + Addr offset=0, Addr addr_mask=MaxAddr) override; static ObjectFile *tryFile(const std::string &fname, size_t len, uint8_t *data); diff --git a/src/base/loader/elf_object.cc b/src/base/loader/elf_object.cc index 4cf20975d..7a83c0bd2 100644 --- a/src/base/loader/elf_object.cc +++ b/src/base/loader/elf_object.cc @@ -339,26 +339,25 @@ ElfObject::ElfObject(const std::string &_filename, size_t _len, section = elf_getscn(elf, ++sec_idx); } - addSegment(name, phdr.p_paddr, fileData + phdr.p_offset, - phdr.p_filesz); + image.addSegment(name, phdr.p_paddr, fileData + phdr.p_offset, + phdr.p_filesz); Addr uninitialized = phdr.p_memsz - phdr.p_filesz; if (uninitialized) { // There may be parts of a segment which aren't included in the // file. In those cases, we need to create a new segment with no // data to take up the extra space. This should be zeroed when // loaded into memory. - addSegment(name + "(uninitialized)", phdr.p_paddr + phdr.p_filesz, - nullptr, uninitialized); + image.addSegment(name + "(uninitialized)", + phdr.p_paddr + phdr.p_filesz, nullptr, uninitialized); } } // should have found at least one loadable segment - warn_if(segments.empty(), - "No loadable segments in '%s'. ELF file corrupted?\n", - filename); + warn_if(image.segments().empty(), + "No loadable segments in '%s'. ELF file corrupted?\n", filename); - for (auto &seg: segments) - DPRINTFR(Loader, "%s\n", *seg); + for (auto &seg: image.segments()) + DPRINTFR(Loader, "%s\n", seg); elf_end(elf); @@ -518,6 +517,5 @@ ElfObject::updateBias(Addr bias_addr) entry += bias_addr; // Patch segments with the bias_addr. - for (auto &segment : segments) - segment->base += bias_addr; + image.offset(bias_addr); } diff --git a/src/base/loader/elf_object.hh b/src/base/loader/elf_object.hh index dbefadd19..0b8c79b47 100644 --- a/src/base/loader/elf_object.hh +++ b/src/base/loader/elf_object.hh @@ -86,34 +86,30 @@ class ElfObject : public ObjectFile void getSections(); bool sectionExists(std::string sec); + MemoryImage image; + public: virtual ~ElfObject() {} - virtual bool loadAllSymbols(SymbolTable *symtab, Addr base = 0, - Addr offset = 0, Addr addr_mask = maxAddr) - override; - - virtual bool loadGlobalSymbols(SymbolTable *symtab, Addr base = 0, - Addr offset = 0, Addr addr_mask = maxAddr) - override; - - virtual bool loadLocalSymbols(SymbolTable *symtab, Addr base = 0, - Addr offset = 0, Addr addr_mask = maxAddr) - override; + MemoryImage buildImage() const override { return image; } - virtual bool loadWeakSymbols(SymbolTable *symtab, Addr base = 0, - Addr offset = 0, Addr addr_mask = maxAddr) - override; + bool loadAllSymbols(SymbolTable *symtab, Addr base=0, + Addr offset=0, Addr addr_mask=MaxAddr) override; + bool loadGlobalSymbols(SymbolTable *symtab, Addr base=0, + Addr offset=0, Addr addr_mask=MaxAddr) override; + bool loadLocalSymbols(SymbolTable *symtab, Addr base=0, + Addr offset=0, Addr addr_mask=MaxAddr) override; + bool loadWeakSymbols(SymbolTable *symtab, Addr base=0, + Addr offset=0, Addr addr_mask=MaxAddr) override; - virtual ObjectFile *getInterpreter() const override - { return interpreter; } - virtual Addr bias() const override { return ldBias; } - virtual bool relocatable() const override { return relocate; } - virtual Addr mapSize() const override { return ldMax - ldMin; } - virtual void updateBias(Addr bias_addr) override; + ObjectFile *getInterpreter() const override { return interpreter; } + Addr bias() const override { return ldBias; } + bool relocatable() const override { return relocate; } + Addr mapSize() const override { return ldMax - ldMin; } + void updateBias(Addr bias_addr) override; - virtual bool hasTLS() override { return sectionExists(".tbss"); } + bool hasTLS() override { return sectionExists(".tbss"); } static ObjectFile *tryFile(const std::string &fname, size_t len, uint8_t *data, diff --git a/src/base/loader/memory_image.cc b/src/base/loader/memory_image.cc new file mode 100644 index 000000000..6fa70c99d --- /dev/null +++ b/src/base/loader/memory_image.cc @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2002-2004 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + * Steve Reinhardt + */ + +#include "base/loader/memory_image.hh" +#include "mem/port_proxy.hh" + +bool +MemoryImage::writeSegment(const Segment &seg, const PortProxy &proxy) const +{ + if (seg.size != 0) { + if (seg.data) { + proxy.writeBlob(seg.base, seg.data, seg.size); + } else { + // no image: must be bss + proxy.memsetBlob(seg.base, 0, seg.size); + } + } + return true; +} + +bool +MemoryImage::write(const PortProxy &proxy) const +{ + for (auto &seg: _segments) + if (!writeSegment(seg, proxy)) + return false; + return true; +} + +MemoryImage & +MemoryImage::move(std::function<Addr(Addr)> mapper) +{ + for (auto &seg: _segments) + seg.base = mapper(seg.base); + return *this; +} diff --git a/src/base/loader/memory_image.hh b/src/base/loader/memory_image.hh new file mode 100644 index 000000000..866e9560c --- /dev/null +++ b/src/base/loader/memory_image.hh @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2002-2004 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + * Steve Reinhardt + */ + +#ifndef __BASE_LOADER_MEMORY_IMAGE_HH__ +#define __BASE_LOADER_MEMORY_IMAGE_HH__ + +#include <functional> +#include <initializer_list> +#include <memory> +#include <string> +#include <vector> + +#include "base/logging.hh" +#include "base/types.hh" + +class PortProxy; +class Process; +class ProcessParams; +class SymbolTable; + +class MemoryImage +{ + public: + struct Segment + { + std::string name; + Addr base; + uint8_t *data; + size_t size; + }; + + MemoryImage() {} + + MemoryImage(std::initializer_list<Segment> new_segs) + { + for (auto &seg: new_segs) + addSegment(seg); + } + + private: + std::vector<Segment> _segments; + bool writeSegment(const Segment &seg, const PortProxy &proxy) const; + + public: + const std::vector<Segment> & + segments() const + { + return _segments; + } + + void + addSegment(const Segment &seg) + { + _segments.emplace_back(seg); + } + + void + addSegment(std::string name, Addr base, uint8_t *data, size_t size) + { + _segments.push_back(Segment({name, base, data, size})); + } + + bool write(const PortProxy &proxy) const; + MemoryImage &move(std::function<Addr(Addr)> mapper); + MemoryImage & + offset(Addr by) + { + return move([by](Addr a){ return by + a; }); + } + MemoryImage & + mask(Addr m) { + return move([m](Addr a) { return a & m; }); + } + + Addr + maxAddr() const + { + Addr max = 0; + for (auto &seg: _segments) { + Addr end = seg.base + seg.size; + if (end > max) + max = end; + } + return max; + } + + Addr + minAddr() const + { + Addr min = MaxAddr; + for (auto &seg: _segments) + if (seg.base < min) + min = seg.base; + return min; + } + + bool + contains(Addr addr) const + { + for (auto &seg: _segments) { + Addr start = seg.base; + Addr end = seg.base + seg.size; + if (addr >= start && addr < end) + return true; + } + return false; + } +}; + +static inline std::ostream & +operator << (std::ostream &os, const MemoryImage::Segment &seg) +{ + ccprintf(os, "%s: %#x %d", seg.name, seg.base, seg.size); + return os; +} + + +#endif // __BASE_LOADER_MEMORY_IMAGE_HH__ diff --git a/src/base/loader/object_file.cc b/src/base/loader/object_file.cc index d63b2221b..afecd21e3 100644 --- a/src/base/loader/object_file.cc +++ b/src/base/loader/object_file.cc @@ -70,31 +70,6 @@ ObjectFile::~ObjectFile() } -bool -ObjectFile::loadSegment(Segment *seg, const PortProxy &mem_proxy) -{ - if (seg->size != 0) { - Addr addr = (seg->base & loadMask) + loadOffset; - if (seg->data) { - mem_proxy.writeBlob(addr, seg->data, seg->size); - } else { - // no image: must be bss - mem_proxy.memsetBlob(addr, 0, seg->size); - } - } - return true; -} - - -bool -ObjectFile::loadSegments(const PortProxy &proxy) -{ - for (auto &seg: segments) - if (!loadSegment(seg.get(), proxy)) - return false; - return true; -} - namespace { diff --git a/src/base/loader/object_file.hh b/src/base/loader/object_file.hh index e5053ad82..669afeb11 100644 --- a/src/base/loader/object_file.hh +++ b/src/base/loader/object_file.hh @@ -37,6 +37,7 @@ #include <string> #include <vector> +#include "base/loader/memory_image.hh" #include "base/logging.hh" #include "base/types.hh" @@ -74,14 +75,10 @@ class ObjectFile FreeBSD }; - static const Addr maxAddr = std::numeric_limits<Addr>::max(); - protected: const std::string filename; uint8_t *fileData; size_t len; - Addr loadOffset=0; - Addr loadMask=maxAddr; Arch arch; OpSys opSys; @@ -92,16 +89,16 @@ class ObjectFile public: virtual ~ObjectFile(); - virtual bool loadSegments(const PortProxy &mem_proxy); + virtual MemoryImage buildImage() const = 0; virtual bool loadAllSymbols(SymbolTable *symtab, Addr base = 0, - Addr offset=0, Addr mask=maxAddr) = 0; + Addr offset=0, Addr mask=MaxAddr) = 0; virtual bool loadGlobalSymbols(SymbolTable *symtab, Addr base = 0, - Addr offset=0, Addr mask=maxAddr) = 0; + Addr offset=0, Addr mask=MaxAddr) = 0; virtual bool loadLocalSymbols(SymbolTable *symtab, Addr base=0, - Addr offset=0, Addr mask=maxAddr) = 0; + Addr offset=0, Addr mask=MaxAddr) = 0; virtual bool loadWeakSymbols(SymbolTable *symtab, Addr base=0, - Addr offset=0, Addr mask=maxAddr) + Addr offset=0, Addr mask=MaxAddr) { return false; } virtual ObjectFile *getInterpreter() const { return nullptr; } @@ -117,77 +114,12 @@ class ObjectFile Arch getArch() const { return arch; } OpSys getOpSys() const { return opSys; } - struct Segment - { - std::string name; - Addr base; - uint8_t *data; - size_t size; - }; - protected: Addr entry; - std::vector<std::unique_ptr<Segment>> segments; - - void - addSegment(std::string name, Addr base, uint8_t *data, size_t size) - { - Segment *seg = new Segment; - seg->name = name; - seg->base = base; - seg->data = data; - seg->size = size; - segments.emplace_back(seg); - } - - bool loadSegment(Segment *seg, const PortProxy &mem_proxy); - public: Addr entryPoint() const { return entry; } - Addr - maxSegmentAddr() const - { - Addr max = 0; - for (auto &seg: segments) { - Addr end = seg->base + seg->size; - if (end > max) - max = end; - } - return max; - } - - Addr - minSegmentAddr() const - { - Addr min = maxAddr; - for (auto &seg: segments) - if (seg->base < min) - min = seg->base; - return min; - } - - bool - contains(Addr addr) const - { - for (auto &seg: segments) { - Addr start = seg->base; - Addr end = seg->base + seg->size; - if (addr >= start && addr < end) - return true; - } - return false; - } - - /* This function allows you to override the base address where - * a binary is going to be loaded or set it if the binary is just a - * blob that doesn't include an object header. - * @param a address to load the binary/text section at - */ - void setLoadOffset(Addr val) { loadOffset = val; } - void setLoadMask(Addr val) { loadMask = val; } - /** * Each instance of a Loader subclass will have a chance to try to load * an object file when tryLoaders is called. If they can't because they @@ -221,13 +153,6 @@ class ObjectFile static Process *tryLoaders(ProcessParams *params, ObjectFile *obj_file); }; -static inline std::ostream & -operator << (std::ostream &os, const ObjectFile::Segment &seg) -{ - ccprintf(os, "%s: %#x %d", seg.name, seg.base, seg.size); - return os; -} - ObjectFile *createObjectFile(const std::string &fname, bool raw = false); diff --git a/src/base/loader/raw_object.cc b/src/base/loader/raw_object.cc index b0ece3ba2..35ed485c4 100644 --- a/src/base/loader/raw_object.cc +++ b/src/base/loader/raw_object.cc @@ -43,10 +43,14 @@ RawObject::tryFile(const std::string &fname, size_t len, uint8_t *data) RawObject::RawObject(const std::string &_filename, size_t _len, uint8_t *_data, Arch _arch, OpSys _opSys) - : ObjectFile(_filename, _len, _data, _arch, _opSys), - data(new Segment{ "data", 0, fileData, len }) + : ObjectFile(_filename, _len, _data, _arch, _opSys) { - segments.emplace_back(data); +} + +MemoryImage +RawObject::buildImage() const +{ + return {{ "data", 0, fileData, len }}; } bool diff --git a/src/base/loader/raw_object.hh b/src/base/loader/raw_object.hh index 9eb929107..6dc54c7aa 100644 --- a/src/base/loader/raw_object.hh +++ b/src/base/loader/raw_object.hh @@ -39,18 +39,17 @@ class RawObject: public ObjectFile RawObject(const std::string &_filename, size_t _len, uint8_t *_data, Arch _arch, OpSys _opSys); - Segment *data; - public: virtual ~RawObject() {} - virtual bool loadAllSymbols(SymbolTable *symtab, Addr base = 0, - Addr offset = 0, Addr addr_mask = maxAddr); - virtual bool loadGlobalSymbols(SymbolTable *symtab, Addr base = 0, - Addr offset = 0, - Addr addr_mask = maxAddr); - virtual bool loadLocalSymbols(SymbolTable *symtab, Addr base = 0, - Addr offset = 0, Addr addr_mask = maxAddr); + MemoryImage buildImage() const override; + + bool loadAllSymbols(SymbolTable *symtab, Addr base=0, + Addr offset=0, Addr addr_mask=MaxAddr) override; + bool loadGlobalSymbols(SymbolTable *symtab, Addr base=0, + Addr offset=0, Addr addr_mask=MaxAddr) override; + bool loadLocalSymbols(SymbolTable *symtab, Addr base=0, + Addr offset=0, Addr addr_mask=MaxAddr) override; static ObjectFile *tryFile(const std::string &fname, size_t len, uint8_t *data); diff --git a/src/sim/process.cc b/src/sim/process.cc index 224152a32..a01cfea91 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -129,6 +129,8 @@ Process::Process(ProcessParams *params, EmulationPageTable *pTable, exitGroup = new bool(); sigchld = new bool(); + image = objFile->buildImage(); + if (!debugSymbolTable) { debugSymbolTable = new SymbolTable(); if (!objFile->loadGlobalSymbols(debugSymbolTable) || @@ -271,6 +273,16 @@ Process::revokeThreadContext(int context_id) } void +Process::init() +{ + // Patch the ld_bias for dynamic executables. + updateBias(); + + if (objFile->getInterpreter()) + interpImage = objFile->getInterpreter()->buildImage(); +} + +void Process::initState() { if (contextIds.empty()) @@ -283,6 +295,10 @@ Process::initState() tc->activate(); pTable->initState(); + + // load object file into target memory + image.write(initVirtMem); + interpImage.write(initVirtMem); } DrainState diff --git a/src/sim/process.hh b/src/sim/process.hh index ae23de420..8e353071c 100644 --- a/src/sim/process.hh +++ b/src/sim/process.hh @@ -41,6 +41,7 @@ #include <vector> #include "arch/registers.hh" +#include "base/loader/memory_image.hh" #include "base/statistics.hh" #include "base/types.hh" #include "config/the_isa.hh" @@ -69,6 +70,7 @@ class Process : public SimObject void serialize(CheckpointOut &cp) const override; void unserialize(CheckpointIn &cp) override; + void init() override; void initState() override; DrainState drain() override; @@ -182,6 +184,8 @@ class Process : public SimObject SETranslatingPortProxy initVirtMem; // memory proxy for initial image load ObjectFile *objFile; + MemoryImage image; + MemoryImage interpImage; std::vector<std::string> argv; std::vector<std::string> envp; std::string executable; diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index 6c3b172c2..91ddb2567 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -1886,17 +1886,14 @@ mmapImpl(SyscallDesc *desc, int num, ThreadContext *tc, bool is_mmap2) // executing inside the loader by checking the program counter value. // XXX: with multiprogrammed workloads or multi-node configurations, // this will not work since there is a single global symbol table. - ObjectFile *interpreter = p->getInterpreter(); - if (interpreter) { - if (interpreter->contains(tc->pcState().instAddr())) { - std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd]; - auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep); - ObjectFile *lib = createObjectFile(ffdp->getFileName()); - - if (lib) { - lib->loadAllSymbols(debugSymbolTable, - lib->minSegmentAddr(), start); - } + if (p->interpImage.contains(tc->pcState().instAddr())) { + std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd]; + auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep); + ObjectFile *lib = createObjectFile(ffdp->getFileName()); + + if (lib) { + lib->loadAllSymbols(debugSymbolTable, + lib->buildImage().minAddr(), start); } } diff --git a/src/sim/system.cc b/src/sim/system.cc index bf8b45239..87a220311 100644 --- a/src/sim/system.cc +++ b/src/sim/system.cc @@ -152,16 +152,16 @@ System::System(Params *p) } else { // Get the kernel code kernel = createObjectFile(params()->kernel); - kernel->setLoadOffset(loadAddrOffset); - kernel->setLoadMask(loadAddrMask); inform("kernel located at: %s", params()->kernel); if (kernel == NULL) fatal("Could not load kernel file %s", params()->kernel); + kernelImage = kernel->buildImage(); + // setup entry points - kernelStart = kernel->minSegmentAddr(); - kernelEnd = kernel->maxSegmentAddr(); + kernelStart = kernelImage.minAddr(); + kernelEnd = kernelImage.maxAddr(); kernelEntry = kernel->entryPoint(); // If load_addr_mask is set to 0x0, then auto-calculate @@ -170,9 +170,12 @@ System::System(Params *p) if (loadAddrMask == 0) { Addr shift_amt = findMsbSet(kernelEnd - kernelStart) + 1; loadAddrMask = ((Addr)1 << shift_amt) - 1; - kernel->setLoadMask(loadAddrMask); } + kernelImage.move([this](Addr a) { + return (a & loadAddrMask) + loadAddrOffset; + }); + // load symbols if (!kernel->loadGlobalSymbols(kernelSymtab)) fatal("could not load kernel symbols\n"); @@ -195,8 +198,6 @@ System::System(Params *p) ObjectFile *obj = createObjectFile(obj_name); fatal_if(!obj, "Failed to additional kernel object '%s'.\n", obj_name); - obj->setLoadOffset(loadAddrOffset); - obj->setLoadMask(loadAddrMask); kernelExtras.push_back(obj); } } @@ -316,25 +317,24 @@ System::initState() /** * Load the kernel code into memory */ + auto mapper = [this](Addr a) { + return (a & loadAddrMask) + loadAddrOffset; + }; if (params()->kernel != "") { if (params()->kernel_addr_check) { // Validate kernel mapping before loading binary - if (!(isMemAddr((kernelStart & loadAddrMask) + - loadAddrOffset) && - isMemAddr((kernelEnd & loadAddrMask) + - loadAddrOffset))) { + if (!isMemAddr(mapper(kernelStart)) || + !isMemAddr(mapper(kernelEnd))) { fatal("Kernel is mapped to invalid location (not memory). " "kernelStart 0x(%x) - kernelEnd 0x(%x) %#x:%#x\n", - kernelStart, - kernelEnd, (kernelStart & loadAddrMask) + - loadAddrOffset, - (kernelEnd & loadAddrMask) + loadAddrOffset); + kernelStart, kernelEnd, + mapper(kernelStart), mapper(kernelEnd)); } } // Load program sections into memory - kernel->loadSegments(physProxy); + kernelImage.write(physProxy); for (const auto &extra_kernel : kernelExtras) - extra_kernel->loadSegments(physProxy); + extra_kernel->buildImage().move(mapper).write(physProxy); DPRINTF(Loader, "Kernel start = %#x\n", kernelStart); DPRINTF(Loader, "Kernel end = %#x\n", kernelEnd); diff --git a/src/sim/system.hh b/src/sim/system.hh index c618e3944..345d83c2a 100644 --- a/src/sim/system.hh +++ b/src/sim/system.hh @@ -53,6 +53,7 @@ #include <vector> #include "arch/isa_traits.hh" +#include "base/loader/memory_image.hh" #include "base/loader/symtab.hh" #include "base/statistics.hh" #include "config/the_isa.hh" @@ -224,6 +225,7 @@ class System : public SimObject /** Object pointer for the kernel code */ ObjectFile *kernel; + MemoryImage kernelImage; /** Additional object files */ std::vector<ObjectFile *> kernelExtras; |