From: <mic...@us...> - 2007-05-21 14:20:22
|
Revision: 126 http://svn.sourceforge.net/pearcolator/?rev=126&view=rev Author: michael_baer Date: 2007-05-21 07:20:19 -0700 (Mon, 21 May 2007) Log Message: ----------- - Added interface to change memory protections after initial mapping - Implemented system call mprotect - restoring correctly protected memory map after dynamic linking Modified Paths: -------------- src/org/binarytranslator/generic/memory/AutoMappingMemory.java src/org/binarytranslator/generic/memory/ByteAddressedMemory.java src/org/binarytranslator/generic/memory/IntAddressedMemory.java src/org/binarytranslator/generic/memory/Memory.java src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java src/org/binarytranslator/generic/os/loader/elf/ELF_File.java src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java src/org/binarytranslator/generic/os/loader/elf/JavaRuntimeLinker.java Removed Paths: ------------- src/org/binarytranslator/generic/memory/DebugMemory.java Modified: src/org/binarytranslator/generic/memory/AutoMappingMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/AutoMappingMemory.java 2007-05-19 15:21:09 UTC (rev 125) +++ src/org/binarytranslator/generic/memory/AutoMappingMemory.java 2007-05-21 14:20:19 UTC (rev 126) @@ -2,7 +2,9 @@ import java.io.RandomAccessFile; +import org.binarytranslator.DBT; + /** * A memory implementation that will automatically map pages into memory, as soon * as they are requested. Therefore, this memory never fails with an exception @@ -22,6 +24,8 @@ public AutoMappingMemory(Memory memoryImplementation) { super(AutoMappingMemory.class); + if (DBT.VerifyAssertions) DBT._assert(mem != null); + this.mem = memoryImplementation; } @@ -168,4 +172,9 @@ public void unmap(int addr, int len) { mem.unmap(addr, len); } + + @Override + public void changeProtection(int address, int len, boolean newRead, boolean newWrite, boolean newExec) { + mem.changeProtection(address, len, newRead, newWrite, newExec); + } } Modified: src/org/binarytranslator/generic/memory/ByteAddressedMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/ByteAddressedMemory.java 2007-05-19 15:21:09 UTC (rev 125) +++ src/org/binarytranslator/generic/memory/ByteAddressedMemory.java 2007-05-21 14:20:19 UTC (rev 126) @@ -34,48 +34,32 @@ * </pre> */ public class ByteAddressedMemory extends CallBasedMemory { - /** - * The size of pages - */ + + /** The size of a single page in bytes. */ private static final int PAGE_SIZE = 4096; - /** - * Bits in offset - */ + /** Bits in offset */ private static final int OFFSET_BITS = 12; - /** - * The number of pages - */ + /** The number of pages */ private static final int NUM_PAGES = 0x100000; - /** - * The maximum amount of RAM available - */ - private static final long MAX_RAM = (long) PAGE_SIZE * (long) NUM_PAGES; + /** The maximum amount of RAM available */ + protected static final long MAX_RAM = (long) PAGE_SIZE * (long) NUM_PAGES; - /** - * The memory backing store - */ + /** The memory backing store */ private byte readableMemory[][]; - private byte writableMemory[][]; - private byte executableMemory[][]; - /** - * Do we have more optimal nio mmap operation? - */ + /** Do we have more optimal nio mmap operation? */ private boolean HAVE_java_nio_FileChannelImpl_nio_mmap_file = false; /** * Constructor - used when this is the instatiated class */ public ByteAddressedMemory() { - super(ByteAddressedMemory.class); - readableMemory = new byte[NUM_PAGES][]; - writableMemory = new byte[NUM_PAGES][]; - executableMemory = new byte[NUM_PAGES][]; + this(null); } /** @@ -85,7 +69,7 @@ * the name of the over-riding class */ protected ByteAddressedMemory(Class classType) { - super(classType); + super(classType != null ? classType : ByteAddressedMemory.class); readableMemory = new byte[NUM_PAGES][]; writableMemory = new byte[NUM_PAGES][]; executableMemory = new byte[NUM_PAGES][]; @@ -114,13 +98,11 @@ */ private final int findFreePages(int pages) { starting_page_search: for (int i = 0; i < NUM_PAGES; i++) { - if ((readableMemory[i] == null) && (writableMemory[i] == null) - && (executableMemory[i] == null)) { + if (getPage(i) == null) { int start = i; int end = i + pages; for (; i <= end; i++) { - if ((readableMemory[i] != null) || (writableMemory[i] != null) - || (executableMemory[i] != null)) { + if (getPage(i) != null) { continue starting_page_search; } } @@ -152,39 +134,38 @@ if ((addr % PAGE_SIZE) != 0) { MemoryMapException.unalignedAddress(addr); } + // Create memory int num_pages = (len + PAGE_SIZE - 1) / PAGE_SIZE; byte pages[][] = new byte[num_pages][PAGE_SIZE]; + // Find address if not specified if (addr == 0) { addr = findFreePages(num_pages); } + if (DBT_Options.debugMemory) { - System.err.println("Anonymous mapping: addr=0x" + System.out.println("Anonymous mapping: addr=0x" + Integer.toHexString(addr) + " len=" + len + (read ? " r" : " -") + (write ? "w" : "-") + (exec ? "x" : "-")); } + // Get page table entry int pte = getPTE(addr); for (int i = 0; i < num_pages; i++) { + // Check pages aren't already allocated - if ((readableMemory[pte + i] != null) - || (writableMemory[pte + i] != null) - || (executableMemory[pte + i] != null)) { + if (getPage(pte + i) != null) { throw new Error("Memory map of already mapped location addr=0x" + Integer.toHexString(addr) + " len=" + len); } + // Allocate pages - if (read) { - readableMemory[pte + i] = pages[i]; - } - if (write) { - writableMemory[pte + i] = pages[i]; - } - if (exec) { - executableMemory[pte + i] = pages[i]; - } + readableMemory[pte + i] = read ? pages[i] : null; + writableMemory[pte + i] = write ? pages[i] : null; + executableMemory[pte + i] = exec ? pages[i] : null; } + return addr; } @@ -210,12 +191,11 @@ if ((addr % PAGE_SIZE) != 0) { MemoryMapException.unalignedAddress(addr); } + // Check file offset is page aligned - /* if ((offset % PAGE_SIZE) != 0) { MemoryMapException.unalignedFileOffset(offset); } - */ // Calculate number of pages int num_pages = (len + PAGE_SIZE - 1) / PAGE_SIZE; @@ -224,7 +204,7 @@ addr = findFreePages(num_pages); } if (DBT_Options.debugMemory) { - System.err.println("Mapping file " + file + " offset=" + offset + System.out.println("Mapping file " + file + " offset=" + offset + " addr=0x" + Integer.toHexString(addr) + " len=" + len + (read ? " r" : " -") + (write ? "w" : "-") + (exec ? "x" : "-")); } @@ -237,9 +217,7 @@ file.seek(offset); for (int i = 0; i < num_pages; i++) { // Check pages aren't already allocated - if ((readableMemory[pte + i] != null) - || (writableMemory[pte + i] != null) - || (executableMemory[pte + i] != null)) { + if (getPage(pte + i) != null) { throw new Error("Memory map of already mapped location addr=0x" + Integer.toHexString(addr) + " len=" + len); } @@ -252,25 +230,19 @@ } else { file.read(page); } - if (read) { - readableMemory[pte + i] = page; - } - if (write) { - writableMemory[pte + i] = page; - } - if (exec) { - executableMemory[pte + i] = page; - } + + readableMemory[pte + i] = read ? page : null; + writableMemory[pte + i] = write ? page : null; + executableMemory[pte + i] = exec ? page : null; } } else { for (int i = 0; i < num_pages; i++) { // Check pages aren't already allocated - if ((readableMemory[pte + i] != null) - || (writableMemory[pte + i] != null) - || (executableMemory[pte + i] != null)) { + if (getPage(pte + i) != null) { throw new Error("Memory map of already mapped location addr=0x" + Integer.toHexString(addr) + " len=" + len); } + // Allocate page if (read && write) { readableMemory[pte + i] = file.getChannel().map( @@ -303,6 +275,29 @@ throw new Error(e); } } + + /** + * Returns the page currently mapped at the given page table entry. + * + * @param pte + * The page table entry, for which a page is to be retrieved. + * @return + * The page mapped at the given page table entry or null, if no page is currently mapped + * to that entry. + */ + private byte[] getPage(int pte) { + + if (readableMemory[pte] != null) + return readableMemory[pte]; + + if (writableMemory[pte] != null) + return writableMemory[pte]; + + if (executableMemory[pte] != null) + return executableMemory[pte]; + + return null; + } /** * Unmap a page of memory @@ -314,20 +309,14 @@ */ public void unmap(int addr, int len) { for (int i = 0; i < len; i += PAGE_SIZE) { - boolean unmapped_something = false; - if (readableMemory[getPTE(addr + i)] != null) { - readableMemory[getPTE(addr + i)] = null; - unmapped_something = true; + + int pte = getPTE(addr + i); + if (getPage(pte) != null) { + readableMemory[pte] = null; + writableMemory[pte] = null; + executableMemory[pte] = null; } - if (writableMemory[getPTE(addr + i)] != null) { - writableMemory[getPTE(addr + i)] = null; - unmapped_something = true; - } - if (executableMemory[getPTE(addr + i)] != null) { - executableMemory[getPTE(addr + i)] = null; - unmapped_something = true; - } - if (unmapped_something == false) { + else { throw new Error("Unmapping memory that's not mapped addr=0x" + Integer.toHexString(addr) + " len=" + len); } @@ -340,9 +329,7 @@ * @return true => memory is mapped */ public boolean isMapped(int addr) { - return ((readableMemory[getPTE(addr)] != null) || - (writableMemory[getPTE(addr)] != null) || - (executableMemory[getPTE(addr)] != null)); + return getPage(getPTE(addr)) != null; } /** @@ -536,4 +523,23 @@ throw new SegmentationFault(addr); } } + + @Override + public void changeProtection(int address, int len, boolean newRead, boolean newWrite, boolean newExec) { + + while (len > 0) { + int pte = getPTE(address); + byte[] page = getPage(pte); + + if (page == null) + throw new SegmentationFault(address); + + readableMemory[pte] = newRead ? page : null; + writableMemory[pte] = newWrite ? page : null; + executableMemory[pte] = newExec ? page : null; + + address += PAGE_SIZE; + len -= PAGE_SIZE; + } + } } Deleted: src/org/binarytranslator/generic/memory/DebugMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/DebugMemory.java 2007-05-19 15:21:09 UTC (rev 125) +++ src/org/binarytranslator/generic/memory/DebugMemory.java 2007-05-21 14:20:19 UTC (rev 126) @@ -1,598 +0,0 @@ -/* - * This file is part of binarytranslator.org. The binarytranslator.org - * project is distributed under the Common Public License (CPL). - * A copy of the license is included in the distribution, and is also - * available at http://www.opensource.org/licenses/cpl1.0.php - * - * (C) Copyright Ian Rogers, The University of Manchester 2003-2006 - */ -package org.binarytranslator.generic.memory; - -import java.io.RandomAccessFile; -import java.nio.channels.FileChannel; - -import org.binarytranslator.DBT_Options; -import org.binarytranslator.generic.decoder.AbstractCodeTranslator; -import org.jikesrvm.compilers.opt.ir.OPT_Operand; -import org.jikesrvm.compilers.opt.ir.OPT_RegisterOperand; - -/** - * A copy of byte-addressed memory, that does not allow the translation of accesses to bytecode. - * This is stricly for debugging purposes, as it allows the Pearcolator interpreter to be executed - * in a windows environment. - */ -public class DebugMemory extends Memory { - /** - * The size of pages - */ - private static final int PAGE_SIZE = 4096; - - /** - * Bits in offset - */ - private static final int OFFSET_BITS = 12; - - /** - * The number of pages - */ - private static final int NUM_PAGES = 0x100000; - - /** - * The maximum amount of RAM available - */ - protected static final long MAX_RAM = (long) PAGE_SIZE * (long) NUM_PAGES; - - /** - * The memory backing store - */ - private byte readableMemory[][]; - - private byte writableMemory[][]; - - private byte executableMemory[][]; - - /** - * Do we have more optimal nio mmap operation? - */ - private boolean HAVE_java_nio_FileChannelImpl_nio_mmap_file = false; - - /** - * Constructor - used when this is the instatiated class - */ - public DebugMemory() { - readableMemory = new byte[NUM_PAGES][]; - writableMemory = new byte[NUM_PAGES][]; - executableMemory = new byte[NUM_PAGES][]; - } - - /** - * Return the offset part of the address - */ - private static final int getOffset(int address) { - return address & (PAGE_SIZE - 1); - } - - /** - * Return the page table entry part of the address - */ - private static final int getPTE(int address) { - return address >>> OFFSET_BITS; - } - - /** - * Ensure memory between start and end is mapped - * @param startAddr starting address for mapped memory - * @param endAddr ending address for mapped memory - */ - @Override - public void ensureMapped(int startAddr, int endAddr) throws MemoryMapException { - startAddr = truncateToPage(startAddr); - endAddr = truncateToNextPage(endAddr); - for (;startAddr < endAddr; startAddr += getPageSize()) { - if (!isMapped(startAddr)) { - map(startAddr, getPageSize(), true, true, true); - } - } - } - - /** - * Find free consecutive pages - * - * @param pages - * the number of pages required - * @return the address found - */ - private final int findFreePages(int pages) { - starting_page_search: for (int i = 0; i < NUM_PAGES; i++) { - if ((readableMemory[i] == null) && (writableMemory[i] == null) - && (executableMemory[i] == null)) { - int start = i; - int end = i + pages; - for (; i <= end; i++) { - if ((readableMemory[i] != null) || (writableMemory[i] != null) - || (executableMemory[i] != null)) { - continue starting_page_search; - } - } - return start << OFFSET_BITS; - } - } - throw new Error( - "No mappable consecutive pages found for an anonymous map of size" - + (pages * PAGE_SIZE)); - } - - /** - * Map an anonymous page of memory - * - * @param addr - * the address to map or NULL if don't care - * @param len - * the amount of memory to map - * @param read - * is the page readable - * @param write - * is the page writable - * @param exec - * is the page executable - * @return - * The start address of the mapped memory. - */ - public int map(int addr, int len, boolean read, boolean write, boolean exec) - throws MemoryMapException { - // Check that the address is page aligned - if ((addr % PAGE_SIZE) != 0) { - MemoryMapException.unalignedAddress(addr); - - /* - // if it is not, truncate the address down to the next page boundary and - // start mapping from there - int validPageCount = addr / PAGE_SIZE; - int oldStartAddress = addr; - addr = validPageCount * PAGE_SIZE; - - if (DBT.VerifyAssertions) - DBT._assert(oldStartAddress > addr); - - // we have to map more more memory now to reach the same end address - len += (oldStartAddress - addr);*/ - } - - // Create memory - int num_pages = (len + PAGE_SIZE - 1) / PAGE_SIZE; - byte pages[][] = new byte[num_pages][PAGE_SIZE]; - // Find address if not specified - if (addr == 0) { - addr = findFreePages(num_pages); - } - if (DBT_Options.debugMemory) { - System.err.println("Anonymous mapping: addr=0x" - + Integer.toHexString(addr) + " len=" + len + (read ? " r" : " -") - + (write ? "w" : "-") + (exec ? "x" : "-")); - } - // Get page table entry - int pte = getPTE(addr); - for (int i = 0; i < num_pages; i++) { - // Check pages aren't already allocated - if ((readableMemory[pte + i] != null) - || (writableMemory[pte + i] != null) - || (executableMemory[pte + i] != null)) { - throw new Error("Memory map of already mapped location addr=0x" - + Integer.toHexString(addr) + " len=" + len); - } - // Allocate pages - if (read) { - readableMemory[pte + i] = pages[i]; - } - if (write) { - writableMemory[pte + i] = pages[i]; - } - if (exec) { - executableMemory[pte + i] = pages[i]; - } - } - return addr; - } - - /** - * Map a page of memory from file - * - * @param file - * the file map in from - * @param addr - * the address to map or NULL if don't care - * @param len - * the amount of memory to map - * @param read - * is the page readable - * @param write - * is the page writable - * @param exec - * is the page executable - */ - public int map(RandomAccessFile file, long offset, int addr, int len, - boolean read, boolean write, boolean exec) throws MemoryMapException { - // Check address is page aligned - if ((addr % PAGE_SIZE) != 0) { - MemoryMapException.unalignedAddress(addr); - } - - // Calculate number of pages - int num_pages = (len + PAGE_SIZE - 1) / PAGE_SIZE; - - // Find address if not specified - /*if (addr == 0) { - addr = findFreePages(num_pages); - }*/ - - if (DBT_Options.debugMemory) { - System.err.println("Mapping file " + file + " offset=" + offset - + " addr=0x" + Integer.toHexString(addr) + " len=" + len - + (read ? " r" : " -") + (write ? "w" : "-") + (exec ? "x" : "-")); - } - try { - // Get page table entry - int pte = getPTE(addr); - // Can we optimise the reads to use mmap? - if (!HAVE_java_nio_FileChannelImpl_nio_mmap_file) { - // Sub-optimal - file.seek(offset); - for (int i = 0; i < num_pages; i++) { - - byte page[]; - - // Check pages aren't already allocated - if ((readableMemory[pte + i] != null) - || (writableMemory[pte + i] != null) - || (executableMemory[pte + i] != null)) { - - /*page = readableMemory[pte + i]; - - if (page == null) - page = writableMemory[pte + i]; - - if (page == null) - page = executableMemory[pte + i]; - - if (DBT.VerifyAssertions) DBT._assert(page != null);*/ - - throw new Error("Memory map of already mapped location addr=0x" - + Integer.toHexString(addr) + " len=" + len); - } - else - page = new byte[PAGE_SIZE]; //Allocate page - - if (i == 0) { // first read, start from offset upto a page length - file.read(page, getOffset(addr), PAGE_SIZE - getOffset(addr)); - } else if (i == (num_pages - 1)) { // last read - file.read(page, 0, ((len - getOffset(addr)) % PAGE_SIZE)); - } else { - file.read(page); - } - - if (read) { - readableMemory[pte + i] = page; - } - if (write) { - writableMemory[pte + i] = page; - } - if (exec) { - executableMemory[pte + i] = page; - } - } - } else { - for (int i = 0; i < num_pages; i++) { - // Check pages aren't already allocated - if ((readableMemory[pte + i] != null) - || (writableMemory[pte + i] != null) - || (executableMemory[pte + i] != null)) { - throw new Error("Memory map of already mapped location addr=0x" - + Integer.toHexString(addr) + " len=" + len); - } - - System.out.println("Unexpected page mapping!!!!!!!!!!!!!!!!!!!!"); - - byte[] page; - - if (write) - page = file.getChannel().map(FileChannel.MapMode.READ_WRITE, offset + (i * PAGE_SIZE), PAGE_SIZE).array(); - else - page = file.getChannel().map(FileChannel.MapMode.READ_ONLY, offset + (i * PAGE_SIZE), PAGE_SIZE).array(); - - if (write) { - writableMemory[pte + i] = page; - } - - if (read) { - readableMemory[pte + i] = page; - } - - if (exec) { - executableMemory[pte + i] = page; - } - } - } - return addr; - } catch (java.io.IOException e) { - throw new Error(e); - } - } - - /** - * Unmap a page of memory - * - * @param addr - * the address to unmap - * @param len - * the amount of memory to unmap - */ - public void unmap(int addr, int len) { - for (int i = 0; i < len; i += PAGE_SIZE) { - boolean unmapped_something = false; - if (readableMemory[getPTE(addr + i)] != null) { - readableMemory[getPTE(addr + i)] = null; - unmapped_something = true; - } - if (readableMemory[getPTE(addr + i)] != null) { - writableMemory[getPTE(addr + i)] = null; - unmapped_something = true; - } - if (readableMemory[getPTE(addr + i)] != null) { - executableMemory[getPTE(addr + i)] = null; - unmapped_something = true; - } - if (unmapped_something == false) { - throw new Error("Unmapping memory that's not mapped addr=0x" - + Integer.toHexString(addr) + " len=" + len); - } - } - } - - /** - * Is the given address mapped into memory? - * @param addr to check - * @return true => memory is mapped - */ - public boolean isMapped(int addr) { - return ((readableMemory[getPTE(addr)] != null) || - (writableMemory[getPTE(addr)] != null) || - (executableMemory[getPTE(addr)] != null)); - } - - /** - * @return the size of a page - */ - public int getPageSize() { - return PAGE_SIZE; - } - - /** - * Is the given address aligned on a page boundary? - * - * @param addr - * the address to check - * @return whether the address is aligned - */ - public boolean isPageAligned(int addr) { - return (addr % PAGE_SIZE) == 0; - } - - /** - * Make the given address page aligned to the page beneath it - * - * @param addr - * the address to truncate - * @return the truncated address - */ - public int truncateToPage(int addr) { - return (addr >> OFFSET_BITS) << OFFSET_BITS; - } - - /** - * Make the given address page aligned to the page above it - * - * @param addr - * the address to truncate - * @return the truncated address - */ - public int truncateToNextPage(int addr) { - return ((addr + PAGE_SIZE - 1) >> OFFSET_BITS) << OFFSET_BITS; - } - - /** - * Perform a byte load where the sign extended result fills the return value - * - * @param addr - * the address of the value to load - * @return the sign extended result - */ - final public int loadSigned8(int addr) { - try { - if (DBT_Options.debugMemory) - System.err.println("LoadS8 address: 0x" + Integer.toHexString(addr) - + " val: " + readableMemory[getPTE(addr)][getOffset(addr)]); - return readableMemory[getPTE(addr)][getOffset(addr)]; - } catch (NullPointerException e) { - System.err.println("Null pointer exception at address: 0x" - + Integer.toHexString(addr)); - throw e; - } - } - - /** - * Perform a byte load where the zero extended result fills the return value - * - * @param addr - * the address of the value to load - * @return the zero extended result - */ - final public int loadUnsigned8(int addr) { - try { - if (DBT_Options.debugMemory) - System.err.println("LoadU8 address: 0x" + Integer.toHexString(addr) - + " val: " + readableMemory[getPTE(addr)][getOffset(addr)]); - return readableMemory[getPTE(addr)][getOffset(addr)] & 0xFF; - } catch (NullPointerException e) { - System.err.println("Null pointer exception at address: 0x" - + Integer.toHexString(addr)); - throw e; - } - } - - /** - * Perform a 16bit load where the sign extended result fills the return value - * - * @param addr - * the address of the value to load - * @return the sign extended result - */ - public int loadSigned16(int addr) { - return (loadSigned8(addr + 1) << 8) | loadUnsigned8(addr); - } - - /** - * Perform a 16bit load where the zero extended result fills the return value - * - * @param addr - * the address of the value to load - * @return the zero extended result - */ - public int loadUnsigned16(int addr) { - return (loadUnsigned8(addr + 1) << 8) | loadUnsigned8(addr); - } - - /** - * Perform a 32bit load - * - * @param addr - * the address of the value to load - * @return the result - */ - public int load32(int addr) { - return (loadUnsigned8(addr + 3) << 24) | (loadUnsigned8(addr + 2) << 16) - | (loadUnsigned8(addr + 1) << 8) | loadUnsigned8(addr); - } - - /** - * Perform a 8bit load from memory that must be executable - * - * @param addr - * the address of the value to load - * @return the result - */ - public int loadInstruction8(int addr) { - if (DBT_Options.debugMemory) - System.err.println("LoadI8 address: 0x" + Integer.toHexString(addr) - + " val: " + executableMemory[getPTE(addr)][getOffset(addr)]); - return executableMemory[getPTE(addr)][getOffset(addr)] & 0xFF; - } - - /** - * Perform a 32bit load from memory that must be executable - * - * @param addr - * the address of the value to load - * @return the result - */ - public int loadInstruction32(int addr) { - return (loadInstruction8(addr + 3) << 24) - | (loadInstruction8(addr + 2) << 16) - | (loadInstruction8(addr + 1) << 8) | loadInstruction8(addr); - } - - /** - * Perform a byte store - * - * @param value - * the value to store - * @param addr - * the address of where to store - */ - public final void store8(int addr, int value) { - if (DBT_Options.debugMemory) - System.err.println("Store8 address: 0x" + Integer.toHexString(addr) - + " val: 0x" + Integer.toHexString(value & 0xFF)); - writableMemory[getPTE(addr)][getOffset(addr)] = (byte) value; - } - - /** - * Perform a 16bit store - * - * @param value - * the value to store - * @param addr - * the address of where to store - */ - public void store16(int addr, int value) { - store8(addr + 1, value >> 8); - store8(addr, value); - } - - /** - * Perform a 32bit store - * - * @param value - * the value to store - * @param addr - * the address of where to store - */ - public void store32(int addr, int value) { - store8(addr + 3, value >> 24); - store8(addr + 2, value >> 16); - store8(addr + 1, value >> 8); - store8(addr, value); - } - - @Override - public void initTranslate(AbstractCodeTranslator helper) { - throw new UnsupportedOperationException(); - } - - @Override - public void translateLoad32(OPT_Operand addr, OPT_RegisterOperand dest) { - throw new UnsupportedOperationException(); - - } - - @Override - public void translateLoadSigned16(OPT_Operand addr, OPT_RegisterOperand dest) { - throw new UnsupportedOperationException(); - - } - - @Override - public void translateLoadSigned8(OPT_Operand addr, OPT_RegisterOperand dest) { - throw new UnsupportedOperationException(); - - } - - @Override - public void translateLoadUnsigned16(OPT_Operand addr, OPT_RegisterOperand dest) { - throw new UnsupportedOperationException(); - - } - - @Override - public void translateLoadUnsigned8(OPT_Operand addr, OPT_RegisterOperand dest) { - throw new UnsupportedOperationException(); - - } - - @Override - public void translateStore16(OPT_Operand addr, OPT_Operand src) { - throw new UnsupportedOperationException(); - - } - - @Override - public void translateStore32(OPT_Operand addr, OPT_Operand src) { - throw new UnsupportedOperationException(); - - } - - @Override - public void translateStore8(OPT_Operand addr, OPT_Operand src) { - throw new UnsupportedOperationException(); - - } -} Modified: src/org/binarytranslator/generic/memory/IntAddressedMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/IntAddressedMemory.java 2007-05-19 15:21:09 UTC (rev 125) +++ src/org/binarytranslator/generic/memory/IntAddressedMemory.java 2007-05-21 14:20:19 UTC (rev 126) @@ -12,6 +12,7 @@ import org.binarytranslator.DBT; import org.binarytranslator.DBT_Options; +import org.binarytranslator.generic.fault.SegmentationFault; import org.jikesrvm.VM_Configuration; /** @@ -65,10 +66,7 @@ * Constructor - used when this is the instatiated class */ public IntAddressedMemory() { - super(IntAddressedMemory.class); - readableMemory = new int[NUM_PAGES][]; - writableMemory = new int[NUM_PAGES][]; - executableMemory = new int[NUM_PAGES][]; + this(null); } /** @@ -78,7 +76,7 @@ * the type of the over-riding class */ protected IntAddressedMemory(Class classType) { - super(classType); + super(classType != null ? classType : IntAddressedMemory.class); readableMemory = new int[NUM_PAGES][]; writableMemory = new int[NUM_PAGES][]; executableMemory = new int[NUM_PAGES][]; @@ -104,9 +102,7 @@ * @return true => memory is mapped */ public boolean isMapped(int addr) { - return ((readableMemory[getPTE(addr)] != null) || - (writableMemory[getPTE(addr)] != null) || - (executableMemory[getPTE(addr)] != null)); + return getPage(getPTE(addr)) != null; } /** @@ -158,13 +154,11 @@ */ private final int findFreePages(int pages) { starting_page_search: for (int i = 0; i < NUM_PAGES; i++) { - if ((readableMemory[i] == null) && (writableMemory[i] == null) - && (executableMemory[i] == null)) { + if (getPage(i) == null) { int start = i; int end = i + pages; for (; i <= end; i++) { - if ((readableMemory[i] != null) || (writableMemory[i] != null) - || (executableMemory[i] != null)) { + if (getPage(i) != null) { continue starting_page_search; } } @@ -224,27 +218,61 @@ int pte = getPTE(addr); for (int i = 0; i < num_pages; i++) { // Check pages aren't already allocated - if ((readableMemory[pte + i] != null) - || (writableMemory[pte + i] != null) - || (executableMemory[pte + i] != null)) { + if (getPage(pte + i) != null) { throw new Error("Memory map of already mapped location addr=0x" + Integer.toHexString(addr) + " len=" + len); } - // Allocate pages - if (read) { - readableMemory[pte + i] = pages[i]; - } - if (write) { - writableMemory[pte + i] = pages[i]; - } - if (exec) { - executableMemory[pte + i] = pages[i]; - } + + readableMemory[pte+i] = read ? pages[i] : null; + writableMemory[pte+i] = write ? pages[i] : null; + executableMemory[pte+i] = exec ? pages[i] : null; } return addr; } /** + * Returns the page currently mapped at the given page table entry. + * + * @param pte + * The page table entry, for which a page is to be retrieved. + * @return + * The page mapped at the given page table entry or null, if no page is currently mapped + * to that entry. + */ + private int[] getPage(int pte) { + + if (readableMemory[pte] != null) + return readableMemory[pte]; + + if (writableMemory[pte] != null) + return writableMemory[pte]; + + if (executableMemory[pte] != null) + return executableMemory[pte]; + + return null; + } + + @Override + public void changeProtection(int address, int len, boolean newRead, boolean newWrite, boolean newExec) { + + while (len > 0) { + int pte = getPTE(address); + int[] page = getPage(pte); + + if (page == null) + throw new SegmentationFault(address); + + readableMemory[pte] = newRead ? page : null; + writableMemory[pte] = newWrite ? page : null; + executableMemory[pte] = newExec ? page : null; + + address += PAGE_SIZE; + len -= PAGE_SIZE; + } + } + + /** * Read an int from RandomAccessFile ensuring that a byte swap isn't performed * * @param file @@ -292,20 +320,19 @@ + (read ? " r" : " -") + (write ? "w" : "-") + (exec ? "x" : "-")); } addr = map(addr, len, read, write, exec); - try { + + try { file.seek(offset); for (int i = 0; i < len; i += 4) { - int value = readInt(file); - if (read) { - readableMemory[getPTE(addr + i)][getOffset(addr + i)] = value; - } else if (write) { - writableMemory[getPTE(addr + i)][getOffset(addr + i)] = value; - } else if (exec) { - executableMemory[getPTE(addr + i)][getOffset(addr + i)] = value; - } + + int[] page = getPage(getPTE(addr + i)); + page[getOffset(addr + i)] = readInt(file); } + return addr; - } catch (java.io.IOException e) { + + } + catch (java.io.IOException e) { throw new Error(e); } } @@ -320,20 +347,15 @@ */ public final void unmap(int addr, int len) { for (int i = 0; i < len; i += PAGE_SIZE) { - boolean unmapped_something = false; - if (readableMemory[getPTE(addr + i)] != null) { - readableMemory[getPTE(addr + i)] = null; - unmapped_something = true; + + int pte = getPTE(addr + i); + + if (getPage(pte) != null) { + readableMemory[pte] = null; + writableMemory[pte] = null; + executableMemory[pte] = null; } - if (readableMemory[getPTE(addr + i)] != null) { - writableMemory[getPTE(addr + i)] = null; - unmapped_something = true; - } - if (readableMemory[getPTE(addr + i)] != null) { - executableMemory[getPTE(addr + i)] = null; - unmapped_something = true; - } - if (unmapped_something == false) { + else { throw new Error("Unmapping memory that's not mapped addr=0x" + Integer.toHexString(addr) + " len=" + len); } Modified: src/org/binarytranslator/generic/memory/Memory.java =================================================================== --- src/org/binarytranslator/generic/memory/Memory.java 2007-05-19 15:21:09 UTC (rev 125) +++ src/org/binarytranslator/generic/memory/Memory.java 2007-05-21 14:20:19 UTC (rev 126) @@ -43,6 +43,26 @@ public abstract int map(RandomAccessFile file, long offset, int addr, int len, boolean read, boolean write, boolean exec) throws MemoryMapException; + + /** + * Changes the protection of a region of memory. Note that this function only guarantees + * protection to be changed on a page level. Therefore, if <code>address</code> is not page + * aligned or len is not a muliple of {@link #getPageSize()}, then the function may + * change the protection of a larger memory range than initally requested. + * + * @param address + * The start address of a memory block, whose protection shall be changed. + * @param len + * The length of the memory block. + * @param newRead + * Set to true to allow reading from this memory block, false otherwise. + * @param newWrite + * Set to true to allow writing to this memory block, false otherwise. + * @param newExec + * Set to true to allow executing code from this memory block, false otherwise. + */ + public abstract void changeProtection(int address, int len, boolean newRead, + boolean newWrite, boolean newExec); /** * Unmap a page of memory Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-05-19 15:21:09 UTC (rev 125) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-05-21 14:20:19 UTC (rev 126) @@ -31,6 +31,7 @@ import org.binarytranslator.generic.os.abi.linux.filesystem.ReadonlyFilesystem; import org.binarytranslator.generic.os.abi.linux.filesystem.TempFileSystem; import org.binarytranslator.generic.os.abi.linux.filesystem.FileProvider.FileMode; +import org.binarytranslator.generic.os.process.ProcessSpace; /** * Linux system call handling class @@ -206,9 +207,8 @@ * Unknown System Call */ private class UnknownSystemCall extends SystemCall { - /** - * Handle a system call - */ + + @Override public void doSysCall() { if (!DBT_Options.unimplementedSystemCallsFatal) { src.setSysCallError(errno.ENOSYS); @@ -223,6 +223,8 @@ * Exit system call */ public class SysExit extends SystemCall { + + @Override public void doSysCall() { int status = arguments.nextInt(); System.exit(status); @@ -233,6 +235,8 @@ * Read from a file */ public class SysRead extends SystemCall { + + @Override public void doSysCall() { int fd = arguments.nextInt(); int buf = arguments.nextInt(); @@ -265,6 +269,8 @@ * Write to a file */ public class SysWrite extends SystemCall { + + @Override public void doSysCall() { int fd = arguments.nextInt(); int buf = arguments.nextInt(); @@ -296,6 +302,8 @@ * Write data into multiple buffers */ public class SysWriteV extends SystemCall { + + @Override public void doSysCall() { int fd = arguments.nextInt(); int vector = arguments.nextInt(); @@ -334,6 +342,8 @@ } public class SysOpen extends SystemCall { + + @Override public void doSysCall() { int pathname = arguments.nextInt(); int flags = arguments.nextInt(); @@ -406,6 +416,8 @@ } public class SysClose extends SystemCall { + + @Override public void doSysCall() { int fd = arguments.nextInt(); @@ -421,30 +433,40 @@ } public class SysGetEUID extends SystemCall { + + @Override public void doSysCall() { src.setSysCallReturn(DBT_Options.UID); } } public class SysGetUID extends SystemCall { + + @Override public void doSysCall() { src.setSysCallReturn(DBT_Options.UID); } } public class SysGetEGID extends SystemCall { + + @Override public void doSysCall() { src.setSysCallReturn(DBT_Options.GID); } } public class SysGetGID extends SystemCall { + + @Override public void doSysCall() { src.setSysCallReturn(DBT_Options.GID); } } public class SysBrk extends SystemCall { + + @Override public void doSysCall() { int newBrk = arguments.nextInt(); if (newBrk != 0) { @@ -458,6 +480,8 @@ } public class SysFstat64 extends SystemCall { + + @Override public void doSysCall() { int fd = arguments.nextInt(); int structAddr = arguments.nextInt(); @@ -506,6 +530,8 @@ } public class SysFcntl64 extends SystemCall { + + @Override public void doSysCall() { // This is complicated so fudge it for now. int fd = arguments.nextInt(); @@ -519,6 +545,8 @@ } public class SysUname extends SystemCall { + + @Override public void doSysCall() { // Simple uname support int addr = arguments.nextInt(); @@ -556,6 +584,8 @@ } public class SysMmap extends SystemCall { + + @Override public void doSysCall() { int addr = arguments.nextInt(); @@ -589,8 +619,27 @@ } } } + + public class SysMRemap extends SystemCall { + @Override + public void doSysCall() { + int addr = arguments.nextInt(); + int len = arguments.nextInt(); + int prot = arguments.nextInt(); + + ProcessSpace ps = src.getProcessSpace(); + ps.memory.changeProtection(addr, len, (prot & mman.PROT_READ) != 0, + (prot & mman.PROT_WRITE) != 0, (prot & mman.PROT_EXEC) != 0); + + src.setSysCallReturn(0); + } + + } + public class SysMunmap extends SystemCall { + + @Override public void doSysCall() { int start = arguments.nextInt(); @@ -602,6 +651,8 @@ } public class SysExitGroup extends SystemCall { + + @Override public void doSysCall() { // For now, equivalent to SysExit System.exit(arguments.nextInt()); Modified: src/org/binarytranslator/generic/os/loader/elf/ELF_File.java =================================================================== --- src/org/binarytranslator/generic/os/loader/elf/ELF_File.java 2007-05-19 15:21:09 UTC (rev 125) +++ src/org/binarytranslator/generic/os/loader/elf/ELF_File.java 2007-05-21 14:20:19 UTC (rev 126) @@ -29,9 +29,7 @@ /** Header of ELF file */ private Header header; - /** - * Program segment headers - */ + /** Program segment headers */ private SegmentHeader segmentHeaders[]; /** @@ -1409,7 +1407,7 @@ * @param write is segment writable * @param exec is segment executable */ - public void createSegment(Memory memory, RandomAccessFile file, + private void createSegment(Memory memory, RandomAccessFile file, long offset, int address, int filesize, int memsize, boolean read, boolean write, boolean exec) throws MemoryMapException { // Sanity check @@ -1439,12 +1437,14 @@ alignedOffset = offset - delta; alignedFilesize = filesize + delta; } - memory.map(file, alignedOffset, alignedAddress, alignedFilesize, read, - write, exec); + + memory.map(file, alignedOffset, alignedAddress, alignedFilesize, read, write, exec); + // Do we need to map in some blank pages at the end of the segment? if (filesize < memsize) { alignedAddress = memory.truncateToNextPage(address + filesize); - memory.map(alignedAddress, memsize - filesize, read, write, exec); + int delta = alignedAddress - (address + filesize); + memory.map(alignedAddress, memsize - filesize - delta, read, write, exec); } } } Modified: src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java =================================================================== --- src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-05-19 15:21:09 UTC (rev 125) +++ src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-05-21 14:20:19 UTC (rev 126) @@ -81,7 +81,7 @@ System.out.println("ELF has segments:"); for (ELF_File.SegmentHeader segment : segments) { - System.out.println(" - " + segment.toString()); + System.out.println(" " + segment.toString()); } } Modified: src/org/binarytranslator/generic/os/loader/elf/JavaRuntimeLinker.java =================================================================== --- src/org/binarytranslator/generic/os/loader/elf/JavaRuntimeLinker.java 2007-05-19 15:21:09 UTC (rev 125) +++ src/org/binarytranslator/generic/os/loader/elf/JavaRuntimeLinker.java 2007-05-21 14:20:19 UTC (rev 126) @@ -29,7 +29,7 @@ private LinkedList<SharedObject> libraries = new LinkedList<SharedObject>(); /** A list of the star addres of all init routines, that we're supposed to execute. */ - public LinkedList<Integer> initMethods = new LinkedList<Integer>(); + private LinkedList<Integer> initMethods = new LinkedList<Integer>(); /** The address of the memory block that is going to be allocated to the next library*/ private int nextMemoryBlock = 1024*1024*1024; //start mapping libraries at 1GB (0x40000000) @@ -59,6 +59,11 @@ /** Other libraries, that this library depends upon. */ private SharedObject[] dependencies = null; + /** + * A list of segments that have additionally received write protection to allow + * relocations within the segment, although the segment was originally write protected. */ + private LinkedList<SegmentHeader> removedWriteProtection = new LinkedList<SegmentHeader>(); + public SharedObject(String filename) { this.filename = filename; this.hasFixedLoadOffset = false; @@ -135,6 +140,15 @@ //relocate all dynamic libraries relocateLibRecursively(programfile); + + //Add write protections to all segments from which we removed it during relocation + for (SharedObject lib : libraries) { + for (SegmentHeader segment : lib.removedWriteProtection) { + boolean read = (segment.p_flags & SegmentHeader.PF_R) != 0; + boolean exec = (segment.p_flags & SegmentHeader.PF_X) != 0; + ps.memory.changeProtection(segment.p_vaddr + lib.loadedAt, segment.p_filesz, read, false, exec); + } + } //Call the init routines that were registered by the different libraries callInitRoutines(); @@ -325,7 +339,7 @@ */ private void loadSingleLibrary(SharedObject lib) { - if (DBT.VerifyAssertions) DBT._assert(lib.loadedAt == 0); + if (DBT.VerifyAssertions) DBT._assert(lib.loadedAt == 0 || lib.hasFixedLoadOffset()); if (!lib.hasFixedLoadOffset()) { // load the library to the next available address @@ -340,15 +354,24 @@ //the highest offset from nextMemoryBlock that this shared object uses long highestUsedAddress = 1; + + if (DBT_Options.debugLoader) + System.out.println(String.format("Loading Shared Object: %s to 0x%x", lib, lib.loadedAt)); for (int i = 0; i < segments.length; i++) { + + SegmentHeader segment = segments[i]; + if (DBT_Options.debugLoader) System.out.println(" Loading Segment: " + segment); - //TODO: This is only a hack. We are making this segment writeable, because we need to relocate within it... - if (needRelocText) - segments[i].p_flags |= ELF_File.SegmentHeader.PF_W; + if (needRelocText && (segment.p_flags & ELF_File.SegmentHeader.PF_W) == 0) { + //We are making this segment writeable, because we need to relocate inside of it. + //Remember that segment to remove the write protection later on + lib.removedWriteProtection.add(segment); + segment.p_flags |= ELF_File.SegmentHeader.PF_W; + } //create the actual segment - segments[i].create(ps, lib.loadedAt); + segment.create(ps, lib.loadedAt); long thisAddress = segments[i].p_vaddr; thisAddress += segments[i].p_memsz; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |