/* * Copyright (c) 2010, 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.unix; import static com.sun.max.platform.Platform.*; import java.io.*; import java.nio.*; import java.util.*; import com.sun.max.lang.*; import com.sun.max.platform.*; import com.sun.max.tele.MaxWatchpoint.WatchpointSettings; import com.sun.max.tele.*; import com.sun.max.tele.channel.*; import com.sun.max.tele.data.*; import com.sun.max.tele.debug.*; import com.sun.max.tele.page.*; import com.sun.max.unsafe.*; import com.sun.max.vm.*; import com.sun.max.vm.hosted.*; /** * Abstracts the common code for {@link TeleProcess} for the various flavors of Unix supported by Maxine. * */ public abstract class UnixTeleProcessAdaptor extends TeleProcess { protected final TeleChannelProtocol protocol; protected final DataAccess dataAccess; private UnixTeleProcessAdaptor(TeleVM teleVM, Platform platform, File programFile, String[] commandLineArguments, int id) throws BootImageException { super(teleVM, platform, ProcessState.STOPPED); protocol = TeleVM.teleChannelProtocol(); dataAccess = new PageDataAccess(teleVM, this, platform.dataModel); protocol.initialize(teleVM.bootImage().header.tlaSize, platform().endianness() == Endianness.BIG ? true : false); if (commandLineArguments != null) { final long processHandle = protocol.create(programFile.getAbsolutePath(), commandLineArguments); if (processHandle < 0) { String exe = programFile.getName(); Log.println("This may be due to resources being consumed by zombie maxvm processes. Try running:"); Log.println(); Log.println(" pgrep " + exe + "; pkill -9 " + exe); Log.println(); throw new BootImageException("Could not start VM process"); } try { resume(); } catch (OSExecutionRequestException e) { throw new BootImageException("Error resuming VM after starting it", e); } } else { protocol.attach(id); } } protected UnixTeleProcessAdaptor(TeleVM teleVM, Platform platform, File programFile, int id) throws BootImageException { this(teleVM, platform, programFile, null, id); } protected UnixTeleProcessAdaptor(TeleVM teleVM, Platform platform, File programFile, String[] commandLineArguments) throws BootImageException { this(teleVM, platform, programFile, commandLineArguments, -1); } @Override public DataAccess dataAccess() { return dataAccess; } @Override public void kill() throws OSExecutionRequestException { if (!protocol.kill()) { throw new OSExecutionRequestException("Could not kill target VM"); } } @Override public void suspend() throws OSExecutionRequestException { if (!protocol.suspendAll()) { throw new OSExecutionRequestException("Could not suspend target VM"); } } @Override protected void resume() throws OSExecutionRequestException { if (!protocol.resumeAll()) { throw new OSExecutionRequestException("Could not resume the target VM "); } } /** * Waits until this process is stopped. */ @Override protected ProcessState waitUntilStopped() { return protocol.waitUntilStopped(); } @Override protected void gatherThreads(List<TeleNativeThread> threads) { final Word tlaList = dataAccess().readWord(vm().bootImageStart().plus(vm().bootImage().header.tlaListHeadOffset)); protocol.gatherThreads(this, threads, tlaList.asAddress().toLong()); } @Override protected int read0(Address src, ByteBuffer dst, int offset, int length) { return TeleChannelTransferBytes.readBytes(protocol, dst, offset, length, src); } @Override protected int write0(ByteBuffer src, int offset, int length, Address dst) { return TeleChannelTransferBytes.writeBytes(protocol, src, offset, length, dst); } @Override public int platformWatchpointCount() { return 0; } @Override protected boolean activateWatchpoint(VmWatchpoint watchpoint) { final WatchpointSettings settings = watchpoint.getSettings(); return protocol.activateWatchpoint(watchpoint.memoryRegion().start().toLong(), watchpoint.memoryRegion().nBytes(), true, settings.trapOnRead, settings.trapOnWrite, settings.trapOnExec); } @Override protected boolean deactivateWatchpoint(VmWatchpoint watchpoint) { return protocol.deactivateWatchpoint(watchpoint.memoryRegion().start().toLong(), watchpoint.memoryRegion().nBytes()); } /** * Reads the address which triggered a watchpoint signal. * * @return address */ @Override protected long readWatchpointAddress() { return protocol.readWatchpointAddress(); } /** * Reads the access code of the watchpoint which triggered a signal. * * @return access code */ @Override protected int readWatchpointAccessCode() { int code = protocol.readWatchpointAccessCode(); if (code == 3) { return 1; } else if (code == 4) { return 2; } else if (code == 5) { return 3; } return 0; } }