From: Gabe Black Date: Wed, 2 Oct 2019 04:15:06 +0000 (-0700) Subject: arch,base: Separate the idea of a memory image and object file. X-Git-Tag: v19.0.0.0~456 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=6ee86bf497ea87a585fe8e4651760e71244fa2fb;p=gem5.git arch,base: Separate the idea of a memory image and object file. A memory image can be described by an object file, but an object file is more than a memory image. Also, it makes sense to manipulate a memory image to, for instance, change how it's loaded into memory. That takes on larger implications (relocations, the entry point, symbols, etc.) when talking about the whole object file, and also modifies aspects which may not need to change. For instance if an image needs to be loaded into memory at addresses different from what's in the object file, but other things like symbols need to stay unmodified. Change-Id: Ia360405ffb2c1c48e0cc201ac0a0764357996a54 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/21466 Tested-by: kokoro Reviewed-by: Brandon Potter Maintainer: Gabe Black --- 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> auxv; ElfObject * elfObject = dynamic_cast(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(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(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> auxv; ElfObject * elfObject = dynamic_cast(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(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(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(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 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 +#include +#include +#include +#include + +#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 new_segs) + { + for (auto &seg: new_segs) + addSegment(seg); + } + + private: + std::vector _segments; + bool writeSegment(const Segment &seg, const PortProxy &proxy) const; + + public: + const std::vector & + 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 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 #include +#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::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> 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) || @@ -270,6 +272,16 @@ Process::revokeThreadContext(int context_id) warn("Unable to find thread context to revoke"); } +void +Process::init() +{ + // Patch the ld_bias for dynamic executables. + updateBias(); + + if (objFile->getInterpreter()) + interpImage = objFile->getInterpreter()->buildImage(); +} + void Process::initState() { @@ -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 #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 argv; std::vector 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 fdep = (*p->fds)[tgt_fd]; - auto ffdp = std::dynamic_pointer_cast(fdep); - ObjectFile *lib = createObjectFile(ffdp->getFileName()); - - if (lib) { - lib->loadAllSymbols(debugSymbolTable, - lib->minSegmentAddr(), start); - } + if (p->interpImage.contains(tc->pcState().instAddr())) { + std::shared_ptr fdep = (*p->fds)[tgt_fd]; + auto ffdp = std::dynamic_pointer_cast(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 #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 kernelExtras;