diff -r 87c240f9882a -r f2ce908634ee src/base/SConscript --- a/src/base/SConscript Fri Feb 11 18:34:42 2011 -0600 +++ b/src/base/SConscript Fri Feb 11 18:35:48 2011 -0600 @@ -57,6 +57,7 @@ if env['TARGET_ISA'] != 'no': Source('remote_gdb.cc') Source('socket.cc') +Source('sparse_mem.cc') Source('statistics.cc') Source('str.cc') Source('time.cc') diff -r 87c240f9882a -r f2ce908634ee src/base/loader/elf_object.hh --- a/src/base/loader/elf_object.hh Fri Feb 11 18:34:42 2011 -0600 +++ b/src/base/loader/elf_object.hh Fri Feb 11 18:35:48 2011 -0600 @@ -66,6 +66,8 @@ bool loadSections(Port *memPort, Addr addrMask = std::numeric_limits::max()); + bool loadSections(SparseMem *mem, + Addr addrMask = std::numeric_limits::max()); virtual bool loadGlobalSymbols(SymbolTable *symtab, Addr addrMask = std::numeric_limits::max()); virtual bool loadLocalSymbols(SymbolTable *symtab, Addr addrMask = diff -r 87c240f9882a -r f2ce908634ee src/base/loader/elf_object.cc --- a/src/base/loader/elf_object.cc Fri Feb 11 18:34:42 2011 -0600 +++ b/src/base/loader/elf_object.cc Fri Feb 11 18:35:48 2011 -0600 @@ -421,6 +421,22 @@ return true; } +bool +ElfObject::loadSections(SparseMem *mem, Addr addrMask) +{ + if (!ObjectFile::loadSections(mem, addrMask)) + return false; + + vector::iterator extraIt; + for (extraIt = extraSegments.begin(); + extraIt != extraSegments.end(); extraIt++) { + if (!loadSection(&(*extraIt), mem, addrMask)) { + return false; + } + } + return true; +} + void ElfObject::getSections() { diff -r 87c240f9882a -r f2ce908634ee src/base/loader/object_file.hh --- a/src/base/loader/object_file.hh Fri Feb 11 18:34:42 2011 -0600 +++ b/src/base/loader/object_file.hh Fri Feb 11 18:35:48 2011 -0600 @@ -38,6 +38,7 @@ #include "base/types.hh" class Port; +class SparseMem; class SymbolTable; class ObjectFile @@ -85,6 +86,8 @@ virtual bool loadSections(Port *memPort, Addr addrMask = std::numeric_limits::max()); + virtual bool loadSections(SparseMem *mem, Addr addrMask = + std::numeric_limits::max()); virtual bool loadGlobalSymbols(SymbolTable *symtab, Addr addrMask = std::numeric_limits::max()) = 0; virtual bool loadLocalSymbols(SymbolTable *symtab, Addr addrMask = @@ -112,6 +115,7 @@ Section bss; bool loadSection(Section *sec, Port *memPort, Addr addrMask); + bool loadSection(Section *sec, SparseMem *mem, Addr addrMask); void setGlobalPointer(Addr global_ptr) { globalPtr = global_ptr; } public: diff -r 87c240f9882a -r f2ce908634ee src/base/loader/object_file.cc --- a/src/base/loader/object_file.cc Fri Feb 11 18:34:42 2011 -0600 +++ b/src/base/loader/object_file.cc Fri Feb 11 18:35:48 2011 -0600 @@ -47,8 +47,11 @@ #include "base/loader/elf_object.hh" #include "base/loader/raw_object.hh" +#include "base/sparse_mem.hh" + #include "mem/translating_port.hh" + using namespace std; ObjectFile::ObjectFile(const string &_filename, int _fd, @@ -82,6 +85,18 @@ return true; } +bool +ObjectFile::loadSection(Section *sec, SparseMem *mem, Addr addrMask) +{ + if (sec->size != 0) { + Addr addr = sec->baseAddr & addrMask; + if (sec->fileImage) { + mem->write(addr, sec->size, sec->fileImage); + } + // ignore bss section + } + return true; +} bool ObjectFile::loadSections(Port *memPort, Addr addrMask) @@ -91,6 +106,13 @@ && loadSection(&bss, memPort, addrMask)); } +bool +ObjectFile::loadSections(SparseMem *mem, Addr addrMask) +{ + return (loadSection(&text, mem, addrMask) + && loadSection(&data, mem, addrMask) + && loadSection(&bss, mem, addrMask)); +} void ObjectFile::close() diff -r 87c240f9882a -r f2ce908634ee src/base/sparse_mem.hh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/base/sparse_mem.hh Fri Feb 11 18:35:48 2011 -0600 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2010-2011 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * 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: Geza Lore + */ + +/** @file + * Declaration of a sparse memory array + */ + +#ifndef __SPARSE_MEM_HH__ +#define __SPARSE_MEM_HH__ + +#include +#include + +/** + * A byte addressable sparse memory array. Storage is automatically allocated + * if a previously unaccessed range is accessed by either a read or a + * write operation. The address width is 64 bits. + */ +class SparseMem { + + private: + /** The itnernal associative container used to implement sparse storage */ + std::map< uint64_t, uint8_t* > memoryBlocks; + + uint8_t blockSize; + uint64_t offsetMask; + uint64_t indexMask; + + uint64_t getIndex(uint64_t address); + uint64_t getOffset(uint64_t address); + + uint8_t* getBlock(uint64_t address); + + public: + /** Constructor. + * @param _blockSize Memory is allocated in 2^_blockSize byte chunks. + */ + SparseMem(uint8_t _blockSize); + + virtual ~SparseMem(); + + /** Read from memory. A new byte (uint8_t) array is allocated and the + * appropriate address range is copied from the memory. The caller + * must delete[] the returned pointer if no longer needed. + * @param address Start address of read. + * @param numBytes Number of bytes to read. + * @return Pointer to the newly allocated data array. + */ + uint8_t* read(uint64_t address, uint64_t numBytes); + + /** Write to memory. The provided byte array is copied to the memory + * at the specified address. The data array is not deleted by this call. + * @param address Start address of write. + * @param numBytes Number of bytes to write. + * @param data Pointer to write data array. + */ + void write(uint64_t address, uint64_t numBytes, const uint8_t *data); + +}; + +#endif // __SPARSE_MEM_HH__ + diff -r 87c240f9882a -r f2ce908634ee src/base/sparse_mem.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/base/sparse_mem.cc Fri Feb 11 18:35:48 2011 -0600 @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2010-2011 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * 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: Geza Lore + */ + +/** @file + * Implementation of sparse memory array + */ + +#include "sparse_mem.hh" + +#include +#include + +using namespace std; + +SparseMem::SparseMem(uint8_t _blockSize) + : blockSize(_blockSize), + offsetMask((1<::iterator it; + for (it = memoryBlocks.begin(); it != memoryBlocks.end(); ++it) { + delete[] it->second; + } +} + +// Returns the block index (low order bits set to 0) of the address. +uint64_t +SparseMem::getIndex(uint64_t address) +{ + return address & indexMask; +} + +// Returns the block offset (high order bits set to 0) of the address. +uint64_t +SparseMem::getOffset(uint64_t address) +{ + return address & offsetMask; +} + +uint8_t* +SparseMem::read(uint64_t address, uint64_t numBytes) +{ + assert(numBytes > 0); // minimum 1 byte + uint64_t topAddress = address+numBytes-1; + assert(topAddress >= address); // overflow + uint8_t *data = new uint8_t[numBytes]; // allocate storage + + uint64_t blockEnd = getIndex(address)+offsetMask; + uint64_t blockOffset = getOffset(address); + uint64_t numCopiedBytes = 0; + + uint8_t *block = getBlock(address); + + if (topAddress <= blockEnd) { + // Copy required number of bytes + memcpy(data, block+blockOffset, numBytes); + } else { + // Copy to end of block + memcpy(data, block+blockOffset, offsetMask-blockOffset+1 ); + numBytes -= offsetMask-blockOffset+1; + numCopiedBytes += offsetMask-blockOffset+1; + address = blockEnd+1; // begining of next block + blockEnd = address + offsetMask; // end of next block + + while (topAddress > blockEnd) { + block = getBlock(address); + // Copy untill end of block + memcpy(data+numCopiedBytes, block, offsetMask+1 ); + numBytes -= offsetMask+1; + numCopiedBytes += offsetMask+1; + address = blockEnd+1; // begining of next block + blockEnd = address + offsetMask; // end of next block + } + + if (numBytes > 0) { + block = getBlock(address); + // Copy the rest + memcpy(data+numCopiedBytes, block, numBytes ); + } + } + + return data; +} + + +void +SparseMem::write(uint64_t address, uint64_t numBytes, const uint8_t *data) +{ + assert(numBytes > 0); // minimum 1 byte + uint64_t topAddress = address+numBytes-1; + assert(topAddress >= address); // overflow + + uint64_t blockEnd = getIndex(address)+offsetMask; + uint64_t blockOffset = getOffset(address); + uint64_t numCopiedBytes = 0; + + uint8_t *block = getBlock(address); + + if (topAddress <= blockEnd) { + // Copy required number of byteso + memcpy(block+blockOffset, data, numBytes); + } else { + // Copy to end of block + memcpy(block+blockOffset, data, offsetMask-blockOffset+1 ); + numBytes -= offsetMask-blockOffset+1; + numCopiedBytes += offsetMask-blockOffset+1; + address = blockEnd+1; // begining of next block + blockEnd = address + offsetMask; // end of next block + + while (topAddress > blockEnd) { + block = getBlock(address); + // Copy untill end of block + memcpy(block, data+numCopiedBytes, offsetMask+1 ); + numBytes -= offsetMask+1; + numCopiedBytes += offsetMask+1; + address = blockEnd+1; // begining of next block + blockEnd = address + offsetMask; // end of next block + } + + if (numBytes > 0) { + block = getBlock(address); + // Copy the rest + memcpy(block, data+numCopiedBytes, numBytes ); + } + } +} + +// Returns the memory block that contains the specified address. +uint8_t* +SparseMem::getBlock(uint64_t address) +{ + address = getIndex(address); + + // if the block is not allocated then allocate + if (memoryBlocks[address] == NULL) { + memoryBlocks[address] = new uint8_t[1 << blockSize]; + } + + return memoryBlocks[address]; +} +