diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/arch/alpha/process.cc | 6 | ||||
-rw-r--r-- | src/arch/alpha/system.cc | 6 | ||||
-rw-r--r-- | src/arch/arm/freebsd/system.cc | 2 | ||||
-rw-r--r-- | src/arch/arm/linux/system.cc | 2 | ||||
-rw-r--r-- | src/arch/arm/process.cc | 6 | ||||
-rw-r--r-- | src/arch/mips/process.cc | 3 | ||||
-rw-r--r-- | src/arch/power/process.cc | 3 | ||||
-rw-r--r-- | src/arch/riscv/process.cc | 6 | ||||
-rw-r--r-- | src/arch/sparc/process.hh | 6 | ||||
-rw-r--r-- | src/arch/sparc/system.cc | 12 | ||||
-rw-r--r-- | src/arch/x86/process.cc | 6 | ||||
-rw-r--r-- | src/base/loader/aout_object.cc | 23 | ||||
-rw-r--r-- | src/base/loader/dtb_object.cc | 51 | ||||
-rw-r--r-- | src/base/loader/dtb_object.hh | 2 | ||||
-rw-r--r-- | src/base/loader/ecoff_object.cc | 23 | ||||
-rw-r--r-- | src/base/loader/elf_object.cc | 133 | ||||
-rw-r--r-- | src/base/loader/elf_object.hh | 5 | ||||
-rw-r--r-- | src/base/loader/object_file.cc | 21 | ||||
-rw-r--r-- | src/base/loader/object_file.hh | 83 | ||||
-rw-r--r-- | src/base/loader/raw_object.cc | 19 | ||||
-rw-r--r-- | src/base/loader/raw_object.hh | 3 | ||||
-rw-r--r-- | src/sim/syscall_emul.hh | 9 | ||||
-rw-r--r-- | src/sim/system.cc | 17 |
23 files changed, 201 insertions, 246 deletions
diff --git a/src/arch/alpha/process.cc b/src/arch/alpha/process.cc index d0bfa79c8..59cbebc1c 100644 --- a/src/arch/alpha/process.cc +++ b/src/arch/alpha/process.cc @@ -54,12 +54,10 @@ AlphaProcess::AlphaProcess(ProcessParams *params, ObjectFile *objFile) objFile) { fatal_if(params->useArchPT, "Arch page tables not implemented."); - Addr brk_point = objFile->dataBase() + objFile->dataSize() + - objFile->bssSize(); - brk_point = roundUp(brk_point, PageBytes); + Addr brk_point = roundUp(objFile->maxSegmentAddr(), PageBytes); // Set up stack. On Alpha, stack goes below the image. - Addr stack_base = objFile->textBase() - (409600 + 4096); + Addr stack_base = objFile->minSegmentAddr() - (409600 + 4096); // Set up region for mmaps. Addr mmap_end = 0x10000; diff --git a/src/arch/alpha/system.cc b/src/arch/alpha/system.cc index 7bff6da01..31e7aa062 100644 --- a/src/arch/alpha/system.cc +++ b/src/arch/alpha/system.cc @@ -57,11 +57,13 @@ 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); @@ -109,8 +111,8 @@ AlphaSystem::initState() System::initState(); // Load program sections into memory - pal->loadSegments(physProxy, loadAddrMask); - console->loadSegments(physProxy, loadAddrMask); + pal->loadSegments(physProxy); + console->loadSegments(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 6e544a70e..764f036b4 100644 --- a/src/arch/arm/freebsd/system.cc +++ b/src/arch/arm/freebsd/system.cc @@ -132,7 +132,7 @@ FreebsdArmSystem::initState() if (ra) bootReleaseAddr = ra & ~ULL(0x7F); - dtb_file->setTextBase(params()->atags_addr + loadAddrOffset); + dtb_file->setLoadOffset(params()->atags_addr + loadAddrOffset); dtb_file->loadSegments(physProxy); delete dtb_file; diff --git a/src/arch/arm/linux/system.cc b/src/arch/arm/linux/system.cc index f03a5c6cb..a0869b46a 100644 --- a/src/arch/arm/linux/system.cc +++ b/src/arch/arm/linux/system.cc @@ -151,7 +151,7 @@ LinuxArmSystem::initState() "to DTB file: %s\n", params()->dtb_filename); } - dtb_file->setTextBase(params()->atags_addr + loadAddrOffset); + dtb_file->setLoadOffset(params()->atags_addr + loadAddrOffset); dtb_file->loadSegments(physProxy); delete dtb_file; } else { diff --git a/src/arch/arm/process.cc b/src/arch/arm/process.cc index 1a1d4a2a0..f98572690 100644 --- a/src/arch/arm/process.cc +++ b/src/arch/arm/process.cc @@ -75,8 +75,7 @@ ArmProcess32::ArmProcess32(ProcessParams *params, ObjectFile *objFile, ObjectFile::Arch _arch) : ArmProcess(params, objFile, _arch) { - Addr brk_point = roundUp(objFile->dataBase() + objFile->dataSize() + - objFile->bssSize(), PageBytes); + Addr brk_point = roundUp(objFile->maxSegmentAddr(), PageBytes); Addr stack_base = 0xbf000000L; Addr max_stack_size = 8 * 1024 * 1024; Addr next_thread_stack_base = stack_base - max_stack_size; @@ -90,8 +89,7 @@ ArmProcess64::ArmProcess64(ProcessParams *params, ObjectFile *objFile, ObjectFile::Arch _arch) : ArmProcess(params, objFile, _arch) { - Addr brk_point = roundUp(objFile->dataBase() + objFile->dataSize() + - objFile->bssSize(), PageBytes); + Addr brk_point = roundUp(objFile->maxSegmentAddr(), PageBytes); Addr stack_base = 0x7fffff0000L; Addr max_stack_size = 8 * 1024 * 1024; Addr next_thread_stack_base = stack_base - max_stack_size; diff --git a/src/arch/mips/process.cc b/src/arch/mips/process.cc index e3405fdaa..1808372d9 100644 --- a/src/arch/mips/process.cc +++ b/src/arch/mips/process.cc @@ -65,8 +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->dataBase() + objFile->dataSize() + - objFile->bssSize(); + Addr brk_point = objFile->maxSegmentAddr(); brk_point = roundUp(brk_point, PageBytes); // Set up region for mmaps. Start it 1GB above the top of the heap. diff --git a/src/arch/power/process.cc b/src/arch/power/process.cc index 467c820f2..b391773ee 100644 --- a/src/arch/power/process.cc +++ b/src/arch/power/process.cc @@ -56,8 +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->dataBase() + objFile->dataSize() + - objFile->bssSize(); + Addr brk_point = objFile->maxSegmentAddr(); brk_point = roundUp(brk_point, PageBytes); Addr stack_base = 0xbf000000L; diff --git a/src/arch/riscv/process.cc b/src/arch/riscv/process.cc index ca3f0e2b8..e15197d78 100644 --- a/src/arch/riscv/process.cc +++ b/src/arch/riscv/process.cc @@ -75,8 +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->bssBase() + objFile->bssSize(), - PageBytes); + const Addr brk_point = roundUp(objFile->maxSegmentAddr(), PageBytes); const Addr mmap_end = 0x4000000000000000L; memState = make_shared<MemState>(brk_point, stack_base, max_stack_size, next_thread_stack_base, mmap_end); @@ -88,8 +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->bssBase() + objFile->bssSize(), - PageBytes); + const Addr brk_point = roundUp(objFile->maxSegmentAddr(), PageBytes); const Addr mmap_end = 0x40000000L; memState = make_shared<MemState>(brk_point, stack_base, max_stack_size, next_thread_stack_base, mmap_end); diff --git a/src/arch/sparc/process.hh b/src/arch/sparc/process.hh index eeb267116..f8f19f290 100644 --- a/src/arch/sparc/process.hh +++ b/src/arch/sparc/process.hh @@ -78,8 +78,7 @@ class Sparc32Process : public SparcProcess Sparc32Process(ProcessParams * params, ObjectFile *objFile) : SparcProcess(params, objFile, 0) { - Addr brk_point = objFile->dataBase() + objFile->dataSize() + - objFile->bssSize(); + Addr brk_point = objFile->maxSegmentAddr(); brk_point = roundUp(brk_point, SparcISA::PageBytes); // Reserve 8M for main stack. @@ -123,8 +122,7 @@ class Sparc64Process : public SparcProcess Sparc64Process(ProcessParams * params, ObjectFile *objFile) : SparcProcess(params, objFile, 2047) { - Addr brk_point = objFile->dataBase() + objFile->dataSize() + - objFile->bssSize(); + Addr brk_point = objFile->maxSegmentAddr(); 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 5896061a6..e9615b00c 100644 --- a/src/arch/sparc/system.cc +++ b/src/arch/sparc/system.cc @@ -137,22 +137,22 @@ SparcSystem::initState() System::initState(); // Load reset binary into memory - reset->setTextBase(params()->reset_addr); + reset->setLoadOffset(params()->reset_addr); reset->loadSegments(physProxy); // Load the openboot binary - openboot->setTextBase(params()->openboot_addr); + openboot->setLoadOffset(params()->openboot_addr); openboot->loadSegments(physProxy); // Load the hypervisor binary - hypervisor->setTextBase(params()->hypervisor_addr); + hypervisor->setLoadOffset(params()->hypervisor_addr); hypervisor->loadSegments(physProxy); // Load the nvram image - nvram->setTextBase(params()->nvram_addr); + nvram->setLoadOffset(params()->nvram_addr); nvram->loadSegments(physProxy); // Load the hypervisor description image - hypervisor_desc->setTextBase(params()->hypervisor_desc_addr); + hypervisor_desc->setLoadOffset(params()->hypervisor_desc_addr); hypervisor_desc->loadSegments(physProxy); // Load the partition description image - partition_desc->setTextBase(params()->partition_desc_addr); + partition_desc->setLoadOffset(params()->partition_desc_addr); partition_desc->loadSegments(physProxy); diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc index 60f4f474b..c743685d0 100644 --- a/src/arch/x86/process.cc +++ b/src/arch/x86/process.cc @@ -136,8 +136,7 @@ X86_64Process::X86_64Process(ProcessParams *params, ObjectFile *objFile, vsyscallPage.vtimeOffset = 0x400; vsyscallPage.vgettimeofdayOffset = 0x0; - Addr brk_point = roundUp(objFile->dataBase() + objFile->dataSize() + - objFile->bssSize(), PageBytes); + Addr brk_point = roundUp(objFile->maxSegmentAddr(), PageBytes); Addr stack_base = 0x7FFFFFFFF000ULL; Addr max_stack_size = 8 * 1024 * 1024; Addr next_thread_stack_base = stack_base - max_stack_size; @@ -176,8 +175,7 @@ I386Process::I386Process(ProcessParams *params, ObjectFile *objFile, vsyscallPage.vsyscallOffset = 0x400; vsyscallPage.vsysexitOffset = 0x410; - Addr brk_point = roundUp(objFile->dataBase() + objFile->dataSize() + - objFile->bssSize(), PageBytes); + Addr brk_point = roundUp(objFile->maxSegmentAddr(), PageBytes); Addr stack_base = _gdtStart; Addr max_stack_size = 8 * 1024 * 1024; Addr next_thread_stack_base = stack_base - max_stack_size; diff --git a/src/base/loader/aout_object.cc b/src/base/loader/aout_object.cc index e3f703e1d..97651586f 100644 --- a/src/base/loader/aout_object.cc +++ b/src/base/loader/aout_object.cc @@ -61,21 +61,14 @@ AoutObject::AoutObject(const string &_filename, entry = execHdr->entry; - text.base = N_TXTADDR(*execHdr); - text.size = execHdr->tsize; - text.data = fileData + N_TXTOFF(*execHdr); - - data.base = N_DATADDR(*execHdr); - data.size = execHdr->dsize; - data.data = fileData + N_DATOFF(*execHdr); - - bss.base = N_BSSADDR(*execHdr); - bss.size = execHdr->bsize; - bss.data = NULL; - - DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n", - text.base, text.size, data.base, data.size, - bss.base, bss.size); + 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); + + for (auto &seg: segments) + DPRINTFR(Loader, "%s\n", *seg); } diff --git a/src/base/loader/dtb_object.cc b/src/base/loader/dtb_object.cc index 92e305ffa..275139a8c 100644 --- a/src/base/loader/dtb_object.cc +++ b/src/base/loader/dtb_object.cc @@ -53,20 +53,10 @@ 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) + : ObjectFile(_filename, _len, _data, _arch, _opSys), + data(new Segment{ "data", 0, fileData, len }) { - text.base = 0; - text.size = len; - text.data = fileData; - - data.base = 0; - data.size = 0; - data.data = nullptr; - - bss.base = 0; - bss.size = 0; - bss.data = nullptr; - + segments.emplace_back(data); fileDataMmapped = true; } @@ -92,10 +82,10 @@ DtbObject::addBootCmdLine(const char* _args, size_t len) const char* property_name = "bootargs"; // Make a new buffer that has extra space to add nodes/properties - int newLen = 2*this->len; - uint8_t* fdt_buf_w_space = new uint8_t[newLen]; + int newLen = 2 * this->len; + uint8_t *fdt_buf_w_space = new uint8_t[newLen]; // Copy and unpack flattened device tree into new buffer - int ret = fdt_open_into((void*)fileData, (void*)fdt_buf_w_space, (newLen)); + int ret = fdt_open_into((void *)fileData, (void *)fdt_buf_w_space, newLen); if (ret < 0) { warn("Error resizing buffer of flattened device tree, " "errno: %d\n", ret); @@ -104,14 +94,15 @@ DtbObject::addBootCmdLine(const char* _args, size_t len) } // First try finding the /chosen node in the dtb - int offset = fdt_path_offset((void*)fdt_buf_w_space, full_path_node_name); + int offset = fdt_path_offset((void *)fdt_buf_w_space, full_path_node_name); if (offset < 0) { // try adding the node by walking dtb tree to proper insertion point - offset = fdt_path_offset((void*)fdt_buf_w_space, root_path); - offset = fdt_add_subnode((void*)fdt_buf_w_space, offset, node_name); + offset = fdt_path_offset((void *)fdt_buf_w_space, root_path); + offset = fdt_add_subnode((void *)fdt_buf_w_space, offset, node_name); // if we successfully add the subnode, get the offset if (offset >= 0) - offset = fdt_path_offset((void*)fdt_buf_w_space, full_path_node_name); + offset = fdt_path_offset((void *)fdt_buf_w_space, + full_path_node_name); if (offset < 0) { warn("Error finding or adding \"chosen\" subnode to flattened " @@ -122,8 +113,8 @@ DtbObject::addBootCmdLine(const char* _args, size_t len) } // Set the bootargs property in the /chosen node - ret = fdt_setprop((void*)fdt_buf_w_space, offset, property_name, - (const void*)_args, len+1); + ret = fdt_setprop((void *)fdt_buf_w_space, offset, property_name, + (const void *)_args, len+1); if (ret < 0) { warn("Error setting \"bootargs\" property to flattened device tree, " "errno: %d\n", ret); @@ -132,7 +123,7 @@ DtbObject::addBootCmdLine(const char* _args, size_t len) } // Repack the dtb for kernel use - ret = fdt_pack((void*)fdt_buf_w_space); + ret = fdt_pack((void *)fdt_buf_w_space); if (ret < 0) { warn("Error re-packing flattened device tree structure, " "errno: %d\n", ret); @@ -140,8 +131,8 @@ DtbObject::addBootCmdLine(const char* _args, size_t len) return false; } - text.size = newLen; - text.data = fdt_buf_w_space; + data->size = newLen; + data->data = fdt_buf_w_space; // clean up old buffer and set to new fdt blob munmap(fileData, this->len); @@ -155,7 +146,7 @@ DtbObject::addBootCmdLine(const char* _args, size_t len) Addr DtbObject::findReleaseAddr() { - void *fd = (void*)fileData; + void *fd = (void *)fileData; int offset = fdt_path_offset(fd, "/cpus/cpu@0"); int len; @@ -164,9 +155,11 @@ DtbObject::findReleaseAddr() Addr rel_addr = 0; if (len > 3) - rel_addr = betoh(*static_cast<const uint32_t*>(temp)); - if (len == 8) - rel_addr = (rel_addr << 32) | betoh(*(static_cast<const uint32_t*>(temp)+1)); + rel_addr = betoh(*static_cast<const uint32_t *>(temp)); + if (len == 8) { + rel_addr = (rel_addr << 32) | + betoh(*(static_cast<const uint32_t *>(temp) + 1)); + } return rel_addr; } diff --git a/src/base/loader/dtb_object.hh b/src/base/loader/dtb_object.hh index c49b144ac..7cb842e43 100644 --- a/src/base/loader/dtb_object.hh +++ b/src/base/loader/dtb_object.hh @@ -49,6 +49,8 @@ class DtbObject : public ObjectFile */ bool fileDataMmapped; + Segment *data; + public: virtual ~DtbObject(); diff --git a/src/base/loader/ecoff_object.cc b/src/base/loader/ecoff_object.cc index 76b91dd66..56f9b35fc 100644 --- a/src/base/loader/ecoff_object.cc +++ b/src/base/loader/ecoff_object.cc @@ -73,21 +73,14 @@ EcoffObject::EcoffObject(const string &_filename, size_t _len, uint8_t *_data, entry = aoutHdr->entry; - text.base = aoutHdr->text_start; - text.size = aoutHdr->tsize; - text.data = fileData + ECOFF_TXTOFF(execHdr); - - data.base = aoutHdr->data_start; - data.size = aoutHdr->dsize; - data.data = fileData + ECOFF_DATOFF(execHdr); - - bss.base = aoutHdr->bss_start; - bss.size = aoutHdr->bsize; - bss.data = nullptr; - - DPRINTFR(Loader, "text: %#x %d\ndata: %#x %d\nbss: %#x %d\n", - text.base, text.size, data.base, data.size, - bss.base, bss.size); + 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); } bool diff --git a/src/base/loader/elf_object.cc b/src/base/loader/elf_object.cc index 327919540..4dee7d2c0 100644 --- a/src/base/loader/elf_object.cc +++ b/src/base/loader/elf_object.cc @@ -293,45 +293,8 @@ ElfObject::ElfObject(const std::string &_filename, size_t _len, entry = ehdr.e_entry; - // initialize segment sizes to 0 in case they're not present - text.size = data.size = bss.size = 0; - text.base = data.base = bss.base = 0; - int sec_idx = 1; - // The first address of some important sections. - Addr text_sec_start = 0; - Addr data_sec_start = 0; - Addr bss_sec_start = 0; - - // Get the first section - Elf_Scn *section = elf_getscn(elf, sec_idx); - - // Find the beginning of the most interesting sections. - while (section) { - GElf_Shdr shdr; - gelf_getshdr(section, &shdr); - char *sec_name = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name); - - if (sec_name) { - if (!strcmp(".text", sec_name)) { - text_sec_start = shdr.sh_addr; - } else if (!strcmp(".data", sec_name)) { - data_sec_start = shdr.sh_addr; - } else if (!strcmp(".bss", sec_name)) { - bss_sec_start = shdr.sh_addr; - } - } else { - Elf_Error errorNum = (Elf_Error)elf_errno(); - if (errorNum != ELF_E_NONE) { - const char *errorMessage = elf_errmsg(errorNum); - fatal("Error from libelf: %s.\n", errorMessage); - } - } - - section = elf_getscn(elf, ++sec_idx); - } - // Go through all the segments in the program, record them, and scrape // out information about the text, data, and bss areas needed by other // code. @@ -348,50 +311,54 @@ ElfObject::ElfObject(const std::string &_filename, size_t _len, ldMin = std::min(ldMin, phdr.p_vaddr); ldMax = std::max(ldMax, phdr.p_vaddr + phdr.p_memsz); - // Check to see if this segment contains the bss section. - if (phdr.p_paddr <= bss_sec_start && - phdr.p_paddr + phdr.p_memsz > bss_sec_start && - phdr.p_memsz - phdr.p_filesz > 0) { - bss.base = phdr.p_paddr + phdr.p_filesz; - bss.size = phdr.p_memsz - phdr.p_filesz; - bss.data = nullptr; + std::string name; + + // Get the first section + Elf_Scn *section = elf_getscn(elf, sec_idx); + + // Name segments after the sections they contain. + while (section) { + GElf_Shdr shdr; + gelf_getshdr(section, &shdr); + char *sec_name = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name); + + if (!sec_name) { + Elf_Error errorNum = (Elf_Error)elf_errno(); + if (errorNum != ELF_E_NONE) { + const char *errorMessage = elf_errmsg(errorNum); + fatal("Error from libelf: %s.\n", errorMessage); + } + } + + if (shdr.sh_addr >= ldMin && shdr.sh_addr < ldMax) { + if (name != "") + name += ","; + name += sec_name; + } + + section = elf_getscn(elf, ++sec_idx); } - // Check to see if this is the text or data segment - if (phdr.p_vaddr <= text_sec_start && - phdr.p_vaddr + phdr.p_filesz > text_sec_start) { - - // If this value is nonzero, we need to flip the relocate flag. - if (phdr.p_vaddr != 0) - relocate = false; - - text.base = phdr.p_paddr; - text.size = phdr.p_filesz; - text.data = fileData + phdr.p_offset; - } else if (phdr.p_vaddr <= data_sec_start && - phdr.p_vaddr + phdr.p_filesz > data_sec_start) { - data.base = phdr.p_paddr; - data.size = phdr.p_filesz; - data.data = fileData + phdr.p_offset; - } else { - // If it's none of the above but is loadable, - // load the filesize worth of data - Segment extra; - extra.base = phdr.p_paddr; - extra.size = phdr.p_filesz; - extra.data = fileData + phdr.p_offset; - extraSegments.push_back(extra); + 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); } } // should have found at least one loadable segment - warn_if(text.size == 0, - "Empty .text segment in '%s'. ELF file corrupted?\n", + warn_if(segments.empty(), + "No loadable segments in '%s'. ELF file corrupted?\n", filename); - DPRINTFR(Loader, "text: %#x %d\ndata: %#x %d\nbss: %#x %d\n", - text.base, text.size, data.base, data.size, - bss.base, bss.size); + for (auto &seg: segments) + DPRINTFR(Loader, "%s\n", *seg); elf_end(elf); @@ -498,20 +465,13 @@ ElfObject::loadWeakSymbols(SymbolTable *symtab, Addr base, Addr offset, } bool -ElfObject::loadSegments(const PortProxy& mem_proxy, Addr addr_mask, - Addr offset) +ElfObject::loadSegments(const PortProxy &mem_proxy) { - if (!ObjectFile::loadSegments(mem_proxy, addr_mask, offset)) + if (!ObjectFile::loadSegments(mem_proxy)) return false; - for (auto seg : extraSegments) { - if (!loadSegment(&seg, mem_proxy, addr_mask, offset)) { - return false; - } - } - if (interpreter) - interpreter->loadSegments(mem_proxy, addr_mask, offset); + interpreter->loadSegments(mem_proxy); return true; } @@ -570,9 +530,6 @@ ElfObject::updateBias(Addr bias_addr) entry += bias_addr; // Patch segments with the bias_addr. - text.base += bias_addr; - data.base += bias_addr; - bss.base += bias_addr; - for (auto &segment : extraSegments) - segment.base += bias_addr; + for (auto &segment : segments) + segment->base += bias_addr; } diff --git a/src/base/loader/elf_object.hh b/src/base/loader/elf_object.hh index 244b9fc3f..f2af4142a 100644 --- a/src/base/loader/elf_object.hh +++ b/src/base/loader/elf_object.hh @@ -86,13 +86,10 @@ class ElfObject : public ObjectFile void getSections(); bool sectionExists(std::string sec); - std::vector<Segment> extraSegments; - public: virtual ~ElfObject() {} - bool loadSegments(const PortProxy& mem_proxy, Addr addr_mask = maxAddr, - Addr offset = 0) override; + bool loadSegments(const PortProxy &mem_proxy) override; virtual bool loadAllSymbols(SymbolTable *symtab, Addr base = 0, Addr offset = 0, Addr addr_mask = maxAddr) diff --git a/src/base/loader/object_file.cc b/src/base/loader/object_file.cc index 8a6b063de..d63b2221b 100644 --- a/src/base/loader/object_file.cc +++ b/src/base/loader/object_file.cc @@ -57,10 +57,8 @@ ObjectFile::ObjectFile(const string &_filename, size_t _len, uint8_t *_data, Arch _arch, OpSys _op_sys) : filename(_filename), fileData(_data), len(_len), - arch(_arch), opSys(_op_sys), entry(0), - text{0, nullptr, 0}, data{0, nullptr, 0}, bss{0, nullptr, 0} -{ -} + arch(_arch), opSys(_op_sys), entry(0) +{} ObjectFile::~ObjectFile() @@ -73,11 +71,10 @@ ObjectFile::~ObjectFile() bool -ObjectFile::loadSegment(Segment *seg, const PortProxy& mem_proxy, - Addr addr_mask, Addr offset) +ObjectFile::loadSegment(Segment *seg, const PortProxy &mem_proxy) { if (seg->size != 0) { - Addr addr = (seg->base & addr_mask) + offset; + Addr addr = (seg->base & loadMask) + loadOffset; if (seg->data) { mem_proxy.writeBlob(addr, seg->data, seg->size); } else { @@ -90,12 +87,12 @@ ObjectFile::loadSegment(Segment *seg, const PortProxy& mem_proxy, bool -ObjectFile::loadSegments(const PortProxy& mem_proxy, Addr addr_mask, - Addr offset) +ObjectFile::loadSegments(const PortProxy &proxy) { - return (loadSegment(&text, mem_proxy, addr_mask, offset) - && loadSegment(&data, mem_proxy, addr_mask, offset) - && loadSegment(&bss, mem_proxy, addr_mask, offset)); + 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 db995f5d7..e5053ad82 100644 --- a/src/base/loader/object_file.hh +++ b/src/base/loader/object_file.hh @@ -33,7 +33,9 @@ #define __OBJECT_FILE_HH__ #include <limits> +#include <memory> #include <string> +#include <vector> #include "base/logging.hh" #include "base/types.hh" @@ -72,10 +74,14 @@ 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; @@ -86,10 +92,7 @@ class ObjectFile public: virtual ~ObjectFile(); - static const Addr maxAddr = std::numeric_limits<Addr>::max(); - - virtual bool loadSegments(const PortProxy &mem_proxy, - Addr mask=maxAddr, Addr offset=0); + virtual bool loadSegments(const PortProxy &mem_proxy); virtual bool loadAllSymbols(SymbolTable *symtab, Addr base = 0, Addr offset=0, Addr mask=maxAddr) = 0; @@ -114,41 +117,76 @@ class ObjectFile Arch getArch() const { return arch; } OpSys getOpSys() const { return opSys; } - protected: - struct Segment { + std::string name; Addr base; uint8_t *data; size_t size; }; + protected: Addr entry; - Segment text; - Segment data; - Segment bss; + std::vector<std::unique_ptr<Segment>> segments; - bool loadSegment(Segment *seg, const PortProxy &mem_proxy, Addr mask, - Addr offset=0); + 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 textBase() const { return text.base; } - Addr dataBase() const { return data.base; } - Addr bssBase() const { return bss.base; } - - size_t textSize() const { return text.size; } - size_t dataSize() const { return data.size; } - size_t bssSize() const { return bss.size; } + 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 setTextBase(Addr a) { text.base = a; } + 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 @@ -183,6 +221,13 @@ 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 9662d8613..b0ece3ba2 100644 --- a/src/base/loader/raw_object.cc +++ b/src/base/loader/raw_object.cc @@ -43,23 +43,10 @@ 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) + : ObjectFile(_filename, _len, _data, _arch, _opSys), + data(new Segment{ "data", 0, fileData, len }) { - text.base = 0; - text.size = len; - text.data = fileData; - - data.base = 0; - data.size = 0; - data.data = nullptr; - - bss.base = 0; - bss.size = 0; - bss.data = nullptr; - - DPRINTFR(Loader, "text: %#x %d\ndata: %#x %d\nbss: %#x %d\n", - text.base, text.size, data.base, data.size, - bss.base, bss.size); + segments.emplace_back(data); } bool diff --git a/src/base/loader/raw_object.hh b/src/base/loader/raw_object.hh index 6931a1321..9eb929107 100644 --- a/src/base/loader/raw_object.hh +++ b/src/base/loader/raw_object.hh @@ -38,6 +38,9 @@ class RawObject: public ObjectFile protected: RawObject(const std::string &_filename, size_t _len, uint8_t *_data, Arch _arch, OpSys _opSys); + + Segment *data; + public: virtual ~RawObject() {} diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index fb6e9a168..6c3b172c2 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -1888,19 +1888,14 @@ mmapImpl(SyscallDesc *desc, int num, ThreadContext *tc, bool is_mmap2) // this will not work since there is a single global symbol table. ObjectFile *interpreter = p->getInterpreter(); if (interpreter) { - Addr text_start = interpreter->textBase(); - Addr text_end = text_start + interpreter->textSize(); - - Addr pc = tc->pcState().pc(); - - if (pc >= text_start && pc < text_end) { + 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->textBase(), start); + lib->minSegmentAddr(), start); } } } diff --git a/src/sim/system.cc b/src/sim/system.cc index 73f93a257..bf8b45239 100644 --- a/src/sim/system.cc +++ b/src/sim/system.cc @@ -152,14 +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); // setup entry points - kernelStart = kernel->textBase(); - kernelEnd = kernel->bssBase() + kernel->bssSize(); + kernelStart = kernel->minSegmentAddr(); + kernelEnd = kernel->maxSegmentAddr(); kernelEntry = kernel->entryPoint(); // If load_addr_mask is set to 0x0, then auto-calculate @@ -168,6 +170,7 @@ System::System(Params *p) if (loadAddrMask == 0) { Addr shift_amt = findMsbSet(kernelEnd - kernelStart) + 1; loadAddrMask = ((Addr)1 << shift_amt) - 1; + kernel->setLoadMask(loadAddrMask); } // load symbols @@ -192,6 +195,8 @@ 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); } } @@ -327,11 +332,9 @@ System::initState() } } // Load program sections into memory - kernel->loadSegments(physProxy, loadAddrMask, loadAddrOffset); - for (const auto &extra_kernel : kernelExtras) { - extra_kernel->loadSegments(physProxy, loadAddrMask, - loadAddrOffset); - } + kernel->loadSegments(physProxy); + for (const auto &extra_kernel : kernelExtras) + extra_kernel->loadSegments(physProxy); DPRINTF(Loader, "Kernel start = %#x\n", kernelStart); DPRINTF(Loader, "Kernel end = %#x\n", kernelEnd); |