You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
156
mcs/tools/mono-symbolicate/SeqPointInfo.cs
Normal file
156
mcs/tools/mono-symbolicate/SeqPointInfo.cs
Normal file
@@ -0,0 +1,156 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Mono
|
||||
{
|
||||
static class BinaryReaderExtensions
|
||||
{
|
||||
public static int ReadVariableInt (this BinaryReader reader)
|
||||
{
|
||||
int val = 0;
|
||||
for (var i = 0; i < 4; i++) {
|
||||
var b = reader.ReadByte ();
|
||||
val |= (b & 0x7f) << (7 * i);
|
||||
if ((b & 0x80) == 0)
|
||||
return val;
|
||||
}
|
||||
|
||||
throw new Exception ("Invalid variable int");
|
||||
}
|
||||
|
||||
public static int ReadVariableZigZagInt (this BinaryReader reader)
|
||||
{
|
||||
int enc = ReadVariableInt (reader);
|
||||
int val = enc >> 1;
|
||||
return ((enc & 1) == 0)? val : -val;
|
||||
}
|
||||
}
|
||||
|
||||
class SeqPointInfo
|
||||
{
|
||||
class MethodData
|
||||
{
|
||||
List<SeqPoint> seqPoints;
|
||||
|
||||
public static MethodData Read (BinaryReader reader)
|
||||
{
|
||||
var hasDebugData = reader.ReadVariableInt () != 0;
|
||||
var dataSize = reader.ReadVariableInt ();
|
||||
var dataEnd = reader.BaseStream.Position + dataSize;
|
||||
|
||||
var seqPoints = new List<SeqPoint> ();
|
||||
SeqPoint prev = null;
|
||||
while (reader.BaseStream.Position < dataEnd) {
|
||||
var seqPoint = SeqPoint.Read (reader, prev, hasDebugData);
|
||||
seqPoints.Add (seqPoint);
|
||||
prev = seqPoint;
|
||||
}
|
||||
|
||||
if (reader.BaseStream.Position != dataEnd)
|
||||
throw new Exception ("Read more seq point than expected.");
|
||||
|
||||
return new MethodData () { seqPoints = seqPoints };
|
||||
}
|
||||
|
||||
public bool TryGetILOffset (int nativeOffset, out int ilOffset)
|
||||
{
|
||||
ilOffset = 0;
|
||||
SeqPoint prev = null;
|
||||
foreach (var seqPoint in seqPoints) {
|
||||
if (seqPoint.NativeOffset > nativeOffset)
|
||||
break;
|
||||
prev = seqPoint;
|
||||
}
|
||||
|
||||
if (prev == null)
|
||||
return false;
|
||||
|
||||
ilOffset = prev.ILOffset;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class SeqPoint
|
||||
{
|
||||
public readonly int ILOffset;
|
||||
public readonly int NativeOffset;
|
||||
|
||||
public SeqPoint (int ilOffset, int nativeOffset)
|
||||
{
|
||||
ILOffset = ilOffset;
|
||||
NativeOffset = nativeOffset;
|
||||
}
|
||||
|
||||
public static SeqPoint Read (BinaryReader reader, SeqPoint prev, bool hasDebug)
|
||||
{
|
||||
var ilOffset = reader.ReadVariableZigZagInt ();
|
||||
var nativeOffset = reader.ReadVariableZigZagInt ();
|
||||
|
||||
// Respect delta encoding
|
||||
if (prev != null) {
|
||||
ilOffset += prev.ILOffset;
|
||||
nativeOffset += prev.NativeOffset;
|
||||
}
|
||||
|
||||
//Read everything to ensure the buffer position is at the end of the seq point data.
|
||||
if (hasDebug) {
|
||||
reader.ReadVariableInt (); // flags
|
||||
|
||||
var next_length = reader.ReadVariableInt ();
|
||||
for (var i = 0; i < next_length; ++i)
|
||||
reader.ReadVariableInt ();
|
||||
}
|
||||
|
||||
return new SeqPoint (ilOffset, nativeOffset);
|
||||
}
|
||||
};
|
||||
|
||||
Dictionary<Tuple<int,int>, MethodData> dataByIds;
|
||||
Dictionary<int, MethodData> dataByTokens;
|
||||
|
||||
public static SeqPointInfo Read (string path)
|
||||
{
|
||||
using (var reader = new BinaryReader (File.Open (path, FileMode.Open)))
|
||||
{
|
||||
var dataByIds = new Dictionary<Tuple<int,int>, MethodData> ();
|
||||
var dataByTokens = new Dictionary<int, MethodData> ();
|
||||
|
||||
var methodCount = reader.ReadVariableInt ();
|
||||
|
||||
for (var i = 0; i < methodCount; ++i) {
|
||||
var methodToken = reader.ReadVariableInt ();
|
||||
var methodIndex = reader.ReadVariableInt ();
|
||||
var methodId = new Tuple<int, int> (methodToken, methodIndex);
|
||||
|
||||
var methodData = MethodData.Read (reader);
|
||||
|
||||
dataByIds.Add (methodId, methodData);
|
||||
if (!dataByTokens.ContainsKey (methodToken))
|
||||
dataByTokens.Add (methodToken, methodData);
|
||||
}
|
||||
|
||||
return new SeqPointInfo { dataByIds = dataByIds, dataByTokens = dataByTokens };
|
||||
}
|
||||
}
|
||||
|
||||
public int GetILOffset (int methodToken, uint methodIndex, int nativeOffset)
|
||||
{
|
||||
MethodData methodData;
|
||||
if (methodIndex == 0xffffff) {
|
||||
if (!dataByTokens.TryGetValue (methodToken, out methodData))
|
||||
throw new Exception (string.Format ("Could not find data for method token {0:X}", methodToken));
|
||||
} else {
|
||||
var methodId = new Tuple<int, int> (methodToken, (int)methodIndex);
|
||||
if (!dataByIds.TryGetValue (methodId, out methodData))
|
||||
throw new Exception (string.Format ("Could not find data for method token {0:X} with index {1:X}", methodToken, methodIndex));
|
||||
}
|
||||
|
||||
int ilOffset;
|
||||
if (!methodData.TryGetILOffset (nativeOffset, out ilOffset))
|
||||
throw new Exception ("Could not retrieve IL offset");
|
||||
|
||||
return ilOffset;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user