/*
* Copyright (c) 2010, 2011, 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.linux;
import java.io.*;
import java.nio.*;
import java.util.*;
import com.sun.max.tele.*;
import com.sun.max.tele.debug.dump.*;
/**
* Linux implementation of the channel protocol for accessing core dump files.
*
*/
public class LinuxDumpTeleChannelProtocol extends ELFDumpTeleChannelProtocolAdaptor implements LinuxTeleChannelProtocol {
private List<TaskData> taskDataList = new ArrayList<TaskData>();
private ByteBuffer taskPsInfo;
private LinuxDumpThreadAccess linuxDumpThreadAccess;
static class TaskData {
ByteBuffer status;
ByteBuffer fpreg;
ByteBuffer psinfo; // copy of taskPsInfo
}
public LinuxDumpTeleChannelProtocol(MaxVM teleVM, File vm, File dump) {
super(teleVM, vm, dump);
LinuxNoteEntryHandler noteEntryHandler = new LinuxNoteEntryHandler();
processNoteSection(noteEntryHandler);
}
class LinuxNoteEntryHandler extends NoteEntryHandler {
private TaskData taskData; // NT_PRSTATUS, NT_PRFPREG come in pairs, this holds the data across the callbacks
@Override
protected void processNoteEntry(int type, String name, byte[] desc) {
final NoteType noteType = NoteType.get(type);
switch (noteType) {
case NT_PRSTATUS:
checkCreate();
final ByteBuffer status = ByteBuffer.allocateDirect(desc.length);
status.put(desc);
taskData.status = status;
if (taskData.fpreg != null) {
taskData = null;
}
break;
case NT_PRFPREG:
checkCreate();
final ByteBuffer fpreg = ByteBuffer.allocateDirect(desc.length);
fpreg.put(desc);
taskData.fpreg = fpreg;
if (taskData.status != null) {
taskData = null;
}
break;
case NT_PRPSINFO:
taskPsInfo = ByteBuffer.allocateDirect(desc.length);
taskPsInfo.put(desc);
}
}
private void checkCreate() {
if (taskData == null) {
taskData = new TaskData();
taskData.psinfo = taskPsInfo;
taskDataList.add(taskData);
}
}
}
private static enum NoteType {
NT_PRSTATUS(1),
NT_PRFPREG(2),
NT_PRPSINFO(3),
NT_AUXV(6);
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);
linuxDumpThreadAccess = new LinuxDumpThreadAccess(this, tlaSize, taskDataList);
return true;
}
@Override
public boolean readRegisters(long threadId, byte[] integerRegisters, int integerRegistersSize, byte[] floatingPointRegisters, int floatingPointRegistersSize, byte[] stateRegisters,
int stateRegistersSize) {
LinuxDumpThreadAccess.LinuxThreadInfo threadInfo = (LinuxDumpThreadAccess.LinuxThreadInfo) linuxDumpThreadAccess.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 teleDomainObject, Object threadList, long tlaList) {
return linuxDumpThreadAccess.gatherThreads(teleDomainObject, threadList, tlaList);
}
}