blob: 01b2605178ee8c4f5a8a4227bc06343a47887711 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009 STMicroelectronics.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Xavier Raynaud <xavier.raynaud@st.com> - initial API and implementation
*******************************************************************************/
package org.eclipse.linuxtools.internal.gprof.parser;
import java.io.DataInput;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.cdt.core.IAddress;
import org.eclipse.cdt.core.IAddressFactory;
import org.eclipse.cdt.core.IBinaryParser.IBinaryObject;
import org.eclipse.cdt.core.IBinaryParser.ISymbol;
import org.eclipse.linuxtools.internal.gprof.symbolManager.CallGraphArc;
import org.eclipse.linuxtools.internal.gprof.symbolManager.CallGraphNode;
import org.eclipse.linuxtools.internal.gprof.view.histogram.HistRoot;
/**
* This class in on charge of parsing the call graph section
* of gmon files
* @author Xavier Raynaud <xavier.raynaud@st.com>
*/
public class CallGraphDecoder {
protected final GmonDecoder decoder;
private final Map<ISymbol, CallGraphNode> nodes = new HashMap<>();
/**
* Constructor
* @param decoder the Gmon decoder
*/
public CallGraphDecoder(GmonDecoder decoder) {
this.decoder = decoder;
}
/**
* Decode call-graph record from gmon file.
* @param stream
* @throws IOException
*/
public void decodeCallGraphRecord(DataInput stream, boolean BSDFormat) throws IOException {
long from_pc = readAddress(stream);
long self_pc = readAddress(stream);
int count = BSDFormat?(int)readAddress(stream):stream.readInt();
IBinaryObject program = decoder.getProgram();
IAddressFactory addressFactory = program.getAddressFactory();
IAddress parentAddress = addressFactory.createAddress(Long.toString(from_pc));
ISymbol parentSymbol = program.getSymbol(parentAddress);
IAddress childAddress = addressFactory.createAddress(Long.toString(self_pc));
ISymbol childSymbol = program.getSymbol(childAddress);
if (childSymbol == null || parentSymbol == null) {
return;
}
addCallArc(parentSymbol, parentAddress, childSymbol, count);
}
protected long readAddress(DataInput stream) throws IOException {
long ret = stream.readInt() & 0xFFFFFFFFL;
return ret;
}
private void addCallArc(ISymbol parent, IAddress parentAddress, ISymbol child, int count) {
CallGraphNode parentNode = nodes.get(parent);
CallGraphNode childNode = nodes.get(child);
if (parentNode == null) {
parentNode = new CallGraphNode(parent);
nodes.put(parent, parentNode);
}
if (childNode == null) {
childNode = new CallGraphNode(child);
nodes.put(child, childNode);
}
CallGraphArc arc = parentNode.getOutputArc(childNode);
if (arc == null) {
arc = new CallGraphArc(parentNode, parentAddress, childNode, count, decoder.getProgram(), decoder.getProject());
parentNode.getChildren().add(arc);
childNode.getParents().add(arc);
} else {
arc.setCount(arc.getCount() + count);
}
}
void populate(HistRoot rootNode) {
for (CallGraphNode callGraphNode : nodes.values()) {
rootNode.addCallGraphNode(callGraphNode);
}
}
}