/* * 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.solaris; import java.io.*; import java.nio.*; import java.util.*; import com.sun.max.tele.*; import com.sun.max.tele.debug.dump.*; /** * Solaris implementation of the channel protocol for accessing core dump files. * */ public class SolarisDumpTeleChannelProtocol extends ELFDumpTeleChannelProtocolAdaptor implements SolarisTeleChannelProtocol { private List<LwpData> lwpDataList = new ArrayList<LwpData>(); private SolarisDumpThreadAccess solarisDumpThreadAccess; private ByteBuffer pStatus; static class LwpData { // direct buffers ByteBuffer lwpStatus; ByteBuffer lwpInfo; LwpData(ByteBuffer lwpInfo) { this.lwpInfo = lwpInfo; } } public SolarisDumpTeleChannelProtocol(MaxVM teleVM, File vm, File dumpFile) { super(teleVM, vm, dumpFile); SolarisNoteEntryHandler noteEntryHandler = new SolarisNoteEntryHandler(); processNoteSection(noteEntryHandler); } @Override protected long getBootHeapStartSymbolAddress() { // On Solaris a randomly generated prefix is added to static symbols so, // if this code were invoked, it would need to do a search that coped with that. unimplemented("getBootHeapStartSymbolAddress"); return 0; } class SolarisNoteEntryHandler extends NoteEntryHandler { LwpData lwpData; @Override protected void processNoteEntry(int type, String name, byte[] desc) { final NoteType noteType = NoteType.get(type); switch (noteType) { case NT_PSTATUS: pStatus = ByteBuffer.allocateDirect(desc.length); pStatus.put(desc); @SuppressWarnings("unused") final int numActiveLwps = numActiveLwps(pStatus); @SuppressWarnings("unused") final int numZombieLwps = numZombieLwps(pStatus); break; case NT_LWPSINFO: { // this comes before NT_LWPSTATUS ByteBuffer lwpInfo = ByteBuffer.allocateDirect(desc.length); lwpInfo.put(desc); if (!isZombieLwp(lwpInfo)) { lwpData = new LwpData(lwpInfo); lwpDataList.add(lwpData); } break; } case NT_LWPSTATUS: { ByteBuffer lwpStatus = ByteBuffer.allocateDirect(desc.length); lwpStatus.put(desc); lwpData.lwpStatus = lwpStatus; lwpData = null; break; } } } } private static native int numActiveLwps(ByteBuffer pStatus); private static native int numZombieLwps(ByteBuffer pStatus); private static native boolean isZombieLwp(ByteBuffer lwpInfo); private int readInt(byte[] data, int index) { final ByteBuffer byteBuffer = ByteBuffer.wrap(data).order(bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN); return byteBuffer.getInt(index); } private static enum NoteType { NT_PRSTATUS(1), NT_PRFPREG(2), NT_PRPSINFO(3), NT_PRXREG(4), NT_PLATFORM(5), NT_AUXV(6), NT_GWINDOWS(7), NT_ASRS(8), NT_LDT(9), NT_PSTATUS(10), NT_PSINFO(13), NT_PRCRED(14), NT_UTSNAME(15), NT_LWPSTATUS(16), NT_LWPSINFO(17), NT_PRPRIV(18), NT_PRPRIVINFO(19), NT_CONTENT(20), NT_ZONENAME(21); int value; static NoteType get(int type) { for (NoteType noteType : values()) { if (noteType.value == type) { return noteType; } } return null; } NoteType(int value) { this.value = value; } } @Override public boolean initialize(int tlaSize, boolean bigEndian) { super.initialize(tlaSize, bigEndian); solarisDumpThreadAccess = new SolarisDumpThreadAccess(this, tlaSize, lwpDataList); return true; } @Override public boolean readRegisters(long threadId, byte[] integerRegisters, int integerRegistersSize, byte[] floatingPointRegisters, int floatingPointRegistersSize, byte[] stateRegisters, int stateRegistersSize) { SolarisDumpThreadAccess.SolarisThreadInfo threadInfo = (SolarisDumpThreadAccess.SolarisThreadInfo) solarisDumpThreadAccess.getThreadInfo((int) threadId); System.arraycopy(threadInfo.integerRegisters, 0, integerRegisters, 0, integerRegisters.length); System.arraycopy(threadInfo.floatingPointRegisters, 0, floatingPointRegisters, 0, floatingPointRegisters.length); System.arraycopy(threadInfo.stateRegisters, 0, stateRegisters, 0, stateRegisters.length); return true; } @Override public boolean gatherThreads(Object teleProcessObject, Object threadList, long tlaList) { return solarisDumpThreadAccess.gatherThreads(teleProcessObject, threadList, tlaList); } }