[CodeView] Add support for dumping binary annotations

Binary annotations are encoded along the lines of UTF-8 and ECI but with
a few minor differences.

The algorithm specified in "ECMA-335 CLI Section II.3.2 - Blobs and
Signatures" is used to compress binary annotations.  Signed binary
annotations are encoded like unsigned annotations except the sign bit is
rotated left to reduce the number of bits needed to be encoded.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@257742 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Majnemer 2016-01-14 06:12:30 +00:00
parent e6075bdf86
commit 294255bbe4
2 changed files with 117 additions and 1 deletions

View File

@ -66,6 +66,23 @@ struct ProcSym {
// Name: The null-terminated name follows.
};
enum BinaryAnnotationsOpCode : uint32_t {
Invalid,
CodeOffset,
ChangeCodeOffsetBase,
ChangeCodeOffset,
ChangeCodeLength,
ChangeFile,
ChangeLineOffset,
ChangeLineEndDelta,
ChangeRangeKind,
ChangeColumnStart,
ChangeColumnEndDelta,
ChangeCodeOffsetAndLineOffset,
ChangeCodeLengthAndCodeOffset,
ChangeColumnEnd,
};
// S_INLINESITE
struct InlineSiteSym {
ulittle32_t PtrParent;

View File

@ -1321,7 +1321,106 @@ void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection,
W.printHex("PtrParent", InlineSite->PtrParent);
W.printHex("PtrEnd", InlineSite->PtrEnd);
printTypeIndex("Inlinee", InlineSite->Inlinee);
W.printBinaryBlock("BinaryAnnotations", SymData);
auto GetCompressedAnnotation = [&]() -> uint32_t {
if (SymData.empty())
return -1;
uint8_t FirstByte = SymData.front();
SymData = SymData.drop_front();
if ((FirstByte & 0x80) == 0x00)
return FirstByte;
if (SymData.empty())
return -1;
uint8_t SecondByte = SymData.front();
SymData = SymData.drop_front();
if ((FirstByte & 0xC0) == 0x80)
return ((FirstByte & 0x3F) << 8) | SecondByte;
if (SymData.empty())
return -1;
uint8_t ThirdByte = SymData.front();
SymData = SymData.drop_front();
if (SymData.empty())
return -1;
uint8_t FourthByte = SymData.front();
SymData = SymData.drop_front();
if ((FirstByte & 0xE0) == 0xC0)
return ((FirstByte & 0x1F) << 24) | (SecondByte << 16) |
(ThirdByte << 8) | FourthByte;
return -1;
};
auto DecodeSignedOperand = [](uint32_t Operand) -> int32_t {
if (Operand & 1)
return -(Operand >> 1);
return Operand >> 1;
};
ListScope BinaryAnnotations(W, "BinaryAnnotations");
while (!SymData.empty()) {
uint32_t OpCode = GetCompressedAnnotation();
switch (OpCode) {
default:
case Invalid:
return error(object_error::parse_failed);
case CodeOffset:
W.printNumber("CodeOffset", GetCompressedAnnotation());
break;
case ChangeCodeOffsetBase:
W.printNumber("ChangeCodeOffsetBase", GetCompressedAnnotation());
break;
case ChangeCodeOffset:
W.printNumber("ChangeCodeOffset", GetCompressedAnnotation());
break;
case ChangeCodeLength:
W.printNumber("ChangeCodeLength", GetCompressedAnnotation());
break;
case ChangeFile:
W.printNumber("ChangeFile", GetCompressedAnnotation());
break;
case ChangeLineOffset:
W.printNumber("ChangeLineOffset",
DecodeSignedOperand(GetCompressedAnnotation()));
break;
case ChangeLineEndDelta:
W.printNumber("ChangeLineEndDelta", GetCompressedAnnotation());
break;
case ChangeRangeKind:
W.printNumber("ChangeRangeKind", GetCompressedAnnotation());
break;
case ChangeColumnStart:
W.printNumber("ChangeColumnStart", GetCompressedAnnotation());
break;
case ChangeColumnEndDelta:
W.printNumber("ChangeColumnEndDelta",
DecodeSignedOperand(GetCompressedAnnotation()));
break;
case ChangeCodeOffsetAndLineOffset: {
uint32_t Annotation = GetCompressedAnnotation();
uint32_t Operands[] = {Annotation >> 4, Annotation & 0xf};
W.printList("ChangeCodeOffsetAndLineOffset", Operands);
break;
}
case ChangeCodeLengthAndCodeOffset: {
uint32_t Operands[] = {GetCompressedAnnotation(),
GetCompressedAnnotation()};
W.printList("ChangeCodeLengthAndCodeOffset", Operands);
break;
}
case ChangeColumnEnd:
W.printNumber("ChangeColumnEnd", GetCompressedAnnotation());
break;
}
}
break;
}