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;
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);
*/
// 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);
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
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
"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
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;
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;
//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);
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());
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.
{
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);
{
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;
//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.
RiscvSystem::initState();
// load program sections into memory
- if (!bootloader->loadSegments(physProxy)) {
+ if (!bootloader->buildImage().write(physProxy)) {
warn("could not load sections to memory");
}
}
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);
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);
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());
// 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,
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.
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;
// 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.
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;
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;
// 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,
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')
: 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;
}
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);
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;
}
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;
return rel_addr;
}
+MemoryImage
+DtbObject::buildImage() const
+{
+ return {{"data", 0, fileData, len}};
+}
+
bool
DtbObject::loadAllSymbols(SymbolTable *symtab, Addr base, Addr offset,
Addr addr_mask)
*/
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__
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
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);
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);
entry += bias_addr;
// Patch segments with the bias_addr.
- for (auto &segment : segments)
- segment->base += bias_addr;
+ image.offset(bias_addr);
}
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,
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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__
}
-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
{
#include <string>
#include <vector>
+#include "base/loader/memory_image.hh"
#include "base/logging.hh"
#include "base/types.hh"
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;
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; }
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
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);
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
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);
exitGroup = new bool();
sigchld = new bool();
+ image = objFile->buildImage();
+
if (!debugSymbolTable) {
debugSymbolTable = new SymbolTable();
if (!objFile->loadGlobalSymbols(debugSymbolTable) ||
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()
{
tc->activate();
pTable->initState();
+
+ // load object file into target memory
+ image.write(initVirtMem);
+ interpImage.write(initVirtMem);
}
DrainState
#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"
void serialize(CheckpointOut &cp) const override;
void unserialize(CheckpointIn &cp) override;
+ void init() override;
void initState() override;
DrainState drain() override;
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;
// 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);
}
}
} 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
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");
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);
}
}
/**
* 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);
#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"
/** Object pointer for the kernel code */
ObjectFile *kernel;
+ MemoryImage kernelImage;
/** Additional object files */
std::vector<ObjectFile *> kernelExtras;