1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
/*******************************************************************************
* 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.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.gprof.symbolManager.CallGraphArc;
import org.eclipse.linuxtools.gprof.symbolManager.CallGraphNode;
import org.eclipse.linuxtools.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<ISymbol, CallGraphNode>();
/**
* 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;
}
public 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());
parentNode.getChildren().add(arc);
childNode.getParents().add(arc);
} else {
arc.setCount(arc.getCount() + count);
}
}
/**
* @return the nodes
*/
public Map<ISymbol, CallGraphNode> getNodes() {
return nodes;
}
void populate(HistRoot rootNode) {
for (CallGraphNode callGraphNode : getNodes().values()) {
rootNode.addCallGraphNode(callGraphNode);
}
}
}
|