Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Commit

Permalink
R2RDump - Documentation (#19497)
Browse files Browse the repository at this point in the history
* Add comments

* Add README

* Use href links, disable disasm
  • Loading branch information
acmyu authored Aug 17, 2018
1 parent 4e89ab7 commit 07330ca
Show file tree
Hide file tree
Showing 23 changed files with 322 additions and 34 deletions.
53 changes: 35 additions & 18 deletions src/tools/r2rdump/Amd64/GcInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ namespace R2RDump.Amd64
{
public class GcInfo : BaseGcInfo
{
/// <summary>
/// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/inc/gcinfodecoder.h">src/inc/gcinfodecoder.h</a> GcInfoHeaderFlags
/// </summary>
private enum GcInfoHeaderFlags
{
GC_INFO_IS_VARARG = 0x1,
Expand Down Expand Up @@ -81,6 +84,9 @@ public SafePointOffset(int index, uint value)

public GcInfo() { }

/// <summary>
/// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/vm/gcinfodecoder.cpp">GcInfoDecoder::GcInfoDecoder</a>
/// </summary>
public GcInfo(byte[] image, int offset, Machine machine, ushort majorVersion)
{
Offset = offset;
Expand Down Expand Up @@ -253,19 +259,14 @@ public override string ToString()
}
sb.AppendLine($"\tSlotTable:");
sb.Append(SlotTable.ToString());
sb.AppendLine($"\tTransitions:");
foreach (List<BaseGcTransition> transList in Transitions.Values)
{
foreach (GcTransition trans in transList)
{
sb.AppendLine("\t\t" + trans.ToString());
}
}
sb.AppendLine($"\tSize: {Size} bytes");

return sb.ToString();
}

/// <summary>
/// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/vm/gcinfodecoder.cpp">GcInfoDecoder::GcInfoDecoder</a>
/// </summary>
private void ParseHeaderFlags(byte[] image, ref int bitOffset)
{
GcInfoHeaderFlags headerFlags;
Expand Down Expand Up @@ -305,6 +306,9 @@ private List<SafePointOffset> EnumerateSafePoints(byte[] image, ref int bitOffse
return safePoints;
}

/// <summary>
/// based on beginning of <a href="https://github.com/dotnet/coreclr/blob/master/src/vm/gcinfodecoder.cpp">GcInfoDecoder::EnumerateLiveSlots</a>
/// </summary>
private List<InterruptibleRange> EnumerateInterruptibleRanges(byte[] image, int interruptibleRangeDelta1EncBase, int interruptibleRangeDelta2EncBase, ref int bitOffset)
{
List<InterruptibleRange> ranges = new List<InterruptibleRange>();
Expand Down Expand Up @@ -333,6 +337,9 @@ private int ReadyToRunVersionToGcInfoVersion(int readyToRunMajorVersion)
return (readyToRunMajorVersion == 1) ? 1 : GCINFO_VERSION;
}

/// <summary>
/// based on end of <a href="https://github.com/dotnet/coreclr/blob/master/src/vm/gcinfodecoder.cpp">GcInfoDecoder::EnumerateLiveSlots and GcInfoEncoder::Build</a>
/// </summary>
public Dictionary<int, List<BaseGcTransition>> GetTranstions(byte[] image, ref int bitOffset)
{
int totalInterruptibleLength = 0;
Expand All @@ -348,22 +355,25 @@ public Dictionary<int, List<BaseGcTransition>> GetTranstions(byte[] image, ref i
}
}

int numChunks = (totalInterruptibleLength + _gcInfoTypes.NUM_NORM_CODE_OFFSETS_PER_CHUNK - 1) / _gcInfoTypes.NUM_NORM_CODE_OFFSETS_PER_CHUNK; //=2
int numChunks = (totalInterruptibleLength + _gcInfoTypes.NUM_NORM_CODE_OFFSETS_PER_CHUNK - 1) / _gcInfoTypes.NUM_NORM_CODE_OFFSETS_PER_CHUNK;
int numBitsPerPointer = (int)NativeReader.DecodeVarLengthUnsigned(image, _gcInfoTypes.POINTER_SIZE_ENCBASE, ref bitOffset);
if (numBitsPerPointer == 0)
{
return new Dictionary<int, List<BaseGcTransition>>();
}

// get offsets of each chunk
int[] chunkPointers = new int[numChunks];
for (int i = 0; i < numChunks; i++)
{
chunkPointers[i] = NativeReader.ReadBits(image, numBitsPerPointer, ref bitOffset);
}

// Offset to m_Info2 containing all the info on register liveness
int info2Offset = (int)Math.Ceiling(bitOffset / 8.0) * 8;

List<GcTransition> transitions = new List<GcTransition>();
bool[] liveAtEnd = new bool[SlotTable.GcSlots.Count - SlotTable.NumUntracked];
bool[] liveAtEnd = new bool[SlotTable.GcSlots.Count - SlotTable.NumUntracked]; // true if slot is live at the end of the chunk
for (int currentChunk = 0; currentChunk < numChunks; currentChunk++)
{
if (chunkPointers[currentChunk] == 0)
Expand All @@ -375,7 +385,7 @@ public Dictionary<int, List<BaseGcTransition>> GetTranstions(byte[] image, ref i
bitOffset = info2Offset + chunkPointers[currentChunk] - 1;
}

int couldBeLiveOffset = bitOffset;
int couldBeLiveOffset = bitOffset; // points to the couldBeLive bit array (array of bits indicating the slot changed state in the chunk)
int slotId = 0;
bool fSimple = (NativeReader.ReadBits(image, 1, ref couldBeLiveOffset) == 0);
bool fSkipFirst = false;
Expand All @@ -386,20 +396,22 @@ public Dictionary<int, List<BaseGcTransition>> GetTranstions(byte[] image, ref i
slotId = -1;
}

uint numCouldBeLiveSlots = GetNumCouldBeLiveSlots(image, ref bitOffset);
uint numCouldBeLiveSlots = GetNumCouldBeLiveSlots(image, ref bitOffset); // count the number of set bits in the couldBeLive array

int finalStateOffset = bitOffset;
bitOffset += (int)numCouldBeLiveSlots;
int finalStateOffset = bitOffset; // points to the finalState bit array (array of bits indicating if the slot is live at the end of the chunk)
bitOffset += (int)numCouldBeLiveSlots; // points to the array of code offsets

int normChunkBaseCodeOffset = currentChunk * _gcInfoTypes.NUM_NORM_CODE_OFFSETS_PER_CHUNK;
int normChunkBaseCodeOffset = currentChunk * _gcInfoTypes.NUM_NORM_CODE_OFFSETS_PER_CHUNK; // the sum of the sizes of all preceeding chunks
for (int i = 0; i < numCouldBeLiveSlots; i++)
{
// get the index of the next couldBeLive slot
slotId = GetNextSlotId(image, fSimple, fSkipFirst, slotId, ref couldBeLiveCnt, ref couldBeLiveOffset);

// set the liveAtEnd for the slot at slotId
bool isLive = !liveAtEnd[slotId];
liveAtEnd[slotId] = (NativeReader.ReadBits(image, 1, ref finalStateOffset) != 0);

// Read transitions
// Read all the code offsets where the slot at slotId changed state
while (NativeReader.ReadBits(image, 1, ref bitOffset) != 0)
{
int transitionOffset = NativeReader.ReadBits(image, _gcInfoTypes.NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2, ref bitOffset) + normChunkBaseCodeOffset;
Expand All @@ -410,8 +422,8 @@ public Dictionary<int, List<BaseGcTransition>> GetTranstions(byte[] image, ref i
}
}

// convert normCodeOffsetDelta to the actual CodeOffset
transitions.Sort((s1, s2) => s1.CodeOffset.CompareTo(s2.CodeOffset));

return UpdateTransitionCodeOffset(transitions);
}

Expand Down Expand Up @@ -440,6 +452,7 @@ private uint GetNumCouldBeLiveSlots(byte[] image, ref int bitOffset)
}
else
{
// count the number of set bits in the couldBeLive bit array
foreach (var slot in SlotTable.GcSlots)
{
if (slot.Flags == GcSlotFlags.GC_SLOT_UNTRACKED)
Expand All @@ -456,6 +469,7 @@ private int GetNextSlotId(byte[] image, bool fSimple, bool fSkipFirst, int slotI
{
if (fSimple)
{
// Get the slotId by iterating through the couldBeLive bit array. The slotId is the index of the next set bit
while (NativeReader.ReadBits(image, 1, ref couldBeLiveOffset) == 0)
slotId++;
}
Expand All @@ -480,10 +494,13 @@ private int GetNextSlotId(byte[] image, bool fSimple, bool fSkipFirst, int slotI
return slotId;
}

/// <summary>
/// convert normCodeOffsetDelta to the actual CodeOffset
/// </summary>
private Dictionary<int, List<BaseGcTransition>> UpdateTransitionCodeOffset(List<GcTransition> transitions)
{
Dictionary<int, List<BaseGcTransition>> updatedTransitions = new Dictionary<int, List<BaseGcTransition>>();
int cumInterruptibleLength = 0;
int cumInterruptibleLength = 0; // the sum of the lengths of all preceeding interruptible ranges
using (IEnumerator<InterruptibleRange> interruptibleRangesIter = InterruptibleRanges.GetEnumerator())
{
interruptibleRangesIter.MoveNext();
Expand Down
3 changes: 3 additions & 0 deletions src/tools/r2rdump/Amd64/GcSlotTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ public override string ToString()

public GcSlotTable() { }

/// <summary>
/// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/vm/gcinfodecoder.cpp">GcSlotDecoder::DecodeSlotTable</a>
/// </summary>
public GcSlotTable(byte[] image, Machine machine, GcInfoTypes gcInfoTypes, ref int bitOffset)
{
if (NativeReader.ReadBits(image, 1, ref bitOffset) != 0)
Expand Down
3 changes: 3 additions & 0 deletions src/tools/r2rdump/Amd64/Registers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

namespace R2RDump.Amd64
{
/// <summary>
/// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/gcdump/gcdumpnonx86.cpp">src\gcdump\gcdumpnonx86.cpp</a> GetRegName
/// </summary>
public enum Registers
{
EAX = 0,
Expand Down
18 changes: 18 additions & 0 deletions src/tools/r2rdump/Amd64/UnwindInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

namespace R2RDump.Amd64
{
/// <summary>
/// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/inc/win64unwind.h">src\inc\win64unwind.h</a> _UNWIND_OP_CODES
/// </summary>
public enum UnwindOpCodes
{
UWOP_PUSH_NONVOL = 0,
Expand All @@ -23,6 +26,9 @@ public enum UnwindOpCodes
UWOP_SET_FPREG_LARGE,
}

/// <summary>
/// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/inc/win64unwind.h">src\inc\win64unwind.h</a> _UNWIND_OP_CODES
/// </summary>
public enum UnwindFlags
{
UNW_FLAG_NHANDLER = 0x0,
Expand All @@ -31,6 +37,9 @@ public enum UnwindFlags
UNW_FLAG_CHAININFO = 0x4,
}

/// <summary>
/// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/inc/win64unwind.h">src\inc\win64unwind.h</a> _UNWIND_CODE
/// </summary>
public struct UnwindCode
{
[XmlAttribute("Index")]
Expand Down Expand Up @@ -62,6 +71,9 @@ public UnwindCode(byte[] image, int index, ref int offset)
}
}

/// <summary>
/// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/inc/win64unwind.h">src\inc\win64unwind.h</a> _UNWIND_INFO
/// </summary>
public class UnwindInfo : BaseUnwindInfo
{
private const int _sizeofUnwindCode = 2;
Expand All @@ -78,6 +90,9 @@ public class UnwindInfo : BaseUnwindInfo

public UnwindInfo() { }

/// <summary>
/// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/zap/zapcode.cpp">ZapUnwindData::Save</a>
/// </summary>
public UnwindInfo(byte[] image, int offset)
{
byte versionAndFlags = NativeReader.ReadByte(image, ref offset);
Expand Down Expand Up @@ -140,6 +155,9 @@ public override string ToString()
return sb.ToString();
}

/// <summary>
/// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/jit/unwindamd64.cpp">src\jit\unwindamd64.cpp</a> DumpUnwindInfo
/// </summary>
private string GetUnwindCode(ref int i)
{
StringBuilder sb = new StringBuilder();
Expand Down
13 changes: 10 additions & 3 deletions src/tools/r2rdump/GCInfoTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

namespace R2RDump
{
/// <summary>
/// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/inc/gcinfotypes.h">src\inc\gcinfotypes.h</a> infoHdrAdjustConstants
/// </summary>
enum InfoHdrAdjustConstants
{
// Constants
Expand All @@ -22,9 +25,10 @@ enum InfoHdrAdjustConstants
MORE_BYTES_TO_FOLLOW = 0x80
};

//
// Enum to define codes that are used to incrementally adjust the InfoHdr structure.
// First set of opcodes
/// <summary>
/// Enum to define codes that are used to incrementally adjust the InfoHdr structure.
/// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/inc/gcinfotypes.h">src\inc\gcinfotypes.h</a> infoHdrAdjustConstants
/// </summary>
enum InfoHdrAdjust
{
SET_FRAMESIZE = 0, // 0x00
Expand Down Expand Up @@ -64,6 +68,9 @@ enum InfoHdrAdjust
NEXT_THREE_EPILOGSIZE = 0x78
};

/// <summary>
/// based on macros defined in <a href="https://github.com/dotnet/coreclr/blob/master/src/inc/gcinfotypes.h">src\inc\gcinfotypes.h</a>
/// </summary>
public class GcInfoTypes
{
private Machine _target;
Expand Down
3 changes: 3 additions & 0 deletions src/tools/r2rdump/NativeArray.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

namespace R2RDump
{
/// <summary>
/// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/vm/nativeformatreader.h">NativeFormat::NativeArray</a>
/// </summary>
class NativeArray
{
private const int _blockSize = 16;
Expand Down
6 changes: 6 additions & 0 deletions src/tools/r2rdump/NativeHashtable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

namespace R2RDump
{
/// <summary>
/// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/vm/nativeformatreader.h">NativeFormat::NativeParser</a>
/// </summary>
struct NativeParser
{
/// <summary>
Expand Down Expand Up @@ -76,6 +79,9 @@ public int GetSigned()
}
}

/// <summary>
/// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/vm/nativeformatreader.h">NativeFormat::NativeHashtable</a>
/// </summary>
struct NativeHashtable
{
private byte[] _image;
Expand Down
23 changes: 21 additions & 2 deletions src/tools/r2rdump/NativeReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ public static int ReadBits(byte[] image, int numBits, ref int bitOffset)

// <summary>
/// Decode variable length numbers
/// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/inc/gcinfodecoder.h">src\inc\gcinfodecoder.h</a> DecodeVarLengthUnsigned
/// </summary>
/// <param name="image">PE image</param>
/// <param name="len">Number of bits to read</param>
Expand All @@ -150,6 +151,9 @@ public static uint DecodeVarLengthUnsigned(byte[] image, int len, ref int bitOff
}
}

// <summary>
/// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/inc/gcinfodecoder.h">src\inc\gcinfodecoder.h</a> DecodeVarLengthSigned
/// </summary>
public static int DecodeVarLengthSigned(byte[] image, int len, ref int bitOffset)
{
int numEncodings = (1 << len);
Expand All @@ -169,6 +173,9 @@ public static int DecodeVarLengthSigned(byte[] image, int len, ref int bitOffset
}
}

// <summary>
/// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/vm/nativeformatreader.h">src\vm\nativeformatreader.h</a> DecodeUnsigned
/// </summary>
public static uint DecodeUnsigned(byte[] image, uint offset, ref uint pValue)
{
if (offset >= image.Length)
Expand Down Expand Up @@ -225,6 +232,9 @@ public static uint DecodeUnsigned(byte[] image, uint offset, ref uint pValue)
return offset;
}

// <summary>
/// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/vm/nativeformatreader.h">src\vm\nativeformatreader.h</a> DecodeSigned
/// </summary>
public static uint DecodeSigned(byte[] image, uint offset, ref int pValue)
{
if (offset >= image.Length)
Expand Down Expand Up @@ -281,6 +291,9 @@ public static uint DecodeSigned(byte[] image, uint offset, ref int pValue)
return offset;
}

// <summary>
/// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/debug/daccess/nidump.cpp">src\debug\daccess\nidump.cpp</a> DacSigUncompressData and DacSigUncompressBigData
/// </summary>
public static uint ReadCompressedData(byte[] image, ref int start)
{
int off = start;
Expand All @@ -306,7 +319,7 @@ public static uint ReadCompressedData(byte[] image, ref int start)
}

/// <summary>
/// Based on decodeUnsigned in gcdecoder.cpp, used by the x86 gcdump and unwindinfo
/// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/inc/gcdecoder.cpp">src\inc\gcdecoder.cpp</a> decodeUnsigned
/// </summary>
public static uint DecodeUnsignedGc(byte[] image, ref int start)
{
Expand All @@ -323,7 +336,10 @@ public static uint DecodeUnsignedGc(byte[] image, ref int start)
return value;
}

public static int DecodeSigned(byte[] image, ref int start)
/// <summary>
/// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/inc/gcdecoder.cpp">src\inc\gcdecoder.cpp</a> decodeSigned
/// </summary>
public static int DecodeSignedGc(byte[] image, ref int start)
{
int size = 1;
byte data = image[start++];
Expand All @@ -342,6 +358,9 @@ public static int DecodeSigned(byte[] image, ref int start)
return value;
}

/// <summary>
/// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/inc/gcdecoder.cpp">src\inc\gcdecoder.cpp</a> decodeUDelta
/// </summary>
public static uint DecodeUDelta(byte[] image, ref int start, uint lastValue)
{
uint delta = DecodeUnsignedGc(image, ref start);
Expand Down
Loading

0 comments on commit 07330ca

Please sign in to comment.