/*
* Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.max.tele.debug.no;
import static com.sun.max.platform.Platform.*;
import java.io.*;
import java.nio.*;
import java.nio.channels.FileChannel.MapMode;
import java.util.*;
import com.sun.max.platform.*;
import com.sun.max.tele.*;
import com.sun.max.tele.data.*;
import com.sun.max.tele.debug.*;
import com.sun.max.tele.debug.TeleNativeThread.Params;
import com.sun.max.tele.heap.*;
import com.sun.max.tele.util.*;
import com.sun.max.unsafe.*;
import com.sun.max.vm.hosted.*;
import com.sun.max.vm.hosted.BootImage.Header;
/**
* A null process that "contains" the boot image for inspection, as if it were a VM.
*/
public final class ReadOnlyTeleProcess extends TeleProcess {
private final DataAccess dataAccess;
private final Pointer heapPointer;
@Override
public DataAccess dataAccess() {
return dataAccess;
}
public ReadOnlyTeleProcess(TeleVM vm, Platform platform, File programFile) throws BootImageException {
super(vm, platform, ProcessState.UNKNOWN);
this.heapPointer = Pointer.fromLong(VmHeapAccess.heapAddressOption());
try {
dataAccess = map(vm.bootImageFile(), vm.bootImage());
} catch (IOException ioException) {
throw new BootImageException("Error mapping in boot image", ioException);
}
}
@Override
public void updateCache(long epoch) {
}
@Override
public int platformWatchpointCount() {
return 0;
}
public Pointer heapPointer() {
return heapPointer;
}
/**
* Maps the heapPointer and code sections of the boot image in a given file into memory.
*
* @param bootImageFile the file containing the heapPointer and code sections to map into memory
* @return a {@link DataAccess} object that can be used to access the mapped sections
* @throws IOException if an IO error occurs while performing the memory mapping
*/
private DataAccess map(File bootImageFile, BootImage bootImage) throws IOException {
final RandomAccessFile randomAccessFile = new RandomAccessFile(bootImageFile, "rwd");
final Header header = bootImage.header;
int heapOffset = bootImage.heapOffset();
int heapAndCodeSize = header.heapSize + header.codeSize;
final MappedByteBuffer bootImageBuffer = randomAccessFile.getChannel().map(MapMode.PRIVATE, heapOffset, heapAndCodeSize);
bootImageBuffer.order(platform().endianness().asByteOrder());
randomAccessFile.close();
if (heapPointer.isNotZero()) {
long address = (Long) WithoutAccessCheck.getInstanceField(bootImageBuffer, "address");
bootImage.relocate(address, heapPointer);
}
return new MappedByteBufferDataAccess(bootImageBuffer, heapPointer, header.wordWidth());
}
private static final String FAIL_MESSAGE = "Attempt to run/write/modify a read-only bootimage VM with no live process";
@Override
protected void gatherThreads(List<TeleNativeThread> threads) {
TeleError.unexpected(FAIL_MESSAGE);
}
@Override
protected TeleNativeThread createTeleNativeThread(Params params) {
TeleError.unexpected(FAIL_MESSAGE);
return null;
}
@Override
protected int read0(Address address, ByteBuffer buffer, int offset, int length) {
return dataAccess.read(address, buffer, offset, length);
}
@Override
protected int write0(ByteBuffer buffer, int offset, int length, Address address) {
TeleError.unexpected(FAIL_MESSAGE);
return 0;
}
@Override
protected void kill() throws OSExecutionRequestException {
TeleError.unexpected(FAIL_MESSAGE);
}
@Override
protected void resume() throws OSExecutionRequestException {
TeleError.unexpected(FAIL_MESSAGE);
}
@Override
protected void suspend() throws OSExecutionRequestException {
TeleError.unexpected(FAIL_MESSAGE);
}
@Override
protected ProcessState waitUntilStopped() {
TeleError.unexpected(FAIL_MESSAGE);
return ProcessState.UNKNOWN;
}
}