diff options
Diffstat (limited to 'lib/DebugInfo')
66 files changed, 2724 insertions, 960 deletions
diff --git a/lib/DebugInfo/CodeView/CVTypeVisitor.cpp b/lib/DebugInfo/CodeView/CVTypeVisitor.cpp index ec4773d571c8..dd6f75f97a4a 100644 --- a/lib/DebugInfo/CodeView/CVTypeVisitor.cpp +++ b/lib/DebugInfo/CodeView/CVTypeVisitor.cpp @@ -209,14 +209,6 @@ struct VisitHelper { } } - VisitHelper(TypeVisitorCallbackPipeline &Callbacks, VisitorDataSource Source) - : Visitor((Source == VDS_BytesPresent) ? Pipeline : Callbacks) { - if (Source == VDS_BytesPresent) { - Pipeline = Callbacks; - Pipeline.addCallbackToPipelineFront(Deserializer); - } - } - TypeDeserializer Deserializer; TypeVisitorCallbackPipeline Pipeline; CVTypeVisitor Visitor; @@ -230,13 +222,6 @@ Error llvm::codeview::visitTypeRecord(CVType &Record, TypeIndex Index, return V.Visitor.visitTypeRecord(Record, Index); } -Error llvm::codeview::visitTypeRecord(CVType &Record, TypeIndex Index, - TypeVisitorCallbackPipeline &Callbacks, - VisitorDataSource Source) { - VisitHelper V(Callbacks, Source); - return V.Visitor.visitTypeRecord(Record, Index); -} - Error llvm::codeview::visitTypeRecord(CVType &Record, TypeVisitorCallbacks &Callbacks, VisitorDataSource Source) { diff --git a/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp b/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp index 2f49474115a1..36a384baa13d 100644 --- a/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp +++ b/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp @@ -20,7 +20,6 @@ Error CodeViewRecordIO::beginRecord(Optional<uint32_t> MaxLength) { Limit.MaxLength = MaxLength; Limit.BeginOffset = getCurrentOffset(); Limits.push_back(Limit); - resetStreamedLen(); return Error::success(); } @@ -50,6 +49,7 @@ Error CodeViewRecordIO::endRecord() { Streamer->EmitBytes(BytesSR); --PaddingBytes; } + resetStreamedLen(); } return Error::success(); } @@ -126,7 +126,11 @@ Error CodeViewRecordIO::mapByteVectorTail(std::vector<uint8_t> &Bytes, Error CodeViewRecordIO::mapInteger(TypeIndex &TypeInd, const Twine &Comment) { if (isStreaming()) { - emitComment(Comment); + std::string TypeNameStr = Streamer->getTypeName(TypeInd); + if (!TypeNameStr.empty()) + emitComment(Comment + ": " + TypeNameStr); + else + emitComment(Comment); Streamer->EmitIntValue(TypeInd.getIndex(), sizeof(TypeInd.getIndex())); incrStreamedLen(sizeof(TypeInd.getIndex())); } else if (isWriting()) { diff --git a/lib/DebugInfo/CodeView/EnumTables.cpp b/lib/DebugInfo/CodeView/EnumTables.cpp index 54e68ae4ea9f..82f6713a88f5 100644 --- a/lib/DebugInfo/CodeView/EnumTables.cpp +++ b/lib/DebugInfo/CodeView/EnumTables.cpp @@ -300,6 +300,128 @@ static const EnumEntry<COFF::SectionCharacteristics> CV_ENUM_ENT(COFF, IMAGE_SCN_MEM_READ), CV_ENUM_ENT(COFF, IMAGE_SCN_MEM_WRITE)}; +static const EnumEntry<uint16_t> ClassOptionNames[] = { + CV_ENUM_CLASS_ENT(ClassOptions, Packed), + CV_ENUM_CLASS_ENT(ClassOptions, HasConstructorOrDestructor), + CV_ENUM_CLASS_ENT(ClassOptions, HasOverloadedOperator), + CV_ENUM_CLASS_ENT(ClassOptions, Nested), + CV_ENUM_CLASS_ENT(ClassOptions, ContainsNestedClass), + CV_ENUM_CLASS_ENT(ClassOptions, HasOverloadedAssignmentOperator), + CV_ENUM_CLASS_ENT(ClassOptions, HasConversionOperator), + CV_ENUM_CLASS_ENT(ClassOptions, ForwardReference), + CV_ENUM_CLASS_ENT(ClassOptions, Scoped), + CV_ENUM_CLASS_ENT(ClassOptions, HasUniqueName), + CV_ENUM_CLASS_ENT(ClassOptions, Sealed), + CV_ENUM_CLASS_ENT(ClassOptions, Intrinsic), +}; + +static const EnumEntry<uint8_t> MemberAccessNames[] = { + CV_ENUM_CLASS_ENT(MemberAccess, None), + CV_ENUM_CLASS_ENT(MemberAccess, Private), + CV_ENUM_CLASS_ENT(MemberAccess, Protected), + CV_ENUM_CLASS_ENT(MemberAccess, Public), +}; + +static const EnumEntry<uint16_t> MethodOptionNames[] = { + CV_ENUM_CLASS_ENT(MethodOptions, Pseudo), + CV_ENUM_CLASS_ENT(MethodOptions, NoInherit), + CV_ENUM_CLASS_ENT(MethodOptions, NoConstruct), + CV_ENUM_CLASS_ENT(MethodOptions, CompilerGenerated), + CV_ENUM_CLASS_ENT(MethodOptions, Sealed), +}; + +static const EnumEntry<uint16_t> MemberKindNames[] = { + CV_ENUM_CLASS_ENT(MethodKind, Vanilla), + CV_ENUM_CLASS_ENT(MethodKind, Virtual), + CV_ENUM_CLASS_ENT(MethodKind, Static), + CV_ENUM_CLASS_ENT(MethodKind, Friend), + CV_ENUM_CLASS_ENT(MethodKind, IntroducingVirtual), + CV_ENUM_CLASS_ENT(MethodKind, PureVirtual), + CV_ENUM_CLASS_ENT(MethodKind, PureIntroducingVirtual), +}; + +static const EnumEntry<uint8_t> PtrKindNames[] = { + CV_ENUM_CLASS_ENT(PointerKind, Near16), + CV_ENUM_CLASS_ENT(PointerKind, Far16), + CV_ENUM_CLASS_ENT(PointerKind, Huge16), + CV_ENUM_CLASS_ENT(PointerKind, BasedOnSegment), + CV_ENUM_CLASS_ENT(PointerKind, BasedOnValue), + CV_ENUM_CLASS_ENT(PointerKind, BasedOnSegmentValue), + CV_ENUM_CLASS_ENT(PointerKind, BasedOnAddress), + CV_ENUM_CLASS_ENT(PointerKind, BasedOnSegmentAddress), + CV_ENUM_CLASS_ENT(PointerKind, BasedOnType), + CV_ENUM_CLASS_ENT(PointerKind, BasedOnSelf), + CV_ENUM_CLASS_ENT(PointerKind, Near32), + CV_ENUM_CLASS_ENT(PointerKind, Far32), + CV_ENUM_CLASS_ENT(PointerKind, Near64), +}; + +static const EnumEntry<uint8_t> PtrModeNames[] = { + CV_ENUM_CLASS_ENT(PointerMode, Pointer), + CV_ENUM_CLASS_ENT(PointerMode, LValueReference), + CV_ENUM_CLASS_ENT(PointerMode, PointerToDataMember), + CV_ENUM_CLASS_ENT(PointerMode, PointerToMemberFunction), + CV_ENUM_CLASS_ENT(PointerMode, RValueReference), +}; + +static const EnumEntry<uint16_t> PtrMemberRepNames[] = { + CV_ENUM_CLASS_ENT(PointerToMemberRepresentation, Unknown), + CV_ENUM_CLASS_ENT(PointerToMemberRepresentation, SingleInheritanceData), + CV_ENUM_CLASS_ENT(PointerToMemberRepresentation, MultipleInheritanceData), + CV_ENUM_CLASS_ENT(PointerToMemberRepresentation, VirtualInheritanceData), + CV_ENUM_CLASS_ENT(PointerToMemberRepresentation, GeneralData), + CV_ENUM_CLASS_ENT(PointerToMemberRepresentation, SingleInheritanceFunction), + CV_ENUM_CLASS_ENT(PointerToMemberRepresentation, + MultipleInheritanceFunction), + CV_ENUM_CLASS_ENT(PointerToMemberRepresentation, + VirtualInheritanceFunction), + CV_ENUM_CLASS_ENT(PointerToMemberRepresentation, GeneralFunction), +}; + +static const EnumEntry<uint16_t> TypeModifierNames[] = { + CV_ENUM_CLASS_ENT(ModifierOptions, Const), + CV_ENUM_CLASS_ENT(ModifierOptions, Volatile), + CV_ENUM_CLASS_ENT(ModifierOptions, Unaligned), +}; + +static const EnumEntry<uint8_t> CallingConventions[] = { + CV_ENUM_CLASS_ENT(CallingConvention, NearC), + CV_ENUM_CLASS_ENT(CallingConvention, FarC), + CV_ENUM_CLASS_ENT(CallingConvention, NearPascal), + CV_ENUM_CLASS_ENT(CallingConvention, FarPascal), + CV_ENUM_CLASS_ENT(CallingConvention, NearFast), + CV_ENUM_CLASS_ENT(CallingConvention, FarFast), + CV_ENUM_CLASS_ENT(CallingConvention, NearStdCall), + CV_ENUM_CLASS_ENT(CallingConvention, FarStdCall), + CV_ENUM_CLASS_ENT(CallingConvention, NearSysCall), + CV_ENUM_CLASS_ENT(CallingConvention, FarSysCall), + CV_ENUM_CLASS_ENT(CallingConvention, ThisCall), + CV_ENUM_CLASS_ENT(CallingConvention, MipsCall), + CV_ENUM_CLASS_ENT(CallingConvention, Generic), + CV_ENUM_CLASS_ENT(CallingConvention, AlphaCall), + CV_ENUM_CLASS_ENT(CallingConvention, PpcCall), + CV_ENUM_CLASS_ENT(CallingConvention, SHCall), + CV_ENUM_CLASS_ENT(CallingConvention, ArmCall), + CV_ENUM_CLASS_ENT(CallingConvention, AM33Call), + CV_ENUM_CLASS_ENT(CallingConvention, TriCall), + CV_ENUM_CLASS_ENT(CallingConvention, SH5Call), + CV_ENUM_CLASS_ENT(CallingConvention, M32RCall), + CV_ENUM_CLASS_ENT(CallingConvention, ClrCall), + CV_ENUM_CLASS_ENT(CallingConvention, Inline), + CV_ENUM_CLASS_ENT(CallingConvention, NearVector), +}; + +static const EnumEntry<uint8_t> FunctionOptionEnum[] = { + CV_ENUM_CLASS_ENT(FunctionOptions, CxxReturnUdt), + CV_ENUM_CLASS_ENT(FunctionOptions, Constructor), + CV_ENUM_CLASS_ENT(FunctionOptions, ConstructorWithVirtualBases), +}; + +static const EnumEntry<uint16_t> LabelTypeEnum[] = { + CV_ENUM_CLASS_ENT(LabelType, Near), + CV_ENUM_CLASS_ENT(LabelType, Far), +}; + namespace llvm { namespace codeview { @@ -379,5 +501,49 @@ getImageSectionCharacteristicNames() { return makeArrayRef(ImageSectionCharacteristicNames); } +ArrayRef<EnumEntry<uint16_t>> getClassOptionNames() { + return makeArrayRef(ClassOptionNames); +} + +ArrayRef<EnumEntry<uint8_t>> getMemberAccessNames() { + return makeArrayRef(MemberAccessNames); +} + +ArrayRef<EnumEntry<uint16_t>> getMethodOptionNames() { + return makeArrayRef(MethodOptionNames); +} + +ArrayRef<EnumEntry<uint16_t>> getMemberKindNames() { + return makeArrayRef(MemberKindNames); +} + +ArrayRef<EnumEntry<uint8_t>> getPtrKindNames() { + return makeArrayRef(PtrKindNames); +} + +ArrayRef<EnumEntry<uint8_t>> getPtrModeNames() { + return makeArrayRef(PtrModeNames); +} + +ArrayRef<EnumEntry<uint16_t>> getPtrMemberRepNames() { + return makeArrayRef(PtrMemberRepNames); +} + +ArrayRef<EnumEntry<uint16_t>> getTypeModifierNames() { + return makeArrayRef(TypeModifierNames); +} + +ArrayRef<EnumEntry<uint8_t>> getCallingConventions() { + return makeArrayRef(CallingConventions); +} + +ArrayRef<EnumEntry<uint8_t>> getFunctionOptionEnum() { + return makeArrayRef(FunctionOptionEnum); +} + +ArrayRef<EnumEntry<uint16_t>> getLabelTypeEnum() { + return makeArrayRef(LabelTypeEnum); +} + } // end namespace codeview } // end namespace llvm diff --git a/lib/DebugInfo/CodeView/SymbolDumper.cpp b/lib/DebugInfo/CodeView/SymbolDumper.cpp index 27cb7e35234b..45b63983beb4 100644 --- a/lib/DebugInfo/CodeView/SymbolDumper.cpp +++ b/lib/DebugInfo/CodeView/SymbolDumper.cpp @@ -315,7 +315,7 @@ Error CVSymbolDumperImpl::visitKnownRecord( Error CVSymbolDumperImpl::visitKnownRecord( CVSymbol &CVR, DefRangeFramePointerRelSym &DefRangeFramePointerRel) { - W.printNumber("Offset", DefRangeFramePointerRel.Offset); + W.printNumber("Offset", DefRangeFramePointerRel.Hdr.Offset); printLocalVariableAddrRange(DefRangeFramePointerRel.Range, DefRangeFramePointerRel.getRelocationOffset()); printLocalVariableAddrGap(DefRangeFramePointerRel.Gaps); diff --git a/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp b/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp index 70889839ef48..3b627930e271 100644 --- a/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp +++ b/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp @@ -229,7 +229,7 @@ Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, DataSym &Data) { Error SymbolRecordMapping::visitKnownRecord( CVSymbol &CVR, DefRangeFramePointerRelSym &DefRangeFramePointerRel) { - error(IO.mapInteger(DefRangeFramePointerRel.Offset)); + error(IO.mapObject(DefRangeFramePointerRel.Hdr.Offset)); error(mapLocalVariableAddrRange(IO, DefRangeFramePointerRel.Range)); error(IO.mapVectorTail(DefRangeFramePointerRel.Gaps, MapGap())); diff --git a/lib/DebugInfo/CodeView/TypeRecordMapping.cpp b/lib/DebugInfo/CodeView/TypeRecordMapping.cpp index 47928c2eef64..1aded589e565 100644 --- a/lib/DebugInfo/CodeView/TypeRecordMapping.cpp +++ b/lib/DebugInfo/CodeView/TypeRecordMapping.cpp @@ -7,24 +7,125 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/CodeView/TypeRecordMapping.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/DebugInfo/CodeView/EnumTables.h" using namespace llvm; using namespace llvm::codeview; +namespace { + #define error(X) \ if (auto EC = X) \ return EC; -namespace { +static const EnumEntry<TypeLeafKind> LeafTypeNames[] = { +#define CV_TYPE(enum, val) {#enum, enum}, +#include "llvm/DebugInfo/CodeView/CodeViewTypes.def" +}; + +static StringRef getLeafTypeName(TypeLeafKind LT) { + switch (LT) { +#define TYPE_RECORD(ename, value, name) \ + case ename: \ + return #name; +#include "llvm/DebugInfo/CodeView/CodeViewTypes.def" + default: + break; + } + return "UnknownLeaf"; +} + +template <typename T> +static bool compEnumNames(const EnumEntry<T> &lhs, const EnumEntry<T> &rhs) { + return lhs.Name < rhs.Name; +} + +template <typename T, typename TFlag> +static std::string getFlagNames(CodeViewRecordIO &IO, T Value, + ArrayRef<EnumEntry<TFlag>> Flags) { + if (!IO.isStreaming()) + return std::string(""); + typedef EnumEntry<TFlag> FlagEntry; + typedef SmallVector<FlagEntry, 10> FlagVector; + FlagVector SetFlags; + for (const auto &Flag : Flags) { + if (Flag.Value == 0) + continue; + if ((Value & Flag.Value) == Flag.Value) { + SetFlags.push_back(Flag); + } + } + + llvm::sort(SetFlags, &compEnumNames<TFlag>); + + std::string FlagLabel; + bool FirstOcc = true; + for (const auto &Flag : SetFlags) { + if (FirstOcc) + FirstOcc = false; + else + FlagLabel += (" | "); + + FlagLabel += (Flag.Name.str() + " (0x" + utohexstr(Flag.Value) + ")"); + } + + if (!FlagLabel.empty()) { + std::string LabelWithBraces(" ( "); + LabelWithBraces += FlagLabel + " )"; + return LabelWithBraces; + } else + return FlagLabel; +} + +template <typename T, typename TEnum> +static StringRef getEnumName(CodeViewRecordIO &IO, T Value, + ArrayRef<EnumEntry<TEnum>> EnumValues) { + if (!IO.isStreaming()) + return ""; + StringRef Name; + for (const auto &EnumItem : EnumValues) { + if (EnumItem.Value == Value) { + Name = EnumItem.Name; + break; + } + } + + return Name; +} + +static std::string getMemberAttributes(CodeViewRecordIO &IO, + MemberAccess Access, MethodKind Kind, + MethodOptions Options) { + if (!IO.isStreaming()) + return ""; + std::string AccessSpecifier = + getEnumName(IO, uint8_t(Access), makeArrayRef(getMemberAccessNames())); + std::string MemberAttrs(AccessSpecifier); + if (Kind != MethodKind::Vanilla) { + std::string MethodKind = + getEnumName(IO, unsigned(Kind), makeArrayRef(getMemberKindNames())); + MemberAttrs += ", " + MethodKind; + } + if (Options != MethodOptions::None) { + std::string MethodOptions = getFlagNames( + IO, unsigned(Options), makeArrayRef(getMethodOptionNames())); + MemberAttrs += ", " + MethodOptions; + } + return MemberAttrs; +} + struct MapOneMethodRecord { explicit MapOneMethodRecord(bool IsFromOverloadList) : IsFromOverloadList(IsFromOverloadList) {} Error operator()(CodeViewRecordIO &IO, OneMethodRecord &Method) const { - error(IO.mapInteger(Method.Attrs.Attrs, "AccessSpecifier")); + std::string Attrs = getMemberAttributes( + IO, Method.getAccess(), Method.getMethodKind(), Method.getOptions()); + error(IO.mapInteger(Method.Attrs.Attrs, "Attrs: " + Attrs)); if (IsFromOverloadList) { uint16_t Padding = 0; - error(IO.mapInteger(Padding, "Padding")); + error(IO.mapInteger(Padding)); } error(IO.mapInteger(Method.Type, "Type")); if (Method.isIntroducingVirtual()) { @@ -41,7 +142,7 @@ struct MapOneMethodRecord { private: bool IsFromOverloadList; }; -} +} // namespace static Error mapNameAndUniqueName(CodeViewRecordIO &IO, StringRef &Name, StringRef &UniqueName, bool HasUniqueName) { @@ -96,10 +197,22 @@ Error TypeRecordMapping::visitTypeBegin(CVType &CVR) { MaxLen = MaxRecordLength - sizeof(RecordPrefix); error(IO.beginRecord(MaxLen)); TypeKind = CVR.kind(); + + if (IO.isStreaming()) { + auto RecordKind = CVR.kind(); + uint16_t RecordLen = CVR.length() - 2; + std::string RecordKindName = + getEnumName(IO, unsigned(RecordKind), makeArrayRef(LeafTypeNames)); + error(IO.mapInteger(RecordLen, "Record length")); + error(IO.mapEnum(RecordKind, "Record kind: " + RecordKindName)); + } return Error::success(); } Error TypeRecordMapping::visitTypeBegin(CVType &CVR, TypeIndex Index) { + if (IO.isStreaming()) + IO.emitRawComment(" " + getLeafTypeName(CVR.kind()) + " (0x" + + utohexstr(Index.getIndex()) + ")"); return visitTypeBegin(CVR); } @@ -121,11 +234,21 @@ Error TypeRecordMapping::visitMemberBegin(CVMemberRecord &Record) { // followed by the subrecord, followed by a continuation, and that entire // sequence spaws `MaxRecordLength` bytes. So the record's length is // calculated as follows. + constexpr uint32_t ContinuationLength = 8; error(IO.beginRecord(MaxRecordLength - sizeof(RecordPrefix) - ContinuationLength)); MemberKind = Record.Kind; + if (IO.isStreaming()) { + std::string MemberKindName = getLeafTypeName(Record.Kind); + MemberKindName += + " ( " + + (getEnumName(IO, unsigned(Record.Kind), makeArrayRef(LeafTypeNames))) + .str() + + " )"; + error(IO.mapEnum(Record.Kind, "Member kind: " + MemberKindName)); + } return Error::success(); } @@ -144,16 +267,24 @@ Error TypeRecordMapping::visitMemberEnd(CVMemberRecord &Record) { } Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ModifierRecord &Record) { + std::string ModifierNames = + getFlagNames(IO, static_cast<uint16_t>(Record.Modifiers), + makeArrayRef(getTypeModifierNames())); error(IO.mapInteger(Record.ModifiedType, "ModifiedType")); - error(IO.mapEnum(Record.Modifiers, "Modifiers")); + error(IO.mapEnum(Record.Modifiers, "Modifiers" + ModifierNames)); return Error::success(); } Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ProcedureRecord &Record) { + std::string CallingConvName = getEnumName( + IO, uint8_t(Record.CallConv), makeArrayRef(getCallingConventions())); + std::string FuncOptionNames = + getFlagNames(IO, static_cast<uint16_t>(Record.Options), + makeArrayRef(getFunctionOptionEnum())); error(IO.mapInteger(Record.ReturnType, "ReturnType")); - error(IO.mapEnum(Record.CallConv, "CallingConvention")); - error(IO.mapEnum(Record.Options, "FunctionOptions")); + error(IO.mapEnum(Record.CallConv, "CallingConvention: " + CallingConvName)); + error(IO.mapEnum(Record.Options, "FunctionOptions" + FuncOptionNames)); error(IO.mapInteger(Record.ParameterCount, "NumParameters")); error(IO.mapInteger(Record.ArgumentList, "ArgListType")); @@ -162,11 +293,16 @@ Error TypeRecordMapping::visitKnownRecord(CVType &CVR, Error TypeRecordMapping::visitKnownRecord(CVType &CVR, MemberFunctionRecord &Record) { + std::string CallingConvName = getEnumName( + IO, uint8_t(Record.CallConv), makeArrayRef(getCallingConventions())); + std::string FuncOptionNames = + getFlagNames(IO, static_cast<uint16_t>(Record.Options), + makeArrayRef(getFunctionOptionEnum())); error(IO.mapInteger(Record.ReturnType, "ReturnType")); error(IO.mapInteger(Record.ClassType, "ClassType")); error(IO.mapInteger(Record.ThisType, "ThisType")); - error(IO.mapEnum(Record.CallConv, "CallingConvention")); - error(IO.mapEnum(Record.Options, "FunctionOptions")); + error(IO.mapEnum(Record.CallConv, "CallingConvention: " + CallingConvName)); + error(IO.mapEnum(Record.Options, "FunctionOptions" + FuncOptionNames)); error(IO.mapInteger(Record.ParameterCount, "NumParameters")); error(IO.mapInteger(Record.ArgumentList, "ArgListType")); error(IO.mapInteger(Record.ThisPointerAdjustment, "ThisAdjustment")); @@ -197,8 +333,40 @@ Error TypeRecordMapping::visitKnownRecord(CVType &CVR, } Error TypeRecordMapping::visitKnownRecord(CVType &CVR, PointerRecord &Record) { + + SmallString<128> Attr("Attrs: "); + + if (IO.isStreaming()) { + std::string PtrType = getEnumName(IO, unsigned(Record.getPointerKind()), + makeArrayRef(getPtrKindNames())); + Attr += "[ Type: " + PtrType; + + std::string PtrMode = getEnumName(IO, unsigned(Record.getMode()), + makeArrayRef(getPtrModeNames())); + Attr += ", Mode: " + PtrMode; + + auto PtrSizeOf = Record.getSize(); + Attr += ", SizeOf: " + itostr(PtrSizeOf); + + if (Record.isFlat()) + Attr += ", isFlat"; + if (Record.isConst()) + Attr += ", isConst"; + if (Record.isVolatile()) + Attr += ", isVolatile"; + if (Record.isUnaligned()) + Attr += ", isUnaligned"; + if (Record.isRestrict()) + Attr += ", isRestricted"; + if (Record.isLValueReferenceThisPtr()) + Attr += ", isThisPtr&"; + if (Record.isRValueReferenceThisPtr()) + Attr += ", isThisPtr&&"; + Attr += " ]"; + } + error(IO.mapInteger(Record.ReferentType, "PointeeType")); - error(IO.mapInteger(Record.Attrs, "Attributes")); + error(IO.mapInteger(Record.Attrs, Attr)); if (Record.isPointerToMember()) { if (IO.isReading()) @@ -206,7 +374,10 @@ Error TypeRecordMapping::visitKnownRecord(CVType &CVR, PointerRecord &Record) { MemberPointerInfo &M = *Record.MemberInfo; error(IO.mapInteger(M.ContainingType, "ClassType")); - error(IO.mapEnum(M.Representation, "Representation")); + std::string PtrMemberGetRepresentation = getEnumName( + IO, uint16_t(M.Representation), makeArrayRef(getPtrMemberRepNames())); + error(IO.mapEnum(M.Representation, + "Representation: " + PtrMemberGetRepresentation)); } return Error::success(); @@ -226,8 +397,11 @@ Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ClassRecord &Record) { (CVR.kind() == TypeLeafKind::LF_CLASS) || (CVR.kind() == TypeLeafKind::LF_INTERFACE)); + std::string PropertiesNames = + getFlagNames(IO, static_cast<uint16_t>(Record.Options), + makeArrayRef(getClassOptionNames())); error(IO.mapInteger(Record.MemberCount, "MemberCount")); - error(IO.mapEnum(Record.Options, "Properties")); + error(IO.mapEnum(Record.Options, "Properties" + PropertiesNames)); error(IO.mapInteger(Record.FieldList, "FieldList")); error(IO.mapInteger(Record.DerivationList, "DerivedFrom")); error(IO.mapInteger(Record.VTableShape, "VShape")); @@ -239,8 +413,11 @@ Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ClassRecord &Record) { } Error TypeRecordMapping::visitKnownRecord(CVType &CVR, UnionRecord &Record) { + std::string PropertiesNames = + getFlagNames(IO, static_cast<uint16_t>(Record.Options), + makeArrayRef(getClassOptionNames())); error(IO.mapInteger(Record.MemberCount, "MemberCount")); - error(IO.mapEnum(Record.Options, "Properties")); + error(IO.mapEnum(Record.Options, "Properties" + PropertiesNames)); error(IO.mapInteger(Record.FieldList, "FieldList")); error(IO.mapEncodedInteger(Record.Size, "SizeOf")); error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName, @@ -250,8 +427,11 @@ Error TypeRecordMapping::visitKnownRecord(CVType &CVR, UnionRecord &Record) { } Error TypeRecordMapping::visitKnownRecord(CVType &CVR, EnumRecord &Record) { + std::string PropertiesNames = + getFlagNames(IO, static_cast<uint16_t>(Record.Options), + makeArrayRef(getClassOptionNames())); error(IO.mapInteger(Record.MemberCount, "NumEnumerators")); - error(IO.mapEnum(Record.Options, "Properties")); + error(IO.mapEnum(Record.Options, "Properties" + PropertiesNames)); error(IO.mapInteger(Record.UnderlyingType, "UnderlyingType")); error(IO.mapInteger(Record.FieldList, "FieldListType")); error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName, @@ -383,7 +563,11 @@ Error TypeRecordMapping::visitKnownRecord(CVType &CVR, Error TypeRecordMapping::visitKnownRecord(CVType &CVR, FieldListRecord &Record) { - error(IO.mapByteVectorTail(Record.Data)); + if (IO.isStreaming()) { + if (auto EC = codeview::visitMemberRecordStream(Record.Data, *this)) + return EC; + } else + error(IO.mapByteVectorTail(Record.Data)); return Error::success(); } @@ -397,13 +581,17 @@ Error TypeRecordMapping::visitKnownRecord(CVType &CVR, } Error TypeRecordMapping::visitKnownRecord(CVType &CVR, LabelRecord &Record) { - error(IO.mapEnum(Record.Mode, "Mode")); + std::string ModeName = + getEnumName(IO, uint16_t(Record.Mode), makeArrayRef(getLabelTypeEnum())); + error(IO.mapEnum(Record.Mode, "Mode: " + ModeName)); return Error::success(); } Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR, BaseClassRecord &Record) { - error(IO.mapInteger(Record.Attrs.Attrs, "AccessSpecifier")); + std::string Attrs = getMemberAttributes( + IO, Record.getAccess(), MethodKind::Vanilla, MethodOptions::None); + error(IO.mapInteger(Record.Attrs.Attrs, "Attrs: " + Attrs)); error(IO.mapInteger(Record.Type, "BaseType")); error(IO.mapEncodedInteger(Record.Offset, "BaseOffset")); @@ -412,7 +600,9 @@ Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR, Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR, EnumeratorRecord &Record) { - error(IO.mapInteger(Record.Attrs.Attrs)); + std::string Attrs = getMemberAttributes( + IO, Record.getAccess(), MethodKind::Vanilla, MethodOptions::None); + error(IO.mapInteger(Record.Attrs.Attrs, "Attrs: " + Attrs)); // FIXME: Handle full APInt such as __int128. error(IO.mapEncodedInteger(Record.Value, "EnumValue")); @@ -423,7 +613,9 @@ Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR, Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR, DataMemberRecord &Record) { - error(IO.mapInteger(Record.Attrs.Attrs, "AccessSpecifier")); + std::string Attrs = getMemberAttributes( + IO, Record.getAccess(), MethodKind::Vanilla, MethodOptions::None); + error(IO.mapInteger(Record.Attrs.Attrs, "Attrs: " + Attrs)); error(IO.mapInteger(Record.Type, "Type")); error(IO.mapEncodedInteger(Record.FieldOffset, "FieldOffset")); error(IO.mapStringZ(Record.Name, "Name")); @@ -460,7 +652,9 @@ Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR, Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR, StaticDataMemberRecord &Record) { - error(IO.mapInteger(Record.Attrs.Attrs, "AccessSpecifier")); + std::string Attrs = getMemberAttributes( + IO, Record.getAccess(), MethodKind::Vanilla, MethodOptions::None); + error(IO.mapInteger(Record.Attrs.Attrs, "Attrs: " + Attrs)); error(IO.mapInteger(Record.Type, "Type")); error(IO.mapStringZ(Record.Name, "Name")); @@ -470,7 +664,9 @@ Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR, Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR, VirtualBaseClassRecord &Record) { - error(IO.mapInteger(Record.Attrs.Attrs, "AccessSpecifier")); + std::string Attrs = getMemberAttributes( + IO, Record.getAccess(), MethodKind::Vanilla, MethodOptions::None); + error(IO.mapInteger(Record.Attrs.Attrs, "Attrs: " + Attrs)); error(IO.mapInteger(Record.BaseType, "BaseType")); error(IO.mapInteger(Record.VBPtrType, "VBPtrType")); error(IO.mapEncodedInteger(Record.VBPtrOffset, "VBPtrOffset")); diff --git a/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp b/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp index f4dd79937608..abbea3a868c8 100644 --- a/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp +++ b/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp @@ -38,9 +38,9 @@ DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration() { bool DWARFAbbreviationDeclaration::extract(DataExtractor Data, - uint32_t* OffsetPtr) { + uint64_t* OffsetPtr) { clear(); - const uint32_t Offset = *OffsetPtr; + const uint64_t Offset = *OffsetPtr; Code = Data.getULEB128(OffsetPtr); if (Code == 0) { return false; @@ -148,7 +148,7 @@ DWARFAbbreviationDeclaration::findAttributeIndex(dwarf::Attribute Attr) const { } Optional<DWARFFormValue> DWARFAbbreviationDeclaration::getAttributeValue( - const uint32_t DIEOffset, const dwarf::Attribute Attr, + const uint64_t DIEOffset, const dwarf::Attribute Attr, const DWARFUnit &U) const { Optional<uint32_t> MatchAttrIndex = findAttributeIndex(Attr); if (!MatchAttrIndex) @@ -158,7 +158,7 @@ Optional<DWARFFormValue> DWARFAbbreviationDeclaration::getAttributeValue( // Add the byte size of ULEB that for the abbrev Code so we can start // skipping the attribute data. - uint32_t Offset = DIEOffset + CodeByteSize; + uint64_t Offset = DIEOffset + CodeByteSize; uint32_t AttrIndex = 0; for (const auto &Spec : AttributeSpecs) { if (*MatchAttrIndex == AttrIndex) { diff --git a/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp b/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp index 0721efb40f6a..875f5e9989a0 100644 --- a/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp +++ b/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp @@ -42,7 +42,7 @@ static Atom formatAtom(unsigned Atom) { return {Atom}; } DWARFAcceleratorTable::~DWARFAcceleratorTable() = default; Error AppleAcceleratorTable::extract() { - uint32_t Offset = 0; + uint64_t Offset = 0; // Check that we can at least read the header. if (!AccelSection.isValidOffset(offsetof(Header, HeaderDataLength) + 4)) @@ -111,15 +111,15 @@ bool AppleAcceleratorTable::validateForms() { return true; } -std::pair<uint32_t, dwarf::Tag> -AppleAcceleratorTable::readAtoms(uint32_t &HashDataOffset) { - uint32_t DieOffset = dwarf::DW_INVALID_OFFSET; +std::pair<uint64_t, dwarf::Tag> +AppleAcceleratorTable::readAtoms(uint64_t *HashDataOffset) { + uint64_t DieOffset = dwarf::DW_INVALID_OFFSET; dwarf::Tag DieTag = dwarf::DW_TAG_null; dwarf::FormParams FormParams = {Hdr.Version, 0, dwarf::DwarfFormat::DWARF32}; for (auto Atom : getAtomsDesc()) { DWARFFormValue FormValue(Atom.second); - FormValue.extractValue(AccelSection, &HashDataOffset, FormParams); + FormValue.extractValue(AccelSection, HashDataOffset, FormParams); switch (Atom.first) { case dwarf::DW_ATOM_die_offset: DieOffset = *FormValue.getAsUnsignedConstant(); @@ -163,19 +163,19 @@ Optional<uint64_t> AppleAcceleratorTable::HeaderData::extractOffset( bool AppleAcceleratorTable::dumpName(ScopedPrinter &W, SmallVectorImpl<DWARFFormValue> &AtomForms, - uint32_t *DataOffset) const { + uint64_t *DataOffset) const { dwarf::FormParams FormParams = {Hdr.Version, 0, dwarf::DwarfFormat::DWARF32}; - uint32_t NameOffset = *DataOffset; + uint64_t NameOffset = *DataOffset; if (!AccelSection.isValidOffsetForDataOfSize(*DataOffset, 4)) { W.printString("Incorrectly terminated list."); return false; } - unsigned StringOffset = AccelSection.getRelocatedValue(4, DataOffset); + uint64_t StringOffset = AccelSection.getRelocatedValue(4, DataOffset); if (!StringOffset) return false; // End of list DictScope NameScope(W, ("Name@0x" + Twine::utohexstr(NameOffset)).str()); - W.startLine() << format("String: 0x%08x", StringOffset); + W.startLine() << format("String: 0x%08" PRIx64, StringOffset); W.getOStream() << " \"" << StringSection.getCStr(&StringOffset) << "\"\n"; unsigned NumData = AccelSection.getU32(DataOffset); @@ -223,9 +223,9 @@ LLVM_DUMP_METHOD void AppleAcceleratorTable::dump(raw_ostream &OS) const { } // Now go through the actual tables and dump them. - uint32_t Offset = sizeof(Hdr) + Hdr.HeaderDataLength; - unsigned HashesBase = Offset + Hdr.BucketCount * 4; - unsigned OffsetsBase = HashesBase + Hdr.HashCount * 4; + uint64_t Offset = sizeof(Hdr) + Hdr.HeaderDataLength; + uint64_t HashesBase = Offset + Hdr.BucketCount * 4; + uint64_t OffsetsBase = HashesBase + Hdr.HashCount * 4; for (unsigned Bucket = 0; Bucket < Hdr.BucketCount; ++Bucket) { unsigned Index = AccelSection.getU32(&Offset); @@ -237,14 +237,14 @@ LLVM_DUMP_METHOD void AppleAcceleratorTable::dump(raw_ostream &OS) const { } for (unsigned HashIdx = Index; HashIdx < Hdr.HashCount; ++HashIdx) { - unsigned HashOffset = HashesBase + HashIdx*4; - unsigned OffsetsOffset = OffsetsBase + HashIdx*4; + uint64_t HashOffset = HashesBase + HashIdx*4; + uint64_t OffsetsOffset = OffsetsBase + HashIdx*4; uint32_t Hash = AccelSection.getU32(&HashOffset); if (Hash % Hdr.BucketCount != Bucket) break; - unsigned DataOffset = AccelSection.getU32(&OffsetsOffset); + uint64_t DataOffset = AccelSection.getU32(&OffsetsOffset); ListScope HashScope(W, ("Hash 0x" + Twine::utohexstr(Hash)).str()); if (!AccelSection.isValidOffset(DataOffset)) { W.printString("Invalid section offset"); @@ -265,7 +265,7 @@ AppleAcceleratorTable::Entry::Entry( } void AppleAcceleratorTable::Entry::extract( - const AppleAcceleratorTable &AccelTable, uint32_t *Offset) { + const AppleAcceleratorTable &AccelTable, uint64_t *Offset) { dwarf::FormParams FormParams = {AccelTable.Hdr.Version, 0, dwarf::DwarfFormat::DWARF32}; @@ -302,7 +302,7 @@ Optional<dwarf::Tag> AppleAcceleratorTable::Entry::getTag() const { } AppleAcceleratorTable::ValueIterator::ValueIterator( - const AppleAcceleratorTable &AccelTable, unsigned Offset) + const AppleAcceleratorTable &AccelTable, uint64_t Offset) : AccelTable(&AccelTable), Current(AccelTable.HdrData), DataOffset(Offset) { if (!AccelTable.AccelSection.isValidOffsetForDataOfSize(DataOffset, 4)) return; @@ -333,25 +333,25 @@ AppleAcceleratorTable::equal_range(StringRef Key) const { // Find the bucket. unsigned HashValue = djbHash(Key); unsigned Bucket = HashValue % Hdr.BucketCount; - unsigned BucketBase = sizeof(Hdr) + Hdr.HeaderDataLength; - unsigned HashesBase = BucketBase + Hdr.BucketCount * 4; - unsigned OffsetsBase = HashesBase + Hdr.HashCount * 4; + uint64_t BucketBase = sizeof(Hdr) + Hdr.HeaderDataLength; + uint64_t HashesBase = BucketBase + Hdr.BucketCount * 4; + uint64_t OffsetsBase = HashesBase + Hdr.HashCount * 4; - unsigned BucketOffset = BucketBase + Bucket * 4; + uint64_t BucketOffset = BucketBase + Bucket * 4; unsigned Index = AccelSection.getU32(&BucketOffset); // Search through all hashes in the bucket. for (unsigned HashIdx = Index; HashIdx < Hdr.HashCount; ++HashIdx) { - unsigned HashOffset = HashesBase + HashIdx * 4; - unsigned OffsetsOffset = OffsetsBase + HashIdx * 4; + uint64_t HashOffset = HashesBase + HashIdx * 4; + uint64_t OffsetsOffset = OffsetsBase + HashIdx * 4; uint32_t Hash = AccelSection.getU32(&HashOffset); if (Hash % Hdr.BucketCount != Bucket) // We are already in the next bucket. break; - unsigned DataOffset = AccelSection.getU32(&OffsetsOffset); - unsigned StringOffset = AccelSection.getRelocatedValue(4, &DataOffset); + uint64_t DataOffset = AccelSection.getU32(&OffsetsOffset); + uint64_t StringOffset = AccelSection.getRelocatedValue(4, &DataOffset); if (!StringOffset) break; @@ -377,7 +377,7 @@ void DWARFDebugNames::Header::dump(ScopedPrinter &W) const { } Error DWARFDebugNames::Header::extract(const DWARFDataExtractor &AS, - uint32_t *Offset) { + uint64_t *Offset) { // Check that we can read the fixed-size part. if (!AS.isValidOffset(*Offset + sizeof(HeaderPOD) - 1)) return createStringError(errc::illegal_byte_sequence, @@ -437,7 +437,7 @@ DWARFDebugNames::Abbrev DWARFDebugNames::AbbrevMapInfo::getTombstoneKey() { } Expected<DWARFDebugNames::AttributeEncoding> -DWARFDebugNames::NameIndex::extractAttributeEncoding(uint32_t *Offset) { +DWARFDebugNames::NameIndex::extractAttributeEncoding(uint64_t *Offset) { if (*Offset >= EntriesBase) { return createStringError(errc::illegal_byte_sequence, "Incorrectly terminated abbreviation table."); @@ -449,7 +449,7 @@ DWARFDebugNames::NameIndex::extractAttributeEncoding(uint32_t *Offset) { } Expected<std::vector<DWARFDebugNames::AttributeEncoding>> -DWARFDebugNames::NameIndex::extractAttributeEncodings(uint32_t *Offset) { +DWARFDebugNames::NameIndex::extractAttributeEncodings(uint64_t *Offset) { std::vector<AttributeEncoding> Result; for (;;) { auto AttrEncOr = extractAttributeEncoding(Offset); @@ -463,7 +463,7 @@ DWARFDebugNames::NameIndex::extractAttributeEncodings(uint32_t *Offset) { } Expected<DWARFDebugNames::Abbrev> -DWARFDebugNames::NameIndex::extractAbbrev(uint32_t *Offset) { +DWARFDebugNames::NameIndex::extractAbbrev(uint64_t *Offset) { if (*Offset >= EntriesBase) { return createStringError(errc::illegal_byte_sequence, "Incorrectly terminated abbreviation table."); @@ -482,7 +482,7 @@ DWARFDebugNames::NameIndex::extractAbbrev(uint32_t *Offset) { Error DWARFDebugNames::NameIndex::extract() { const DWARFDataExtractor &AS = Section.AccelSection; - uint32_t Offset = Base; + uint64_t Offset = Base; if (Error E = Hdr.extract(AS, &Offset)) return E; @@ -577,27 +577,27 @@ std::error_code DWARFDebugNames::SentinelError::convertToErrorCode() const { return inconvertibleErrorCode(); } -uint32_t DWARFDebugNames::NameIndex::getCUOffset(uint32_t CU) const { +uint64_t DWARFDebugNames::NameIndex::getCUOffset(uint32_t CU) const { assert(CU < Hdr.CompUnitCount); - uint32_t Offset = CUsBase + 4 * CU; + uint64_t Offset = CUsBase + 4 * CU; return Section.AccelSection.getRelocatedValue(4, &Offset); } -uint32_t DWARFDebugNames::NameIndex::getLocalTUOffset(uint32_t TU) const { +uint64_t DWARFDebugNames::NameIndex::getLocalTUOffset(uint32_t TU) const { assert(TU < Hdr.LocalTypeUnitCount); - uint32_t Offset = CUsBase + 4 * (Hdr.CompUnitCount + TU); + uint64_t Offset = CUsBase + 4 * (Hdr.CompUnitCount + TU); return Section.AccelSection.getRelocatedValue(4, &Offset); } uint64_t DWARFDebugNames::NameIndex::getForeignTUSignature(uint32_t TU) const { assert(TU < Hdr.ForeignTypeUnitCount); - uint32_t Offset = + uint64_t Offset = CUsBase + 4 * (Hdr.CompUnitCount + Hdr.LocalTypeUnitCount) + 8 * TU; return Section.AccelSection.getU64(&Offset); } Expected<DWARFDebugNames::Entry> -DWARFDebugNames::NameIndex::getEntry(uint32_t *Offset) const { +DWARFDebugNames::NameIndex::getEntry(uint64_t *Offset) const { const DWARFDataExtractor &AS = Section.AccelSection; if (!AS.isValidOffset(*Offset)) return createStringError(errc::illegal_byte_sequence, @@ -625,12 +625,12 @@ DWARFDebugNames::NameIndex::getEntry(uint32_t *Offset) const { DWARFDebugNames::NameTableEntry DWARFDebugNames::NameIndex::getNameTableEntry(uint32_t Index) const { assert(0 < Index && Index <= Hdr.NameCount); - uint32_t StringOffsetOffset = StringOffsetsBase + 4 * (Index - 1); - uint32_t EntryOffsetOffset = EntryOffsetsBase + 4 * (Index - 1); + uint64_t StringOffsetOffset = StringOffsetsBase + 4 * (Index - 1); + uint64_t EntryOffsetOffset = EntryOffsetsBase + 4 * (Index - 1); const DWARFDataExtractor &AS = Section.AccelSection; - uint32_t StringOffset = AS.getRelocatedValue(4, &StringOffsetOffset); - uint32_t EntryOffset = AS.getU32(&EntryOffsetOffset); + uint64_t StringOffset = AS.getRelocatedValue(4, &StringOffsetOffset); + uint64_t EntryOffset = AS.getU32(&EntryOffsetOffset); EntryOffset += EntriesBase; return {Section.StringSection, Index, StringOffset, EntryOffset}; } @@ -638,13 +638,13 @@ DWARFDebugNames::NameIndex::getNameTableEntry(uint32_t Index) const { uint32_t DWARFDebugNames::NameIndex::getBucketArrayEntry(uint32_t Bucket) const { assert(Bucket < Hdr.BucketCount); - uint32_t BucketOffset = BucketsBase + 4 * Bucket; + uint64_t BucketOffset = BucketsBase + 4 * Bucket; return Section.AccelSection.getU32(&BucketOffset); } uint32_t DWARFDebugNames::NameIndex::getHashArrayEntry(uint32_t Index) const { assert(0 < Index && Index <= Hdr.NameCount); - uint32_t HashOffset = HashesBase + 4 * (Index - 1); + uint64_t HashOffset = HashesBase + 4 * (Index - 1); return Section.AccelSection.getU32(&HashOffset); } @@ -653,8 +653,8 @@ uint32_t DWARFDebugNames::NameIndex::getHashArrayEntry(uint32_t Index) const { // it's not possible to recover this entry list (but the other lists may still // parse OK). bool DWARFDebugNames::NameIndex::dumpEntry(ScopedPrinter &W, - uint32_t *Offset) const { - uint32_t EntryId = *Offset; + uint64_t *Offset) const { + uint64_t EntryId = *Offset; auto EntryOr = getEntry(Offset); if (!EntryOr) { handleAllErrors(EntryOr.takeError(), [](const SentinelError &) {}, @@ -674,10 +674,10 @@ void DWARFDebugNames::NameIndex::dumpName(ScopedPrinter &W, if (Hash) W.printHex("Hash", *Hash); - W.startLine() << format("String: 0x%08x", NTE.getStringOffset()); + W.startLine() << format("String: 0x%08" PRIx64, NTE.getStringOffset()); W.getOStream() << " \"" << NTE.getString() << "\"\n"; - uint32_t EntryOffset = NTE.getEntryOffset(); + uint64_t EntryOffset = NTE.getEntryOffset(); while (dumpEntry(W, &EntryOffset)) /*empty*/; } @@ -685,7 +685,7 @@ void DWARFDebugNames::NameIndex::dumpName(ScopedPrinter &W, void DWARFDebugNames::NameIndex::dumpCUs(ScopedPrinter &W) const { ListScope CUScope(W, "Compilation Unit offsets"); for (uint32_t CU = 0; CU < Hdr.CompUnitCount; ++CU) - W.startLine() << format("CU[%u]: 0x%08x\n", CU, getCUOffset(CU)); + W.startLine() << format("CU[%u]: 0x%08" PRIx64 "\n", CU, getCUOffset(CU)); } void DWARFDebugNames::NameIndex::dumpLocalTUs(ScopedPrinter &W) const { @@ -694,7 +694,8 @@ void DWARFDebugNames::NameIndex::dumpLocalTUs(ScopedPrinter &W) const { ListScope TUScope(W, "Local Type Unit offsets"); for (uint32_t TU = 0; TU < Hdr.LocalTypeUnitCount; ++TU) - W.startLine() << format("LocalTU[%u]: 0x%08x\n", TU, getLocalTUOffset(TU)); + W.startLine() << format("LocalTU[%u]: 0x%08" PRIx64 "\n", TU, + getLocalTUOffset(TU)); } void DWARFDebugNames::NameIndex::dumpForeignTUs(ScopedPrinter &W) const { @@ -756,7 +757,7 @@ LLVM_DUMP_METHOD void DWARFDebugNames::NameIndex::dump(ScopedPrinter &W) const { } Error DWARFDebugNames::extract() { - uint32_t Offset = 0; + uint64_t Offset = 0; while (AccelSection.isValidOffset(Offset)) { NameIndex Next(*this, Offset); if (Error E = Next.extract()) @@ -778,7 +779,7 @@ LLVM_DUMP_METHOD void DWARFDebugNames::dump(raw_ostream &OS) const { NI.dump(W); } -Optional<uint32_t> +Optional<uint64_t> DWARFDebugNames::ValueIterator::findEntryOffsetInCurrentIndex() { const Header &Hdr = CurrentIndex->Hdr; if (Hdr.BucketCount == 0) { @@ -822,7 +823,7 @@ bool DWARFDebugNames::ValueIterator::getEntryAtCurrentOffset() { } bool DWARFDebugNames::ValueIterator::findInCurrentIndex() { - Optional<uint32_t> Offset = findEntryOffsetInCurrentIndex(); + Optional<uint64_t> Offset = findEntryOffsetInCurrentIndex(); if (!Offset) return false; DataOffset = *Offset; @@ -877,7 +878,7 @@ DWARFDebugNames::equal_range(StringRef Key) const { } const DWARFDebugNames::NameIndex * -DWARFDebugNames::getCUNameIndex(uint32_t CUOffset) { +DWARFDebugNames::getCUNameIndex(uint64_t CUOffset) { if (CUToNameIndex.size() == 0 && NameIndices.size() > 0) { for (const auto &NI : *this) { for (uint32_t CU = 0; CU < NI.getCUCount(); ++CU) diff --git a/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp b/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp index 74cce42466dd..f59e49268288 100644 --- a/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp +++ b/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp @@ -15,16 +15,18 @@ using namespace llvm; void DWARFCompileUnit::dump(raw_ostream &OS, DIDumpOptions DumpOpts) { - OS << format("0x%08x", getOffset()) << ": Compile Unit:" - << " length = " << format("0x%08x", getLength()) + OS << format("0x%08" PRIx64, getOffset()) << ": Compile Unit:" + << " length = " << format("0x%08" PRIx64, getLength()) << " version = " << format("0x%04x", getVersion()); if (getVersion() >= 5) OS << " unit_type = " << dwarf::UnitTypeString(getUnitType()); - OS << " abbr_offset = " << format("0x%04x", getAbbreviations()->getOffset()) + OS << " abbr_offset = " + << format("0x%04" PRIx64, getAbbreviations()->getOffset()) << " addr_size = " << format("0x%02x", getAddressByteSize()); if (getVersion() >= 5 && getUnitType() != dwarf::DW_UT_compile) OS << " DWO_id = " << format("0x%016" PRIx64, *getDWOId()); - OS << " (next unit at " << format("0x%08x", getNextUnitOffset()) << ")\n"; + OS << " (next unit at " << format("0x%08" PRIx64, getNextUnitOffset()) + << ")\n"; if (DWARFDie CUDie = getUnitDIE(false)) CUDie.dump(OS, 0, DumpOpts); diff --git a/lib/DebugInfo/DWARF/DWARFContext.cpp b/lib/DebugInfo/DWARF/DWARFContext.cpp index 5ede9bf59619..c06d85d50609 100644 --- a/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -138,7 +138,7 @@ static void dumpDWARFv5StringOffsetsSection( DWARFDataExtractor StrOffsetExt(Obj, StringOffsetsSection, LittleEndian, 0); DataExtractor StrData(StringSection, LittleEndian, 0); uint64_t SectionSize = StringOffsetsSection.Data.size(); - uint32_t Offset = 0; + uint64_t Offset = 0; for (auto &Contribution : Contributions) { // Report an ill-formed contribution. if (!Contribution) { @@ -166,10 +166,10 @@ static void dumpDWARFv5StringOffsetsSection( } // Report a gap in the table. if (Offset < ContributionHeader) { - OS << format("0x%8.8x: Gap, length = ", Offset); + OS << format("0x%8.8" PRIx64 ": Gap, length = ", Offset); OS << (ContributionHeader - Offset) << "\n"; } - OS << format("0x%8.8x: ", (uint32_t)ContributionHeader); + OS << format("0x%8.8" PRIx64 ": ", ContributionHeader); // In DWARF v5 the contribution size in the descriptor does not equal // the originally encoded length (it does not contain the length of the // version field and the padding, a total of 4 bytes). Add them back in @@ -181,26 +181,19 @@ static void dumpDWARFv5StringOffsetsSection( Offset = Contribution->Base; unsigned EntrySize = Contribution->getDwarfOffsetByteSize(); while (Offset - Contribution->Base < Contribution->Size) { - OS << format("0x%8.8x: ", Offset); - // FIXME: We can only extract strings if the offset fits in 32 bits. + OS << format("0x%8.8" PRIx64 ": ", Offset); uint64_t StringOffset = StrOffsetExt.getRelocatedValue(EntrySize, &Offset); - // Extract the string if we can and display it. Otherwise just report - // the offset. - if (StringOffset <= std::numeric_limits<uint32_t>::max()) { - uint32_t StringOffset32 = (uint32_t)StringOffset; - OS << format("%8.8x ", StringOffset32); - const char *S = StrData.getCStr(&StringOffset32); - if (S) - OS << format("\"%s\"", S); - } else - OS << format("%16.16" PRIx64 " ", StringOffset); + OS << format("%8.8" PRIx64 " ", StringOffset); + const char *S = StrData.getCStr(&StringOffset); + if (S) + OS << format("\"%s\"", S); OS << "\n"; } } // Report a gap at the end of the table. if (Offset < SectionSize) { - OS << format("0x%8.8x: Gap, length = ", Offset); + OS << format("0x%8.8" PRIx64 ": Gap, length = ", Offset); OS << (SectionSize - Offset) << "\n"; } } @@ -225,7 +218,7 @@ static void dumpStringOffsetsSection(raw_ostream &OS, StringRef SectionName, StringSection, Units, LittleEndian); else { DataExtractor strOffsetExt(StringOffsetsSection.Data, LittleEndian, 0); - uint32_t offset = 0; + uint64_t offset = 0; uint64_t size = StringOffsetsSection.Data.size(); // Ensure that size is a multiple of the size of an entry. if (size & ((uint64_t)(sizeof(uint32_t) - 1))) { @@ -235,9 +228,9 @@ static void dumpStringOffsetsSection(raw_ostream &OS, StringRef SectionName, } DataExtractor StrData(StringSection, LittleEndian, 0); while (offset < size) { - OS << format("0x%8.8x: ", offset); - uint32_t StringOffset = strOffsetExt.getU32(&offset); - OS << format("%8.8x ", StringOffset); + OS << format("0x%8.8" PRIx64 ": ", offset); + uint64_t StringOffset = strOffsetExt.getU32(&offset); + OS << format("%8.8" PRIx64 " ", StringOffset); const char *S = StrData.getCStr(&StringOffset); if (S) OS << format("\"%s\"", S); @@ -250,10 +243,10 @@ static void dumpStringOffsetsSection(raw_ostream &OS, StringRef SectionName, static void dumpAddrSection(raw_ostream &OS, DWARFDataExtractor &AddrData, DIDumpOptions DumpOpts, uint16_t Version, uint8_t AddrSize) { - uint32_t Offset = 0; + uint64_t Offset = 0; while (AddrData.isValidOffset(Offset)) { DWARFDebugAddrTable AddrTable; - uint32_t TableOffset = Offset; + uint64_t TableOffset = Offset; if (Error Err = AddrTable.extract(AddrData, &Offset, Version, AddrSize, DWARFContext::dumpWarning)) { WithColor::error() << toString(std::move(Err)) << '\n'; @@ -261,8 +254,7 @@ static void dumpAddrSection(raw_ostream &OS, DWARFDataExtractor &AddrData, // could be read. If it couldn't, stop reading the section. if (!AddrTable.hasValidLength()) break; - uint64_t Length = AddrTable.getLength(); - Offset = TableOffset + Length; + Offset = TableOffset + AddrTable.getLength(); } else { AddrTable.dump(OS, DumpOpts); } @@ -275,10 +267,10 @@ static void dumpRnglistsSection( llvm::function_ref<Optional<object::SectionedAddress>(uint32_t)> LookupPooledAddress, DIDumpOptions DumpOpts) { - uint32_t Offset = 0; + uint64_t Offset = 0; while (rnglistData.isValidOffset(Offset)) { llvm::DWARFDebugRnglistTable Rnglists; - uint32_t TableOffset = Offset; + uint64_t TableOffset = Offset; if (Error Err = Rnglists.extract(rnglistData, &Offset)) { WithColor::error() << toString(std::move(Err)) << '\n'; uint64_t Length = Rnglists.length(); @@ -297,21 +289,25 @@ static void dumpLoclistsSection(raw_ostream &OS, DIDumpOptions DumpOpts, DWARFDataExtractor Data, const MCRegisterInfo *MRI, Optional<uint64_t> DumpOffset) { - uint32_t Offset = 0; - DWARFDebugLoclists Loclists; + uint64_t Offset = 0; - DWARFListTableHeader Header(".debug_loclists", "locations"); - if (Error E = Header.extract(Data, &Offset)) { - WithColor::error() << toString(std::move(E)) << '\n'; - return; - } + while (Data.isValidOffset(Offset)) { + DWARFListTableHeader Header(".debug_loclists", "locations"); + if (Error E = Header.extract(Data, &Offset)) { + WithColor::error() << toString(std::move(E)) << '\n'; + return; + } - Header.dump(OS, DumpOpts); - DataExtractor LocData(Data.getData().drop_front(Offset), - Data.isLittleEndian(), Header.getAddrSize()); + Header.dump(OS, DumpOpts); + DataExtractor LocData(Data.getData(), + Data.isLittleEndian(), Header.getAddrSize()); - Loclists.parse(LocData, Header.getVersion()); - Loclists.dump(OS, 0, MRI, DumpOffset); + DWARFDebugLoclists Loclists; + uint64_t EndOffset = Header.length() + Header.getHeaderOffset(); + Loclists.parse(LocData, Offset, EndOffset, Header.getVersion()); + Loclists.dump(OS, 0, MRI, DumpOpts, DumpOffset); + Offset = EndOffset; + } } void DWARFContext::dump( @@ -386,7 +382,7 @@ void DWARFContext::dump( if (const auto *Off = shouldDump(Explicit, ".debug_loc", DIDT_ID_DebugLoc, DObj->getLocSection().Data)) { - getDebugLoc()->dump(OS, getRegisterInfo(), *Off); + getDebugLoc()->dump(OS, getRegisterInfo(), DumpOpts, *Off); } if (const auto *Off = shouldDump(Explicit, ".debug_loclists", DIDT_ID_DebugLoclists, @@ -398,15 +394,15 @@ void DWARFContext::dump( if (const auto *Off = shouldDump(ExplicitDWO, ".debug_loc.dwo", DIDT_ID_DebugLoc, DObj->getLocDWOSection().Data)) { - getDebugLocDWO()->dump(OS, 0, getRegisterInfo(), *Off); + getDebugLocDWO()->dump(OS, 0, getRegisterInfo(), DumpOpts, *Off); } if (const auto *Off = shouldDump(Explicit, ".debug_frame", DIDT_ID_DebugFrame, - DObj->getDebugFrameSection())) + DObj->getFrameSection().Data)) getDebugFrame()->dump(OS, getRegisterInfo(), *Off); if (const auto *Off = shouldDump(Explicit, ".eh_frame", DIDT_ID_DebugFrame, - DObj->getEHFrameSection())) + DObj->getEHFrameSection().Data)) getEHFrame()->dump(OS, getRegisterInfo(), *Off); if (DumpType & DIDT_DebugMacro) { @@ -417,9 +413,9 @@ void DWARFContext::dump( } if (shouldDump(Explicit, ".debug_aranges", DIDT_ID_DebugAranges, - DObj->getARangeSection())) { - uint32_t offset = 0; - DataExtractor arangesData(DObj->getARangeSection(), isLittleEndian(), 0); + DObj->getArangesSection())) { + uint64_t offset = 0; + DataExtractor arangesData(DObj->getArangesSection(), isLittleEndian(), 0); DWARFDebugArangeSet set; while (set.extract(arangesData, &offset)) set.dump(OS); @@ -433,7 +429,8 @@ void DWARFContext::dump( Parser.skip(dumpWarning); continue; } - OS << "debug_line[" << format("0x%8.8x", Parser.getOffset()) << "]\n"; + OS << "debug_line[" << format("0x%8.8" PRIx64, Parser.getOffset()) + << "]\n"; if (DumpOpts.Verbose) { Parser.parseNext(dumpWarning, dumpWarning, &OS); } else { @@ -474,32 +471,32 @@ void DWARFContext::dump( } if (shouldDump(Explicit, ".debug_str", DIDT_ID_DebugStr, - DObj->getStringSection())) { - DataExtractor strData(DObj->getStringSection(), isLittleEndian(), 0); - uint32_t offset = 0; - uint32_t strOffset = 0; + DObj->getStrSection())) { + DataExtractor strData(DObj->getStrSection(), isLittleEndian(), 0); + uint64_t offset = 0; + uint64_t strOffset = 0; while (const char *s = strData.getCStr(&offset)) { - OS << format("0x%8.8x: \"%s\"\n", strOffset, s); + OS << format("0x%8.8" PRIx64 ": \"%s\"\n", strOffset, s); strOffset = offset; } } if (shouldDump(ExplicitDWO, ".debug_str.dwo", DIDT_ID_DebugStr, - DObj->getStringDWOSection())) { - DataExtractor strDWOData(DObj->getStringDWOSection(), isLittleEndian(), 0); - uint32_t offset = 0; - uint32_t strDWOOffset = 0; + DObj->getStrDWOSection())) { + DataExtractor strDWOData(DObj->getStrDWOSection(), isLittleEndian(), 0); + uint64_t offset = 0; + uint64_t strDWOOffset = 0; while (const char *s = strDWOData.getCStr(&offset)) { - OS << format("0x%8.8x: \"%s\"\n", strDWOOffset, s); + OS << format("0x%8.8" PRIx64 ": \"%s\"\n", strDWOOffset, s); strDWOOffset = offset; } } if (shouldDump(Explicit, ".debug_line_str", DIDT_ID_DebugLineStr, - DObj->getLineStringSection())) { - DataExtractor strData(DObj->getLineStringSection(), isLittleEndian(), 0); - uint32_t offset = 0; - uint32_t strOffset = 0; + DObj->getLineStrSection())) { + DataExtractor strData(DObj->getLineStrSection(), isLittleEndian(), 0); + uint64_t offset = 0; + uint64_t strOffset = 0; while (const char *s = strData.getCStr(&offset)) { - OS << format("0x%8.8x: \"", strOffset); + OS << format("0x%8.8" PRIx64 ": \"", strOffset); OS.write_escaped(s); OS << "\"\n"; strOffset = offset; @@ -514,11 +511,11 @@ void DWARFContext::dump( } if (shouldDump(Explicit, ".debug_ranges", DIDT_ID_DebugRanges, - DObj->getRangeSection().Data)) { + DObj->getRangesSection().Data)) { uint8_t savedAddressByteSize = getCUAddrSize(); - DWARFDataExtractor rangesData(*DObj, DObj->getRangeSection(), + DWARFDataExtractor rangesData(*DObj, DObj->getRangesSection(), isLittleEndian(), savedAddressByteSize); - uint32_t offset = 0; + uint64_t offset = 0; DWARFDebugRangeList rangeList; while (rangesData.isValidOffset(offset)) { if (Error E = rangeList.extract(rangesData, &offset)) { @@ -552,38 +549,38 @@ void DWARFContext::dump( } if (shouldDump(Explicit, ".debug_pubnames", DIDT_ID_DebugPubnames, - DObj->getPubNamesSection().Data)) - DWARFDebugPubTable(*DObj, DObj->getPubNamesSection(), isLittleEndian(), false) + DObj->getPubnamesSection().Data)) + DWARFDebugPubTable(*DObj, DObj->getPubnamesSection(), isLittleEndian(), false) .dump(OS); if (shouldDump(Explicit, ".debug_pubtypes", DIDT_ID_DebugPubtypes, - DObj->getPubTypesSection().Data)) - DWARFDebugPubTable(*DObj, DObj->getPubTypesSection(), isLittleEndian(), false) + DObj->getPubtypesSection().Data)) + DWARFDebugPubTable(*DObj, DObj->getPubtypesSection(), isLittleEndian(), false) .dump(OS); if (shouldDump(Explicit, ".debug_gnu_pubnames", DIDT_ID_DebugGnuPubnames, - DObj->getGnuPubNamesSection().Data)) - DWARFDebugPubTable(*DObj, DObj->getGnuPubNamesSection(), isLittleEndian(), + DObj->getGnuPubnamesSection().Data)) + DWARFDebugPubTable(*DObj, DObj->getGnuPubnamesSection(), isLittleEndian(), true /* GnuStyle */) .dump(OS); if (shouldDump(Explicit, ".debug_gnu_pubtypes", DIDT_ID_DebugGnuPubtypes, - DObj->getGnuPubTypesSection().Data)) - DWARFDebugPubTable(*DObj, DObj->getGnuPubTypesSection(), isLittleEndian(), + DObj->getGnuPubtypesSection().Data)) + DWARFDebugPubTable(*DObj, DObj->getGnuPubtypesSection(), isLittleEndian(), true /* GnuStyle */) .dump(OS); if (shouldDump(Explicit, ".debug_str_offsets", DIDT_ID_DebugStrOffsets, - DObj->getStringOffsetSection().Data)) + DObj->getStrOffsetsSection().Data)) dumpStringOffsetsSection(OS, "debug_str_offsets", *DObj, - DObj->getStringOffsetSection(), - DObj->getStringSection(), normal_units(), + DObj->getStrOffsetsSection(), + DObj->getStrSection(), normal_units(), isLittleEndian(), getMaxVersion()); if (shouldDump(ExplicitDWO, ".debug_str_offsets.dwo", DIDT_ID_DebugStrOffsets, - DObj->getStringOffsetDWOSection().Data)) + DObj->getStrOffsetsDWOSection().Data)) dumpStringOffsetsSection(OS, "debug_str_offsets.dwo", *DObj, - DObj->getStringOffsetDWOSection(), - DObj->getStringDWOSection(), dwo_units(), + DObj->getStrOffsetsDWOSection(), + DObj->getStrDWOSection(), dwo_units(), isLittleEndian(), getMaxDWOVersion()); if (shouldDump(Explicit, ".gdb_index", DIDT_ID_GdbIndex, @@ -607,7 +604,7 @@ void DWARFContext::dump( DObj->getAppleObjCSection().Data)) getAppleObjC().dump(OS); if (shouldDump(Explicit, ".debug_names", DIDT_ID_DebugNames, - DObj->getDebugNamesSection().Data)) + DObj->getNamesSection().Data)) getDebugNames().dump(OS); } @@ -641,7 +638,7 @@ DWARFCompileUnit *DWARFContext::getDWOCompileUnitForHash(uint64_t Hash) { return nullptr; } -DWARFDie DWARFContext::getDIEForOffset(uint32_t Offset) { +DWARFDie DWARFContext::getDIEForOffset(uint64_t Offset) { parseNormalUnits(); if (auto *CU = NormalUnits.getUnitForOffset(Offset)) return CU->getDIEForOffset(Offset); @@ -667,7 +664,7 @@ const DWARFUnitIndex &DWARFContext::getCUIndex() { DataExtractor CUIndexData(DObj->getCUIndexSection(), isLittleEndian(), 0); - CUIndex = llvm::make_unique<DWARFUnitIndex>(DW_SECT_INFO); + CUIndex = std::make_unique<DWARFUnitIndex>(DW_SECT_INFO); CUIndex->parse(CUIndexData); return *CUIndex; } @@ -678,7 +675,7 @@ const DWARFUnitIndex &DWARFContext::getTUIndex() { DataExtractor TUIndexData(DObj->getTUIndexSection(), isLittleEndian(), 0); - TUIndex = llvm::make_unique<DWARFUnitIndex>(DW_SECT_TYPES); + TUIndex = std::make_unique<DWARFUnitIndex>(DW_SECT_TYPES); TUIndex->parse(TUIndexData); return *TUIndex; } @@ -688,7 +685,7 @@ DWARFGdbIndex &DWARFContext::getGdbIndex() { return *GdbIndex; DataExtractor GdbIndexData(DObj->getGdbIndexSection(), true /*LE*/, 0); - GdbIndex = llvm::make_unique<DWARFGdbIndex>(); + GdbIndex = std::make_unique<DWARFGdbIndex>(); GdbIndex->parse(GdbIndexData); return *GdbIndex; } @@ -740,7 +737,7 @@ const DWARFDebugLoclists *DWARFContext::getDebugLocDWO() { // Use version 4. DWO does not support the DWARF v5 .debug_loclists yet and // that means we are parsing the new style .debug_loc (pre-standatized version // of the .debug_loclists). - LocDWO->parse(LocData, 4 /* Version */); + LocDWO->parse(LocData, 0, LocData.getData().size(), 4 /* Version */); return LocDWO.get(); } @@ -766,7 +763,7 @@ const DWARFDebugFrame *DWARFContext::getDebugFrame() { // provides this information). This problem is fixed in DWARFv4 // See this dwarf-discuss discussion for more details: // http://lists.dwarfstd.org/htdig.cgi/dwarf-discuss-dwarfstd.org/2011-December/001173.html - DWARFDataExtractor debugFrameData(DObj->getDebugFrameSection(), + DWARFDataExtractor debugFrameData(*DObj, DObj->getFrameSection(), isLittleEndian(), DObj->getAddressSize()); DebugFrame.reset(new DWARFDebugFrame(getArch(), false /* IsEH */)); DebugFrame->parse(debugFrameData); @@ -777,8 +774,8 @@ const DWARFDebugFrame *DWARFContext::getEHFrame() { if (EHFrame) return EHFrame.get(); - DWARFDataExtractor debugFrameData(DObj->getEHFrameSection(), isLittleEndian(), - DObj->getAddressSize()); + DWARFDataExtractor debugFrameData(*DObj, DObj->getEHFrameSection(), + isLittleEndian(), DObj->getAddressSize()); DebugFrame.reset(new DWARFDebugFrame(getArch(), true /* IsEH */)); DebugFrame->parse(debugFrameData); return DebugFrame.get(); @@ -809,29 +806,29 @@ static T &getAccelTable(std::unique_ptr<T> &Cache, const DWARFObject &Obj, } const DWARFDebugNames &DWARFContext::getDebugNames() { - return getAccelTable(Names, *DObj, DObj->getDebugNamesSection(), - DObj->getStringSection(), isLittleEndian()); + return getAccelTable(Names, *DObj, DObj->getNamesSection(), + DObj->getStrSection(), isLittleEndian()); } const AppleAcceleratorTable &DWARFContext::getAppleNames() { return getAccelTable(AppleNames, *DObj, DObj->getAppleNamesSection(), - DObj->getStringSection(), isLittleEndian()); + DObj->getStrSection(), isLittleEndian()); } const AppleAcceleratorTable &DWARFContext::getAppleTypes() { return getAccelTable(AppleTypes, *DObj, DObj->getAppleTypesSection(), - DObj->getStringSection(), isLittleEndian()); + DObj->getStrSection(), isLittleEndian()); } const AppleAcceleratorTable &DWARFContext::getAppleNamespaces() { return getAccelTable(AppleNamespaces, *DObj, DObj->getAppleNamespacesSection(), - DObj->getStringSection(), isLittleEndian()); + DObj->getStrSection(), isLittleEndian()); } const AppleAcceleratorTable &DWARFContext::getAppleObjC() { return getAccelTable(AppleObjC, *DObj, DObj->getAppleObjCSection(), - DObj->getStringSection(), isLittleEndian()); + DObj->getStrSection(), isLittleEndian()); } const DWARFDebugLine::LineTable * @@ -858,7 +855,7 @@ Expected<const DWARFDebugLine::LineTable *> DWARFContext::getLineTableForUnit( if (!Offset) return nullptr; // No line table for this compile unit. - uint32_t stmtOffset = *Offset + U->getLineTableOffset(); + uint64_t stmtOffset = *Offset + U->getLineTableOffset(); // See if the line table is cached. if (const DWARFLineTable *lt = Line->getLineTable(stmtOffset)) return lt; @@ -898,7 +895,7 @@ void DWARFContext::parseDWOUnits(bool Lazy) { }); } -DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint32_t Offset) { +DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint64_t Offset) { parseNormalUnits(); return dyn_cast_or_null<DWARFCompileUnit>( NormalUnits.getUnitForOffset(Offset)); @@ -906,7 +903,7 @@ DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint32_t Offset) { DWARFCompileUnit *DWARFContext::getCompileUnitForAddress(uint64_t Address) { // First, get the offset of the compile unit. - uint32_t CUOffset = getDebugAranges()->findAddress(Address); + uint64_t CUOffset = getDebugAranges()->findAddress(Address); // Retrieve the compile unit. return getCompileUnitForOffset(CUOffset); } @@ -1118,8 +1115,8 @@ DILineInfoTable DWARFContext::getLineInfoForAddressRange( if (!CU) return Lines; - std::string FunctionName = "<invalid>"; uint32_t StartLine = 0; + std::string FunctionName(DILineInfo::BadString); getFunctionNameAndStartLineForAddress(CU, Address.Address, Spec.FNKind, FunctionName, StartLine); @@ -1379,46 +1376,50 @@ class DWARFObjInMemory final : public DWARFObject { InfoSectionMap TypesDWOSections; DWARFSectionMap LocSection; - DWARFSectionMap LocListsSection; + DWARFSectionMap LoclistsSection; DWARFSectionMap LineSection; - DWARFSectionMap RangeSection; + DWARFSectionMap RangesSection; DWARFSectionMap RnglistsSection; - DWARFSectionMap StringOffsetSection; + DWARFSectionMap StrOffsetsSection; DWARFSectionMap LineDWOSection; + DWARFSectionMap FrameSection; + DWARFSectionMap EHFrameSection; DWARFSectionMap LocDWOSection; - DWARFSectionMap StringOffsetDWOSection; - DWARFSectionMap RangeDWOSection; + DWARFSectionMap StrOffsetsDWOSection; + DWARFSectionMap RangesDWOSection; DWARFSectionMap RnglistsDWOSection; DWARFSectionMap AddrSection; DWARFSectionMap AppleNamesSection; DWARFSectionMap AppleTypesSection; DWARFSectionMap AppleNamespacesSection; DWARFSectionMap AppleObjCSection; - DWARFSectionMap DebugNamesSection; - DWARFSectionMap PubNamesSection; - DWARFSectionMap PubTypesSection; - DWARFSectionMap GnuPubNamesSection; - DWARFSectionMap GnuPubTypesSection; + DWARFSectionMap NamesSection; + DWARFSectionMap PubnamesSection; + DWARFSectionMap PubtypesSection; + DWARFSectionMap GnuPubnamesSection; + DWARFSectionMap GnuPubtypesSection; DWARFSectionMap *mapNameToDWARFSection(StringRef Name) { return StringSwitch<DWARFSectionMap *>(Name) .Case("debug_loc", &LocSection) - .Case("debug_loclists", &LocListsSection) + .Case("debug_loclists", &LoclistsSection) .Case("debug_line", &LineSection) - .Case("debug_str_offsets", &StringOffsetSection) - .Case("debug_ranges", &RangeSection) + .Case("debug_frame", &FrameSection) + .Case("eh_frame", &EHFrameSection) + .Case("debug_str_offsets", &StrOffsetsSection) + .Case("debug_ranges", &RangesSection) .Case("debug_rnglists", &RnglistsSection) .Case("debug_loc.dwo", &LocDWOSection) .Case("debug_line.dwo", &LineDWOSection) - .Case("debug_names", &DebugNamesSection) + .Case("debug_names", &NamesSection) .Case("debug_rnglists.dwo", &RnglistsDWOSection) - .Case("debug_str_offsets.dwo", &StringOffsetDWOSection) + .Case("debug_str_offsets.dwo", &StrOffsetsDWOSection) .Case("debug_addr", &AddrSection) .Case("apple_names", &AppleNamesSection) - .Case("debug_pubnames", &PubNamesSection) - .Case("debug_pubtypes", &PubTypesSection) - .Case("debug_gnu_pubnames", &GnuPubNamesSection) - .Case("debug_gnu_pubtypes", &GnuPubTypesSection) + .Case("debug_pubnames", &PubnamesSection) + .Case("debug_pubtypes", &PubtypesSection) + .Case("debug_gnu_pubnames", &GnuPubnamesSection) + .Case("debug_gnu_pubtypes", &GnuPubtypesSection) .Case("apple_types", &AppleTypesSection) .Case("apple_namespaces", &AppleNamespacesSection) .Case("apple_namespac", &AppleNamespacesSection) @@ -1427,17 +1428,15 @@ class DWARFObjInMemory final : public DWARFObject { } StringRef AbbrevSection; - StringRef ARangeSection; - StringRef DebugFrameSection; - StringRef EHFrameSection; - StringRef StringSection; + StringRef ArangesSection; + StringRef StrSection; StringRef MacinfoSection; StringRef AbbrevDWOSection; - StringRef StringDWOSection; + StringRef StrDWOSection; StringRef CUIndexSection; StringRef GdbIndexSection; StringRef TUIndexSection; - StringRef LineStringSection; + StringRef LineStrSection; // A deque holding section data whose iterators are not invalidated when // new decompressed sections are inserted at the end. @@ -1448,17 +1447,15 @@ class DWARFObjInMemory final : public DWARFObject { return &Sec->Data; return StringSwitch<StringRef *>(Name) .Case("debug_abbrev", &AbbrevSection) - .Case("debug_aranges", &ARangeSection) - .Case("debug_frame", &DebugFrameSection) - .Case("eh_frame", &EHFrameSection) - .Case("debug_str", &StringSection) + .Case("debug_aranges", &ArangesSection) + .Case("debug_str", &StrSection) .Case("debug_macinfo", &MacinfoSection) .Case("debug_abbrev.dwo", &AbbrevDWOSection) - .Case("debug_str.dwo", &StringDWOSection) + .Case("debug_str.dwo", &StrDWOSection) .Case("debug_cu_index", &CUIndexSection) .Case("debug_tu_index", &TUIndexSection) .Case("gdb_index", &GdbIndexSection) - .Case("debug_line_str", &LineStringSection) + .Case("debug_line_str", &LineStrSection) // Any more debug info sections go here. .Default(nullptr); } @@ -1513,7 +1510,11 @@ public: StringMap<unsigned> SectionAmountMap; for (const SectionRef &Section : Obj.sections()) { StringRef Name; - Section.getName(Name); + if (auto NameOrErr = Section.getName()) + Name = *NameOrErr; + else + consumeError(NameOrErr.takeError()); + ++SectionAmountMap[Name]; SectionNames.push_back({ Name, true }); @@ -1526,10 +1527,19 @@ public: continue; StringRef Data; - section_iterator RelocatedSection = Section.getRelocatedSection(); + Expected<section_iterator> SecOrErr = Section.getRelocatedSection(); + if (!SecOrErr) { + ErrorPolicy EP = HandleError(createError( + "failed to get relocated section: ", SecOrErr.takeError())); + if (EP == ErrorPolicy::Halt) + return; + continue; + } + // Try to obtain an already relocated version of this section. // Else use the unrelocated section from the object file. We'll have to // apply relocations ourselves later. + section_iterator RelocatedSection = *SecOrErr; if (!L || !L->getLoadedSectionContents(*RelocatedSection, Data)) { Expected<StringRef> E = Section.getContents(); if (E) @@ -1560,7 +1570,7 @@ public: *SectionData = Data; if (Name == "debug_ranges") { // FIXME: Use the other dwo range section when we emit it. - RangeDWOSection.Data = Data; + RangesDWOSection.Data = Data; } } else if (Name == "debug_info") { // Find debug_info and debug_types data by section rather than name as @@ -1578,12 +1588,15 @@ public: continue; StringRef RelSecName; - StringRef RelSecData; - RelocatedSection->getName(RelSecName); + if (auto NameOrErr = RelocatedSection->getName()) + RelSecName = *NameOrErr; + else + consumeError(NameOrErr.takeError()); // If the section we're relocating was relocated already by the JIT, // then we used the relocated version above, so we do not need to process // relocations for it now. + StringRef RelSecData; if (L && L->getLoadedSectionContents(*RelocatedSection, RelSecData)) continue; @@ -1710,12 +1723,12 @@ public: const DWARFSection &getLocDWOSection() const override { return LocDWOSection; } - StringRef getStringDWOSection() const override { return StringDWOSection; } - const DWARFSection &getStringOffsetDWOSection() const override { - return StringOffsetDWOSection; + StringRef getStrDWOSection() const override { return StrDWOSection; } + const DWARFSection &getStrOffsetsDWOSection() const override { + return StrOffsetsDWOSection; } - const DWARFSection &getRangeDWOSection() const override { - return RangeDWOSection; + const DWARFSection &getRangesDWOSection() const override { + return RangesDWOSection; } const DWARFSection &getRnglistsDWOSection() const override { return RnglistsDWOSection; @@ -1726,10 +1739,10 @@ public: StringRef getTUIndexSection() const override { return TUIndexSection; } // DWARF v5 - const DWARFSection &getStringOffsetSection() const override { - return StringOffsetSection; + const DWARFSection &getStrOffsetsSection() const override { + return StrOffsetsSection; } - StringRef getLineStringSection() const override { return LineStringSection; } + StringRef getLineStrSection() const override { return LineStrSection; } // Sections for DWARF5 split dwarf proposal. void forEachInfoDWOSections( @@ -1745,24 +1758,28 @@ public: StringRef getAbbrevSection() const override { return AbbrevSection; } const DWARFSection &getLocSection() const override { return LocSection; } - const DWARFSection &getLoclistsSection() const override { return LocListsSection; } - StringRef getARangeSection() const override { return ARangeSection; } - StringRef getDebugFrameSection() const override { return DebugFrameSection; } - StringRef getEHFrameSection() const override { return EHFrameSection; } + const DWARFSection &getLoclistsSection() const override { return LoclistsSection; } + StringRef getArangesSection() const override { return ArangesSection; } + const DWARFSection &getFrameSection() const override { + return FrameSection; + } + const DWARFSection &getEHFrameSection() const override { + return EHFrameSection; + } const DWARFSection &getLineSection() const override { return LineSection; } - StringRef getStringSection() const override { return StringSection; } - const DWARFSection &getRangeSection() const override { return RangeSection; } + StringRef getStrSection() const override { return StrSection; } + const DWARFSection &getRangesSection() const override { return RangesSection; } const DWARFSection &getRnglistsSection() const override { return RnglistsSection; } StringRef getMacinfoSection() const override { return MacinfoSection; } - const DWARFSection &getPubNamesSection() const override { return PubNamesSection; } - const DWARFSection &getPubTypesSection() const override { return PubTypesSection; } - const DWARFSection &getGnuPubNamesSection() const override { - return GnuPubNamesSection; + const DWARFSection &getPubnamesSection() const override { return PubnamesSection; } + const DWARFSection &getPubtypesSection() const override { return PubtypesSection; } + const DWARFSection &getGnuPubnamesSection() const override { + return GnuPubnamesSection; } - const DWARFSection &getGnuPubTypesSection() const override { - return GnuPubTypesSection; + const DWARFSection &getGnuPubtypesSection() const override { + return GnuPubtypesSection; } const DWARFSection &getAppleNamesSection() const override { return AppleNamesSection; @@ -1776,8 +1793,8 @@ public: const DWARFSection &getAppleObjCSection() const override { return AppleObjCSection; } - const DWARFSection &getDebugNamesSection() const override { - return DebugNamesSection; + const DWARFSection &getNamesSection() const override { + return NamesSection; } StringRef getFileName() const override { return FileName; } @@ -1799,16 +1816,16 @@ std::unique_ptr<DWARFContext> DWARFContext::create(const object::ObjectFile &Obj, const LoadedObjectInfo *L, function_ref<ErrorPolicy(Error)> HandleError, std::string DWPName) { - auto DObj = llvm::make_unique<DWARFObjInMemory>(Obj, L, HandleError); - return llvm::make_unique<DWARFContext>(std::move(DObj), std::move(DWPName)); + auto DObj = std::make_unique<DWARFObjInMemory>(Obj, L, HandleError); + return std::make_unique<DWARFContext>(std::move(DObj), std::move(DWPName)); } std::unique_ptr<DWARFContext> DWARFContext::create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections, uint8_t AddrSize, bool isLittleEndian) { auto DObj = - llvm::make_unique<DWARFObjInMemory>(Sections, AddrSize, isLittleEndian); - return llvm::make_unique<DWARFContext>(std::move(DObj), ""); + std::make_unique<DWARFObjInMemory>(Sections, AddrSize, isLittleEndian); + return std::make_unique<DWARFContext>(std::move(DObj), ""); } Error DWARFContext::loadRegisterInfo(const object::ObjectFile &Obj) { diff --git a/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp b/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp index b9adf8cb1d99..53e676bc7031 100644 --- a/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp +++ b/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp @@ -12,14 +12,15 @@ using namespace llvm; -uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint32_t *Off, - uint64_t *SecNdx) const { +uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint64_t *Off, + uint64_t *SecNdx, + Error *Err) const { if (SecNdx) *SecNdx = object::SectionedAddress::UndefSection; if (!Section) - return getUnsigned(Off, Size); + return getUnsigned(Off, Size, Err); Optional<RelocAddrEntry> E = Obj->find(*Section, *Off); - uint64_t A = getUnsigned(Off, Size); + uint64_t A = getUnsigned(Off, Size, Err); if (!E) return A; if (SecNdx) @@ -31,13 +32,13 @@ uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint32_t *Off, } Optional<uint64_t> -DWARFDataExtractor::getEncodedPointer(uint32_t *Offset, uint8_t Encoding, +DWARFDataExtractor::getEncodedPointer(uint64_t *Offset, uint8_t Encoding, uint64_t PCRelOffset) const { if (Encoding == dwarf::DW_EH_PE_omit) return None; uint64_t Result = 0; - uint32_t OldOffset = *Offset; + uint64_t OldOffset = *Offset; // First get value switch (Encoding & 0x0F) { case dwarf::DW_EH_PE_absptr: diff --git a/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp b/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp index 31b324e5eb27..4afac2f99503 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp @@ -26,9 +26,9 @@ void DWARFAbbreviationDeclarationSet::clear() { } bool DWARFAbbreviationDeclarationSet::extract(DataExtractor Data, - uint32_t *OffsetPtr) { + uint64_t *OffsetPtr) { clear(); - const uint32_t BeginOffset = *OffsetPtr; + const uint64_t BeginOffset = *OffsetPtr; Offset = BeginOffset; DWARFAbbreviationDeclaration AbbrDecl; uint32_t PrevAbbrCode = 0; @@ -82,12 +82,12 @@ void DWARFDebugAbbrev::extract(DataExtractor Data) { void DWARFDebugAbbrev::parse() const { if (!Data) return; - uint32_t Offset = 0; + uint64_t Offset = 0; auto I = AbbrDeclSets.begin(); while (Data->isValidOffset(Offset)) { while (I != AbbrDeclSets.end() && I->first < Offset) ++I; - uint32_t CUAbbrOffset = Offset; + uint64_t CUAbbrOffset = Offset; DWARFAbbreviationDeclarationSet AbbrDecls; if (!AbbrDecls.extract(*Data, &Offset)) break; @@ -124,7 +124,7 @@ DWARFDebugAbbrev::getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const { } if (Data && CUAbbrOffset < Data->getData().size()) { - uint32_t Offset = CUAbbrOffset; + uint64_t Offset = CUAbbrOffset; DWARFAbbreviationDeclarationSet AbbrDecls; if (!AbbrDecls.extract(*Data, &Offset)) return nullptr; diff --git a/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp b/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp index 58626539bba4..f71543799e28 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp @@ -19,7 +19,7 @@ void DWARFDebugAddrTable::clear() { } Error DWARFDebugAddrTable::extract(DWARFDataExtractor Data, - uint32_t *OffsetPtr, + uint64_t *OffsetPtr, uint16_t Version, uint8_t AddrSize, std::function<void(Error)> WarnCallback) { @@ -30,7 +30,7 @@ Error DWARFDebugAddrTable::extract(DWARFDataExtractor Data, return createStringError(errc::invalid_argument, "section is not large enough to contain a " ".debug_addr table length at offset 0x%" - PRIx32, *OffsetPtr); + PRIx64, *OffsetPtr); uint16_t UnitVersion; if (Version == 0) { WarnCallback(createStringError(errc::invalid_argument, @@ -44,28 +44,28 @@ Error DWARFDebugAddrTable::extract(DWARFDataExtractor Data, Format = dwarf::DwarfFormat::DWARF32; if (UnitVersion >= 5) { HeaderData.Length = Data.getU32(OffsetPtr); - if (HeaderData.Length == 0xffffffffu) { + if (HeaderData.Length == dwarf::DW_LENGTH_DWARF64) { invalidateLength(); return createStringError(errc::not_supported, - "DWARF64 is not supported in .debug_addr at offset 0x%" PRIx32, + "DWARF64 is not supported in .debug_addr at offset 0x%" PRIx64, HeaderOffset); } if (HeaderData.Length + sizeof(uint32_t) < sizeof(Header)) { uint32_t TmpLength = getLength(); invalidateLength(); return createStringError(errc::invalid_argument, - ".debug_addr table at offset 0x%" PRIx32 + ".debug_addr table at offset 0x%" PRIx64 " has too small length (0x%" PRIx32 ") to contain a complete header", HeaderOffset, TmpLength); } - uint32_t End = HeaderOffset + getLength(); + uint64_t End = HeaderOffset + getLength(); if (!Data.isValidOffsetForDataOfSize(HeaderOffset, End - HeaderOffset)) { uint32_t TmpLength = getLength(); invalidateLength(); return createStringError(errc::invalid_argument, "section is not large enough to contain a .debug_addr table " - "of length 0x%" PRIx32 " at offset 0x%" PRIx32, + "of length 0x%" PRIx32 " at offset 0x%" PRIx64, TmpLength, HeaderOffset); } @@ -88,7 +88,7 @@ Error DWARFDebugAddrTable::extract(DWARFDataExtractor Data, // and consists only of a series of addresses. if (HeaderData.Version > 5) { return createStringError(errc::not_supported, "version %" PRIu16 - " of .debug_addr section at offset 0x%" PRIx32 " is not supported", + " of .debug_addr section at offset 0x%" PRIx64 " is not supported", HeaderData.Version, HeaderOffset); } // FIXME: For now we just treat version mismatch as an error, @@ -97,19 +97,19 @@ Error DWARFDebugAddrTable::extract(DWARFDataExtractor Data, // attribute in the info table. if (HeaderData.Version != UnitVersion) return createStringError(errc::invalid_argument, - ".debug_addr table at offset 0x%" PRIx32 + ".debug_addr table at offset 0x%" PRIx64 " has version %" PRIu16 " which is different from the version suggested" " by the DWARF unit header: %" PRIu16, HeaderOffset, HeaderData.Version, UnitVersion); if (HeaderData.AddrSize != 4 && HeaderData.AddrSize != 8) return createStringError(errc::not_supported, - ".debug_addr table at offset 0x%" PRIx32 + ".debug_addr table at offset 0x%" PRIx64 " has unsupported address size %" PRIu8, HeaderOffset, HeaderData.AddrSize); if (HeaderData.AddrSize != AddrSize && AddrSize != 0) return createStringError(errc::invalid_argument, - ".debug_addr table at offset 0x%" PRIx32 + ".debug_addr table at offset 0x%" PRIx64 " has address size %" PRIu8 " which is different from CU address size %" PRIu8, HeaderOffset, HeaderData.AddrSize, AddrSize); @@ -117,13 +117,13 @@ Error DWARFDebugAddrTable::extract(DWARFDataExtractor Data, // TODO: add support for non-zero segment selector size. if (HeaderData.SegSize != 0) return createStringError(errc::not_supported, - ".debug_addr table at offset 0x%" PRIx32 + ".debug_addr table at offset 0x%" PRIx64 " has unsupported segment selector size %" PRIu8, HeaderOffset, HeaderData.SegSize); if (DataSize % HeaderData.AddrSize != 0) { invalidateLength(); return createStringError(errc::invalid_argument, - ".debug_addr table at offset 0x%" PRIx32 + ".debug_addr table at offset 0x%" PRIx64 " contains data of size %" PRIu32 " which is not a multiple of addr size %" PRIu8, HeaderOffset, DataSize, HeaderData.AddrSize); @@ -162,7 +162,7 @@ Expected<uint64_t> DWARFDebugAddrTable::getAddrEntry(uint32_t Index) const { return Addrs[Index]; return createStringError(errc::invalid_argument, "Index %" PRIu32 " is out of range of the " - ".debug_addr table at offset 0x%" PRIx32, + ".debug_addr table at offset 0x%" PRIx64, Index, HeaderOffset); } diff --git a/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp b/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp index 6551b61accb8..200b2d52a02b 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp @@ -24,13 +24,13 @@ void DWARFDebugArangeSet::Descriptor::dump(raw_ostream &OS, } void DWARFDebugArangeSet::clear() { - Offset = -1U; + Offset = -1ULL; std::memset(&HeaderData, 0, sizeof(Header)); ArangeDescriptors.clear(); } bool -DWARFDebugArangeSet::extract(DataExtractor data, uint32_t *offset_ptr) { +DWARFDebugArangeSet::extract(DataExtractor data, uint64_t *offset_ptr) { if (data.isValidOffset(*offset_ptr)) { ArangeDescriptors.clear(); Offset = *offset_ptr; diff --git a/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp b/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp index 6460c9feeab8..ca6043109cdb 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp @@ -23,11 +23,11 @@ using namespace llvm; void DWARFDebugAranges::extract(DataExtractor DebugArangesData) { if (!DebugArangesData.isValidOffset(0)) return; - uint32_t Offset = 0; + uint64_t Offset = 0; DWARFDebugArangeSet Set; while (Set.extract(DebugArangesData, &Offset)) { - uint32_t CUOffset = Set.getCompileUnitDIEOffset(); + uint64_t CUOffset = Set.getCompileUnitDIEOffset(); for (const auto &Desc : Set.descriptors()) { uint64_t LowPC = Desc.Address; uint64_t HighPC = Desc.getEndAddress(); @@ -43,7 +43,7 @@ void DWARFDebugAranges::generate(DWARFContext *CTX) { return; // Extract aranges from .debug_aranges section. - DataExtractor ArangesData(CTX->getDWARFObj().getARangeSection(), + DataExtractor ArangesData(CTX->getDWARFObj().getArangesSection(), CTX->isLittleEndian(), 0); extract(ArangesData); @@ -51,7 +51,7 @@ void DWARFDebugAranges::generate(DWARFContext *CTX) { // it may describe only a small subset of compilation units, so we need to // manually build aranges for the rest of them. for (const auto &CU : CTX->compile_units()) { - uint32_t CUOffset = CU->getOffset(); + uint64_t CUOffset = CU->getOffset(); if (ParsedCUOffsets.insert(CUOffset).second) { Expected<DWARFAddressRangesVector> CURanges = CU->collectAddressRanges(); if (!CURanges) @@ -71,7 +71,7 @@ void DWARFDebugAranges::clear() { ParsedCUOffsets.clear(); } -void DWARFDebugAranges::appendRange(uint32_t CUOffset, uint64_t LowPC, +void DWARFDebugAranges::appendRange(uint64_t CUOffset, uint64_t LowPC, uint64_t HighPC) { if (LowPC >= HighPC) return; @@ -80,7 +80,7 @@ void DWARFDebugAranges::appendRange(uint32_t CUOffset, uint64_t LowPC, } void DWARFDebugAranges::construct() { - std::multiset<uint32_t> ValidCUs; // Maintain the set of CUs describing + std::multiset<uint64_t> ValidCUs; // Maintain the set of CUs describing // a current address range. llvm::sort(Endpoints); uint64_t PrevAddress = -1ULL; diff --git a/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp index b3f23366f2a2..81b00f65741b 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp @@ -34,10 +34,10 @@ using namespace dwarf; const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0; const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f; -Error CFIProgram::parse(DataExtractor Data, uint32_t *Offset, - uint32_t EndOffset) { +Error CFIProgram::parse(DWARFDataExtractor Data, uint64_t *Offset, + uint64_t EndOffset) { while (*Offset < EndOffset) { - uint8_t Opcode = Data.getU8(Offset); + uint8_t Opcode = Data.getRelocatedValue(1, Offset); // Some instructions have a primary opcode encoded in the top bits. uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK; @@ -74,19 +74,19 @@ Error CFIProgram::parse(DataExtractor Data, uint32_t *Offset, break; case DW_CFA_set_loc: // Operands: Address - addInstruction(Opcode, Data.getAddress(Offset)); + addInstruction(Opcode, Data.getRelocatedAddress(Offset)); break; case DW_CFA_advance_loc1: // Operands: 1-byte delta - addInstruction(Opcode, Data.getU8(Offset)); + addInstruction(Opcode, Data.getRelocatedValue(1, Offset)); break; case DW_CFA_advance_loc2: // Operands: 2-byte delta - addInstruction(Opcode, Data.getU16(Offset)); + addInstruction(Opcode, Data.getRelocatedValue(2, Offset)); break; case DW_CFA_advance_loc4: // Operands: 4-byte delta - addInstruction(Opcode, Data.getU32(Offset)); + addInstruction(Opcode, Data.getRelocatedValue(4, Offset)); break; case DW_CFA_restore_extended: case DW_CFA_undefined: @@ -331,7 +331,7 @@ DWARFDebugFrame::DWARFDebugFrame(Triple::ArchType Arch, DWARFDebugFrame::~DWARFDebugFrame() = default; static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data, - uint32_t Offset, int Length) { + uint64_t Offset, int Length) { errs() << "DUMP: "; for (int i = 0; i < Length; ++i) { uint8_t c = Data.getU8(&Offset); @@ -344,7 +344,7 @@ static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data, // noreturn attribute usage in lambdas. Once the support for those // compilers are phased out, we can remove this and return back to // a ReportError lambda: [StartOffset](const char *ErrorMsg). -static void LLVM_ATTRIBUTE_NORETURN ReportError(uint32_t StartOffset, +static void LLVM_ATTRIBUTE_NORETURN ReportError(uint64_t StartOffset, const char *ErrorMsg) { std::string Str; raw_string_ostream OS(Str); @@ -354,32 +354,30 @@ static void LLVM_ATTRIBUTE_NORETURN ReportError(uint32_t StartOffset, } void DWARFDebugFrame::parse(DWARFDataExtractor Data) { - uint32_t Offset = 0; - DenseMap<uint32_t, CIE *> CIEs; + uint64_t Offset = 0; + DenseMap<uint64_t, CIE *> CIEs; while (Data.isValidOffset(Offset)) { - uint32_t StartOffset = Offset; + uint64_t StartOffset = Offset; bool IsDWARF64 = false; - uint64_t Length = Data.getU32(&Offset); + uint64_t Length = Data.getRelocatedValue(4, &Offset); uint64_t Id; - if (Length == UINT32_MAX) { + if (Length == dwarf::DW_LENGTH_DWARF64) { // DWARF-64 is distinguished by the first 32 bits of the initial length // field being 0xffffffff. Then, the next 64 bits are the actual entry // length. IsDWARF64 = true; - Length = Data.getU64(&Offset); + Length = Data.getRelocatedValue(8, &Offset); } // At this point, Offset points to the next field after Length. // Length is the structure size excluding itself. Compute an offset one // past the end of the structure (needed to know how many instructions to // read). - // TODO: For honest DWARF64 support, DataExtractor will have to treat - // offset_ptr as uint64_t* - uint32_t StartStructureOffset = Offset; - uint32_t EndStructureOffset = Offset + static_cast<uint32_t>(Length); + uint64_t StartStructureOffset = Offset; + uint64_t EndStructureOffset = Offset + Length; // The Id field's size depends on the DWARF format Id = Data.getUnsigned(&Offset, (IsDWARF64 && !IsEH) ? 8 : 4); @@ -407,22 +405,23 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) { Optional<uint32_t> PersonalityEncoding; if (IsEH) { Optional<uint64_t> AugmentationLength; - uint32_t StartAugmentationOffset; - uint32_t EndAugmentationOffset; + uint64_t StartAugmentationOffset; + uint64_t EndAugmentationOffset; // Walk the augmentation string to get all the augmentation data. for (unsigned i = 0, e = AugmentationString.size(); i != e; ++i) { switch (AugmentationString[i]) { default: - ReportError(StartOffset, - "Unknown augmentation character in entry at %lx"); + ReportError( + StartOffset, + "Unknown augmentation character in entry at %" PRIx64); case 'L': LSDAPointerEncoding = Data.getU8(&Offset); break; case 'P': { if (Personality) ReportError(StartOffset, - "Duplicate personality in entry at %lx"); + "Duplicate personality in entry at %" PRIx64); PersonalityEncoding = Data.getU8(&Offset); Personality = Data.getEncodedPointer( &Offset, *PersonalityEncoding, @@ -438,13 +437,12 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) { case 'z': if (i) ReportError(StartOffset, - "'z' must be the first character at %lx"); + "'z' must be the first character at %" PRIx64); // Parse the augmentation length first. We only parse it if // the string contains a 'z'. AugmentationLength = Data.getULEB128(&Offset); StartAugmentationOffset = Offset; - EndAugmentationOffset = Offset + - static_cast<uint32_t>(*AugmentationLength); + EndAugmentationOffset = Offset + *AugmentationLength; break; case 'B': // B-Key is used for signing functions associated with this @@ -455,14 +453,15 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) { if (AugmentationLength.hasValue()) { if (Offset != EndAugmentationOffset) - ReportError(StartOffset, "Parsing augmentation data at %lx failed"); + ReportError(StartOffset, + "Parsing augmentation data at %" PRIx64 " failed"); AugmentationData = Data.getData().slice(StartAugmentationOffset, EndAugmentationOffset); } } - auto Cie = llvm::make_unique<CIE>( + auto Cie = std::make_unique<CIE>( StartOffset, Length, Version, AugmentationString, AddressSize, SegmentDescriptorSize, CodeAlignmentFactor, DataAlignmentFactor, ReturnAddressRegister, AugmentationData, FDEPointerEncoding, @@ -480,8 +479,8 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) { if (IsEH) { // The address size is encoded in the CIE we reference. if (!Cie) - ReportError(StartOffset, - "Parsing FDE data at %lx failed due to missing CIE"); + ReportError(StartOffset, "Parsing FDE data at %" PRIx64 + " failed due to missing CIE"); if (auto Val = Data.getEncodedPointer( &Offset, Cie->getFDEPointerEncoding(), @@ -498,8 +497,7 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) { // Parse the augmentation length and data for this FDE. uint64_t AugmentationLength = Data.getULEB128(&Offset); - uint32_t EndAugmentationOffset = - Offset + static_cast<uint32_t>(AugmentationLength); + uint64_t EndAugmentationOffset = Offset + AugmentationLength; // Decode the LSDA if the CIE augmentation string said we should. if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit) { @@ -509,11 +507,12 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) { } if (Offset != EndAugmentationOffset) - ReportError(StartOffset, "Parsing augmentation data at %lx failed"); + ReportError(StartOffset, + "Parsing augmentation data at %" PRIx64 " failed"); } } else { - InitialLocation = Data.getAddress(&Offset); - AddressRange = Data.getAddress(&Offset); + InitialLocation = Data.getRelocatedAddress(&Offset); + AddressRange = Data.getRelocatedAddress(&Offset); } Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer, @@ -527,7 +526,8 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) { } if (Offset != EndStructureOffset) - ReportError(StartOffset, "Parsing entry instructions at %lx failed"); + ReportError(StartOffset, + "Parsing entry instructions at %" PRIx64 " failed"); } } diff --git a/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp b/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp index d8a755e90df4..87eab34d58ee 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp @@ -19,15 +19,15 @@ using namespace llvm; using namespace dwarf; bool DWARFDebugInfoEntry::extractFast(const DWARFUnit &U, - uint32_t *OffsetPtr) { + uint64_t *OffsetPtr) { DWARFDataExtractor DebugInfoData = U.getDebugInfoExtractor(); - const uint32_t UEndOffset = U.getNextUnitOffset(); + const uint64_t UEndOffset = U.getNextUnitOffset(); return extractFast(U, OffsetPtr, DebugInfoData, UEndOffset, 0); } -bool DWARFDebugInfoEntry::extractFast(const DWARFUnit &U, uint32_t *OffsetPtr, +bool DWARFDebugInfoEntry::extractFast(const DWARFUnit &U, uint64_t *OffsetPtr, const DWARFDataExtractor &DebugInfoData, - uint32_t UEndOffset, uint32_t D) { + uint64_t UEndOffset, uint32_t D) { Offset = *OffsetPtr; Depth = D; if (Offset >= UEndOffset || !DebugInfoData.isValidOffset(Offset)) diff --git a/lib/DebugInfo/DWARF/DWARFDebugLine.cpp b/lib/DebugInfo/DWARF/DWARFDebugLine.cpp index a1cb1e8582ed..dbee28ff5ab1 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugLine.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugLine.cpp @@ -16,7 +16,6 @@ #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" #include "llvm/Support/Errc.h" #include "llvm/Support/Format.h" -#include "llvm/Support/Path.h" #include "llvm/Support/WithColor.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> @@ -156,7 +155,7 @@ void DWARFDebugLine::Prologue::dump(raw_ostream &OS, // Parse v2-v4 directory and file tables. static void parseV2DirFileTables(const DWARFDataExtractor &DebugLineData, - uint32_t *OffsetPtr, uint64_t EndPrologueOffset, + uint64_t *OffsetPtr, uint64_t EndPrologueOffset, DWARFDebugLine::ContentTypeTracker &ContentTypes, std::vector<DWARFFormValue> &IncludeDirectories, std::vector<DWARFDebugLine::FileNameEntry> &FileNames) { @@ -187,18 +186,24 @@ parseV2DirFileTables(const DWARFDataExtractor &DebugLineData, } // Parse v5 directory/file entry content descriptions. -// Returns the descriptors, or an empty vector if we did not find a path or -// ran off the end of the prologue. -static ContentDescriptors -parseV5EntryFormat(const DWARFDataExtractor &DebugLineData, uint32_t - *OffsetPtr, uint64_t EndPrologueOffset, DWARFDebugLine::ContentTypeTracker - *ContentTypes) { +// Returns the descriptors, or an error if we did not find a path or ran off +// the end of the prologue. +static llvm::Expected<ContentDescriptors> +parseV5EntryFormat(const DWARFDataExtractor &DebugLineData, uint64_t *OffsetPtr, + uint64_t EndPrologueOffset, + DWARFDebugLine::ContentTypeTracker *ContentTypes) { ContentDescriptors Descriptors; int FormatCount = DebugLineData.getU8(OffsetPtr); bool HasPath = false; for (int I = 0; I != FormatCount; ++I) { if (*OffsetPtr >= EndPrologueOffset) - return ContentDescriptors(); + return createStringError( + errc::invalid_argument, + "failed to parse entry content descriptions at offset " + "0x%8.8" PRIx64 + " because offset extends beyond the prologue end at offset " + "0x%8.8" PRIx64, + *OffsetPtr, EndPrologueOffset); ContentDescriptor Descriptor; Descriptor.Type = dwarf::LineNumberEntryFormat(DebugLineData.getULEB128(OffsetPtr)); @@ -209,60 +214,82 @@ parseV5EntryFormat(const DWARFDataExtractor &DebugLineData, uint32_t ContentTypes->trackContentType(Descriptor.Type); Descriptors.push_back(Descriptor); } - return HasPath ? Descriptors : ContentDescriptors(); + + if (!HasPath) + return createStringError(errc::invalid_argument, + "failed to parse entry content descriptions" + " because no path was found"); + return Descriptors; } -static bool +static Error parseV5DirFileTables(const DWARFDataExtractor &DebugLineData, - uint32_t *OffsetPtr, uint64_t EndPrologueOffset, + uint64_t *OffsetPtr, uint64_t EndPrologueOffset, const dwarf::FormParams &FormParams, const DWARFContext &Ctx, const DWARFUnit *U, DWARFDebugLine::ContentTypeTracker &ContentTypes, std::vector<DWARFFormValue> &IncludeDirectories, std::vector<DWARFDebugLine::FileNameEntry> &FileNames) { // Get the directory entry description. - ContentDescriptors DirDescriptors = + llvm::Expected<ContentDescriptors> DirDescriptors = parseV5EntryFormat(DebugLineData, OffsetPtr, EndPrologueOffset, nullptr); - if (DirDescriptors.empty()) - return false; + if (!DirDescriptors) + return DirDescriptors.takeError(); // Get the directory entries, according to the format described above. int DirEntryCount = DebugLineData.getU8(OffsetPtr); for (int I = 0; I != DirEntryCount; ++I) { if (*OffsetPtr >= EndPrologueOffset) - return false; - for (auto Descriptor : DirDescriptors) { + return createStringError( + errc::invalid_argument, + "failed to parse directory entry at offset " + "0x%8.8" PRIx64 + " because offset extends beyond the prologue end at offset " + "0x%8.8" PRIx64, + *OffsetPtr, EndPrologueOffset); + for (auto Descriptor : *DirDescriptors) { DWARFFormValue Value(Descriptor.Form); switch (Descriptor.Type) { case DW_LNCT_path: if (!Value.extractValue(DebugLineData, OffsetPtr, FormParams, &Ctx, U)) - return false; + return createStringError(errc::invalid_argument, + "failed to parse directory entry because " + "extracting the form value failed."); IncludeDirectories.push_back(Value); break; default: if (!Value.skipValue(DebugLineData, OffsetPtr, FormParams)) - return false; + return createStringError(errc::invalid_argument, + "failed to parse directory entry because " + "skipping the form value failed."); } } } // Get the file entry description. - ContentDescriptors FileDescriptors = - parseV5EntryFormat(DebugLineData, OffsetPtr, EndPrologueOffset, - &ContentTypes); - if (FileDescriptors.empty()) - return false; + llvm::Expected<ContentDescriptors> FileDescriptors = parseV5EntryFormat( + DebugLineData, OffsetPtr, EndPrologueOffset, &ContentTypes); + if (!FileDescriptors) + return FileDescriptors.takeError(); // Get the file entries, according to the format described above. int FileEntryCount = DebugLineData.getU8(OffsetPtr); for (int I = 0; I != FileEntryCount; ++I) { if (*OffsetPtr >= EndPrologueOffset) - return false; + return createStringError( + errc::invalid_argument, + "failed to parse file entry at offset " + "0x%8.8" PRIx64 + " because offset extends beyond the prologue end at offset " + "0x%8.8" PRIx64, + *OffsetPtr, EndPrologueOffset); DWARFDebugLine::FileNameEntry FileEntry; - for (auto Descriptor : FileDescriptors) { + for (auto Descriptor : *FileDescriptors) { DWARFFormValue Value(Descriptor.Form); if (!Value.extractValue(DebugLineData, OffsetPtr, FormParams, &Ctx, U)) - return false; + return createStringError(errc::invalid_argument, + "failed to parse file entry because " + "extracting the form value failed."); switch (Descriptor.Type) { case DW_LNCT_path: FileEntry.Name = Value; @@ -280,7 +307,10 @@ parseV5DirFileTables(const DWARFDataExtractor &DebugLineData, FileEntry.Length = Value.getAsUnsignedConstant().getValue(); break; case DW_LNCT_MD5: - assert(Value.getAsBlock().getValue().size() == 16); + if (!Value.getAsBlock() || Value.getAsBlock().getValue().size() != 16) + return createStringError( + errc::invalid_argument, + "failed to parse file entry because the MD5 hash is invalid"); std::uninitialized_copy_n(Value.getAsBlock().getValue().begin(), 16, FileEntry.Checksum.Bytes.begin()); break; @@ -290,21 +320,21 @@ parseV5DirFileTables(const DWARFDataExtractor &DebugLineData, } FileNames.push_back(FileEntry); } - return true; + return Error::success(); } Error DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData, - uint32_t *OffsetPtr, + uint64_t *OffsetPtr, const DWARFContext &Ctx, const DWARFUnit *U) { const uint64_t PrologueOffset = *OffsetPtr; clear(); TotalLength = DebugLineData.getRelocatedValue(4, OffsetPtr); - if (TotalLength == UINT32_MAX) { + if (TotalLength == dwarf::DW_LENGTH_DWARF64) { FormParams.Format = dwarf::DWARF64; TotalLength = DebugLineData.getU64(OffsetPtr); - } else if (TotalLength >= 0xfffffff0) { + } else if (TotalLength >= dwarf::DW_LENGTH_lo_reserved) { return createStringError(errc::invalid_argument, "parsing line table prologue at offset 0x%8.8" PRIx64 " unsupported reserved unit length found of value 0x%8.8" PRIx64, @@ -343,14 +373,17 @@ Error DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData, } if (getVersion() >= 5) { - if (!parseV5DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset, - FormParams, Ctx, U, ContentTypes, - IncludeDirectories, FileNames)) { - return createStringError(errc::invalid_argument, - "parsing line table prologue at 0x%8.8" PRIx64 - " found an invalid directory or file table description at" - " 0x%8.8" PRIx64, - PrologueOffset, (uint64_t)*OffsetPtr); + if (Error e = parseV5DirFileTables( + DebugLineData, OffsetPtr, EndPrologueOffset, FormParams, Ctx, U, + ContentTypes, IncludeDirectories, FileNames)) { + return joinErrors( + createStringError( + errc::invalid_argument, + "parsing line table prologue at 0x%8.8" PRIx64 + " found an invalid directory or file table description at" + " 0x%8.8" PRIx64, + PrologueOffset, *OffsetPtr), + std::move(e)); } } else parseV2DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset, @@ -361,7 +394,7 @@ Error DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData, "parsing line table prologue at 0x%8.8" PRIx64 " should have ended at 0x%8.8" PRIx64 " but it ended at 0x%8.8" PRIx64, - PrologueOffset, EndPrologueOffset, (uint64_t)*OffsetPtr); + PrologueOffset, EndPrologueOffset, *OffsetPtr); return Error::success(); } @@ -468,7 +501,7 @@ void DWARFDebugLine::ParsingState::appendRowToMatrix() { } const DWARFDebugLine::LineTable * -DWARFDebugLine::getLineTable(uint32_t Offset) const { +DWARFDebugLine::getLineTable(uint64_t Offset) const { LineTableConstIter Pos = LineTableMap.find(Offset); if (Pos != LineTableMap.end()) return &Pos->second; @@ -476,10 +509,10 @@ DWARFDebugLine::getLineTable(uint32_t Offset) const { } Expected<const DWARFDebugLine::LineTable *> DWARFDebugLine::getOrParseLineTable( - DWARFDataExtractor &DebugLineData, uint32_t Offset, const DWARFContext &Ctx, + DWARFDataExtractor &DebugLineData, uint64_t Offset, const DWARFContext &Ctx, const DWARFUnit *U, std::function<void(Error)> RecoverableErrorCallback) { if (!DebugLineData.isValidOffset(Offset)) - return createStringError(errc::invalid_argument, "offset 0x%8.8" PRIx32 + return createStringError(errc::invalid_argument, "offset 0x%8.8" PRIx64 " is not a valid debug line section offset", Offset); @@ -496,10 +529,10 @@ Expected<const DWARFDebugLine::LineTable *> DWARFDebugLine::getOrParseLineTable( } Error DWARFDebugLine::LineTable::parse( - DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr, + DWARFDataExtractor &DebugLineData, uint64_t *OffsetPtr, const DWARFContext &Ctx, const DWARFUnit *U, std::function<void(Error)> RecoverableErrorCallback, raw_ostream *OS) { - const uint32_t DebugLineOffset = *OffsetPtr; + const uint64_t DebugLineOffset = *OffsetPtr; clear(); @@ -515,7 +548,7 @@ Error DWARFDebugLine::LineTable::parse( if (PrologueErr) return PrologueErr; - const uint32_t EndOffset = + const uint64_t EndOffset = DebugLineOffset + Prologue.TotalLength + Prologue.sizeofTotalLength(); // See if we should tell the data extractor the address size. @@ -529,7 +562,7 @@ Error DWARFDebugLine::LineTable::parse( while (*OffsetPtr < EndOffset) { if (OS) - *OS << format("0x%08.08" PRIx32 ": ", *OffsetPtr); + *OS << format("0x%08.08" PRIx64 ": ", *OffsetPtr); uint8_t Opcode = DebugLineData.getU8(OffsetPtr); @@ -540,7 +573,7 @@ Error DWARFDebugLine::LineTable::parse( // Extended Opcodes always start with a zero opcode followed by // a uleb128 length so you can skip ones you don't know about uint64_t Len = DebugLineData.getULEB128(OffsetPtr); - uint32_t ExtOffset = *OffsetPtr; + uint64_t ExtOffset = *OffsetPtr; // Tolerate zero-length; assume length is correct and soldier on. if (Len == 0) { @@ -585,7 +618,7 @@ Error DWARFDebugLine::LineTable::parse( DebugLineData.setAddressSize(Len - 1); else if (DebugLineData.getAddressSize() != Len - 1) { return createStringError(errc::invalid_argument, - "mismatching address size at offset 0x%8.8" PRIx32 + "mismatching address size at offset 0x%8.8" PRIx64 " expected 0x%2.2" PRIx8 " found 0x%2.2" PRIx64, ExtOffset, DebugLineData.getAddressSize(), Len - 1); @@ -652,8 +685,8 @@ Error DWARFDebugLine::LineTable::parse( // Otherwise we have an unparseable line-number program. if (*OffsetPtr - ExtOffset != Len) return createStringError(errc::illegal_byte_sequence, - "unexpected line op length at offset 0x%8.8" PRIx32 - " expected 0x%2.2" PRIx64 " found 0x%2.2" PRIx32, + "unexpected line op length at offset 0x%8.8" PRIx64 + " expected 0x%2.2" PRIx64 " found 0x%2.2" PRIx64, ExtOffset, Len, *OffsetPtr - ExtOffset); } else if (Opcode < Prologue.OpcodeBase) { if (OS) @@ -1007,10 +1040,9 @@ static bool isPathAbsoluteOnWindowsOrPosix(const Twine &Path) { sys::path::is_absolute(Path, sys::path::Style::windows); } -bool DWARFDebugLine::Prologue::getFileNameByIndex(uint64_t FileIndex, - StringRef CompDir, - FileLineInfoKind Kind, - std::string &Result) const { +bool DWARFDebugLine::Prologue::getFileNameByIndex( + uint64_t FileIndex, StringRef CompDir, FileLineInfoKind Kind, + std::string &Result, sys::path::Style Style) const { if (Kind == FileLineInfoKind::None || !hasFileAtIndex(FileIndex)) return false; const FileNameEntry &Entry = getFileNameEntry(FileIndex); @@ -1036,11 +1068,11 @@ bool DWARFDebugLine::Prologue::getFileNameByIndex(uint64_t FileIndex, // We know that FileName is not absolute, the only way to have an // absolute path at this point would be if IncludeDir is absolute. if (!CompDir.empty() && !isPathAbsoluteOnWindowsOrPosix(IncludeDir)) - sys::path::append(FilePath, CompDir); + sys::path::append(FilePath, Style, CompDir); } // sys::path::append skips empty strings. - sys::path::append(FilePath, IncludeDir, FileName); + sys::path::append(FilePath, Style, IncludeDir, FileName); Result = FilePath.str(); return true; } @@ -1092,7 +1124,8 @@ DWARFDebugLine::SectionParser::SectionParser(DWARFDataExtractor &Data, } bool DWARFDebugLine::Prologue::totalLengthIsValid() const { - return TotalLength == 0xffffffff || TotalLength < 0xfffffff0; + return TotalLength == dwarf::DW_LENGTH_DWARF64 || + TotalLength < dwarf::DW_LENGTH_lo_reserved; } DWARFDebugLine::LineTable DWARFDebugLine::SectionParser::parseNext( @@ -1101,7 +1134,7 @@ DWARFDebugLine::LineTable DWARFDebugLine::SectionParser::parseNext( assert(DebugLineData.isValidOffset(Offset) && "parsing should have terminated"); DWARFUnit *U = prepareToParse(Offset); - uint32_t OldOffset = Offset; + uint64_t OldOffset = Offset; LineTable LT; if (Error Err = LT.parse(DebugLineData, &Offset, Context, U, RecoverableErrorCallback, OS)) @@ -1115,14 +1148,14 @@ void DWARFDebugLine::SectionParser::skip( assert(DebugLineData.isValidOffset(Offset) && "parsing should have terminated"); DWARFUnit *U = prepareToParse(Offset); - uint32_t OldOffset = Offset; + uint64_t OldOffset = Offset; LineTable LT; if (Error Err = LT.Prologue.parse(DebugLineData, &Offset, Context, U)) ErrorCallback(std::move(Err)); moveToNextTable(OldOffset, LT.Prologue); } -DWARFUnit *DWARFDebugLine::SectionParser::prepareToParse(uint32_t Offset) { +DWARFUnit *DWARFDebugLine::SectionParser::prepareToParse(uint64_t Offset) { DWARFUnit *U = nullptr; auto It = LineToUnit.find(Offset); if (It != LineToUnit.end()) @@ -1131,7 +1164,7 @@ DWARFUnit *DWARFDebugLine::SectionParser::prepareToParse(uint32_t Offset) { return U; } -void DWARFDebugLine::SectionParser::moveToNextTable(uint32_t OldOffset, +void DWARFDebugLine::SectionParser::moveToNextTable(uint64_t OldOffset, const Prologue &P) { // If the length field is not valid, we don't know where the next table is, so // cannot continue to parse. Mark the parser as done, and leave the Offset diff --git a/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp b/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp index 6d8f4bee77c4..4f7b01130a47 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp @@ -28,19 +28,18 @@ using namespace llvm; // expression that LLVM doesn't produce. Guessing the wrong version means we // won't be able to pretty print expressions in DWARF2 binaries produced by // non-LLVM tools. -static void dumpExpression(raw_ostream &OS, ArrayRef<char> Data, +static void dumpExpression(raw_ostream &OS, ArrayRef<uint8_t> Data, bool IsLittleEndian, unsigned AddressSize, const MCRegisterInfo *MRI, DWARFUnit *U) { - DWARFDataExtractor Extractor(StringRef(Data.data(), Data.size()), - IsLittleEndian, AddressSize); + DWARFDataExtractor Extractor(toStringRef(Data), IsLittleEndian, AddressSize); DWARFExpression(Extractor, dwarf::DWARF_VERSION, AddressSize).print(OS, MRI, U); } -void DWARFDebugLoc::LocationList::dump(raw_ostream &OS, bool IsLittleEndian, +void DWARFDebugLoc::LocationList::dump(raw_ostream &OS, uint64_t BaseAddress, + bool IsLittleEndian, unsigned AddressSize, - const MCRegisterInfo *MRI, - DWARFUnit *U, - uint64_t BaseAddress, + const MCRegisterInfo *MRI, DWARFUnit *U, + DIDumpOptions DumpOpts, unsigned Indent) const { for (const Entry &E : Entries) { OS << '\n'; @@ -64,12 +63,12 @@ DWARFDebugLoc::getLocationListAtOffset(uint64_t Offset) const { return nullptr; } -void DWARFDebugLoc::dump(raw_ostream &OS, const MCRegisterInfo *MRI, +void DWARFDebugLoc::dump(raw_ostream &OS, const MCRegisterInfo *MRI, DIDumpOptions DumpOpts, Optional<uint64_t> Offset) const { auto DumpLocationList = [&](const LocationList &L) { - OS << format("0x%8.8x: ", L.Offset); - L.dump(OS, IsLittleEndian, AddressSize, MRI, nullptr, 0, 12); - OS << "\n\n"; + OS << format("0x%8.8" PRIx64 ": ", L.Offset); + L.dump(OS, 0, IsLittleEndian, AddressSize, MRI, nullptr, DumpOpts, 12); + OS << "\n"; }; if (Offset) { @@ -80,50 +79,47 @@ void DWARFDebugLoc::dump(raw_ostream &OS, const MCRegisterInfo *MRI, for (const LocationList &L : Locations) { DumpLocationList(L); + if (&L != &Locations.back()) + OS << '\n'; } } -Optional<DWARFDebugLoc::LocationList> -DWARFDebugLoc::parseOneLocationList(DWARFDataExtractor Data, unsigned *Offset) { +Expected<DWARFDebugLoc::LocationList> +DWARFDebugLoc::parseOneLocationList(const DWARFDataExtractor &Data, + uint64_t *Offset) { LocationList LL; LL.Offset = *Offset; + AddressSize = Data.getAddressSize(); + DataExtractor::Cursor C(*Offset); // 2.6.2 Location Lists // A location list entry consists of: while (true) { Entry E; - if (!Data.isValidOffsetForDataOfSize(*Offset, 2 * Data.getAddressSize())) { - WithColor::error() << "location list overflows the debug_loc section.\n"; - return None; - } // 1. A beginning address offset. ... - E.Begin = Data.getRelocatedAddress(Offset); + E.Begin = Data.getRelocatedAddress(C); // 2. An ending address offset. ... - E.End = Data.getRelocatedAddress(Offset); + E.End = Data.getRelocatedAddress(C); + + if (Error Err = C.takeError()) + return std::move(Err); // The end of any given location list is marked by an end of list entry, // which consists of a 0 for the beginning address offset and a 0 for the // ending address offset. - if (E.Begin == 0 && E.End == 0) + if (E.Begin == 0 && E.End == 0) { + *Offset = C.tell(); return LL; - - if (!Data.isValidOffsetForDataOfSize(*Offset, 2)) { - WithColor::error() << "location list overflows the debug_loc section.\n"; - return None; } - unsigned Bytes = Data.getU16(Offset); - if (!Data.isValidOffsetForDataOfSize(*Offset, Bytes)) { - WithColor::error() << "location list overflows the debug_loc section.\n"; - return None; + if (E.Begin != (AddressSize == 4 ? -1U : -1ULL)) { + unsigned Bytes = Data.getU16(C); + // A single location description describing the location of the object... + Data.getU8(C, E.Loc, Bytes); } - // A single location description describing the location of the object... - StringRef str = Data.getData().substr(*Offset, Bytes); - *Offset += Bytes; - E.Loc.reserve(str.size()); - llvm::copy(str, std::back_inserter(E.Loc)); + LL.Entries.push_back(std::move(E)); } } @@ -132,81 +128,89 @@ void DWARFDebugLoc::parse(const DWARFDataExtractor &data) { IsLittleEndian = data.isLittleEndian(); AddressSize = data.getAddressSize(); - uint32_t Offset = 0; - while (data.isValidOffset(Offset + data.getAddressSize() - 1)) { + uint64_t Offset = 0; + while (Offset < data.getData().size()) { if (auto LL = parseOneLocationList(data, &Offset)) Locations.push_back(std::move(*LL)); - else + else { + logAllUnhandledErrors(LL.takeError(), WithColor::error()); break; + } } - if (data.isValidOffset(Offset)) - WithColor::error() << "failed to consume entire .debug_loc section\n"; } -Optional<DWARFDebugLoclists::LocationList> -DWARFDebugLoclists::parseOneLocationList(DataExtractor Data, unsigned *Offset, - unsigned Version) { +Expected<DWARFDebugLoclists::LocationList> +DWARFDebugLoclists::parseOneLocationList(const DataExtractor &Data, + uint64_t *Offset, unsigned Version) { LocationList LL; LL.Offset = *Offset; + DataExtractor::Cursor C(*Offset); // dwarf::DW_LLE_end_of_list_entry is 0 and indicates the end of the list. - while (auto Kind = - static_cast<dwarf::LocationListEntry>(Data.getU8(Offset))) { - + while (auto Kind = Data.getU8(C)) { Entry E; E.Kind = Kind; + E.Offset = C.tell() - 1; switch (Kind) { + case dwarf::DW_LLE_base_addressx: + E.Value0 = Data.getULEB128(C); + break; case dwarf::DW_LLE_startx_length: - E.Value0 = Data.getULEB128(Offset); + E.Value0 = Data.getULEB128(C); // Pre-DWARF 5 has different interpretation of the length field. We have // to support both pre- and standartized styles for the compatibility. if (Version < 5) - E.Value1 = Data.getU32(Offset); + E.Value1 = Data.getU32(C); else - E.Value1 = Data.getULEB128(Offset); + E.Value1 = Data.getULEB128(C); break; case dwarf::DW_LLE_start_length: - E.Value0 = Data.getAddress(Offset); - E.Value1 = Data.getULEB128(Offset); + E.Value0 = Data.getAddress(C); + E.Value1 = Data.getULEB128(C); break; case dwarf::DW_LLE_offset_pair: - E.Value0 = Data.getULEB128(Offset); - E.Value1 = Data.getULEB128(Offset); + E.Value0 = Data.getULEB128(C); + E.Value1 = Data.getULEB128(C); break; case dwarf::DW_LLE_base_address: - E.Value0 = Data.getAddress(Offset); + E.Value0 = Data.getAddress(C); break; default: - WithColor::error() << "dumping support for LLE of kind " << (int)Kind - << " not implemented\n"; - return None; + cantFail(C.takeError()); + return createStringError(errc::illegal_byte_sequence, + "LLE of kind %x not supported", (int)Kind); } - if (Kind != dwarf::DW_LLE_base_address) { - unsigned Bytes = - Version >= 5 ? Data.getULEB128(Offset) : Data.getU16(Offset); + if (Kind != dwarf::DW_LLE_base_address && + Kind != dwarf::DW_LLE_base_addressx) { + unsigned Bytes = Version >= 5 ? Data.getULEB128(C) : Data.getU16(C); // A single location description describing the location of the object... - StringRef str = Data.getData().substr(*Offset, Bytes); - *Offset += Bytes; - E.Loc.resize(str.size()); - llvm::copy(str, E.Loc.begin()); + Data.getU8(C, E.Loc, Bytes); } LL.Entries.push_back(std::move(E)); } + if (Error Err = C.takeError()) + return std::move(Err); + Entry E; + E.Kind = dwarf::DW_LLE_end_of_list; + E.Offset = C.tell() - 1; + LL.Entries.push_back(E); + *Offset = C.tell(); return LL; } -void DWARFDebugLoclists::parse(DataExtractor data, unsigned Version) { +void DWARFDebugLoclists::parse(DataExtractor data, uint64_t Offset, uint64_t EndOffset, uint16_t Version) { IsLittleEndian = data.isLittleEndian(); AddressSize = data.getAddressSize(); - uint32_t Offset = 0; - while (data.isValidOffset(Offset)) { + while (Offset < EndOffset) { if (auto LL = parseOneLocationList(data, &Offset, Version)) Locations.push_back(std::move(*LL)); - else + else { + logAllUnhandledErrors(LL.takeError(), WithColor::error()); return; + } } } @@ -219,51 +223,106 @@ DWARFDebugLoclists::getLocationListAtOffset(uint64_t Offset) const { return nullptr; } -void DWARFDebugLoclists::LocationList::dump(raw_ostream &OS, uint64_t BaseAddr, - bool IsLittleEndian, - unsigned AddressSize, - const MCRegisterInfo *MRI, - DWARFUnit *U, - unsigned Indent) const { - for (const Entry &E : Entries) { - switch (E.Kind) { +void DWARFDebugLoclists::Entry::dump(raw_ostream &OS, uint64_t &BaseAddr, + bool IsLittleEndian, unsigned AddressSize, + const MCRegisterInfo *MRI, DWARFUnit *U, + DIDumpOptions DumpOpts, unsigned Indent, + size_t MaxEncodingStringLength) const { + if (DumpOpts.Verbose) { + OS << "\n"; + OS.indent(Indent); + auto EncodingString = dwarf::LocListEncodingString(Kind); + // Unsupported encodings should have been reported during parsing. + assert(!EncodingString.empty() && "Unknown loclist entry encoding"); + OS << format("%s%*c", EncodingString.data(), + MaxEncodingStringLength - EncodingString.size() + 1, '('); + switch (Kind) { case dwarf::DW_LLE_startx_length: - OS << '\n'; - OS.indent(Indent); - OS << "Addr idx " << E.Value0 << " (w/ length " << E.Value1 << "): "; - break; case dwarf::DW_LLE_start_length: - OS << '\n'; - OS.indent(Indent); - OS << format("[0x%*.*" PRIx64 ", 0x%*.*" PRIx64 "): ", AddressSize * 2, - AddressSize * 2, E.Value0, AddressSize * 2, AddressSize * 2, - E.Value0 + E.Value1); - break; case dwarf::DW_LLE_offset_pair: - OS << '\n'; - OS.indent(Indent); - OS << format("[0x%*.*" PRIx64 ", 0x%*.*" PRIx64 "): ", AddressSize * 2, - AddressSize * 2, BaseAddr + E.Value0, AddressSize * 2, - AddressSize * 2, BaseAddr + E.Value1); + OS << format("0x%*.*" PRIx64 ", 0x%*.*" PRIx64, AddressSize * 2, + AddressSize * 2, Value0, AddressSize * 2, AddressSize * 2, + Value1); break; + case dwarf::DW_LLE_base_addressx: case dwarf::DW_LLE_base_address: - BaseAddr = E.Value0; + OS << format("0x%*.*" PRIx64, AddressSize * 2, AddressSize * 2, + Value0); + break; + case dwarf::DW_LLE_end_of_list: break; - default: - llvm_unreachable("unreachable locations list kind"); } - - dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI, U); + OS << ')'; } + auto PrintPrefix = [&] { + OS << "\n"; + OS.indent(Indent); + if (DumpOpts.Verbose) + OS << format("%*s", MaxEncodingStringLength, (const char *)"=> "); + }; + switch (Kind) { + case dwarf::DW_LLE_startx_length: + PrintPrefix(); + OS << "Addr idx " << Value0 << " (w/ length " << Value1 << "): "; + break; + case dwarf::DW_LLE_start_length: + PrintPrefix(); + DWARFAddressRange(Value0, Value0 + Value1) + .dump(OS, AddressSize, DumpOpts); + OS << ": "; + break; + case dwarf::DW_LLE_offset_pair: + PrintPrefix(); + DWARFAddressRange(BaseAddr + Value0, BaseAddr + Value1) + .dump(OS, AddressSize, DumpOpts); + OS << ": "; + break; + case dwarf::DW_LLE_base_addressx: + if (!DumpOpts.Verbose) + return; + break; + case dwarf::DW_LLE_end_of_list: + if (!DumpOpts.Verbose) + return; + break; + case dwarf::DW_LLE_base_address: + BaseAddr = Value0; + if (!DumpOpts.Verbose) + return; + break; + default: + llvm_unreachable("unreachable locations list kind"); + } + + dumpExpression(OS, Loc, IsLittleEndian, AddressSize, MRI, U); +} +void DWARFDebugLoclists::LocationList::dump(raw_ostream &OS, uint64_t BaseAddr, + bool IsLittleEndian, + unsigned AddressSize, + const MCRegisterInfo *MRI, + DWARFUnit *U, + DIDumpOptions DumpOpts, + unsigned Indent) const { + size_t MaxEncodingStringLength = 0; + if (DumpOpts.Verbose) + for (const auto &Entry : Entries) + MaxEncodingStringLength = + std::max(MaxEncodingStringLength, + dwarf::LocListEncodingString(Entry.Kind).size()); + + for (const Entry &E : Entries) + E.dump(OS, BaseAddr, IsLittleEndian, AddressSize, MRI, U, DumpOpts, Indent, + MaxEncodingStringLength); } void DWARFDebugLoclists::dump(raw_ostream &OS, uint64_t BaseAddr, - const MCRegisterInfo *MRI, + const MCRegisterInfo *MRI, DIDumpOptions DumpOpts, Optional<uint64_t> Offset) const { auto DumpLocationList = [&](const LocationList &L) { - OS << format("0x%8.8x: ", L.Offset); - L.dump(OS, BaseAddr, IsLittleEndian, AddressSize, MRI, nullptr, /*Indent=*/12); - OS << "\n\n"; + OS << format("0x%8.8" PRIx64 ": ", L.Offset); + L.dump(OS, BaseAddr, IsLittleEndian, AddressSize, MRI, nullptr, DumpOpts, + /*Indent=*/12); + OS << "\n"; }; if (Offset) { @@ -274,5 +333,7 @@ void DWARFDebugLoclists::dump(raw_ostream &OS, uint64_t BaseAddr, for (const LocationList &L : Locations) { DumpLocationList(L); + if (&L != &Locations.back()) + OS << '\n'; } } diff --git a/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp b/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp index 3317a778cc70..9a0e770aed3d 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp @@ -53,7 +53,7 @@ void DWARFDebugMacro::dump(raw_ostream &OS) const { } void DWARFDebugMacro::parse(DataExtractor data) { - uint32_t Offset = 0; + uint64_t Offset = 0; while (data.isValidOffset(Offset)) { // A macro list entry consists of: Entry E; diff --git a/lib/DebugInfo/DWARF/DWARFDebugPubTable.cpp b/lib/DebugInfo/DWARF/DWARFDebugPubTable.cpp index 963ec64f5e91..ab71b239cb67 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugPubTable.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugPubTable.cpp @@ -23,7 +23,7 @@ DWARFDebugPubTable::DWARFDebugPubTable(const DWARFObject &Obj, bool LittleEndian, bool GnuStyle) : GnuStyle(GnuStyle) { DWARFDataExtractor PubNames(Obj, Sec, LittleEndian, 0); - uint32_t Offset = 0; + uint64_t Offset = 0; while (PubNames.isValidOffset(Offset)) { Sets.push_back({}); Set &SetData = Sets.back(); @@ -49,13 +49,13 @@ void DWARFDebugPubTable::dump(raw_ostream &OS) const { for (const Set &S : Sets) { OS << "length = " << format("0x%08x", S.Length); OS << " version = " << format("0x%04x", S.Version); - OS << " unit_offset = " << format("0x%08x", S.Offset); + OS << " unit_offset = " << format("0x%08" PRIx64, S.Offset); OS << " unit_size = " << format("0x%08x", S.Size) << '\n'; OS << (GnuStyle ? "Offset Linkage Kind Name\n" : "Offset Name\n"); for (const Entry &E : S.Entries) { - OS << format("0x%8.8x ", E.SecOffset); + OS << format("0x%8.8" PRIx64 " ", E.SecOffset); if (GnuStyle) { StringRef EntryLinkage = GDBIndexEntryLinkageString(E.Descriptor.Linkage); diff --git a/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp b/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp index d8df81a0aa0b..1a1857d8cd79 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp @@ -17,17 +17,17 @@ using namespace llvm; void DWARFDebugRangeList::clear() { - Offset = -1U; + Offset = -1ULL; AddressSize = 0; Entries.clear(); } Error DWARFDebugRangeList::extract(const DWARFDataExtractor &data, - uint32_t *offset_ptr) { + uint64_t *offset_ptr) { clear(); if (!data.isValidOffset(*offset_ptr)) return createStringError(errc::invalid_argument, - "invalid range list offset 0x%" PRIx32, *offset_ptr); + "invalid range list offset 0x%" PRIx64, *offset_ptr); AddressSize = data.getAddressSize(); if (AddressSize != 4 && AddressSize != 8) @@ -38,7 +38,7 @@ Error DWARFDebugRangeList::extract(const DWARFDataExtractor &data, RangeListEntry Entry; Entry.SectionIndex = -1ULL; - uint32_t prev_offset = *offset_ptr; + uint64_t prev_offset = *offset_ptr; Entry.StartAddress = data.getRelocatedAddress(offset_ptr); Entry.EndAddress = data.getRelocatedAddress(offset_ptr, &Entry.SectionIndex); @@ -47,7 +47,7 @@ Error DWARFDebugRangeList::extract(const DWARFDataExtractor &data, if (*offset_ptr != prev_offset + 2 * AddressSize) { clear(); return createStringError(errc::invalid_argument, - "invalid range list entry at offset 0x%" PRIx32, + "invalid range list entry at offset 0x%" PRIx64, prev_offset); } if (Entry.isEndOfListEntry()) @@ -59,12 +59,12 @@ Error DWARFDebugRangeList::extract(const DWARFDataExtractor &data, void DWARFDebugRangeList::dump(raw_ostream &OS) const { for (const RangeListEntry &RLE : Entries) { - const char *format_str = (AddressSize == 4 - ? "%08x %08" PRIx64 " %08" PRIx64 "\n" - : "%08x %016" PRIx64 " %016" PRIx64 "\n"); + const char *format_str = + (AddressSize == 4 ? "%08" PRIx64 " %08" PRIx64 " %08" PRIx64 "\n" + : "%08" PRIx64 " %016" PRIx64 " %016" PRIx64 "\n"); OS << format(format_str, Offset, RLE.StartAddress, RLE.EndAddress); } - OS << format("%08x <End of list>\n", Offset); + OS << format("%08" PRIx64 " <End of list>\n", Offset); } DWARFAddressRangesVector DWARFDebugRangeList::getAbsoluteRanges( diff --git a/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp b/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp index 5ac3326f6681..f6785b89e86d 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp @@ -16,8 +16,8 @@ using namespace llvm; -Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End, - uint32_t *OffsetPtr) { +Error RangeListEntry::extract(DWARFDataExtractor Data, uint64_t End, + uint64_t *OffsetPtr) { Offset = *OffsetPtr; SectionIndex = -1ULL; // The caller should guarantee that we have at least 1 byte available, so @@ -32,41 +32,41 @@ Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End, break; // TODO: Support other encodings. case dwarf::DW_RLE_base_addressx: { - uint32_t PreviousOffset = *OffsetPtr - 1; + uint64_t PreviousOffset = *OffsetPtr - 1; Value0 = Data.getULEB128(OffsetPtr); if (End < *OffsetPtr) return createStringError( errc::invalid_argument, "read past end of table when reading " - "DW_RLE_base_addressx encoding at offset 0x%" PRIx32, + "DW_RLE_base_addressx encoding at offset 0x%" PRIx64, PreviousOffset); break; } case dwarf::DW_RLE_startx_endx: return createStringError(errc::not_supported, "unsupported rnglists encoding DW_RLE_startx_endx at " - "offset 0x%" PRIx32, + "offset 0x%" PRIx64, *OffsetPtr - 1); case dwarf::DW_RLE_startx_length: { - uint32_t PreviousOffset = *OffsetPtr - 1; + uint64_t PreviousOffset = *OffsetPtr - 1; Value0 = Data.getULEB128(OffsetPtr); Value1 = Data.getULEB128(OffsetPtr); if (End < *OffsetPtr) return createStringError( errc::invalid_argument, "read past end of table when reading " - "DW_RLE_startx_length encoding at offset 0x%" PRIx32, + "DW_RLE_startx_length encoding at offset 0x%" PRIx64, PreviousOffset); break; } case dwarf::DW_RLE_offset_pair: { - uint32_t PreviousOffset = *OffsetPtr - 1; + uint64_t PreviousOffset = *OffsetPtr - 1; Value0 = Data.getULEB128(OffsetPtr); Value1 = Data.getULEB128(OffsetPtr); if (End < *OffsetPtr) return createStringError(errc::invalid_argument, "read past end of table when reading " - "DW_RLE_offset_pair encoding at offset 0x%" PRIx32, + "DW_RLE_offset_pair encoding at offset 0x%" PRIx64, PreviousOffset); break; } @@ -74,7 +74,7 @@ Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End, if ((End - *OffsetPtr) < Data.getAddressSize()) return createStringError(errc::invalid_argument, "insufficient space remaining in table for " - "DW_RLE_base_address encoding at offset 0x%" PRIx32, + "DW_RLE_base_address encoding at offset 0x%" PRIx64, *OffsetPtr - 1); Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex); break; @@ -84,27 +84,27 @@ Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End, return createStringError(errc::invalid_argument, "insufficient space remaining in table for " "DW_RLE_start_end encoding " - "at offset 0x%" PRIx32, + "at offset 0x%" PRIx64, *OffsetPtr - 1); Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex); Value1 = Data.getRelocatedAddress(OffsetPtr); break; } case dwarf::DW_RLE_start_length: { - uint32_t PreviousOffset = *OffsetPtr - 1; + uint64_t PreviousOffset = *OffsetPtr - 1; Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex); Value1 = Data.getULEB128(OffsetPtr); if (End < *OffsetPtr) return createStringError(errc::invalid_argument, "read past end of table when reading " - "DW_RLE_start_length encoding at offset 0x%" PRIx32, + "DW_RLE_start_length encoding at offset 0x%" PRIx64, PreviousOffset); break; } default: return createStringError(errc::not_supported, "unknown rnglists encoding 0x%" PRIx32 - " at offset 0x%" PRIx32, + " at offset 0x%" PRIx64, uint32_t(Encoding), *OffsetPtr - 1); } @@ -187,7 +187,7 @@ void RangeListEntry::dump( if (DumpOpts.Verbose) { // Print the section offset in verbose mode. - OS << format("0x%8.8" PRIx32 ":", Offset); + OS << format("0x%8.8" PRIx64 ":", Offset); auto EncodingString = dwarf::RangeListEncodingString(EntryKind); // Unsupported encodings should have been reported during parsing. assert(!EncodingString.empty() && "Unknown range entry encoding"); diff --git a/lib/DebugInfo/DWARF/DWARFDie.cpp b/lib/DebugInfo/DWARF/DWARFDie.cpp index d638dc4239f4..cec194e8b6b3 100644 --- a/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -21,6 +21,7 @@ #include "llvm/Object/ObjectFile.h" #include "llvm/Support/DataExtractor.h" #include "llvm/Support/Format.h" +#include "llvm/Support/FormatAdapters.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/WithColor.h" @@ -91,21 +92,29 @@ static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue, } FormValue.dump(OS, DumpOpts); + const auto &DumpLL = [&](auto ExpectedLL) { + if (ExpectedLL) { + uint64_t BaseAddr = 0; + if (Optional<object::SectionedAddress> BA = U->getBaseAddress()) + BaseAddr = BA->Address; + auto LLDumpOpts = DumpOpts; + LLDumpOpts.Verbose = false; + ExpectedLL->dump(OS, BaseAddr, Ctx.isLittleEndian(), Obj.getAddressSize(), + MRI, U, LLDumpOpts, Indent); + } else { + OS << '\n'; + OS.indent(Indent); + OS << formatv("error extracting location list: {0}", + fmt_consume(ExpectedLL.takeError())); + } + }; if (FormValue.isFormClass(DWARFFormValue::FC_SectionOffset)) { - uint32_t Offset = *FormValue.getAsSectionOffset(); + uint64_t Offset = *FormValue.getAsSectionOffset(); if (!U->isDWOUnit() && !U->getLocSection()->Data.empty()) { DWARFDebugLoc DebugLoc; DWARFDataExtractor Data(Obj, *U->getLocSection(), Ctx.isLittleEndian(), Obj.getAddressSize()); - auto LL = DebugLoc.parseOneLocationList(Data, &Offset); - if (LL) { - uint64_t BaseAddr = 0; - if (Optional<object::SectionedAddress> BA = U->getBaseAddress()) - BaseAddr = BA->Address; - LL->dump(OS, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, U, - BaseAddr, Indent); - } else - OS << "error extracting location list."; + DumpLL(DebugLoc.parseOneLocationList(Data, &Offset)); return; } @@ -121,18 +130,8 @@ static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue, // Modern locations list (.debug_loclists) are used starting from v5. // Ideally we should take the version from the .debug_loclists section // header, but using CU's version for simplicity. - auto LL = DWARFDebugLoclists::parseOneLocationList( - Data, &Offset, UseLocLists ? U->getVersion() : 4); - - uint64_t BaseAddr = 0; - if (Optional<object::SectionedAddress> BA = U->getBaseAddress()) - BaseAddr = BA->Address; - - if (LL) - LL->dump(OS, BaseAddr, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, - U, Indent); - else - OS << "error extracting location list."; + DumpLL(DWARFDebugLoclists::parseOneLocationList( + Data, &Offset, UseLocLists ? U->getVersion() : 4)); } } } @@ -264,7 +263,7 @@ static void dumpTypeName(raw_ostream &OS, const DWARFDie &D) { } static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, - uint32_t *OffsetPtr, dwarf::Attribute Attr, + uint64_t *OffsetPtr, dwarf::Attribute Attr, dwarf::Form Form, unsigned Indent, DIDumpOptions DumpOpts) { if (!Die.isValid()) @@ -568,8 +567,8 @@ void DWARFDie::dump(raw_ostream &OS, unsigned Indent, if (!isValid()) return; DWARFDataExtractor debug_info_data = U->getDebugInfoExtractor(); - const uint32_t Offset = getOffset(); - uint32_t offset = Offset; + const uint64_t Offset = getOffset(); + uint64_t offset = Offset; if (DumpOpts.ShowParents) { DIDumpOptions ParentDumpOpts = DumpOpts; ParentDumpOpts.ShowParents = false; @@ -581,7 +580,7 @@ void DWARFDie::dump(raw_ostream &OS, unsigned Indent, uint32_t abbrCode = debug_info_data.getULEB128(&offset); if (DumpOpts.ShowAddresses) WithColor(OS, HighlightColor::Address).get() - << format("\n0x%8.8x: ", Offset); + << format("\n0x%8.8" PRIx64 ": ", Offset); if (abbrCode) { auto AbbrevDecl = getAbbreviationDeclarationPtr(); @@ -685,7 +684,7 @@ void DWARFDie::attribute_iterator::updateForIndex( AttrValue.Attr = AbbrDecl.getAttrByIndex(Index); // Add the previous byte size of any previous attribute value. AttrValue.Offset += AttrValue.ByteSize; - uint32_t ParseOffset = AttrValue.Offset; + uint64_t ParseOffset = AttrValue.Offset; auto U = Die.getDwarfUnit(); assert(U && "Die must have valid DWARF unit"); AttrValue.Value = DWARFFormValue::createFromUnit( @@ -733,6 +732,7 @@ bool DWARFAttribute::mayHaveLocationDescription(dwarf::Attribute Attr) { case DW_AT_call_data_value: // Extensions. case DW_AT_GNU_call_site_value: + case DW_AT_GNU_call_site_target: return true; default: return false; diff --git a/lib/DebugInfo/DWARF/DWARFExpression.cpp b/lib/DebugInfo/DWARF/DWARFExpression.cpp index 470d4b5364b4..5009b1b7b412 100644 --- a/lib/DebugInfo/DWARF/DWARFExpression.cpp +++ b/lib/DebugInfo/DWARF/DWARFExpression.cpp @@ -119,7 +119,7 @@ static uint8_t getRefAddrSize(uint8_t AddrSize, uint16_t Version) { } bool DWARFExpression::Operation::extract(DataExtractor Data, uint16_t Version, - uint8_t AddressSize, uint32_t Offset) { + uint8_t AddressSize, uint64_t Offset) { Opcode = Data.getU8(&Offset); Desc = getOpDesc(Opcode); @@ -218,9 +218,8 @@ static bool prettyPrintRegisterOp(raw_ostream &OS, uint8_t Opcode, else DwarfRegNum = Opcode - DW_OP_reg0; - int LLVMRegNum = MRI->getLLVMRegNum(DwarfRegNum, isEH); - if (LLVMRegNum >= 0) { - if (const char *RegName = MRI->getName(LLVMRegNum)) { + if (Optional<unsigned> LLVMRegNum = MRI->getLLVMRegNum(DwarfRegNum, isEH)) { + if (const char *RegName = MRI->getName(*LLVMRegNum)) { if ((Opcode >= DW_OP_breg0 && Opcode <= DW_OP_breg31) || Opcode == DW_OP_bregx) OS << format(" %s%+" PRId64, RegName, Operands[OpNum]); @@ -263,7 +262,7 @@ bool DWARFExpression::Operation::print(raw_ostream &OS, if (Size == Operation::BaseTypeRef && U) { auto Die = U->getDIEForOffset(U->getOffset() + Operands[Operand]); if (Die && Die.getTag() == dwarf::DW_TAG_base_type) { - OS << format(" (0x%08x)", U->getOffset() + Operands[Operand]); + OS << format(" (0x%08" PRIx64 ")", U->getOffset() + Operands[Operand]); if (auto Name = Die.find(dwarf::DW_AT_name)) OS << " \"" << Name->getAsCString() << "\""; } else { @@ -271,7 +270,7 @@ bool DWARFExpression::Operation::print(raw_ostream &OS, Operands[Operand]); } } else if (Size == Operation::SizeBlock) { - uint32_t Offset = Operands[Operand]; + uint64_t Offset = Operands[Operand]; for (unsigned i = 0; i < Operands[Operand - 1]; ++i) OS << format(" 0x%02x", Expr->Data.getU8(&Offset)); } else { @@ -290,7 +289,7 @@ void DWARFExpression::print(raw_ostream &OS, const MCRegisterInfo *RegInfo, uint32_t EntryValExprSize = 0; for (auto &Op : *this) { if (!Op.print(OS, this, RegInfo, U, IsEH)) { - uint32_t FailOffset = Op.getEndOffset(); + uint64_t FailOffset = Op.getEndOffset(); while (FailOffset < Data.getData().size()) OS << format(" %02x", Data.getU8(&FailOffset)); return; diff --git a/lib/DebugInfo/DWARF/DWARFFormValue.cpp b/lib/DebugInfo/DWARF/DWARFFormValue.cpp index 290d35511cdb..26090638b34c 100644 --- a/lib/DebugInfo/DWARF/DWARFFormValue.cpp +++ b/lib/DebugInfo/DWARF/DWARFFormValue.cpp @@ -98,7 +98,7 @@ DWARFFormValue DWARFFormValue::createFromBlockValue(dwarf::Form F, } DWARFFormValue DWARFFormValue::createFromUnit(dwarf::Form F, const DWARFUnit *U, - uint32_t *OffsetPtr) { + uint64_t *OffsetPtr) { DWARFFormValue FormValue(F); FormValue.extractValue(U->getDebugInfoExtractor(), OffsetPtr, U->getFormParams(), U); @@ -106,7 +106,7 @@ DWARFFormValue DWARFFormValue::createFromUnit(dwarf::Form F, const DWARFUnit *U, } bool DWARFFormValue::skipValue(dwarf::Form Form, DataExtractor DebugInfoData, - uint32_t *OffsetPtr, + uint64_t *OffsetPtr, const dwarf::FormParams Params) { bool Indirect = false; do { @@ -234,7 +234,7 @@ bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const { } bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data, - uint32_t *OffsetPtr, dwarf::FormParams FP, + uint64_t *OffsetPtr, dwarf::FormParams FP, const DWARFContext *Ctx, const DWARFUnit *CU) { if (!Ctx && CU) @@ -590,7 +590,7 @@ Optional<const char *> DWARFFormValue::getAsCString() const { // FIXME: Add support for DW_FORM_GNU_strp_alt if (Form == DW_FORM_GNU_strp_alt || C == nullptr) return None; - uint32_t Offset = Value.uval; + uint64_t Offset = Value.uval; if (Form == DW_FORM_line_strp) { // .debug_line_str is tracked in the Context. if (const char *Str = C->getLineStringExtractor().getCStr(&Offset)) @@ -624,6 +624,7 @@ Optional<uint64_t> DWARFFormValue::getAsAddress() const { return SA->Address; return None; } + Optional<object::SectionedAddress> DWARFFormValue::getAsSectionedAddress() const { if (!isFormClass(FC_Address)) diff --git a/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp b/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp index f5f975578082..252b58e5a591 100644 --- a/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp +++ b/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp @@ -112,7 +112,7 @@ void DWARFGdbIndex::dump(raw_ostream &OS) { } bool DWARFGdbIndex::parseImpl(DataExtractor Data) { - uint32_t Offset = 0; + uint64_t Offset = 0; // Only version 7 is supported at this moment. Version = Data.getU32(&Offset); diff --git a/lib/DebugInfo/DWARF/DWARFListTable.cpp b/lib/DebugInfo/DWARF/DWARFListTable.cpp index e38e706227da..269ea9f79a6e 100644 --- a/lib/DebugInfo/DWARF/DWARFListTable.cpp +++ b/lib/DebugInfo/DWARF/DWARFListTable.cpp @@ -16,33 +16,42 @@ using namespace llvm; Error DWARFListTableHeader::extract(DWARFDataExtractor Data, - uint32_t *OffsetPtr) { + uint64_t *OffsetPtr) { HeaderOffset = *OffsetPtr; // Read and verify the length field. if (!Data.isValidOffsetForDataOfSize(*OffsetPtr, sizeof(uint32_t))) return createStringError(errc::invalid_argument, "section is not large enough to contain a " - "%s table length at offset 0x%" PRIx32, + "%s table length at offset 0x%" PRIx64, SectionName.data(), *OffsetPtr); - // TODO: Add support for DWARF64. - HeaderData.Length = Data.getRelocatedValue(4, OffsetPtr); - if (HeaderData.Length == 0xffffffffu) - return createStringError(errc::not_supported, - "DWARF64 is not supported in %s at offset 0x%" PRIx32, - SectionName.data(), HeaderOffset); Format = dwarf::DwarfFormat::DWARF32; - if (HeaderData.Length + sizeof(uint32_t) < sizeof(Header)) + uint8_t OffsetByteSize = 4; + HeaderData.Length = Data.getRelocatedValue(4, OffsetPtr); + if (HeaderData.Length == dwarf::DW_LENGTH_DWARF64) { + Format = dwarf::DwarfFormat::DWARF64; + OffsetByteSize = 8; + HeaderData.Length = Data.getU64(OffsetPtr); + } else if (HeaderData.Length >= dwarf::DW_LENGTH_lo_reserved) { + return createStringError(errc::invalid_argument, + "%s table at offset 0x%" PRIx64 + " has unsupported reserved unit length of value 0x%8.8" PRIx64, + SectionName.data(), HeaderOffset, HeaderData.Length); + } + uint64_t FullLength = + HeaderData.Length + dwarf::getUnitLengthFieldByteSize(Format); + assert(FullLength == length()); + if (FullLength < getHeaderSize(Format)) return createStringError(errc::invalid_argument, - "%s table at offset 0x%" PRIx32 - " has too small length (0x%" PRIx32 + "%s table at offset 0x%" PRIx64 + " has too small length (0x%" PRIx64 ") to contain a complete header", - SectionName.data(), HeaderOffset, length()); - uint32_t End = HeaderOffset + length(); - if (!Data.isValidOffsetForDataOfSize(HeaderOffset, End - HeaderOffset)) + SectionName.data(), HeaderOffset, FullLength); + uint64_t End = HeaderOffset + FullLength; + if (!Data.isValidOffsetForDataOfSize(HeaderOffset, FullLength)) return createStringError(errc::invalid_argument, "section is not large enough to contain a %s table " - "of length 0x%" PRIx32 " at offset 0x%" PRIx32, - SectionName.data(), length(), HeaderOffset); + "of length 0x%" PRIx64 " at offset 0x%" PRIx64, + SectionName.data(), FullLength, HeaderOffset); HeaderData.Version = Data.getU16(OffsetPtr); HeaderData.AddrSize = Data.getU8(OffsetPtr); @@ -53,35 +62,35 @@ Error DWARFListTableHeader::extract(DWARFDataExtractor Data, if (HeaderData.Version != 5) return createStringError(errc::invalid_argument, "unrecognised %s table version %" PRIu16 - " in table at offset 0x%" PRIx32, + " in table at offset 0x%" PRIx64, SectionName.data(), HeaderData.Version, HeaderOffset); if (HeaderData.AddrSize != 4 && HeaderData.AddrSize != 8) return createStringError(errc::not_supported, - "%s table at offset 0x%" PRIx32 + "%s table at offset 0x%" PRIx64 " has unsupported address size %" PRIu8, SectionName.data(), HeaderOffset, HeaderData.AddrSize); if (HeaderData.SegSize != 0) return createStringError(errc::not_supported, - "%s table at offset 0x%" PRIx32 + "%s table at offset 0x%" PRIx64 " has unsupported segment selector size %" PRIu8, SectionName.data(), HeaderOffset, HeaderData.SegSize); - if (End < HeaderOffset + sizeof(HeaderData) + - HeaderData.OffsetEntryCount * sizeof(uint32_t)) + if (End < HeaderOffset + getHeaderSize(Format) + + HeaderData.OffsetEntryCount * OffsetByteSize) return createStringError(errc::invalid_argument, - "%s table at offset 0x%" PRIx32 " has more offset entries (%" PRIu32 + "%s table at offset 0x%" PRIx64 " has more offset entries (%" PRIu32 ") than there is space for", SectionName.data(), HeaderOffset, HeaderData.OffsetEntryCount); Data.setAddressSize(HeaderData.AddrSize); for (uint32_t I = 0; I < HeaderData.OffsetEntryCount; ++I) - Offsets.push_back(Data.getRelocatedValue(4, OffsetPtr)); + Offsets.push_back(Data.getRelocatedValue(OffsetByteSize, OffsetPtr)); return Error::success(); } void DWARFListTableHeader::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const { if (DumpOpts.Verbose) - OS << format("0x%8.8" PRIx32 ": ", HeaderOffset); + OS << format("0x%8.8" PRIx64 ": ", HeaderOffset); OS << format( - "%s list header: length = 0x%8.8" PRIx32 ", version = 0x%4.4" PRIx16 ", " + "%s list header: length = 0x%8.8" PRIx64 ", version = 0x%4.4" PRIx16 ", " "addr_size = 0x%2.2" PRIx8 ", seg_size = 0x%2.2" PRIx8 ", offset_entry_count = " "0x%8.8" PRIx32 "\n", @@ -91,18 +100,17 @@ void DWARFListTableHeader::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const { if (HeaderData.OffsetEntryCount > 0) { OS << "offsets: ["; for (const auto &Off : Offsets) { - OS << format("\n0x%8.8" PRIx32, Off); + OS << format("\n0x%8.8" PRIx64, Off); if (DumpOpts.Verbose) - OS << format(" => 0x%8.8" PRIx32, - Off + HeaderOffset + sizeof(HeaderData)); + OS << format(" => 0x%8.8" PRIx64, + Off + HeaderOffset + getHeaderSize(Format)); } OS << "\n]\n"; } } -uint32_t DWARFListTableHeader::length() const { +uint64_t DWARFListTableHeader::length() const { if (HeaderData.Length == 0) return 0; - // TODO: DWARF64 support. - return HeaderData.Length + sizeof(uint32_t); + return HeaderData.Length + dwarf::getUnitLengthFieldByteSize(Format); } diff --git a/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp b/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp index 844920ba5b11..bb81090ba25c 100644 --- a/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp +++ b/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp @@ -24,21 +24,23 @@ void DWARFTypeUnit::dump(raw_ostream &OS, DIDumpOptions DumpOpts) { if (DumpOpts.SummarizeTypes) { OS << "name = '" << Name << "'" << " type_signature = " << format("0x%016" PRIx64, getTypeHash()) - << " length = " << format("0x%08x", getLength()) << '\n'; + << " length = " << format("0x%08" PRIx64, getLength()) << '\n'; return; } - OS << format("0x%08x", getOffset()) << ": Type Unit:" - << " length = " << format("0x%08x", getLength()) + OS << format("0x%08" PRIx64, getOffset()) << ": Type Unit:" + << " length = " << format("0x%08" PRIx64, getLength()) << " version = " << format("0x%04x", getVersion()); if (getVersion() >= 5) OS << " unit_type = " << dwarf::UnitTypeString(getUnitType()); - OS << " abbr_offset = " << format("0x%04x", getAbbreviations()->getOffset()) + OS << " abbr_offset = " + << format("0x%04" PRIx64, getAbbreviations()->getOffset()) << " addr_size = " << format("0x%02x", getAddressByteSize()) << " name = '" << Name << "'" << " type_signature = " << format("0x%016" PRIx64, getTypeHash()) - << " type_offset = " << format("0x%04x", getTypeOffset()) - << " (next unit at " << format("0x%08x", getNextUnitOffset()) << ")\n"; + << " type_offset = " << format("0x%04" PRIx64, getTypeOffset()) + << " (next unit at " << format("0x%08" PRIx64, getNextUnitOffset()) + << ")\n"; if (DWARFDie TU = getUnitDIE(false)) TU.dump(OS, 0, DumpOpts); diff --git a/lib/DebugInfo/DWARF/DWARFUnit.cpp b/lib/DebugInfo/DWARF/DWARFUnit.cpp index b74acf60c747..a56402a707ad 100644 --- a/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -37,9 +37,9 @@ void DWARFUnitVector::addUnitsForSection(DWARFContext &C, const DWARFSection &Section, DWARFSectionKind SectionKind) { const DWARFObject &D = C.getDWARFObj(); - addUnitsImpl(C, D, Section, C.getDebugAbbrev(), &D.getRangeSection(), - &D.getLocSection(), D.getStringSection(), - D.getStringOffsetSection(), &D.getAddrSection(), + addUnitsImpl(C, D, Section, C.getDebugAbbrev(), &D.getRangesSection(), + &D.getLocSection(), D.getStrSection(), + D.getStrOffsetsSection(), &D.getAddrSection(), D.getLineSection(), D.isLittleEndian(), false, false, SectionKind); } @@ -49,9 +49,9 @@ void DWARFUnitVector::addUnitsForDWOSection(DWARFContext &C, DWARFSectionKind SectionKind, bool Lazy) { const DWARFObject &D = C.getDWARFObj(); - addUnitsImpl(C, D, DWOSection, C.getDebugAbbrevDWO(), &D.getRangeDWOSection(), - &D.getLocDWOSection(), D.getStringDWOSection(), - D.getStringOffsetDWOSection(), &D.getAddrSection(), + addUnitsImpl(C, D, DWOSection, C.getDebugAbbrevDWO(), &D.getRangesDWOSection(), + &D.getLocDWOSection(), D.getStrDWOSection(), + D.getStrOffsetsDWOSection(), &D.getAddrSection(), D.getLineDWOSection(), C.isLittleEndian(), true, Lazy, SectionKind); } @@ -66,7 +66,7 @@ void DWARFUnitVector::addUnitsImpl( // Lazy initialization of Parser, now that we have all section info. if (!Parser) { Parser = [=, &Context, &Obj, &Section, &SOS, - &LS](uint32_t Offset, DWARFSectionKind SectionKind, + &LS](uint64_t Offset, DWARFSectionKind SectionKind, const DWARFSection *CurSection, const DWARFUnitIndex::Entry *IndexEntry) -> std::unique_ptr<DWARFUnit> { @@ -83,11 +83,11 @@ void DWARFUnitVector::addUnitsImpl( return nullptr; std::unique_ptr<DWARFUnit> U; if (Header.isTypeUnit()) - U = llvm::make_unique<DWARFTypeUnit>(Context, InfoSection, Header, DA, + U = std::make_unique<DWARFTypeUnit>(Context, InfoSection, Header, DA, RS, LocSection, SS, SOS, AOS, LS, LE, IsDWO, *this); else - U = llvm::make_unique<DWARFCompileUnit>(Context, InfoSection, Header, + U = std::make_unique<DWARFCompileUnit>(Context, InfoSection, Header, DA, RS, LocSection, SS, SOS, AOS, LS, LE, IsDWO, *this); return U; @@ -101,7 +101,7 @@ void DWARFUnitVector::addUnitsImpl( // within a section, although not necessarily within the object file, // even if we do lazy parsing. auto I = this->begin(); - uint32_t Offset = 0; + uint64_t Offset = 0; while (Data.isValidOffset(Offset)) { if (I != this->end() && (&(*I)->getInfoSection() != &Section || (*I)->getOffset() == Offset)) { @@ -126,11 +126,11 @@ DWARFUnit *DWARFUnitVector::addUnit(std::unique_ptr<DWARFUnit> Unit) { return this->insert(I, std::move(Unit))->get(); } -DWARFUnit *DWARFUnitVector::getUnitForOffset(uint32_t Offset) const { +DWARFUnit *DWARFUnitVector::getUnitForOffset(uint64_t Offset) const { auto end = begin() + getNumInfoUnits(); auto *CU = std::upper_bound(begin(), end, Offset, - [](uint32_t LHS, const std::unique_ptr<DWARFUnit> &RHS) { + [](uint64_t LHS, const std::unique_ptr<DWARFUnit> &RHS) { return LHS < RHS->getNextUnitOffset(); }); if (CU != end && (*CU)->getOffset() <= Offset) @@ -149,7 +149,7 @@ DWARFUnitVector::getUnitForIndexEntry(const DWARFUnitIndex::Entry &E) { auto *CU = std::upper_bound(begin(), end, CUOff->Offset, - [](uint32_t LHS, const std::unique_ptr<DWARFUnit> &RHS) { + [](uint64_t LHS, const std::unique_ptr<DWARFUnit> &RHS) { return LHS < RHS->getNextUnitOffset(); }); if (CU != end && (*CU)->getOffset() <= Offset) @@ -209,7 +209,7 @@ DWARFUnit::getAddrOffsetSectionItem(uint32_t Index) const { if (I != R.end() && std::next(I) == R.end()) return (*I)->getAddrOffsetSectionItem(Index); } - uint32_t Offset = AddrOffsetSectionBase + Index * getAddressByteSize(); + uint64_t Offset = AddrOffsetSectionBase + Index * getAddressByteSize(); if (AddrOffsetSection->Data.size() < Offset + getAddressByteSize()) return None; DWARFDataExtractor DA(Context.getDWARFObj(), *AddrOffsetSection, @@ -223,7 +223,7 @@ Optional<uint64_t> DWARFUnit::getStringOffsetSectionItem(uint32_t Index) const { if (!StringOffsetsTableContribution) return None; unsigned ItemSize = getDwarfStringOffsetsByteSize(); - uint32_t Offset = getStringOffsetsBase() + Index * ItemSize; + uint64_t Offset = getStringOffsetsBase() + Index * ItemSize; if (StringOffsetSection.Data.size() < Offset + ItemSize) return None; DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection, @@ -233,7 +233,7 @@ Optional<uint64_t> DWARFUnit::getStringOffsetSectionItem(uint32_t Index) const { bool DWARFUnitHeader::extract(DWARFContext &Context, const DWARFDataExtractor &debug_info, - uint32_t *offset_ptr, + uint64_t *offset_ptr, DWARFSectionKind SectionKind, const DWARFUnitIndex *Index, const DWARFUnitIndex::Entry *Entry) { @@ -243,11 +243,9 @@ bool DWARFUnitHeader::extract(DWARFContext &Context, IndexEntry = Index->getFromOffset(*offset_ptr); Length = debug_info.getRelocatedValue(4, offset_ptr); FormParams.Format = DWARF32; - unsigned SizeOfLength = 4; - if (Length == 0xffffffff) { + if (Length == dwarf::DW_LENGTH_DWARF64) { Length = debug_info.getU64(offset_ptr); FormParams.Format = DWARF64; - SizeOfLength = 8; } FormParams.Version = debug_info.getU16(offset_ptr); if (FormParams.Version >= 5) { @@ -277,7 +275,8 @@ bool DWARFUnitHeader::extract(DWARFContext &Context, } if (isTypeUnit()) { TypeHash = debug_info.getU64(offset_ptr); - TypeOffset = debug_info.getU32(offset_ptr); + TypeOffset = + debug_info.getUnsigned(offset_ptr, FormParams.getDwarfOffsetByteSize()); } else if (UnitType == DW_UT_split_compile || UnitType == DW_UT_skeleton) DWOId = debug_info.getU64(offset_ptr); @@ -290,7 +289,8 @@ bool DWARFUnitHeader::extract(DWARFContext &Context, bool TypeOffsetOK = !isTypeUnit() ? true - : TypeOffset >= Size && TypeOffset < getLength() + SizeOfLength; + : TypeOffset >= Size && + TypeOffset < getLength() + getUnitLengthFieldByteSize(); bool LengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1); bool VersionOK = DWARFContext::isSupportedVersion(getVersion()); bool AddrSizeOK = getAddressByteSize() == 4 || getAddressByteSize() == 8; @@ -306,16 +306,18 @@ bool DWARFUnitHeader::extract(DWARFContext &Context, // Parse the rangelist table header, including the optional array of offsets // following it (DWARF v5 and later). static Expected<DWARFDebugRnglistTable> -parseRngListTableHeader(DWARFDataExtractor &DA, uint32_t Offset) { - // TODO: Support DWARF64 +parseRngListTableHeader(DWARFDataExtractor &DA, uint64_t Offset, + DwarfFormat Format) { // We are expected to be called with Offset 0 or pointing just past the table - // header, which is 12 bytes long for DWARF32. + // header. Correct Offset in the latter case so that it points to the start + // of the header. if (Offset > 0) { - if (Offset < 12U) + uint64_t HeaderSize = DWARFListTableHeader::getHeaderSize(Format); + if (Offset < HeaderSize) return createStringError(errc::invalid_argument, "Did not detect a valid" - " range list table with base = 0x%" PRIu32, + " range list table with base = 0x%" PRIx64 "\n", Offset); - Offset -= 12U; + Offset -= HeaderSize; } llvm::DWARFDebugRnglistTable Table; if (Error E = Table.extractHeaderAndOffsets(DA, &Offset)) @@ -323,13 +325,13 @@ parseRngListTableHeader(DWARFDataExtractor &DA, uint32_t Offset) { return Table; } -Error DWARFUnit::extractRangeList(uint32_t RangeListOffset, +Error DWARFUnit::extractRangeList(uint64_t RangeListOffset, DWARFDebugRangeList &RangeList) const { // Require that compile unit is extracted. assert(!DieArray.empty()); DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection, isLittleEndian, getAddressByteSize()); - uint32_t ActualRangeListOffset = RangeSectionBase + RangeListOffset; + uint64_t ActualRangeListOffset = RangeSectionBase + RangeListOffset; return RangeList.extract(RangesData, &ActualRangeListOffset); } @@ -354,8 +356,8 @@ void DWARFUnit::extractDIEsToVector( // Set the offset to that of the first DIE and calculate the start of the // next compilation unit header. - uint32_t DIEOffset = getOffset() + getHeaderSize(); - uint32_t NextCUOffset = getNextUnitOffset(); + uint64_t DIEOffset = getOffset() + getHeaderSize(); + uint64_t NextCUOffset = getNextUnitOffset(); DWARFDebugInfoEntry DIE; DWARFDataExtractor DebugInfoData = getDebugInfoExtractor(); uint32_t Depth = 0; @@ -396,90 +398,98 @@ void DWARFUnit::extractDIEsToVector( // unit header). if (DIEOffset > NextCUOffset) WithColor::warning() << format("DWARF compile unit extends beyond its " - "bounds cu 0x%8.8x at 0x%8.8x\n", + "bounds cu 0x%8.8" PRIx64 " " + "at 0x%8.8" PRIx64 "\n", getOffset(), DIEOffset); } -size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) { +void DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) { + if (Error e = tryExtractDIEsIfNeeded(CUDieOnly)) + WithColor::error() << toString(std::move(e)); +} + +Error DWARFUnit::tryExtractDIEsIfNeeded(bool CUDieOnly) { if ((CUDieOnly && !DieArray.empty()) || DieArray.size() > 1) - return 0; // Already parsed. + return Error::success(); // Already parsed. bool HasCUDie = !DieArray.empty(); extractDIEsToVector(!HasCUDie, !CUDieOnly, DieArray); if (DieArray.empty()) - return 0; + return Error::success(); // If CU DIE was just parsed, copy several attribute values from it. - if (!HasCUDie) { - DWARFDie UnitDie = getUnitDIE(); - if (Optional<uint64_t> DWOId = toUnsigned(UnitDie.find(DW_AT_GNU_dwo_id))) - Header.setDWOId(*DWOId); - if (!IsDWO) { - assert(AddrOffsetSectionBase == 0); - assert(RangeSectionBase == 0); - AddrOffsetSectionBase = toSectionOffset(UnitDie.find(DW_AT_addr_base), 0); - if (!AddrOffsetSectionBase) - AddrOffsetSectionBase = - toSectionOffset(UnitDie.find(DW_AT_GNU_addr_base), 0); - RangeSectionBase = toSectionOffset(UnitDie.find(DW_AT_rnglists_base), 0); - } - - // In general, in DWARF v5 and beyond we derive the start of the unit's - // contribution to the string offsets table from the unit DIE's - // DW_AT_str_offsets_base attribute. Split DWARF units do not use this - // attribute, so we assume that there is a contribution to the string - // offsets table starting at offset 0 of the debug_str_offsets.dwo section. - // In both cases we need to determine the format of the contribution, - // which may differ from the unit's format. - DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection, - isLittleEndian, 0); - if (IsDWO || getVersion() >= 5) { - auto StringOffsetOrError = - IsDWO ? determineStringOffsetsTableContributionDWO(DA) - : determineStringOffsetsTableContribution(DA); - if (!StringOffsetOrError) { - WithColor::error() << "invalid contribution to string offsets table in section .debug_str_offsets[.dwo]: " - << toString(StringOffsetOrError.takeError()) << '\n'; - } else { - StringOffsetsTableContribution = *StringOffsetOrError; - } - } + if (HasCUDie) + return Error::success(); + + DWARFDie UnitDie(this, &DieArray[0]); + if (Optional<uint64_t> DWOId = toUnsigned(UnitDie.find(DW_AT_GNU_dwo_id))) + Header.setDWOId(*DWOId); + if (!IsDWO) { + assert(AddrOffsetSectionBase == 0); + assert(RangeSectionBase == 0); + AddrOffsetSectionBase = toSectionOffset(UnitDie.find(DW_AT_addr_base), 0); + if (!AddrOffsetSectionBase) + AddrOffsetSectionBase = + toSectionOffset(UnitDie.find(DW_AT_GNU_addr_base), 0); + RangeSectionBase = toSectionOffset(UnitDie.find(DW_AT_rnglists_base), 0); + } - // DWARF v5 uses the .debug_rnglists and .debug_rnglists.dwo sections to - // describe address ranges. - if (getVersion() >= 5) { - if (IsDWO) - setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(), 0); - else - setRangesSection(&Context.getDWARFObj().getRnglistsSection(), - toSectionOffset(UnitDie.find(DW_AT_rnglists_base), 0)); - if (RangeSection->Data.size()) { - // Parse the range list table header. Individual range lists are - // extracted lazily. - DWARFDataExtractor RangesDA(Context.getDWARFObj(), *RangeSection, - isLittleEndian, 0); - if (auto TableOrError = - parseRngListTableHeader(RangesDA, RangeSectionBase)) - RngListTable = TableOrError.get(); - else - WithColor::error() << "parsing a range list table: " - << toString(TableOrError.takeError()) - << '\n'; - - // In a split dwarf unit, there is no DW_AT_rnglists_base attribute. - // Adjust RangeSectionBase to point past the table header. - if (IsDWO && RngListTable) - RangeSectionBase = RngListTable->getHeaderSize(); - } - } + // In general, in DWARF v5 and beyond we derive the start of the unit's + // contribution to the string offsets table from the unit DIE's + // DW_AT_str_offsets_base attribute. Split DWARF units do not use this + // attribute, so we assume that there is a contribution to the string + // offsets table starting at offset 0 of the debug_str_offsets.dwo section. + // In both cases we need to determine the format of the contribution, + // which may differ from the unit's format. + DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection, + isLittleEndian, 0); + if (IsDWO || getVersion() >= 5) { + auto StringOffsetOrError = + IsDWO ? determineStringOffsetsTableContributionDWO(DA) + : determineStringOffsetsTableContribution(DA); + if (!StringOffsetOrError) + return createStringError(errc::invalid_argument, + "invalid reference to or invalid content in " + ".debug_str_offsets[.dwo]: " + + toString(StringOffsetOrError.takeError())); + + StringOffsetsTableContribution = *StringOffsetOrError; + } - // Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for - // skeleton CU DIE, so that DWARF users not aware of it are not broken. + // DWARF v5 uses the .debug_rnglists and .debug_rnglists.dwo sections to + // describe address ranges. + if (getVersion() >= 5) { + if (IsDWO) + setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(), 0); + else + setRangesSection(&Context.getDWARFObj().getRnglistsSection(), + toSectionOffset(UnitDie.find(DW_AT_rnglists_base), 0)); + if (RangeSection->Data.size()) { + // Parse the range list table header. Individual range lists are + // extracted lazily. + DWARFDataExtractor RangesDA(Context.getDWARFObj(), *RangeSection, + isLittleEndian, 0); + auto TableOrError = parseRngListTableHeader(RangesDA, RangeSectionBase, + Header.getFormat()); + if (!TableOrError) + return createStringError(errc::invalid_argument, + "parsing a range list table: " + + toString(TableOrError.takeError())); + + RngListTable = TableOrError.get(); + + // In a split dwarf unit, there is no DW_AT_rnglists_base attribute. + // Adjust RangeSectionBase to point past the table header. + if (IsDWO && RngListTable) + RangeSectionBase = RngListTable->getHeaderSize(); } + } - return DieArray.size(); + // Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for + // skeleton CU DIE, so that DWARF users not aware of it are not broken. + return Error::success(); } bool DWARFUnit::parseDWO() { @@ -517,7 +527,8 @@ bool DWARFUnit::parseDWO() { DWO->setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(), 0); DWARFDataExtractor RangesDA(Context.getDWARFObj(), *RangeSection, isLittleEndian, 0); - if (auto TableOrError = parseRngListTableHeader(RangesDA, RangeSectionBase)) + if (auto TableOrError = parseRngListTableHeader(RangesDA, RangeSectionBase, + Header.getFormat())) DWO->RngListTable = TableOrError.get(); else WithColor::error() << "parsing a range list table: " @@ -541,7 +552,7 @@ void DWARFUnit::clearDIEs(bool KeepCUDie) { } Expected<DWARFAddressRangesVector> -DWARFUnit::findRnglistFromOffset(uint32_t Offset) { +DWARFUnit::findRnglistFromOffset(uint64_t Offset) { if (getVersion() <= 4) { DWARFDebugRangeList RangeList; if (Error E = extractRangeList(Offset, RangeList)) @@ -569,9 +580,9 @@ DWARFUnit::findRnglistFromIndex(uint32_t Index) { if (RngListTable) return createStringError(errc::invalid_argument, "invalid range list table index %d", Index); - else - return createStringError(errc::invalid_argument, - "missing or invalid range list table"); + + return createStringError(errc::invalid_argument, + "missing or invalid range list table"); } Expected<DWARFAddressRangesVector> DWARFUnit::collectAddressRanges() { @@ -780,11 +791,11 @@ StrOffsetsContributionDescriptor::validateContributionSize( // Look for a DWARF64-formatted contribution to the string offsets table // starting at a given offset and record it in a descriptor. static Expected<StrOffsetsContributionDescriptor> -parseDWARF64StringOffsetsTableHeader(DWARFDataExtractor &DA, uint32_t Offset) { +parseDWARF64StringOffsetsTableHeader(DWARFDataExtractor &DA, uint64_t Offset) { if (!DA.isValidOffsetForDataOfSize(Offset, 16)) return createStringError(errc::invalid_argument, "section offset exceeds section size"); - if (DA.getU32(&Offset) != 0xffffffff) + if (DA.getU32(&Offset) != dwarf::DW_LENGTH_DWARF64) return createStringError(errc::invalid_argument, "32 bit contribution referenced from a 64 bit unit"); uint64_t Size = DA.getU64(&Offset); @@ -798,12 +809,12 @@ parseDWARF64StringOffsetsTableHeader(DWARFDataExtractor &DA, uint32_t Offset) { // Look for a DWARF32-formatted contribution to the string offsets table // starting at a given offset and record it in a descriptor. static Expected<StrOffsetsContributionDescriptor> -parseDWARF32StringOffsetsTableHeader(DWARFDataExtractor &DA, uint32_t Offset) { +parseDWARF32StringOffsetsTableHeader(DWARFDataExtractor &DA, uint64_t Offset) { if (!DA.isValidOffsetForDataOfSize(Offset, 8)) return createStringError(errc::invalid_argument, "section offset exceeds section size"); uint32_t ContributionSize = DA.getU32(&Offset); - if (ContributionSize >= 0xfffffff0) + if (ContributionSize >= dwarf::DW_LENGTH_lo_reserved) return createStringError(errc::invalid_argument, "invalid length"); uint8_t Version = DA.getU16(&Offset); @@ -823,7 +834,7 @@ parseDWARFStringOffsetsTableHeader(DWARFDataExtractor &DA, case dwarf::DwarfFormat::DWARF64: { if (Offset < 16) return createStringError(errc::invalid_argument, "insufficient space for 64 bit header prefix"); - auto DescOrError = parseDWARF64StringOffsetsTableHeader(DA, (uint32_t)Offset - 16); + auto DescOrError = parseDWARF64StringOffsetsTableHeader(DA, Offset - 16); if (!DescOrError) return DescOrError.takeError(); Desc = *DescOrError; @@ -832,7 +843,7 @@ parseDWARFStringOffsetsTableHeader(DWARFDataExtractor &DA, case dwarf::DwarfFormat::DWARF32: { if (Offset < 8) return createStringError(errc::invalid_argument, "insufficient space for 32 bit header prefix"); - auto DescOrError = parseDWARF32StringOffsetsTableHeader(DA, (uint32_t)Offset - 8); + auto DescOrError = parseDWARF32StringOffsetsTableHeader(DA, Offset - 8); if (!DescOrError) return DescOrError.takeError(); Desc = *DescOrError; diff --git a/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp b/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp index 047c63461ccf..f29c1e6cc5c7 100644 --- a/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp +++ b/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp @@ -18,7 +18,7 @@ using namespace llvm; bool DWARFUnitIndex::Header::parse(DataExtractor IndexData, - uint32_t *OffsetPtr) { + uint64_t *OffsetPtr) { if (!IndexData.isValidOffsetForDataOfSize(*OffsetPtr, 16)) return false; Version = IndexData.getU32(OffsetPtr); @@ -45,7 +45,7 @@ bool DWARFUnitIndex::parse(DataExtractor IndexData) { } bool DWARFUnitIndex::parseImpl(DataExtractor IndexData) { - uint32_t Offset = 0; + uint64_t Offset = 0; if (!Header.parse(IndexData, &Offset)) return false; @@ -54,10 +54,10 @@ bool DWARFUnitIndex::parseImpl(DataExtractor IndexData) { (2 * Header.NumUnits + 1) * 4 * Header.NumColumns)) return false; - Rows = llvm::make_unique<Entry[]>(Header.NumBuckets); + Rows = std::make_unique<Entry[]>(Header.NumBuckets); auto Contribs = - llvm::make_unique<Entry::SectionContribution *[]>(Header.NumUnits); - ColumnKinds = llvm::make_unique<DWARFSectionKind[]>(Header.NumColumns); + std::make_unique<Entry::SectionContribution *[]>(Header.NumUnits); + ColumnKinds = std::make_unique<DWARFSectionKind[]>(Header.NumColumns); // Read Hash Table of Signatures for (unsigned i = 0; i != Header.NumBuckets; ++i) @@ -70,7 +70,7 @@ bool DWARFUnitIndex::parseImpl(DataExtractor IndexData) { continue; Rows[i].Index = this; Rows[i].Contributions = - llvm::make_unique<Entry::SectionContribution[]>(Header.NumColumns); + std::make_unique<Entry::SectionContribution[]>(Header.NumColumns); Contribs[Index - 1] = Rows[i].Contributions.get(); } diff --git a/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/lib/DebugInfo/DWARF/DWARFVerifier.cpp index c2b3189514a8..bf499b6ee092 100644 --- a/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ b/lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -34,11 +34,11 @@ DWARFVerifier::DieRangeInfo::insert(const DWARFAddressRange &R) { if (Pos != End) { if (Pos->intersects(R)) - return Pos; + return std::move(Pos); if (Pos != Begin) { auto Iter = Pos - 1; if (Iter->intersects(R)) - return Iter; + return std::move(Iter); } } @@ -98,7 +98,7 @@ bool DWARFVerifier::DieRangeInfo::intersects(const DieRangeInfo &RHS) const { } bool DWARFVerifier::verifyUnitHeader(const DWARFDataExtractor DebugInfoData, - uint32_t *Offset, unsigned UnitIndex, + uint64_t *Offset, unsigned UnitIndex, uint8_t &UnitType, bool &isUnitDWARF64) { uint64_t AbbrOffset, Length; uint8_t AddrSize = 0; @@ -111,9 +111,9 @@ bool DWARFVerifier::verifyUnitHeader(const DWARFDataExtractor DebugInfoData, bool ValidType = true; bool ValidAbbrevOffset = true; - uint32_t OffsetStart = *Offset; + uint64_t OffsetStart = *Offset; Length = DebugInfoData.getU32(Offset); - if (Length == UINT32_MAX) { + if (Length == dwarf::DW_LENGTH_DWARF64) { Length = DebugInfoData.getU64(Offset); isUnitDWARF64 = true; } @@ -139,7 +139,7 @@ bool DWARFVerifier::verifyUnitHeader(const DWARFDataExtractor DebugInfoData, if (!ValidLength || !ValidVersion || !ValidAddrSize || !ValidAbbrevOffset || !ValidType) { Success = false; - error() << format("Units[%d] - start offset: 0x%08x \n", UnitIndex, + error() << format("Units[%d] - start offset: 0x%08" PRIx64 " \n", UnitIndex, OffsetStart); if (!ValidLength) note() << "The length for this unit is too " @@ -203,7 +203,7 @@ unsigned DWARFVerifier::verifyUnitContents(DWARFUnit &Unit) { } unsigned DWARFVerifier::verifyDebugInfoCallSite(const DWARFDie &Die) { - if (Die.getTag() != DW_TAG_call_site) + if (Die.getTag() != DW_TAG_call_site && Die.getTag() != DW_TAG_GNU_call_site) return 0; DWARFDie Curr = Die.getParent(); @@ -223,7 +223,9 @@ unsigned DWARFVerifier::verifyDebugInfoCallSite(const DWARFDie &Die) { Optional<DWARFFormValue> CallAttr = Curr.find({DW_AT_call_all_calls, DW_AT_call_all_source_calls, - DW_AT_call_all_tail_calls}); + DW_AT_call_all_tail_calls, DW_AT_GNU_all_call_sites, + DW_AT_GNU_all_source_call_sites, + DW_AT_GNU_all_tail_call_sites}); if (!CallAttr) { error() << "Subprogram with call site entry has no DW_AT_call attribute:"; Curr.dump(OS); @@ -273,7 +275,7 @@ unsigned DWARFVerifier::verifyUnitSection(const DWARFSection &S, const DWARFObject &DObj = DCtx.getDWARFObj(); DWARFDataExtractor DebugInfoData(DObj, S, DCtx.isLittleEndian(), 0); unsigned NumDebugInfoErrors = 0; - uint32_t OffsetStart = 0, Offset = 0, UnitIdx = 0; + uint64_t OffsetStart = 0, Offset = 0, UnitIdx = 0; uint8_t UnitType = 0; bool isUnitDWARF64 = false; bool isHeaderChainValid = true; @@ -294,10 +296,10 @@ unsigned DWARFVerifier::verifyUnitSection(const DWARFSection &S, switch (UnitType) { case dwarf::DW_UT_type: case dwarf::DW_UT_split_type: { - Unit = TypeUnitVector.addUnit(llvm::make_unique<DWARFTypeUnit>( - DCtx, S, Header, DCtx.getDebugAbbrev(), &DObj.getRangeSection(), - &DObj.getLocSection(), DObj.getStringSection(), - DObj.getStringOffsetSection(), &DObj.getAppleObjCSection(), + Unit = TypeUnitVector.addUnit(std::make_unique<DWARFTypeUnit>( + DCtx, S, Header, DCtx.getDebugAbbrev(), &DObj.getRangesSection(), + &DObj.getLocSection(), DObj.getStrSection(), + DObj.getStrOffsetsSection(), &DObj.getAppleObjCSection(), DObj.getLineSection(), DCtx.isLittleEndian(), false, TypeUnitVector)); break; @@ -308,10 +310,10 @@ unsigned DWARFVerifier::verifyUnitSection(const DWARFSection &S, case dwarf::DW_UT_partial: // UnitType = 0 means that we are verifying a compile unit in DWARF v4. case 0: { - Unit = CompileUnitVector.addUnit(llvm::make_unique<DWARFCompileUnit>( - DCtx, S, Header, DCtx.getDebugAbbrev(), &DObj.getRangeSection(), - &DObj.getLocSection(), DObj.getStringSection(), - DObj.getStringOffsetSection(), &DObj.getAppleObjCSection(), + Unit = CompileUnitVector.addUnit(std::make_unique<DWARFCompileUnit>( + DCtx, S, Header, DCtx.getDebugAbbrev(), &DObj.getRangesSection(), + &DObj.getLocSection(), DObj.getStrSection(), + DObj.getStrOffsetsSection(), &DObj.getAppleObjCSection(), DObj.getLineSection(), DCtx.isLittleEndian(), false, CompileUnitVector)); break; @@ -449,7 +451,7 @@ unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die, case DW_AT_ranges: // Make sure the offset in the DW_AT_ranges attribute is valid. if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) { - if (*SectionOffset >= DObj.getRangeSection().Data.size()) + if (*SectionOffset >= DObj.getRangesSection().Data.size()) ReportError("DW_AT_ranges offset is beyond .debug_ranges bounds:"); break; } @@ -466,9 +468,9 @@ unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die, ReportError("DIE has invalid DW_AT_stmt_list encoding:"); break; case DW_AT_location: { - auto VerifyLocationExpr = [&](StringRef D) { + auto VerifyLocationExpr = [&](ArrayRef<uint8_t> D) { DWARFUnit *U = Die.getDwarfUnit(); - DataExtractor Data(D, DCtx.isLittleEndian(), 0); + DataExtractor Data(toStringRef(D), DCtx.isLittleEndian(), 0); DWARFExpression Expression(Data, U->getVersion(), U->getAddressByteSize()); bool Error = llvm::any_of(Expression, [](DWARFExpression::Operation &Op) { @@ -479,13 +481,13 @@ unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die, }; if (Optional<ArrayRef<uint8_t>> Expr = AttrValue.Value.getAsBlock()) { // Verify inlined location. - VerifyLocationExpr(llvm::toStringRef(*Expr)); + VerifyLocationExpr(*Expr); } else if (auto LocOffset = AttrValue.Value.getAsSectionOffset()) { // Verify location list. if (auto DebugLoc = DCtx.getDebugLoc()) if (auto LocList = DebugLoc->getLocationListAtOffset(*LocOffset)) for (const auto &Entry : LocList->Entries) - VerifyLocationExpr({Entry.Loc.data(), Entry.Loc.size()}); + VerifyLocationExpr(Entry.Loc); } break; } @@ -500,6 +502,9 @@ unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die, break; if (DieTag == DW_TAG_variable && RefTag == DW_TAG_member) break; + // This might be reference to a function declaration. + if (DieTag == DW_TAG_GNU_call_site && RefTag == DW_TAG_subprogram) + break; ReportError("DIE with tag " + TagString(DieTag) + " has " + AttributeString(Attr) + " that points to DIE with " @@ -545,7 +550,7 @@ unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die, error() << FormEncodingString(Form) << " CU offset " << format("0x%08" PRIx64, CUOffset) << " is invalid (must be less than CU size of " - << format("0x%08" PRIx32, CUSize) << "):\n"; + << format("0x%08" PRIx64, CUSize) << "):\n"; Die.dump(OS, 0, DumpOpts); dump(Die) << '\n'; } else { @@ -578,7 +583,7 @@ unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die, case DW_FORM_strp: { auto SecOffset = AttrValue.Value.getAsSectionOffset(); assert(SecOffset); // DW_FORM_strp is a section offset. - if (SecOffset && *SecOffset >= DObj.getStringSection().size()) { + if (SecOffset && *SecOffset >= DObj.getStrSection().size()) { ++NumErrors; error() << "DW_FORM_strp offset beyond .debug_str bounds:\n"; dump(Die) << '\n'; @@ -605,7 +610,7 @@ unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die, // Use a 64-bit type to calculate the offset to guard against overflow. uint64_t Offset = (uint64_t)DieCU->getStringOffsetsBase() + Index * ItemSize; - if (DObj.getStringOffsetSection().Data.size() < Offset + ItemSize) { + if (DObj.getStrOffsetsSection().Data.size() < Offset + ItemSize) { ++NumErrors; error() << FormEncodingString(Form) << " uses index " << format("%" PRIu64, Index) << ", which is too large:\n"; @@ -614,7 +619,7 @@ unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die, } // Check that the string offset is valid. uint64_t StringOffset = *DieCU->getStringOffsetSectionItem(Index); - if (StringOffset >= DObj.getStringSection().size()) { + if (StringOffset >= DObj.getStrSection().size()) { ++NumErrors; error() << FormEncodingString(Form) << " uses index " << format("%" PRIu64, Index) @@ -635,7 +640,7 @@ unsigned DWARFVerifier::verifyDebugInfoReferences() { // getting the DIE by offset and emitting an error OS << "Verifying .debug_info references...\n"; unsigned NumErrors = 0; - for (const std::pair<uint64_t, std::set<uint32_t>> &Pair : + for (const std::pair<uint64_t, std::set<uint64_t>> &Pair : ReferenceToDIEOffsets) { if (DCtx.getDIEForOffset(Pair.first)) continue; @@ -659,12 +664,12 @@ void DWARFVerifier::verifyDebugLineStmtOffsets() { auto StmtSectionOffset = toSectionOffset(Die.find(DW_AT_stmt_list)); if (!StmtSectionOffset) continue; - const uint32_t LineTableOffset = *StmtSectionOffset; + const uint64_t LineTableOffset = *StmtSectionOffset; auto LineTable = DCtx.getLineTableForUnit(CU.get()); if (LineTableOffset < DCtx.getDWARFObj().getLineSection().Data.size()) { if (!LineTable) { ++NumDebugLineErrors; - error() << ".debug_line[" << format("0x%08" PRIx32, LineTableOffset) + error() << ".debug_line[" << format("0x%08" PRIx64, LineTableOffset) << "] was not able to be parsed for CU:\n"; dump(Die) << '\n'; continue; @@ -680,8 +685,8 @@ void DWARFVerifier::verifyDebugLineStmtOffsets() { if (Iter != StmtListToDie.end()) { ++NumDebugLineErrors; error() << "two compile unit DIEs, " - << format("0x%08" PRIx32, Iter->second.getOffset()) << " and " - << format("0x%08" PRIx32, Die.getOffset()) + << format("0x%08" PRIx64, Iter->second.getOffset()) << " and " + << format("0x%08" PRIx64, Die.getOffset()) << ", have the same DW_AT_stmt_list section offset:\n"; dump(Iter->second); dump(Die) << '\n'; @@ -826,10 +831,10 @@ unsigned DWARFVerifier::verifyAppleAccelTable(const DWARFSection *AccelSection, uint32_t NumBuckets = AccelTable.getNumBuckets(); uint32_t NumHashes = AccelTable.getNumHashes(); - uint32_t BucketsOffset = + uint64_t BucketsOffset = AccelTable.getSizeHdr() + AccelTable.getHeaderDataLength(); - uint32_t HashesBase = BucketsOffset + NumBuckets * 4; - uint32_t OffsetsBase = HashesBase + NumHashes * 4; + uint64_t HashesBase = BucketsOffset + NumBuckets * 4; + uint64_t OffsetsBase = HashesBase + NumHashes * 4; for (uint32_t BucketIdx = 0; BucketIdx < NumBuckets; ++BucketIdx) { uint32_t HashIdx = AccelSectionData.getU32(&BucketsOffset); if (HashIdx >= NumHashes && HashIdx != UINT32_MAX) { @@ -849,28 +854,29 @@ unsigned DWARFVerifier::verifyAppleAccelTable(const DWARFSection *AccelSection, } for (uint32_t HashIdx = 0; HashIdx < NumHashes; ++HashIdx) { - uint32_t HashOffset = HashesBase + 4 * HashIdx; - uint32_t DataOffset = OffsetsBase + 4 * HashIdx; + uint64_t HashOffset = HashesBase + 4 * HashIdx; + uint64_t DataOffset = OffsetsBase + 4 * HashIdx; uint32_t Hash = AccelSectionData.getU32(&HashOffset); - uint32_t HashDataOffset = AccelSectionData.getU32(&DataOffset); + uint64_t HashDataOffset = AccelSectionData.getU32(&DataOffset); if (!AccelSectionData.isValidOffsetForDataOfSize(HashDataOffset, sizeof(uint64_t))) { - error() << format("Hash[%d] has invalid HashData offset: 0x%08x.\n", + error() << format("Hash[%d] has invalid HashData offset: " + "0x%08" PRIx64 ".\n", HashIdx, HashDataOffset); ++NumErrors; } - uint32_t StrpOffset; - uint32_t StringOffset; + uint64_t StrpOffset; + uint64_t StringOffset; uint32_t StringCount = 0; - unsigned Offset; + uint64_t Offset; unsigned Tag; while ((StrpOffset = AccelSectionData.getU32(&HashDataOffset)) != 0) { const uint32_t NumHashDataObjects = AccelSectionData.getU32(&HashDataOffset); for (uint32_t HashDataIdx = 0; HashDataIdx < NumHashDataObjects; ++HashDataIdx) { - std::tie(Offset, Tag) = AccelTable.readAtoms(HashDataOffset); + std::tie(Offset, Tag) = AccelTable.readAtoms(&HashDataOffset); auto Die = DCtx.getDIEForOffset(Offset); if (!Die) { const uint32_t BucketIdx = @@ -882,8 +888,8 @@ unsigned DWARFVerifier::verifyAppleAccelTable(const DWARFSection *AccelSection, error() << format( "%s Bucket[%d] Hash[%d] = 0x%08x " - "Str[%u] = 0x%08x " - "DIE[%d] = 0x%08x is not a valid DIE offset for \"%s\".\n", + "Str[%u] = 0x%08" PRIx64 " DIE[%d] = 0x%08" PRIx64 " " + "is not a valid DIE offset for \"%s\".\n", SectionName, BucketIdx, HashIdx, Hash, StringCount, StrpOffset, HashDataIdx, Offset, Name); @@ -908,8 +914,8 @@ unsigned DWARFVerifier::verifyDebugNamesCULists(const DWARFDebugNames &AccelTable) { // A map from CU offset to the (first) Name Index offset which claims to index // this CU. - DenseMap<uint32_t, uint32_t> CUMap; - const uint32_t NotIndexed = std::numeric_limits<uint32_t>::max(); + DenseMap<uint64_t, uint64_t> CUMap; + const uint64_t NotIndexed = std::numeric_limits<uint64_t>::max(); CUMap.reserve(DCtx.getNumCompileUnits()); for (const auto &CU : DCtx.compile_units()) @@ -924,7 +930,7 @@ DWARFVerifier::verifyDebugNamesCULists(const DWARFDebugNames &AccelTable) { continue; } for (uint32_t CU = 0, End = NI.getCUCount(); CU < End; ++CU) { - uint32_t Offset = NI.getCUOffset(CU); + uint64_t Offset = NI.getCUOffset(CU); auto Iter = CUMap.find(Offset); if (Iter == CUMap.end()) { @@ -1205,8 +1211,8 @@ unsigned DWARFVerifier::verifyNameIndexEntries( unsigned NumErrors = 0; unsigned NumEntries = 0; - uint32_t EntryID = NTE.getEntryOffset(); - uint32_t NextEntryID = EntryID; + uint64_t EntryID = NTE.getEntryOffset(); + uint64_t NextEntryID = EntryID; Expected<DWARFDebugNames::Entry> EntryOr = NI.getEntry(&NextEntryID); for (; EntryOr; ++NumEntries, EntryID = NextEntryID, EntryOr = NI.getEntry(&NextEntryID)) { @@ -1218,7 +1224,7 @@ unsigned DWARFVerifier::verifyNameIndexEntries( ++NumErrors; continue; } - uint32_t CUOffset = NI.getCUOffset(CUIndex); + uint64_t CUOffset = NI.getCUOffset(CUIndex); uint64_t DIEOffset = CUOffset + *EntryOr->getDIEUnitOffset(); DWARFDie DIE = DCtx.getDIEForOffset(DIEOffset); if (!DIE) { @@ -1276,9 +1282,9 @@ static bool isVariableIndexable(const DWARFDie &Die, DWARFContext &DCtx) { if (!Location) return false; - auto ContainsInterestingOperators = [&](StringRef D) { + auto ContainsInterestingOperators = [&](ArrayRef<uint8_t> D) { DWARFUnit *U = Die.getDwarfUnit(); - DataExtractor Data(D, DCtx.isLittleEndian(), U->getAddressByteSize()); + DataExtractor Data(toStringRef(D), DCtx.isLittleEndian(), U->getAddressByteSize()); DWARFExpression Expression(Data, U->getVersion(), U->getAddressByteSize()); return any_of(Expression, [](DWARFExpression::Operation &Op) { return !Op.isError() && (Op.getCode() == DW_OP_addr || @@ -1289,7 +1295,7 @@ static bool isVariableIndexable(const DWARFDie &Die, DWARFContext &DCtx) { if (Optional<ArrayRef<uint8_t>> Expr = Location->getAsBlock()) { // Inlined location. - if (ContainsInterestingOperators(toStringRef(*Expr))) + if (ContainsInterestingOperators(*Expr)) return true; } else if (Optional<uint64_t> Offset = Location->getAsSectionOffset()) { // Location list. @@ -1297,7 +1303,7 @@ static bool isVariableIndexable(const DWARFDie &Die, DWARFContext &DCtx) { if (const DWARFDebugLoc::LocationList *LocList = DebugLoc->getLocationListAtOffset(*Offset)) { if (any_of(LocList->Entries, [&](const DWARFDebugLoc::Entry &E) { - return ContainsInterestingOperators({E.Loc.data(), E.Loc.size()}); + return ContainsInterestingOperators(E.Loc); })) return true; } @@ -1455,7 +1461,7 @@ unsigned DWARFVerifier::verifyDebugNames(const DWARFSection &AccelSection, bool DWARFVerifier::handleAccelTables() { const DWARFObject &D = DCtx.getDWARFObj(); - DataExtractor StrData(D.getStringSection(), DCtx.isLittleEndian(), 0); + DataExtractor StrData(D.getStrSection(), DCtx.isLittleEndian(), 0); unsigned NumErrors = 0; if (!D.getAppleNamesSection().Data.empty()) NumErrors += verifyAppleAccelTable(&D.getAppleNamesSection(), &StrData, @@ -1470,8 +1476,8 @@ bool DWARFVerifier::handleAccelTables() { NumErrors += verifyAppleAccelTable(&D.getAppleObjCSection(), &StrData, ".apple_objc"); - if (!D.getDebugNamesSection().Data.empty()) - NumErrors += verifyDebugNames(D.getDebugNamesSection(), StrData); + if (!D.getNamesSection().Data.empty()) + NumErrors += verifyDebugNames(D.getNamesSection(), StrData); return NumErrors == 0; } diff --git a/lib/DebugInfo/GSYM/FileWriter.cpp b/lib/DebugInfo/GSYM/FileWriter.cpp new file mode 100644 index 000000000000..4b30dcb60a7b --- /dev/null +++ b/lib/DebugInfo/GSYM/FileWriter.cpp @@ -0,0 +1,78 @@ +//===- FileWriter.cpp -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/GSYM/FileWriter.h" +#include "llvm/Support/LEB128.h" +#include "llvm/Support/raw_ostream.h" +#include <cassert> + +using namespace llvm; +using namespace gsym; + +FileWriter::~FileWriter() { OS.flush(); } + +void FileWriter::writeSLEB(int64_t S) { + uint8_t Bytes[32]; + auto Length = encodeSLEB128(S, Bytes); + assert(Length < sizeof(Bytes)); + OS.write(reinterpret_cast<const char *>(Bytes), Length); +} + +void FileWriter::writeULEB(uint64_t U) { + uint8_t Bytes[32]; + auto Length = encodeULEB128(U, Bytes); + assert(Length < sizeof(Bytes)); + OS.write(reinterpret_cast<const char *>(Bytes), Length); +} + +void FileWriter::writeU8(uint8_t U) { + OS.write(reinterpret_cast<const char *>(&U), sizeof(U)); +} + +void FileWriter::writeU16(uint16_t U) { + const uint16_t Swapped = support::endian::byte_swap(U, ByteOrder); + OS.write(reinterpret_cast<const char *>(&Swapped), sizeof(Swapped)); +} + +void FileWriter::writeU32(uint32_t U) { + const uint32_t Swapped = support::endian::byte_swap(U, ByteOrder); + OS.write(reinterpret_cast<const char *>(&Swapped), sizeof(Swapped)); +} + +void FileWriter::writeU64(uint64_t U) { + const uint64_t Swapped = support::endian::byte_swap(U, ByteOrder); + OS.write(reinterpret_cast<const char *>(&Swapped), sizeof(Swapped)); +} + +void FileWriter::fixup32(uint32_t U, uint64_t Offset) { + const uint32_t Swapped = support::endian::byte_swap(U, ByteOrder); + OS.pwrite(reinterpret_cast<const char *>(&Swapped), sizeof(Swapped), + Offset); +} + +void FileWriter::writeData(llvm::ArrayRef<uint8_t> Data) { + OS.write(reinterpret_cast<const char *>(Data.data()), Data.size()); +} + +void FileWriter::writeNullTerminated(llvm::StringRef Str) { + OS << Str << '\0'; +} + +uint64_t FileWriter::tell() { + return OS.tell(); +} + +void FileWriter::alignTo(size_t Align) { + off_t Offset = OS.tell(); + off_t AlignedOffset = (Offset + Align - 1) / Align * Align; + if (AlignedOffset == Offset) + return; + off_t PadCount = AlignedOffset - Offset; + OS.write_zeros(PadCount); +} diff --git a/lib/DebugInfo/GSYM/FunctionInfo.cpp b/lib/DebugInfo/GSYM/FunctionInfo.cpp index 55c36a55b4be..ad022fec9e32 100644 --- a/lib/DebugInfo/GSYM/FunctionInfo.cpp +++ b/lib/DebugInfo/GSYM/FunctionInfo.cpp @@ -1,22 +1,147 @@ -//===- FunctionInfo.cpp -----------------------------------------*- C++ -*-===// +//===- FunctionInfo.cpp ---------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/GSYM/FunctionInfo.h" +#include "llvm/DebugInfo/GSYM/FileWriter.h" +#include "llvm/DebugInfo/GSYM/LineTable.h" +#include "llvm/DebugInfo/GSYM/InlineInfo.h" +#include "llvm/Support/DataExtractor.h" using namespace llvm; using namespace gsym; +/// FunctionInfo information type that is used to encode the optional data +/// that is associated with a FunctionInfo object. +enum InfoType : uint32_t { + EndOfList = 0u, + LineTableInfo = 1u, + InlineInfo = 2u +}; + raw_ostream &llvm::gsym::operator<<(raw_ostream &OS, const FunctionInfo &FI) { OS << '[' << HEX64(FI.Range.Start) << '-' << HEX64(FI.Range.End) << "): " - << "Name=" << HEX32(FI.Name) << '\n'; - for (const auto &Line : FI.Lines) - OS << Line << '\n'; - OS << FI.Inline; + << "Name=" << HEX32(FI.Name) << '\n' << FI.OptLineTable << FI.Inline; return OS; } + +llvm::Expected<FunctionInfo> FunctionInfo::decode(DataExtractor &Data, + uint64_t BaseAddr) { + FunctionInfo FI; + FI.Range.Start = BaseAddr; + uint64_t Offset = 0; + if (!Data.isValidOffsetForDataOfSize(Offset, 4)) + return createStringError(std::errc::io_error, + "0x%8.8" PRIx64 ": missing FunctionInfo Size", Offset); + FI.Range.End = FI.Range.Start + Data.getU32(&Offset); + if (!Data.isValidOffsetForDataOfSize(Offset, 4)) + return createStringError(std::errc::io_error, + "0x%8.8" PRIx64 ": missing FunctionInfo Name", Offset); + FI.Name = Data.getU32(&Offset); + if (FI.Name == 0) + return createStringError(std::errc::io_error, + "0x%8.8" PRIx64 ": invalid FunctionInfo Name value 0x%8.8x", + Offset - 4, FI.Name); + bool Done = false; + while (!Done) { + if (!Data.isValidOffsetForDataOfSize(Offset, 4)) + return createStringError(std::errc::io_error, + "0x%8.8" PRIx64 ": missing FunctionInfo InfoType value", Offset); + const uint32_t IT = Data.getU32(&Offset); + if (!Data.isValidOffsetForDataOfSize(Offset, 4)) + return createStringError(std::errc::io_error, + "0x%8.8" PRIx64 ": missing FunctionInfo InfoType length", Offset); + const uint32_t InfoLength = Data.getU32(&Offset); + if (!Data.isValidOffsetForDataOfSize(Offset, InfoLength)) + return createStringError(std::errc::io_error, + "0x%8.8" PRIx64 ": missing FunctionInfo data for InfoType %u", + Offset, IT); + DataExtractor InfoData(Data.getData().substr(Offset, InfoLength), + Data.isLittleEndian(), + Data.getAddressSize()); + switch (IT) { + case InfoType::EndOfList: + Done = true; + break; + + case InfoType::LineTableInfo: + if (Expected<LineTable> LT = LineTable::decode(InfoData, BaseAddr)) + FI.OptLineTable = std::move(LT.get()); + else + return LT.takeError(); + break; + + case InfoType::InlineInfo: + if (Expected<InlineInfo> II = InlineInfo::decode(InfoData, BaseAddr)) + FI.Inline = std::move(II.get()); + else + return II.takeError(); + break; + + default: + return createStringError(std::errc::io_error, + "0x%8.8" PRIx64 ": unsupported InfoType %u", + Offset-8, IT); + } + Offset += InfoLength; + } + return std::move(FI); +} + +llvm::Expected<uint64_t> FunctionInfo::encode(FileWriter &O) const { + if (!isValid()) + return createStringError(std::errc::invalid_argument, + "attempted to encode invalid FunctionInfo object"); + // Align FunctionInfo data to a 4 byte alignment. + O.alignTo(4); + const uint64_t FuncInfoOffset = O.tell(); + // Write the size in bytes of this function as a uint32_t. This can be zero + // if we just have a symbol from a symbol table and that symbol has no size. + O.writeU32(size()); + // Write the name of this function as a uint32_t string table offset. + O.writeU32(Name); + + if (OptLineTable.hasValue()) { + O.writeU32(InfoType::LineTableInfo); + // Write a uint32_t length as zero for now, we will fix this up after + // writing the LineTable out with the number of bytes that were written. + O.writeU32(0); + const auto StartOffset = O.tell(); + llvm::Error err = OptLineTable->encode(O, Range.Start); + if (err) + return std::move(err); + const off_t Length = O.tell() - StartOffset; + if (Length > UINT32_MAX) + return createStringError(std::errc::invalid_argument, + "LineTable length is greater than UINT32_MAX"); + // Fixup the size of the LineTable data with the correct size. + O.fixup32(static_cast<uint32_t>(Length), StartOffset - 4); + } + + // Write out the inline function info if we have any and if it is valid. + if (Inline.hasValue()) { + O.writeU32(InfoType::InlineInfo); + // Write a uint32_t length as zero for now, we will fix this up after + // writing the LineTable out with the number of bytes that were written. + O.writeU32(0); + const auto StartOffset = O.tell(); + llvm::Error err = Inline->encode(O, Range.Start); + if (err) + return std::move(err); + const off_t Length = O.tell() - StartOffset; + if (Length > UINT32_MAX) + return createStringError(std::errc::invalid_argument, + "InlineInfo length is greater than UINT32_MAX"); + // Fixup the size of the InlineInfo data with the correct size. + O.fixup32(static_cast<uint32_t>(Length), StartOffset - 4); + } + + // Terminate the data chunks with and end of list with zero size + O.writeU32(InfoType::EndOfList); + O.writeU32(0); + return FuncInfoOffset; +} diff --git a/lib/DebugInfo/GSYM/GsymCreator.cpp b/lib/DebugInfo/GSYM/GsymCreator.cpp new file mode 100644 index 000000000000..f371426f2010 --- /dev/null +++ b/lib/DebugInfo/GSYM/GsymCreator.cpp @@ -0,0 +1,275 @@ +//===- GsymCreator.cpp ----------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/GSYM/GsymCreator.h" +#include "llvm/DebugInfo/GSYM/FileWriter.h" +#include "llvm/DebugInfo/GSYM/Header.h" +#include "llvm/DebugInfo/GSYM/LineTable.h" +#include "llvm/MC/StringTableBuilder.h" +#include "llvm/Support/raw_ostream.h" + +#include <algorithm> +#include <cassert> +#include <functional> +#include <vector> + +using namespace llvm; +using namespace gsym; + + +GsymCreator::GsymCreator() : StrTab(StringTableBuilder::ELF) { + insertFile(StringRef()); +} + +uint32_t GsymCreator::insertFile(StringRef Path, + llvm::sys::path::Style Style) { + llvm::StringRef directory = llvm::sys::path::parent_path(Path, Style); + llvm::StringRef filename = llvm::sys::path::filename(Path, Style); + FileEntry FE(insertString(directory), insertString(filename)); + + std::lock_guard<std::recursive_mutex> Guard(Mutex); + const auto NextIndex = Files.size(); + // Find FE in hash map and insert if not present. + auto R = FileEntryToIndex.insert(std::make_pair(FE, NextIndex)); + if (R.second) + Files.emplace_back(FE); + return R.first->second; +} + +llvm::Error GsymCreator::save(StringRef Path, + llvm::support::endianness ByteOrder) const { + std::error_code EC; + raw_fd_ostream OutStrm(Path, EC); + if (EC) + return llvm::errorCodeToError(EC); + FileWriter O(OutStrm, ByteOrder); + return encode(O); +} + +llvm::Error GsymCreator::encode(FileWriter &O) const { + std::lock_guard<std::recursive_mutex> Guard(Mutex); + if (Funcs.empty()) + return createStringError(std::errc::invalid_argument, + "no functions to encode"); + if (!Finalized) + return createStringError(std::errc::invalid_argument, + "GsymCreator wasn't finalized prior to encoding"); + + if (Funcs.size() > UINT32_MAX) + return createStringError(std::errc::invalid_argument, + "too many FunctionInfos"); + const uint64_t MinAddr = Funcs.front().startAddress(); + const uint64_t MaxAddr = Funcs.back().startAddress(); + const uint64_t AddrDelta = MaxAddr - MinAddr; + Header Hdr; + Hdr.Magic = GSYM_MAGIC; + Hdr.Version = GSYM_VERSION; + Hdr.AddrOffSize = 0; + Hdr.UUIDSize = static_cast<uint8_t>(UUID.size()); + Hdr.BaseAddress = MinAddr; + Hdr.NumAddresses = static_cast<uint32_t>(Funcs.size()); + Hdr.StrtabOffset = 0; // We will fix this up later. + Hdr.StrtabOffset = 0; // We will fix this up later. + memset(Hdr.UUID, 0, sizeof(Hdr.UUID)); + if (UUID.size() > sizeof(Hdr.UUID)) + return createStringError(std::errc::invalid_argument, + "invalid UUID size %u", (uint32_t)UUID.size()); + // Set the address offset size correctly in the GSYM header. + if (AddrDelta <= UINT8_MAX) + Hdr.AddrOffSize = 1; + else if (AddrDelta <= UINT16_MAX) + Hdr.AddrOffSize = 2; + else if (AddrDelta <= UINT32_MAX) + Hdr.AddrOffSize = 4; + else + Hdr.AddrOffSize = 8; + // Copy the UUID value if we have one. + if (UUID.size() > 0) + memcpy(Hdr.UUID, UUID.data(), UUID.size()); + // Write out the header. + llvm::Error Err = Hdr.encode(O); + if (Err) + return Err; + + // Write out the address offsets. + O.alignTo(Hdr.AddrOffSize); + for (const auto &FuncInfo : Funcs) { + uint64_t AddrOffset = FuncInfo.startAddress() - Hdr.BaseAddress; + switch(Hdr.AddrOffSize) { + case 1: O.writeU8(static_cast<uint8_t>(AddrOffset)); break; + case 2: O.writeU16(static_cast<uint16_t>(AddrOffset)); break; + case 4: O.writeU32(static_cast<uint32_t>(AddrOffset)); break; + case 8: O.writeU64(AddrOffset); break; + } + } + + // Write out all zeros for the AddrInfoOffsets. + O.alignTo(4); + const off_t AddrInfoOffsetsOffset = O.tell(); + for (size_t i = 0, n = Funcs.size(); i < n; ++i) + O.writeU32(0); + + // Write out the file table + O.alignTo(4); + assert(!Files.empty()); + assert(Files[0].Dir == 0); + assert(Files[0].Base == 0); + size_t NumFiles = Files.size(); + if (NumFiles > UINT32_MAX) + return createStringError(std::errc::invalid_argument, + "too many files"); + O.writeU32(static_cast<uint32_t>(NumFiles)); + for (auto File: Files) { + O.writeU32(File.Dir); + O.writeU32(File.Base); + } + + // Write out the sting table. + const off_t StrtabOffset = O.tell(); + StrTab.write(O.get_stream()); + const off_t StrtabSize = O.tell() - StrtabOffset; + std::vector<uint32_t> AddrInfoOffsets; + + // Write out the address infos for each function info. + for (const auto &FuncInfo : Funcs) { + if (Expected<uint64_t> OffsetOrErr = FuncInfo.encode(O)) + AddrInfoOffsets.push_back(OffsetOrErr.get()); + else + return OffsetOrErr.takeError(); + } + // Fixup the string table offset and size in the header + O.fixup32((uint32_t)StrtabOffset, offsetof(Header, StrtabOffset)); + O.fixup32((uint32_t)StrtabSize, offsetof(Header, StrtabSize)); + + // Fixup all address info offsets + uint64_t Offset = 0; + for (auto AddrInfoOffset: AddrInfoOffsets) { + O.fixup32(AddrInfoOffset, AddrInfoOffsetsOffset + Offset); + Offset += 4; + } + return ErrorSuccess(); +} + +llvm::Error GsymCreator::finalize(llvm::raw_ostream &OS) { + std::lock_guard<std::recursive_mutex> Guard(Mutex); + if (Finalized) + return createStringError(std::errc::invalid_argument, + "already finalized"); + Finalized = true; + + // Sort function infos so we can emit sorted functions. + llvm::sort(Funcs.begin(), Funcs.end()); + + // Don't let the string table indexes change by finalizing in order. + StrTab.finalizeInOrder(); + + // Remove duplicates function infos that have both entries from debug info + // (DWARF or Breakpad) and entries from the SymbolTable. + // + // Also handle overlapping function. Usually there shouldn't be any, but they + // can and do happen in some rare cases. + // + // (a) (b) (c) + // ^ ^ ^ ^ + // |X |Y |X ^ |X + // | | | |Y | ^ + // | | | v v |Y + // v v v v + // + // In (a) and (b), Y is ignored and X will be reported for the full range. + // In (c), both functions will be included in the result and lookups for an + // address in the intersection will return Y because of binary search. + // + // Note that in case of (b), we cannot include Y in the result because then + // we wouldn't find any function for range (end of Y, end of X) + // with binary search + auto NumBefore = Funcs.size(); + auto Curr = Funcs.begin(); + auto Prev = Funcs.end(); + while (Curr != Funcs.end()) { + // Can't check for overlaps or same address ranges if we don't have a + // previous entry + if (Prev != Funcs.end()) { + if (Prev->Range.intersects(Curr->Range)) { + // Overlapping address ranges. + if (Prev->Range == Curr->Range) { + // Same address range. Check if one is from debug info and the other + // is from a symbol table. If so, then keep the one with debug info. + // Our sorting guarantees that entries with matching address ranges + // that have debug info are last in the sort. + if (*Prev == *Curr) { + // FunctionInfo entries match exactly (range, lines, inlines) + OS << "warning: duplicate function info entries, removing " + "duplicate:\n" + << *Curr << '\n'; + Curr = Funcs.erase(Prev); + } else { + if (!Prev->hasRichInfo() && Curr->hasRichInfo()) { + // Same address range, one with no debug info (symbol) and the + // next with debug info. Keep the latter. + Curr = Funcs.erase(Prev); + } else { + OS << "warning: same address range contains different debug " + << "info. Removing:\n" + << *Prev << "\nIn favor of this one:\n" + << *Curr << "\n"; + Curr = Funcs.erase(Prev); + } + } + } else { + // print warnings about overlaps + OS << "warning: function ranges overlap:\n" + << *Prev << "\n" + << *Curr << "\n"; + } + } else if (Prev->Range.size() == 0 && + Curr->Range.contains(Prev->Range.Start)) { + OS << "warning: removing symbol:\n" + << *Prev << "\nKeeping:\n" + << *Curr << "\n"; + Curr = Funcs.erase(Prev); + } + } + if (Curr == Funcs.end()) + break; + Prev = Curr++; + } + + OS << "Pruned " << NumBefore - Funcs.size() << " functions, ended with " + << Funcs.size() << " total\n"; + return Error::success(); +} + +uint32_t GsymCreator::insertString(StringRef S) { + std::lock_guard<std::recursive_mutex> Guard(Mutex); + if (S.empty()) + return 0; + return StrTab.add(S); +} + +void GsymCreator::addFunctionInfo(FunctionInfo &&FI) { + std::lock_guard<std::recursive_mutex> Guard(Mutex); + Funcs.emplace_back(FI); +} + +void GsymCreator::forEachFunctionInfo( + std::function<bool(FunctionInfo &)> const &Callback) { + std::lock_guard<std::recursive_mutex> Guard(Mutex); + for (auto &FI : Funcs) { + if (!Callback(FI)) + break; + } +} + +void GsymCreator::forEachFunctionInfo( + std::function<bool(const FunctionInfo &)> const &Callback) const { + std::lock_guard<std::recursive_mutex> Guard(Mutex); + for (const auto &FI : Funcs) { + if (!Callback(FI)) + break; + } +} diff --git a/lib/DebugInfo/GSYM/GsymReader.cpp b/lib/DebugInfo/GSYM/GsymReader.cpp new file mode 100644 index 000000000000..1b448cf80b70 --- /dev/null +++ b/lib/DebugInfo/GSYM/GsymReader.cpp @@ -0,0 +1,265 @@ +//===- GsymReader.cpp -----------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/GSYM/GsymReader.h" + +#include <assert.h> +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> + +#include "llvm/DebugInfo/GSYM/GsymCreator.h" +#include "llvm/DebugInfo/GSYM/InlineInfo.h" +#include "llvm/DebugInfo/GSYM/LineTable.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/DataExtractor.h" +#include "llvm/Support/MemoryBuffer.h" + +using namespace llvm; +using namespace gsym; + +GsymReader::GsymReader(std::unique_ptr<MemoryBuffer> Buffer) : + MemBuffer(std::move(Buffer)), + Endian(support::endian::system_endianness()) {} + + GsymReader::GsymReader(GsymReader &&RHS) = default; + +GsymReader::~GsymReader() = default; + +llvm::Expected<GsymReader> GsymReader::openFile(StringRef Filename) { + // Open the input file and return an appropriate error if needed. + ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr = + MemoryBuffer::getFileOrSTDIN(Filename); + auto Err = BuffOrErr.getError(); + if (Err) + return llvm::errorCodeToError(Err); + return create(BuffOrErr.get()); +} + +llvm::Expected<GsymReader> GsymReader::copyBuffer(StringRef Bytes) { + auto MemBuffer = MemoryBuffer::getMemBufferCopy(Bytes, "GSYM bytes"); + return create(MemBuffer); +} + +llvm::Expected<llvm::gsym::GsymReader> +GsymReader::create(std::unique_ptr<MemoryBuffer> &MemBuffer) { + if (!MemBuffer.get()) + return createStringError(std::errc::invalid_argument, + "invalid memory buffer"); + GsymReader GR(std::move(MemBuffer)); + llvm::Error Err = GR.parse(); + if (Err) + return std::move(Err); + return std::move(GR); +} + +llvm::Error +GsymReader::parse() { + BinaryStreamReader FileData(MemBuffer->getBuffer(), + support::endian::system_endianness()); + // Check for the magic bytes. This file format is designed to be mmap'ed + // into a process and accessed as read only. This is done for performance + // and efficiency for symbolicating and parsing GSYM data. + if (FileData.readObject(Hdr)) + return createStringError(std::errc::invalid_argument, + "not enough data for a GSYM header"); + + const auto HostByteOrder = support::endian::system_endianness(); + switch (Hdr->Magic) { + case GSYM_MAGIC: + Endian = HostByteOrder; + break; + case GSYM_CIGAM: + // This is a GSYM file, but not native endianness. + Endian = sys::IsBigEndianHost ? support::little : support::big; + Swap.reset(new SwappedData); + break; + default: + return createStringError(std::errc::invalid_argument, + "not a GSYM file"); + } + + bool DataIsLittleEndian = HostByteOrder != support::little; + // Read a correctly byte swapped header if we need to. + if (Swap) { + DataExtractor Data(MemBuffer->getBuffer(), DataIsLittleEndian, 4); + if (auto ExpectedHdr = Header::decode(Data)) + Swap->Hdr = ExpectedHdr.get(); + else + return ExpectedHdr.takeError(); + Hdr = &Swap->Hdr; + } + + // Detect errors in the header and report any that are found. If we make it + // past this without errors, we know we have a good magic value, a supported + // version number, verified address offset size and a valid UUID size. + if (Error Err = Hdr->checkForError()) + return Err; + + if (!Swap) { + // This is the native endianness case that is most common and optimized for + // efficient lookups. Here we just grab pointers to the native data and + // use ArrayRef objects to allow efficient read only access. + + // Read the address offsets. + if (FileData.padToAlignment(Hdr->AddrOffSize) || + FileData.readArray(AddrOffsets, + Hdr->NumAddresses * Hdr->AddrOffSize)) + return createStringError(std::errc::invalid_argument, + "failed to read address table"); + + // Read the address info offsets. + if (FileData.padToAlignment(4) || + FileData.readArray(AddrInfoOffsets, Hdr->NumAddresses)) + return createStringError(std::errc::invalid_argument, + "failed to read address info offsets table"); + + // Read the file table. + uint32_t NumFiles = 0; + if (FileData.readInteger(NumFiles) || FileData.readArray(Files, NumFiles)) + return createStringError(std::errc::invalid_argument, + "failed to read file table"); + + // Get the string table. + FileData.setOffset(Hdr->StrtabOffset); + if (FileData.readFixedString(StrTab.Data, Hdr->StrtabSize)) + return createStringError(std::errc::invalid_argument, + "failed to read string table"); +} else { + // This is the non native endianness case that is not common and not + // optimized for lookups. Here we decode the important tables into local + // storage and then set the ArrayRef objects to point to these swapped + // copies of the read only data so lookups can be as efficient as possible. + DataExtractor Data(MemBuffer->getBuffer(), DataIsLittleEndian, 4); + + // Read the address offsets. + uint64_t Offset = alignTo(sizeof(Header), Hdr->AddrOffSize); + Swap->AddrOffsets.resize(Hdr->NumAddresses * Hdr->AddrOffSize); + switch (Hdr->AddrOffSize) { + case 1: + if (!Data.getU8(&Offset, Swap->AddrOffsets.data(), Hdr->NumAddresses)) + return createStringError(std::errc::invalid_argument, + "failed to read address table"); + break; + case 2: + if (!Data.getU16(&Offset, + reinterpret_cast<uint16_t *>(Swap->AddrOffsets.data()), + Hdr->NumAddresses)) + return createStringError(std::errc::invalid_argument, + "failed to read address table"); + break; + case 4: + if (!Data.getU32(&Offset, + reinterpret_cast<uint32_t *>(Swap->AddrOffsets.data()), + Hdr->NumAddresses)) + return createStringError(std::errc::invalid_argument, + "failed to read address table"); + break; + case 8: + if (!Data.getU64(&Offset, + reinterpret_cast<uint64_t *>(Swap->AddrOffsets.data()), + Hdr->NumAddresses)) + return createStringError(std::errc::invalid_argument, + "failed to read address table"); + } + AddrOffsets = ArrayRef<uint8_t>(Swap->AddrOffsets); + + // Read the address info offsets. + Offset = alignTo(Offset, 4); + Swap->AddrInfoOffsets.resize(Hdr->NumAddresses); + if (Data.getU32(&Offset, Swap->AddrInfoOffsets.data(), Hdr->NumAddresses)) + AddrInfoOffsets = ArrayRef<uint32_t>(Swap->AddrInfoOffsets); + else + return createStringError(std::errc::invalid_argument, + "failed to read address table"); + // Read the file table. + const uint32_t NumFiles = Data.getU32(&Offset); + if (NumFiles > 0) { + Swap->Files.resize(NumFiles); + if (Data.getU32(&Offset, &Swap->Files[0].Dir, NumFiles*2)) + Files = ArrayRef<FileEntry>(Swap->Files); + else + return createStringError(std::errc::invalid_argument, + "failed to read file table"); + } + // Get the string table. + StrTab.Data = MemBuffer->getBuffer().substr(Hdr->StrtabOffset, + Hdr->StrtabSize); + if (StrTab.Data.empty()) + return createStringError(std::errc::invalid_argument, + "failed to read string table"); + } + return Error::success(); + +} + +const Header &GsymReader::getHeader() const { + // The only way to get a GsymReader is from GsymReader::openFile(...) or + // GsymReader::copyBuffer() and the header must be valid and initialized to + // a valid pointer value, so the assert below should not trigger. + assert(Hdr); + return *Hdr; +} + +Optional<uint64_t> GsymReader::getAddress(size_t Index) const { + switch (Hdr->AddrOffSize) { + case 1: return addressForIndex<uint8_t>(Index); + case 2: return addressForIndex<uint16_t>(Index); + case 4: return addressForIndex<uint32_t>(Index); + case 8: return addressForIndex<uint64_t>(Index); + } + return llvm::None; +} + +Optional<uint64_t> GsymReader::getAddressInfoOffset(size_t Index) const { + const auto NumAddrInfoOffsets = AddrInfoOffsets.size(); + if (Index < NumAddrInfoOffsets) + return AddrInfoOffsets[Index]; + return llvm::None; +} + +Expected<uint64_t> +GsymReader::getAddressIndex(const uint64_t Addr) const { + if (Addr < Hdr->BaseAddress) + return createStringError(std::errc::invalid_argument, + "address 0x%" PRIx64 " not in GSYM", Addr); + const uint64_t AddrOffset = Addr - Hdr->BaseAddress; + switch (Hdr->AddrOffSize) { + case 1: return getAddressOffsetIndex<uint8_t>(AddrOffset); + case 2: return getAddressOffsetIndex<uint16_t>(AddrOffset); + case 4: return getAddressOffsetIndex<uint32_t>(AddrOffset); + case 8: return getAddressOffsetIndex<uint64_t>(AddrOffset); + default: break; + } + return createStringError(std::errc::invalid_argument, + "unsupported address offset size %u", + Hdr->AddrOffSize); +} + +llvm::Expected<FunctionInfo> GsymReader::getFunctionInfo(uint64_t Addr) const { + Expected<uint64_t> AddressIndex = getAddressIndex(Addr); + if (!AddressIndex) + return AddressIndex.takeError(); + // Address info offsets size should have been checked in parse(). + assert(*AddressIndex < AddrInfoOffsets.size()); + auto AddrInfoOffset = AddrInfoOffsets[*AddressIndex]; + DataExtractor Data(MemBuffer->getBuffer().substr(AddrInfoOffset), Endian, 4); + if (Optional<uint64_t> OptAddr = getAddress(*AddressIndex)) { + auto ExpectedFI = FunctionInfo::decode(Data, *OptAddr); + if (ExpectedFI) { + if (ExpectedFI->Range.contains(Addr) || ExpectedFI->Range.size() == 0) + return ExpectedFI; + return createStringError(std::errc::invalid_argument, + "address 0x%" PRIx64 " not in GSYM", Addr); + } + } + return createStringError(std::errc::invalid_argument, + "failed to extract address[%" PRIu64 "]", + *AddressIndex); +} diff --git a/lib/DebugInfo/GSYM/Header.cpp b/lib/DebugInfo/GSYM/Header.cpp new file mode 100644 index 000000000000..0b3fb9c49894 --- /dev/null +++ b/lib/DebugInfo/GSYM/Header.cpp @@ -0,0 +1,109 @@ +//===- Header.cpp -----------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/GSYM/Header.h" +#include "llvm/DebugInfo/GSYM/FileWriter.h" +#include "llvm/Support/DataExtractor.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" + +#define HEX8(v) llvm::format_hex(v, 4) +#define HEX16(v) llvm::format_hex(v, 6) +#define HEX32(v) llvm::format_hex(v, 10) +#define HEX64(v) llvm::format_hex(v, 18) + +using namespace llvm; +using namespace gsym; + +raw_ostream &llvm::gsym::operator<<(raw_ostream &OS, const Header &H) { + OS << "Header:\n"; + OS << " Magic = " << HEX32(H.Magic) << "\n"; + OS << " Version = " << HEX16(H.Version) << '\n'; + OS << " AddrOffSize = " << HEX8(H.AddrOffSize) << '\n'; + OS << " UUIDSize = " << HEX8(H.UUIDSize) << '\n'; + OS << " BaseAddress = " << HEX64(H.BaseAddress) << '\n'; + OS << " NumAddresses = " << HEX32(H.NumAddresses) << '\n'; + OS << " StrtabOffset = " << HEX32(H.StrtabOffset) << '\n'; + OS << " StrtabSize = " << HEX32(H.StrtabSize) << '\n'; + OS << " UUID = "; + for (uint8_t I = 0; I < H.UUIDSize; ++I) + OS << format_hex_no_prefix(H.UUID[I], 2); + OS << '\n'; + return OS; +} + +/// Check the header and detect any errors. +llvm::Error Header::checkForError() const { + if (Magic != GSYM_MAGIC) + return createStringError(std::errc::invalid_argument, + "invalid GSYM magic 0x%8.8x", Magic); + if (Version != GSYM_VERSION) + return createStringError(std::errc::invalid_argument, + "unsupported GSYM version %u", Version); + switch (AddrOffSize) { + case 1: break; + case 2: break; + case 4: break; + case 8: break; + default: + return createStringError(std::errc::invalid_argument, + "invalid address offset size %u", + AddrOffSize); + } + if (UUIDSize > GSYM_MAX_UUID_SIZE) + return createStringError(std::errc::invalid_argument, + "invalid UUID size %u", UUIDSize); + return Error::success(); +} + +llvm::Expected<Header> Header::decode(DataExtractor &Data) { + uint64_t Offset = 0; + // The header is stored as a single blob of data that has a fixed byte size. + if (!Data.isValidOffsetForDataOfSize(Offset, sizeof(Header))) + return createStringError(std::errc::invalid_argument, + "not enough data for a gsym::Header"); + Header H; + H.Magic = Data.getU32(&Offset); + H.Version = Data.getU16(&Offset); + H.AddrOffSize = Data.getU8(&Offset); + H.UUIDSize = Data.getU8(&Offset); + H.BaseAddress = Data.getU64(&Offset); + H.NumAddresses = Data.getU32(&Offset); + H.StrtabOffset = Data.getU32(&Offset); + H.StrtabSize = Data.getU32(&Offset); + Data.getU8(&Offset, H.UUID, GSYM_MAX_UUID_SIZE); + if (llvm::Error Err = H.checkForError()) + return std::move(Err); + return H; +} + +llvm::Error Header::encode(FileWriter &O) const { + // Users must verify the Header is valid prior to calling this funtion. + if (llvm::Error Err = checkForError()) + return Err; + O.writeU32(Magic); + O.writeU16(Version); + O.writeU8(AddrOffSize); + O.writeU8(UUIDSize); + O.writeU64(BaseAddress); + O.writeU32(NumAddresses); + O.writeU32(StrtabOffset); + O.writeU32(StrtabSize); + O.writeData(llvm::ArrayRef<uint8_t>(UUID)); + return Error::success(); +} + +bool llvm::gsym::operator==(const Header &LHS, const Header &RHS) { + return LHS.Magic == RHS.Magic && LHS.Version == RHS.Version && + LHS.AddrOffSize == RHS.AddrOffSize && LHS.UUIDSize == RHS.UUIDSize && + LHS.BaseAddress == RHS.BaseAddress && + LHS.NumAddresses == RHS.NumAddresses && + LHS.StrtabOffset == RHS.StrtabOffset && + LHS.StrtabSize == RHS.StrtabSize && + memcmp(LHS.UUID, RHS.UUID, LHS.UUIDSize) == 0; +} diff --git a/lib/DebugInfo/GSYM/InlineInfo.cpp b/lib/DebugInfo/GSYM/InlineInfo.cpp index 781c1755241d..32ed2c709575 100644 --- a/lib/DebugInfo/GSYM/InlineInfo.cpp +++ b/lib/DebugInfo/GSYM/InlineInfo.cpp @@ -8,7 +8,9 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/GSYM/FileEntry.h" +#include "llvm/DebugInfo/GSYM/FileWriter.h" #include "llvm/DebugInfo/GSYM/InlineInfo.h" +#include "llvm/Support/DataExtractor.h" #include <algorithm> #include <inttypes.h> @@ -57,3 +59,101 @@ llvm::Optional<InlineInfo::InlineArray> InlineInfo::getInlineStack(uint64_t Addr return Result; return llvm::None; } + +/// Decode an InlineInfo in Data at the specified offset. +/// +/// A local helper function to decode InlineInfo objects. This function is +/// called recursively when parsing child InlineInfo objects. +/// +/// \param Data The data extractor to decode from. +/// \param Offset The offset within \a Data to decode from. +/// \param BaseAddr The base address to use when decoding address ranges. +/// \returns An InlineInfo or an error describing the issue that was +/// encountered during decoding. +static llvm::Expected<InlineInfo> decode(DataExtractor &Data, uint64_t &Offset, + uint64_t BaseAddr) { + InlineInfo Inline; + if (!Data.isValidOffset(Offset)) + return createStringError(std::errc::io_error, + "0x%8.8" PRIx64 ": missing InlineInfo address ranges data", Offset); + Inline.Ranges.decode(Data, BaseAddr, Offset); + if (Inline.Ranges.empty()) + return Inline; + if (!Data.isValidOffsetForDataOfSize(Offset, 1)) + return createStringError(std::errc::io_error, + "0x%8.8" PRIx64 ": missing InlineInfo uint8_t indicating children", + Offset); + bool HasChildren = Data.getU8(&Offset) != 0; + if (!Data.isValidOffsetForDataOfSize(Offset, 4)) + return createStringError(std::errc::io_error, + "0x%8.8" PRIx64 ": missing InlineInfo uint32_t for name", Offset); + Inline.Name = Data.getU32(&Offset); + if (!Data.isValidOffset(Offset)) + return createStringError(std::errc::io_error, + "0x%8.8" PRIx64 ": missing ULEB128 for InlineInfo call file", Offset); + Inline.CallFile = (uint32_t)Data.getULEB128(&Offset); + if (!Data.isValidOffset(Offset)) + return createStringError(std::errc::io_error, + "0x%8.8" PRIx64 ": missing ULEB128 for InlineInfo call line", Offset); + Inline.CallLine = (uint32_t)Data.getULEB128(&Offset); + if (HasChildren) { + // Child address ranges are encoded relative to the first address in the + // parent InlineInfo object. + const auto ChildBaseAddr = Inline.Ranges[0].Start; + while (true) { + llvm::Expected<InlineInfo> Child = decode(Data, Offset, ChildBaseAddr); + if (!Child) + return Child.takeError(); + // InlineInfo with empty Ranges termintes a child sibling chain. + if (Child.get().Ranges.empty()) + break; + Inline.Children.emplace_back(std::move(*Child)); + } + } + return Inline; +} + +llvm::Expected<InlineInfo> InlineInfo::decode(DataExtractor &Data, + uint64_t BaseAddr) { + uint64_t Offset = 0; + return ::decode(Data, Offset, BaseAddr); +} + +llvm::Error InlineInfo::encode(FileWriter &O, uint64_t BaseAddr) const { + // Users must verify the InlineInfo is valid prior to calling this funtion. + // We don't want to emit any InlineInfo objects if they are not valid since + // it will waste space in the GSYM file. + if (!isValid()) + return createStringError(std::errc::invalid_argument, + "attempted to encode invalid InlineInfo object"); + Ranges.encode(O, BaseAddr); + bool HasChildren = !Children.empty(); + O.writeU8(HasChildren); + O.writeU32(Name); + O.writeULEB(CallFile); + O.writeULEB(CallLine); + if (HasChildren) { + // Child address ranges are encoded as relative to the first + // address in the Ranges for this object. This keeps the offsets + // small and allows for efficient encoding using ULEB offsets. + const uint64_t ChildBaseAddr = Ranges[0].Start; + for (const auto &Child : Children) { + // Make sure all child address ranges are contained in the parent address + // ranges. + for (const auto &ChildRange: Child.Ranges) { + if (!Ranges.contains(ChildRange)) + return createStringError(std::errc::invalid_argument, + "child range not contained in parent"); + } + llvm::Error Err = Child.encode(O, ChildBaseAddr); + if (Err) + return Err; + } + + // Terminate child sibling chain by emitting a zero. This zero will cause + // the decodeAll() function above to return false and stop the decoding + // of child InlineInfo objects that are siblings. + O.writeULEB(0); + } + return Error::success(); +} diff --git a/lib/DebugInfo/GSYM/LineTable.cpp b/lib/DebugInfo/GSYM/LineTable.cpp new file mode 100644 index 000000000000..824c0041be9f --- /dev/null +++ b/lib/DebugInfo/GSYM/LineTable.cpp @@ -0,0 +1,287 @@ +//===- LineTable.cpp --------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/GSYM/LineTable.h" +#include "llvm/DebugInfo/GSYM/FileWriter.h" +#include "llvm/Support/DataExtractor.h" + +using namespace llvm; +using namespace gsym; + +enum LineTableOpCode { + EndSequence = 0x00, ///< End of the line table. + SetFile = 0x01, ///< Set LineTableRow.file_idx, don't push a row. + AdvancePC = 0x02, ///< Increment LineTableRow.address, and push a row. + AdvanceLine = 0x03, ///< Set LineTableRow.file_line, don't push a row. + FirstSpecial = 0x04, ///< All special opcodes push a row. +}; + +struct DeltaInfo { + int64_t Delta; + uint32_t Count; + DeltaInfo(int64_t D, uint32_t C) : Delta(D), Count(C) {} +}; + +inline bool operator<(const DeltaInfo &LHS, int64_t Delta) { + return LHS.Delta < Delta; +} + +static bool encodeSpecial(int64_t MinLineDelta, int64_t MaxLineDelta, + int64_t LineDelta, uint64_t AddrDelta, + uint8_t &SpecialOp) { + if (LineDelta < MinLineDelta) + return false; + if (LineDelta > MaxLineDelta) + return false; + int64_t LineRange = MaxLineDelta - MinLineDelta + 1; + int64_t AdjustedOp = ((LineDelta - MinLineDelta) + AddrDelta * LineRange); + int64_t Op = AdjustedOp + FirstSpecial; + if (Op < 0) + return false; + if (Op > 255) + return false; + SpecialOp = (uint8_t)Op; + return true; +} + +typedef std::function<bool(const LineEntry &Row)> LineEntryCallback; + +static llvm::Error parse(DataExtractor &Data, uint64_t BaseAddr, + LineEntryCallback const &Callback) { + uint64_t Offset = 0; + if (!Data.isValidOffset(Offset)) + return createStringError(std::errc::io_error, + "0x%8.8" PRIx64 ": missing LineTable MinDelta", Offset); + int64_t MinDelta = Data.getSLEB128(&Offset); + if (!Data.isValidOffset(Offset)) + return createStringError(std::errc::io_error, + "0x%8.8" PRIx64 ": missing LineTable MaxDelta", Offset); + int64_t MaxDelta = Data.getSLEB128(&Offset); + int64_t LineRange = MaxDelta - MinDelta + 1; + if (!Data.isValidOffset(Offset)) + return createStringError(std::errc::io_error, + "0x%8.8" PRIx64 ": missing LineTable FirstLine", Offset); + const uint32_t FirstLine = (uint32_t)Data.getULEB128(&Offset); + LineEntry Row(BaseAddr, 1, FirstLine); + bool Done = false; + while (!Done) { + if (!Data.isValidOffset(Offset)) + return createStringError(std::errc::io_error, + "0x%8.8" PRIx64 ": EOF found before EndSequence", Offset); + uint8_t Op = Data.getU8(&Offset); + switch (Op) { + case EndSequence: + Done = true; + break; + case SetFile: + if (!Data.isValidOffset(Offset)) + return createStringError(std::errc::io_error, + "0x%8.8" PRIx64 ": EOF found before SetFile value", + Offset); + Row.File = (uint32_t)Data.getULEB128(&Offset); + break; + case AdvancePC: + if (!Data.isValidOffset(Offset)) + return createStringError(std::errc::io_error, + "0x%8.8" PRIx64 ": EOF found before AdvancePC value", + Offset); + Row.Addr += Data.getULEB128(&Offset); + // If the function callback returns false, we stop parsing. + if (Callback(Row) == false) + return Error::success(); + break; + case AdvanceLine: + if (!Data.isValidOffset(Offset)) + return createStringError(std::errc::io_error, + "0x%8.8" PRIx64 ": EOF found before AdvanceLine value", + Offset); + Row.Line += Data.getSLEB128(&Offset); + break; + default: { + // A byte that contains both address and line increment. + uint8_t AdjustedOp = Op - FirstSpecial; + int64_t LineDelta = MinDelta + (AdjustedOp % LineRange); + uint64_t AddrDelta = (AdjustedOp / LineRange); + Row.Line += LineDelta; + Row.Addr += AddrDelta; + // If the function callback returns false, we stop parsing. + if (Callback(Row) == false) + return Error::success(); + break; + } + } + } + return Error::success(); +} + +llvm::Error LineTable::encode(FileWriter &Out, uint64_t BaseAddr) const { + // Users must verify the LineTable is valid prior to calling this funtion. + // We don't want to emit any LineTable objects if they are not valid since + // it will waste space in the GSYM file. + if (!isValid()) + return createStringError(std::errc::invalid_argument, + "attempted to encode invalid LineTable object"); + + int64_t MinLineDelta = INT64_MAX; + int64_t MaxLineDelta = INT64_MIN; + std::vector<DeltaInfo> DeltaInfos; + if (Lines.size() == 1) { + MinLineDelta = 0; + MaxLineDelta = 0; + } else { + int64_t PrevLine = 1; + bool First = true; + for (const auto &line_entry : Lines) { + if (First) + First = false; + else { + int64_t LineDelta = (int64_t)line_entry.Line - PrevLine; + auto End = DeltaInfos.end(); + auto Pos = std::lower_bound(DeltaInfos.begin(), End, LineDelta); + if (Pos != End && Pos->Delta == LineDelta) + ++Pos->Count; + else + DeltaInfos.insert(Pos, DeltaInfo(LineDelta, 1)); + if (LineDelta < MinLineDelta) + MinLineDelta = LineDelta; + if (LineDelta > MaxLineDelta) + MaxLineDelta = LineDelta; + } + PrevLine = (int64_t)line_entry.Line; + } + assert(MinLineDelta <= MaxLineDelta); + } + // Set the min and max line delta intelligently based on the counts of + // the line deltas. if our range is too large. + const int64_t MaxLineRange = 14; + if (MaxLineDelta - MinLineDelta > MaxLineRange) { + uint32_t BestIndex = 0; + uint32_t BestEndIndex = 0; + uint32_t BestCount = 0; + const size_t NumDeltaInfos = DeltaInfos.size(); + for (uint32_t I = 0; I < NumDeltaInfos; ++I) { + const int64_t FirstDelta = DeltaInfos[I].Delta; + uint32_t CurrCount = 0; + uint32_t J; + for (J = I; J < NumDeltaInfos; ++J) { + auto LineRange = DeltaInfos[J].Delta - FirstDelta; + if (LineRange > MaxLineRange) + break; + CurrCount += DeltaInfos[J].Count; + } + if (CurrCount > BestCount) { + BestIndex = I; + BestEndIndex = J - 1; + BestCount = CurrCount; + } + } + MinLineDelta = DeltaInfos[BestIndex].Delta; + MaxLineDelta = DeltaInfos[BestEndIndex].Delta; + } + if (MinLineDelta == MaxLineDelta && MinLineDelta > 0 && + MinLineDelta < MaxLineRange) + MinLineDelta = 0; + assert(MinLineDelta <= MaxLineDelta); + + // Initialize the line entry state as a starting point. All line entries + // will be deltas from this. + LineEntry Prev(BaseAddr, 1, Lines.front().Line); + + // Write out the min and max line delta as signed LEB128. + Out.writeSLEB(MinLineDelta); + Out.writeSLEB(MaxLineDelta); + // Write out the starting line number as a unsigned LEB128. + Out.writeULEB(Prev.Line); + + for (const auto &Curr : Lines) { + if (Curr.Addr < BaseAddr) + return createStringError(std::errc::invalid_argument, + "LineEntry has address 0x%" PRIx64 " which is " + "less than the function start address 0x%" + PRIx64, Curr.Addr, BaseAddr); + if (Curr.Addr < Prev.Addr) + return createStringError(std::errc::invalid_argument, + "LineEntry in LineTable not in ascending order"); + const uint64_t AddrDelta = Curr.Addr - Prev.Addr; + int64_t LineDelta = 0; + if (Curr.Line > Prev.Line) + LineDelta = Curr.Line - Prev.Line; + else if (Prev.Line > Curr.Line) + LineDelta = -((int32_t)(Prev.Line - Curr.Line)); + + // Set the file if it doesn't match the current one. + if (Curr.File != Prev.File) { + Out.writeU8(SetFile); + Out.writeULEB(Curr.File); + } + + uint8_t SpecialOp; + if (encodeSpecial(MinLineDelta, MaxLineDelta, LineDelta, AddrDelta, + SpecialOp)) { + // Advance the PC and line and push a row. + Out.writeU8(SpecialOp); + } else { + // We can't encode the address delta and line delta into + // a single special opcode, we must do them separately. + + // Advance the line. + if (LineDelta != 0) { + Out.writeU8(AdvanceLine); + Out.writeSLEB(LineDelta); + } + + // Advance the PC and push a row. + Out.writeU8(AdvancePC); + Out.writeULEB(AddrDelta); + } + Prev = Curr; + } + Out.writeU8(EndSequence); + return Error::success(); +} + +// Parse all line table entries into the "LineTable" vector. We can +// cache the results of this if needed, or we can call LineTable::lookup() +// below. +llvm::Expected<LineTable> LineTable::decode(DataExtractor &Data, + uint64_t BaseAddr) { + LineTable LT; + llvm::Error Err = parse(Data, BaseAddr, [&](const LineEntry &Row) -> bool { + LT.Lines.push_back(Row); + return true; // Keep parsing by returning true. + }); + if (Err) + return std::move(Err); + return LT; +} +// Parse the line table on the fly and find the row we are looking for. +// We will need to determine if we need to cache the line table by calling +// LineTable::parseAllEntries(...) or just call this function each time. +// There is a CPU vs memory tradeoff we will need to determine. +LineEntry LineTable::lookup(DataExtractor &Data, uint64_t BaseAddr, uint64_t Addr) { + LineEntry Result; + llvm::Error Err = parse(Data, BaseAddr, + [Addr, &Result](const LineEntry &Row) -> bool { + if (Addr < Row.Addr) + return false; // Stop parsing, result contains the line table row! + Result = Row; + if (Addr == Row.Addr) { + // Stop parsing, this is the row we are looking for since the address + // matches. + return false; + } + return true; // Keep parsing till we find the right row. + }); + return Result; +} + +raw_ostream &llvm::gsym::operator<<(raw_ostream &OS, const LineTable <) { + for (const auto &LineEntry : LT) + OS << LineEntry << '\n'; + return OS; +} diff --git a/lib/DebugInfo/GSYM/Range.cpp b/lib/DebugInfo/GSYM/Range.cpp index ca61984dacbd..19ab700fdd57 100644 --- a/lib/DebugInfo/GSYM/Range.cpp +++ b/lib/DebugInfo/GSYM/Range.cpp @@ -8,6 +8,8 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/GSYM/Range.h" +#include "llvm/DebugInfo/GSYM/FileWriter.h" +#include "llvm/Support/DataExtractor.h" #include <algorithm> #include <inttypes.h> @@ -40,6 +42,17 @@ bool AddressRanges::contains(uint64_t Addr) const { return It != Ranges.begin() && Addr < It[-1].End; } +bool AddressRanges::contains(AddressRange Range) const { + if (Range.size() == 0) + return false; + auto It = std::partition_point( + Ranges.begin(), Ranges.end(), + [=](const AddressRange &R) { return R.Start <= Range.Start; }); + if (It == Ranges.begin()) + return false; + return Range.End <= It[-1].End; +} + raw_ostream &llvm::gsym::operator<<(raw_ostream &OS, const AddressRange &R) { return OS << '[' << HEX64(R.Start) << " - " << HEX64(R.End) << ")"; } @@ -53,3 +66,37 @@ raw_ostream &llvm::gsym::operator<<(raw_ostream &OS, const AddressRanges &AR) { } return OS; } + +void AddressRange::encode(FileWriter &O, uint64_t BaseAddr) const { + assert(Start >= BaseAddr); + O.writeULEB(Start - BaseAddr); + O.writeULEB(size()); +} + +void AddressRange::decode(DataExtractor &Data, uint64_t BaseAddr, + uint64_t &Offset) { + const uint64_t AddrOffset = Data.getULEB128(&Offset); + const uint64_t Size = Data.getULEB128(&Offset); + const uint64_t StartAddr = BaseAddr + AddrOffset; + Start = StartAddr; + End = StartAddr + Size; +} + +void AddressRanges::encode(FileWriter &O, uint64_t BaseAddr) const { + O.writeULEB(Ranges.size()); + if (Ranges.empty()) + return; + for (auto Range : Ranges) + Range.encode(O, BaseAddr); +} + +void AddressRanges::decode(DataExtractor &Data, uint64_t BaseAddr, + uint64_t &Offset) { + clear(); + uint64_t NumRanges = Data.getULEB128(&Offset); + if (NumRanges == 0) + return; + Ranges.resize(NumRanges); + for (auto &Range : Ranges) + Range.decode(Data, BaseAddr, Offset); +} diff --git a/lib/DebugInfo/MSF/MappedBlockStream.cpp b/lib/DebugInfo/MSF/MappedBlockStream.cpp index df925771f0d9..5dc9c86b34fd 100644 --- a/lib/DebugInfo/MSF/MappedBlockStream.cpp +++ b/lib/DebugInfo/MSF/MappedBlockStream.cpp @@ -52,7 +52,7 @@ MappedBlockStream::MappedBlockStream(uint32_t BlockSize, std::unique_ptr<MappedBlockStream> MappedBlockStream::createStream( uint32_t BlockSize, const MSFStreamLayout &Layout, BinaryStreamRef MsfData, BumpPtrAllocator &Allocator) { - return llvm::make_unique<MappedBlockStreamImpl<MappedBlockStream>>( + return std::make_unique<MappedBlockStreamImpl<MappedBlockStream>>( BlockSize, Layout, MsfData, Allocator); } @@ -63,7 +63,7 @@ std::unique_ptr<MappedBlockStream> MappedBlockStream::createIndexedStream( MSFStreamLayout SL; SL.Blocks = Layout.StreamMap[StreamIndex]; SL.Length = Layout.StreamSizes[StreamIndex]; - return llvm::make_unique<MappedBlockStreamImpl<MappedBlockStream>>( + return std::make_unique<MappedBlockStreamImpl<MappedBlockStream>>( Layout.SB->BlockSize, SL, MsfData, Allocator); } @@ -318,7 +318,7 @@ WritableMappedBlockStream::createStream(uint32_t BlockSize, const MSFStreamLayout &Layout, WritableBinaryStreamRef MsfData, BumpPtrAllocator &Allocator) { - return llvm::make_unique<MappedBlockStreamImpl<WritableMappedBlockStream>>( + return std::make_unique<MappedBlockStreamImpl<WritableMappedBlockStream>>( BlockSize, Layout, MsfData, Allocator); } diff --git a/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp b/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp index a8ae076e1d6c..c2552f55703c 100644 --- a/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp +++ b/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp @@ -405,7 +405,7 @@ DIARawSymbol::findChildren(PDB_SymType Type) const { return nullptr; } - return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator); + return std::make_unique<DIAEnumSymbols>(Session, DiaEnumerator); } std::unique_ptr<IPDBEnumSymbols> @@ -423,7 +423,7 @@ DIARawSymbol::findChildren(PDB_SymType Type, StringRef Name, Symbol->findChildrenEx(EnumVal, Name16Str, CompareFlags, &DiaEnumerator)) return nullptr; - return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator); + return std::make_unique<DIAEnumSymbols>(Session, DiaEnumerator); } std::unique_ptr<IPDBEnumSymbols> @@ -443,7 +443,7 @@ DIARawSymbol::findChildrenByAddr(PDB_SymType Type, StringRef Name, Section, Offset, &DiaEnumerator)) return nullptr; - return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator); + return std::make_unique<DIAEnumSymbols>(Session, DiaEnumerator); } std::unique_ptr<IPDBEnumSymbols> @@ -462,7 +462,7 @@ DIARawSymbol::findChildrenByVA(PDB_SymType Type, StringRef Name, &DiaEnumerator)) return nullptr; - return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator); + return std::make_unique<DIAEnumSymbols>(Session, DiaEnumerator); } std::unique_ptr<IPDBEnumSymbols> @@ -480,7 +480,7 @@ DIARawSymbol::findChildrenByRVA(PDB_SymType Type, StringRef Name, &DiaEnumerator)) return nullptr; - return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator); + return std::make_unique<DIAEnumSymbols>(Session, DiaEnumerator); } std::unique_ptr<IPDBEnumSymbols> @@ -489,7 +489,7 @@ DIARawSymbol::findInlineFramesByAddr(uint32_t Section, uint32_t Offset) const { if (S_OK != Symbol->findInlineFramesByAddr(Section, Offset, &DiaEnumerator)) return nullptr; - return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator); + return std::make_unique<DIAEnumSymbols>(Session, DiaEnumerator); } std::unique_ptr<IPDBEnumSymbols> @@ -498,7 +498,7 @@ DIARawSymbol::findInlineFramesByRVA(uint32_t RVA) const { if (S_OK != Symbol->findInlineFramesByRVA(RVA, &DiaEnumerator)) return nullptr; - return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator); + return std::make_unique<DIAEnumSymbols>(Session, DiaEnumerator); } std::unique_ptr<IPDBEnumSymbols> @@ -507,7 +507,7 @@ DIARawSymbol::findInlineFramesByVA(uint64_t VA) const { if (S_OK != Symbol->findInlineFramesByVA(VA, &DiaEnumerator)) return nullptr; - return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator); + return std::make_unique<DIAEnumSymbols>(Session, DiaEnumerator); } std::unique_ptr<IPDBEnumLineNumbers> DIARawSymbol::findInlineeLines() const { @@ -515,7 +515,7 @@ std::unique_ptr<IPDBEnumLineNumbers> DIARawSymbol::findInlineeLines() const { if (S_OK != Symbol->findInlineeLines(&DiaEnumerator)) return nullptr; - return llvm::make_unique<DIAEnumLineNumbers>(DiaEnumerator); + return std::make_unique<DIAEnumLineNumbers>(DiaEnumerator); } std::unique_ptr<IPDBEnumLineNumbers> @@ -526,7 +526,7 @@ DIARawSymbol::findInlineeLinesByAddr(uint32_t Section, uint32_t Offset, Symbol->findInlineeLinesByAddr(Section, Offset, Length, &DiaEnumerator)) return nullptr; - return llvm::make_unique<DIAEnumLineNumbers>(DiaEnumerator); + return std::make_unique<DIAEnumLineNumbers>(DiaEnumerator); } std::unique_ptr<IPDBEnumLineNumbers> @@ -535,7 +535,7 @@ DIARawSymbol::findInlineeLinesByRVA(uint32_t RVA, uint32_t Length) const { if (S_OK != Symbol->findInlineeLinesByRVA(RVA, Length, &DiaEnumerator)) return nullptr; - return llvm::make_unique<DIAEnumLineNumbers>(DiaEnumerator); + return std::make_unique<DIAEnumLineNumbers>(DiaEnumerator); } std::unique_ptr<IPDBEnumLineNumbers> @@ -544,7 +544,7 @@ DIARawSymbol::findInlineeLinesByVA(uint64_t VA, uint32_t Length) const { if (S_OK != Symbol->findInlineeLinesByVA(VA, Length, &DiaEnumerator)) return nullptr; - return llvm::make_unique<DIAEnumLineNumbers>(DiaEnumerator); + return std::make_unique<DIAEnumLineNumbers>(DiaEnumerator); } void DIARawSymbol::getDataBytes(llvm::SmallVector<uint8_t, 32> &bytes) const { @@ -776,7 +776,7 @@ std::unique_ptr<IPDBLineNumber> DIARawSymbol::getSrcLineOnTypeDefn() const { if (FAILED(Symbol->getSrcLineOnTypeDefn(&LineNumber)) || !LineNumber) return nullptr; - return llvm::make_unique<DIALineNumber>(LineNumber); + return std::make_unique<DIALineNumber>(LineNumber); } uint32_t DIARawSymbol::getStride() const { @@ -871,7 +871,7 @@ DIARawSymbol::getVirtualBaseTableType() const { if (FAILED(Symbol->get_virtualBaseTableType(&TableType)) || !TableType) return nullptr; - auto RawVT = llvm::make_unique<DIARawSymbol>(Session, TableType); + auto RawVT = std::make_unique<DIARawSymbol>(Session, TableType); auto Pointer = PDBSymbol::createAs<PDBSymbolTypePointer>(Session, std::move(RawVT)); return unique_dyn_cast<PDBSymbolTypeBuiltin>(Pointer->getPointeeType()); diff --git a/lib/DebugInfo/PDB/DIA/DIASectionContrib.cpp b/lib/DebugInfo/PDB/DIA/DIASectionContrib.cpp index e2d928f2c4b2..4f0e078e6712 100644 --- a/lib/DebugInfo/PDB/DIA/DIASectionContrib.cpp +++ b/lib/DebugInfo/PDB/DIA/DIASectionContrib.cpp @@ -23,7 +23,7 @@ std::unique_ptr<PDBSymbolCompiland> DIASectionContrib::getCompiland() const { if (FAILED(Section->get_compiland(&Symbol))) return nullptr; - auto RawSymbol = llvm::make_unique<DIARawSymbol>(Session, Symbol); + auto RawSymbol = std::make_unique<DIARawSymbol>(Session, Symbol); return PDBSymbol::createAs<PDBSymbolCompiland>(Session, std::move(RawSymbol)); } diff --git a/lib/DebugInfo/PDB/DIA/DIASession.cpp b/lib/DebugInfo/PDB/DIA/DIASession.cpp index 4e0b8587c613..64ffa776bbd6 100644 --- a/lib/DebugInfo/PDB/DIA/DIASession.cpp +++ b/lib/DebugInfo/PDB/DIA/DIASession.cpp @@ -73,15 +73,7 @@ static Error LoadDIA(CComPtr<IDiaDataSource> &DiaDataSource) { #if !defined(_MSC_VER) return llvm::make_error<PDBError>(pdb_error_code::dia_failed_loading); #else - const wchar_t *msdia_dll = nullptr; -#if _MSC_VER >= 1900 && _MSC_VER < 2000 - msdia_dll = L"msdia140.dll"; // VS2015 -#elif _MSC_VER >= 1800 - msdia_dll = L"msdia120.dll"; // VS2013 -#else -#error "Unknown Visual Studio version." -#endif - + const wchar_t *msdia_dll = L"msdia140.dll"; HRESULT HR; if (FAILED(HR = NoRegCoCreate(msdia_dll, CLSID_DiaSource, IID_IDiaDataSource, reinterpret_cast<LPVOID *>(&DiaDataSource)))) @@ -158,7 +150,7 @@ std::unique_ptr<PDBSymbolExe> DIASession::getGlobalScope() { if (S_OK != Session->get_globalScope(&GlobalScope)) return nullptr; - auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, GlobalScope); + auto RawSymbol = std::make_unique<DIARawSymbol>(*this, GlobalScope); auto PdbSymbol(PDBSymbol::create(*this, std::move(RawSymbol))); std::unique_ptr<PDBSymbolExe> ExeSymbol( static_cast<PDBSymbolExe *>(PdbSymbol.release())); @@ -193,7 +185,7 @@ DIASession::getSymbolById(SymIndexId SymbolId) const { if (S_OK != Session->symbolById(SymbolId, &LocatedSymbol)) return nullptr; - auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, LocatedSymbol); + auto RawSymbol = std::make_unique<DIARawSymbol>(*this, LocatedSymbol); return PDBSymbol::create(*this, std::move(RawSymbol)); } @@ -210,7 +202,7 @@ DIASession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) const { if (S_OK != Session->findSymbolByRVA(RVA, EnumVal, &Symbol)) return nullptr; } - auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, Symbol); + auto RawSymbol = std::make_unique<DIARawSymbol>(*this, Symbol); return PDBSymbol::create(*this, std::move(RawSymbol)); } @@ -222,7 +214,7 @@ std::unique_ptr<PDBSymbol> DIASession::findSymbolByRVA(uint32_t RVA, if (S_OK != Session->findSymbolByRVA(RVA, EnumVal, &Symbol)) return nullptr; - auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, Symbol); + auto RawSymbol = std::make_unique<DIARawSymbol>(*this, Symbol); return PDBSymbol::create(*this, std::move(RawSymbol)); } @@ -235,7 +227,7 @@ DIASession::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, if (S_OK != Session->findSymbolByAddr(Sect, Offset, EnumVal, &Symbol)) return nullptr; - auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, Symbol); + auto RawSymbol = std::make_unique<DIARawSymbol>(*this, Symbol); return PDBSymbol::create(*this, std::move(RawSymbol)); } @@ -251,7 +243,7 @@ DIASession::findLineNumbers(const PDBSymbolCompiland &Compiland, RawFile.getDiaFile(), &LineNumbers)) return nullptr; - return llvm::make_unique<DIAEnumLineNumbers>(LineNumbers); + return std::make_unique<DIAEnumLineNumbers>(LineNumbers); } std::unique_ptr<IPDBEnumLineNumbers> @@ -265,7 +257,7 @@ DIASession::findLineNumbersByAddress(uint64_t Address, uint32_t Length) const { if (S_OK != Session->findLinesByRVA(RVA, Length, &LineNumbers)) return nullptr; } - return llvm::make_unique<DIAEnumLineNumbers>(LineNumbers); + return std::make_unique<DIAEnumLineNumbers>(LineNumbers); } std::unique_ptr<IPDBEnumLineNumbers> @@ -274,7 +266,7 @@ DIASession::findLineNumbersByRVA(uint32_t RVA, uint32_t Length) const { if (S_OK != Session->findLinesByRVA(RVA, Length, &LineNumbers)) return nullptr; - return llvm::make_unique<DIAEnumLineNumbers>(LineNumbers); + return std::make_unique<DIAEnumLineNumbers>(LineNumbers); } std::unique_ptr<IPDBEnumLineNumbers> @@ -284,7 +276,7 @@ DIASession::findLineNumbersBySectOffset(uint32_t Section, uint32_t Offset, if (S_OK != Session->findLinesByAddr(Section, Offset, Length, &LineNumbers)) return nullptr; - return llvm::make_unique<DIAEnumLineNumbers>(LineNumbers); + return std::make_unique<DIAEnumLineNumbers>(LineNumbers); } std::unique_ptr<IPDBEnumSourceFiles> @@ -306,7 +298,7 @@ DIASession::findSourceFiles(const PDBSymbolCompiland *Compiland, if (S_OK != Session->findFile(DiaCompiland, Utf16Pattern.m_str, Flags, &SourceFiles)) return nullptr; - return llvm::make_unique<DIAEnumSourceFiles>(*this, SourceFiles); + return std::make_unique<DIAEnumSourceFiles>(*this, SourceFiles); } std::unique_ptr<IPDBSourceFile> @@ -342,7 +334,7 @@ std::unique_ptr<IPDBEnumSourceFiles> DIASession::getAllSourceFiles() const { if (S_OK != Session->findFile(nullptr, nullptr, nsNone, &Files)) return nullptr; - return llvm::make_unique<DIAEnumSourceFiles>(*this, Files); + return std::make_unique<DIAEnumSourceFiles>(*this, Files); } std::unique_ptr<IPDBEnumSourceFiles> DIASession::getSourceFilesForCompiland( @@ -355,7 +347,7 @@ std::unique_ptr<IPDBEnumSourceFiles> DIASession::getSourceFilesForCompiland( Session->findFile(RawSymbol.getDiaSymbol(), nullptr, nsNone, &Files)) return nullptr; - return llvm::make_unique<DIAEnumSourceFiles>(*this, Files); + return std::make_unique<DIAEnumSourceFiles>(*this, Files); } std::unique_ptr<IPDBSourceFile> @@ -364,7 +356,7 @@ DIASession::getSourceFileById(uint32_t FileId) const { if (S_OK != Session->findFileById(FileId, &LocatedFile)) return nullptr; - return llvm::make_unique<DIASourceFile>(*this, LocatedFile); + return std::make_unique<DIASourceFile>(*this, LocatedFile); } std::unique_ptr<IPDBEnumDataStreams> DIASession::getDebugStreams() const { @@ -372,7 +364,7 @@ std::unique_ptr<IPDBEnumDataStreams> DIASession::getDebugStreams() const { if (S_OK != Session->getEnumDebugStreams(&DiaEnumerator)) return nullptr; - return llvm::make_unique<DIAEnumDebugStreams>(DiaEnumerator); + return std::make_unique<DIAEnumDebugStreams>(DiaEnumerator); } std::unique_ptr<IPDBEnumTables> DIASession::getEnumTables() const { @@ -380,7 +372,7 @@ std::unique_ptr<IPDBEnumTables> DIASession::getEnumTables() const { if (S_OK != Session->getEnumTables(&DiaEnumerator)) return nullptr; - return llvm::make_unique<DIAEnumTables>(DiaEnumerator); + return std::make_unique<DIAEnumTables>(DiaEnumerator); } template <class T> static CComPtr<T> getTableEnumerator(IDiaSession &Session) { @@ -407,7 +399,7 @@ DIASession::getInjectedSources() const { if (!Files) return nullptr; - return llvm::make_unique<DIAEnumInjectedSources>(Files); + return std::make_unique<DIAEnumInjectedSources>(Files); } std::unique_ptr<IPDBEnumSectionContribs> @@ -417,7 +409,7 @@ DIASession::getSectionContribs() const { if (!Sections) return nullptr; - return llvm::make_unique<DIAEnumSectionContribs>(*this, Sections); + return std::make_unique<DIAEnumSectionContribs>(*this, Sections); } std::unique_ptr<IPDBEnumFrameData> @@ -427,5 +419,5 @@ DIASession::getFrameData() const { if (!FD) return nullptr; - return llvm::make_unique<DIAEnumFrameData>(FD); + return std::make_unique<DIAEnumFrameData>(FD); } diff --git a/lib/DebugInfo/PDB/GenericError.cpp b/lib/DebugInfo/PDB/GenericError.cpp index 70dc094c42ec..0e4cba3174b2 100644 --- a/lib/DebugInfo/PDB/GenericError.cpp +++ b/lib/DebugInfo/PDB/GenericError.cpp @@ -34,8 +34,8 @@ public: return "The PDB file path is an invalid UTF8 sequence."; case pdb_error_code::signature_out_of_date: return "The signature does not match; the file(s) might be out of date."; - case pdb_error_code::external_cmdline_ref: - return "The path to this file must be provided on the command-line."; + case pdb_error_code::no_matching_pch: + return "No matching precompiled header could be located."; } llvm_unreachable("Unrecognized generic_error_code"); } diff --git a/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp b/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp index 20b6c6142547..419734771ccd 100644 --- a/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp +++ b/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp @@ -180,12 +180,12 @@ Error DbiModuleDescriptorBuilder::commit(BinaryStreamWriter &ModiWriter, void DbiModuleDescriptorBuilder::addDebugSubsection( std::shared_ptr<DebugSubsection> Subsection) { assert(Subsection); - C13Builders.push_back(llvm::make_unique<DebugSubsectionRecordBuilder>( + C13Builders.push_back(std::make_unique<DebugSubsectionRecordBuilder>( std::move(Subsection), CodeViewContainer::Pdb)); } void DbiModuleDescriptorBuilder::addDebugSubsection( const DebugSubsectionRecord &SubsectionContents) { - C13Builders.push_back(llvm::make_unique<DebugSubsectionRecordBuilder>( + C13Builders.push_back(std::make_unique<DebugSubsectionRecordBuilder>( SubsectionContents, CodeViewContainer::Pdb)); } diff --git a/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp b/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp index b7ade0072ee5..0e00c2f7ff98 100644 --- a/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp +++ b/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp @@ -114,7 +114,7 @@ Expected<DbiModuleDescriptorBuilder &> DbiStreamBuilder::addModuleInfo(StringRef ModuleName) { uint32_t Index = ModiList.size(); ModiList.push_back( - llvm::make_unique<DbiModuleDescriptorBuilder>(ModuleName, Index, Msf)); + std::make_unique<DbiModuleDescriptorBuilder>(ModuleName, Index, Msf)); return *ModiList.back(); } diff --git a/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp b/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp index 8ed5b8b44c59..432f1e9b24d3 100644 --- a/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp +++ b/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp @@ -183,8 +183,8 @@ void GSIHashStreamBuilder::finalizeBuckets(uint32_t RecordZeroOffset) { } GSIStreamBuilder::GSIStreamBuilder(msf::MSFBuilder &Msf) - : Msf(Msf), PSH(llvm::make_unique<GSIHashStreamBuilder>()), - GSH(llvm::make_unique<GSIHashStreamBuilder>()) {} + : Msf(Msf), PSH(std::make_unique<GSIHashStreamBuilder>()), + GSH(std::make_unique<GSIHashStreamBuilder>()) {} GSIStreamBuilder::~GSIStreamBuilder() {} diff --git a/lib/DebugInfo/PDB/Native/Hash.cpp b/lib/DebugInfo/PDB/Native/Hash.cpp index b5c139ecbec0..7fb6b4bd5d31 100644 --- a/lib/DebugInfo/PDB/Native/Hash.cpp +++ b/lib/DebugInfo/PDB/Native/Hash.cpp @@ -8,8 +8,8 @@ #include "llvm/DebugInfo/PDB/Native/Hash.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/CRC.h" #include "llvm/Support/Endian.h" -#include "llvm/Support/JamCRC.h" #include <cstdint> using namespace llvm; @@ -79,7 +79,6 @@ uint32_t pdb::hashStringV2(StringRef Str) { // Corresponds to `SigForPbCb` in langapi/shared/crc32.h. uint32_t pdb::hashBufferV8(ArrayRef<uint8_t> Buf) { JamCRC JC(/*Init=*/0U); - JC.update(makeArrayRef<char>(reinterpret_cast<const char *>(Buf.data()), - Buf.size())); + JC.update(Buf); return JC.getCRC(); } diff --git a/lib/DebugInfo/PDB/Native/NativeEnumInjectedSources.cpp b/lib/DebugInfo/PDB/Native/NativeEnumInjectedSources.cpp index f17ff5bb01f2..2f6a5bc3d574 100644 --- a/lib/DebugInfo/PDB/Native/NativeEnumInjectedSources.cpp +++ b/lib/DebugInfo/PDB/Native/NativeEnumInjectedSources.cpp @@ -46,30 +46,31 @@ public: uint64_t getCodeByteSize() const override { return Entry.FileSize; } std::string getFileName() const override { - auto Name = Strings.getStringForID(Entry.FileNI); - assert(Name && "InjectedSourceStream should have rejected this"); - return *Name; + StringRef Ret = cantFail(Strings.getStringForID(Entry.FileNI), + "InjectedSourceStream should have rejected this"); + return Ret; } std::string getObjectFileName() const override { - auto ObjName = Strings.getStringForID(Entry.ObjNI); - assert(ObjName && "InjectedSourceStream should have rejected this"); - return *ObjName; + StringRef Ret = cantFail(Strings.getStringForID(Entry.ObjNI), + "InjectedSourceStream should have rejected this"); + return Ret; } std::string getVirtualFileName() const override { - auto VName = Strings.getStringForID(Entry.VFileNI); - assert(VName && "InjectedSourceStream should have rejected this"); - return *VName; + StringRef Ret = cantFail(Strings.getStringForID(Entry.VFileNI), + "InjectedSourceStream should have rejected this"); + return Ret; } uint32_t getCompression() const override { return Entry.Compression; } std::string getCode() const override { // Get name of stream storing the data. - auto VName = Strings.getStringForID(Entry.VFileNI); - assert(VName && "InjectedSourceStream should have rejected this"); - std::string StreamName = ("/src/files/" + *VName).str(); + StringRef VName = + cantFail(Strings.getStringForID(Entry.VFileNI), + "InjectedSourceStream should have rejected this"); + std::string StreamName = ("/src/files/" + VName).str(); // Find stream with that name and read its data. // FIXME: Consider validating (or even loading) all this in @@ -104,14 +105,14 @@ std::unique_ptr<IPDBInjectedSource> NativeEnumInjectedSources::getChildAtIndex(uint32_t N) const { if (N >= getChildCount()) return nullptr; - return make_unique<NativeInjectedSource>(std::next(Stream.begin(), N)->second, + return std::make_unique<NativeInjectedSource>(std::next(Stream.begin(), N)->second, File, Strings); } std::unique_ptr<IPDBInjectedSource> NativeEnumInjectedSources::getNext() { if (Cur == Stream.end()) return nullptr; - return make_unique<NativeInjectedSource>((Cur++)->second, File, Strings); + return std::make_unique<NativeInjectedSource>((Cur++)->second, File, Strings); } void NativeEnumInjectedSources::reset() { Cur = Stream.begin(); } diff --git a/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp b/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp index 8e43cf24495a..2ad552470b61 100644 --- a/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp +++ b/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp @@ -30,68 +30,68 @@ void NativeRawSymbol::dump(raw_ostream &OS, int Indent, std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findChildren(PDB_SymType Type) const { - return llvm::make_unique<NullEnumerator<PDBSymbol>>(); + return std::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findChildren(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags) const { - return llvm::make_unique<NullEnumerator<PDBSymbol>>(); + return std::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findChildrenByAddr(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, uint32_t Section, uint32_t Offset) const { - return llvm::make_unique<NullEnumerator<PDBSymbol>>(); + return std::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findChildrenByVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, uint64_t VA) const { - return llvm::make_unique<NullEnumerator<PDBSymbol>>(); + return std::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findChildrenByRVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, uint32_t RVA) const { - return llvm::make_unique<NullEnumerator<PDBSymbol>>(); + return std::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findInlineFramesByAddr(uint32_t Section, uint32_t Offset) const { - return llvm::make_unique<NullEnumerator<PDBSymbol>>(); + return std::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findInlineFramesByRVA(uint32_t RVA) const { - return llvm::make_unique<NullEnumerator<PDBSymbol>>(); + return std::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findInlineFramesByVA(uint64_t VA) const { - return llvm::make_unique<NullEnumerator<PDBSymbol>>(); + return std::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumLineNumbers> NativeRawSymbol::findInlineeLines() const { - return llvm::make_unique<NullEnumerator<IPDBLineNumber>>(); + return std::make_unique<NullEnumerator<IPDBLineNumber>>(); } std::unique_ptr<IPDBEnumLineNumbers> NativeRawSymbol::findInlineeLinesByAddr(uint32_t Section, uint32_t Offset, uint32_t Length) const { - return llvm::make_unique<NullEnumerator<IPDBLineNumber>>(); + return std::make_unique<NullEnumerator<IPDBLineNumber>>(); } std::unique_ptr<IPDBEnumLineNumbers> NativeRawSymbol::findInlineeLinesByRVA(uint32_t RVA, uint32_t Length) const { - return llvm::make_unique<NullEnumerator<IPDBLineNumber>>(); + return std::make_unique<NullEnumerator<IPDBLineNumber>>(); } std::unique_ptr<IPDBEnumLineNumbers> NativeRawSymbol::findInlineeLinesByVA(uint64_t VA, uint32_t Length) const { - return llvm::make_unique<NullEnumerator<IPDBLineNumber>>(); + return std::make_unique<NullEnumerator<IPDBLineNumber>>(); } void NativeRawSymbol::getDataBytes(SmallVector<uint8_t, 32> &bytes) const { diff --git a/lib/DebugInfo/PDB/Native/NativeSession.cpp b/lib/DebugInfo/PDB/Native/NativeSession.cpp index 8a49cb1c5963..b45a5881dcb5 100644 --- a/lib/DebugInfo/PDB/Native/NativeSession.cpp +++ b/lib/DebugInfo/PDB/Native/NativeSession.cpp @@ -59,18 +59,18 @@ NativeSession::~NativeSession() = default; Error NativeSession::createFromPdb(std::unique_ptr<MemoryBuffer> Buffer, std::unique_ptr<IPDBSession> &Session) { StringRef Path = Buffer->getBufferIdentifier(); - auto Stream = llvm::make_unique<MemoryBufferByteStream>( + auto Stream = std::make_unique<MemoryBufferByteStream>( std::move(Buffer), llvm::support::little); - auto Allocator = llvm::make_unique<BumpPtrAllocator>(); - auto File = llvm::make_unique<PDBFile>(Path, std::move(Stream), *Allocator); + auto Allocator = std::make_unique<BumpPtrAllocator>(); + auto File = std::make_unique<PDBFile>(Path, std::move(Stream), *Allocator); if (auto EC = File->parseFileHeaders()) return EC; if (auto EC = File->parseStreamData()) return EC; Session = - llvm::make_unique<NativeSession>(std::move(File), std::move(Allocator)); + std::make_unique<NativeSession>(std::move(File), std::move(Allocator)); return Error::success(); } @@ -202,7 +202,7 @@ NativeSession::getInjectedSources() const { consumeError(Strings.takeError()); return nullptr; } - return make_unique<NativeEnumInjectedSources>(*Pdb, *ISS, *Strings); + return std::make_unique<NativeEnumInjectedSources>(*Pdb, *ISS, *Strings); } std::unique_ptr<IPDBEnumSectionContribs> diff --git a/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp b/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp index 9f5e86281a23..26ccb7daece0 100644 --- a/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp +++ b/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp @@ -163,14 +163,14 @@ void NativeTypeEnum::dump(raw_ostream &OS, int Indent, std::unique_ptr<IPDBEnumSymbols> NativeTypeEnum::findChildren(PDB_SymType Type) const { if (Type != PDB_SymType::Data) - return llvm::make_unique<NullEnumerator<PDBSymbol>>(); + return std::make_unique<NullEnumerator<PDBSymbol>>(); const NativeTypeEnum *ClassParent = nullptr; if (!Modifiers) ClassParent = this; else ClassParent = UnmodifiedType; - return llvm::make_unique<NativeEnumEnumEnumerators>(Session, *ClassParent); + return std::make_unique<NativeEnumEnumEnumerators>(Session, *ClassParent); } PDB_SymType NativeTypeEnum::getSymTag() const { return PDB_SymType::Enum; } diff --git a/lib/DebugInfo/PDB/Native/NativeTypeFunctionSig.cpp b/lib/DebugInfo/PDB/Native/NativeTypeFunctionSig.cpp index 405303469c18..f98a4c3043eb 100644 --- a/lib/DebugInfo/PDB/Native/NativeTypeFunctionSig.cpp +++ b/lib/DebugInfo/PDB/Native/NativeTypeFunctionSig.cpp @@ -65,7 +65,7 @@ private: std::unique_ptr<PDBSymbol> wrap(std::unique_ptr<PDBSymbol> S) const { if (!S) return nullptr; - auto NTFA = llvm::make_unique<NativeTypeFunctionArg>(Session, std::move(S)); + auto NTFA = std::make_unique<NativeTypeFunctionArg>(Session, std::move(S)); return PDBSymbol::create(Session, std::move(NTFA)); } NativeSession &Session; @@ -133,9 +133,9 @@ void NativeTypeFunctionSig::dump(raw_ostream &OS, int Indent, std::unique_ptr<IPDBEnumSymbols> NativeTypeFunctionSig::findChildren(PDB_SymType Type) const { if (Type != PDB_SymType::FunctionArg) - return llvm::make_unique<NullEnumerator<PDBSymbol>>(); + return std::make_unique<NullEnumerator<PDBSymbol>>(); - auto NET = llvm::make_unique<NativeEnumTypes>(Session, + auto NET = std::make_unique<NativeEnumTypes>(Session, /* copy */ ArgList.ArgIndices); return std::unique_ptr<IPDBEnumSymbols>( new NativeEnumFunctionArgs(Session, std::move(NET))); diff --git a/lib/DebugInfo/PDB/Native/PDBFile.cpp b/lib/DebugInfo/PDB/Native/PDBFile.cpp index 983031dfcb78..9ac226b89139 100644 --- a/lib/DebugInfo/PDB/Native/PDBFile.cpp +++ b/lib/DebugInfo/PDB/Native/PDBFile.cpp @@ -264,7 +264,7 @@ Expected<GlobalsStream &> PDBFile::getPDBGlobalsStream() { safelyCreateIndexedStream(DbiS->getGlobalSymbolStreamIndex()); if (!GlobalS) return GlobalS.takeError(); - auto TempGlobals = llvm::make_unique<GlobalsStream>(std::move(*GlobalS)); + auto TempGlobals = std::make_unique<GlobalsStream>(std::move(*GlobalS)); if (auto EC = TempGlobals->reload()) return std::move(EC); Globals = std::move(TempGlobals); @@ -277,7 +277,7 @@ Expected<InfoStream &> PDBFile::getPDBInfoStream() { auto InfoS = safelyCreateIndexedStream(StreamPDB); if (!InfoS) return InfoS.takeError(); - auto TempInfo = llvm::make_unique<InfoStream>(std::move(*InfoS)); + auto TempInfo = std::make_unique<InfoStream>(std::move(*InfoS)); if (auto EC = TempInfo->reload()) return std::move(EC); Info = std::move(TempInfo); @@ -290,7 +290,7 @@ Expected<DbiStream &> PDBFile::getPDBDbiStream() { auto DbiS = safelyCreateIndexedStream(StreamDBI); if (!DbiS) return DbiS.takeError(); - auto TempDbi = llvm::make_unique<DbiStream>(std::move(*DbiS)); + auto TempDbi = std::make_unique<DbiStream>(std::move(*DbiS)); if (auto EC = TempDbi->reload(this)) return std::move(EC); Dbi = std::move(TempDbi); @@ -303,7 +303,7 @@ Expected<TpiStream &> PDBFile::getPDBTpiStream() { auto TpiS = safelyCreateIndexedStream(StreamTPI); if (!TpiS) return TpiS.takeError(); - auto TempTpi = llvm::make_unique<TpiStream>(*this, std::move(*TpiS)); + auto TempTpi = std::make_unique<TpiStream>(*this, std::move(*TpiS)); if (auto EC = TempTpi->reload()) return std::move(EC); Tpi = std::move(TempTpi); @@ -319,7 +319,7 @@ Expected<TpiStream &> PDBFile::getPDBIpiStream() { auto IpiS = safelyCreateIndexedStream(StreamIPI); if (!IpiS) return IpiS.takeError(); - auto TempIpi = llvm::make_unique<TpiStream>(*this, std::move(*IpiS)); + auto TempIpi = std::make_unique<TpiStream>(*this, std::move(*IpiS)); if (auto EC = TempIpi->reload()) return std::move(EC); Ipi = std::move(TempIpi); @@ -337,7 +337,7 @@ Expected<PublicsStream &> PDBFile::getPDBPublicsStream() { safelyCreateIndexedStream(DbiS->getPublicSymbolStreamIndex()); if (!PublicS) return PublicS.takeError(); - auto TempPublics = llvm::make_unique<PublicsStream>(std::move(*PublicS)); + auto TempPublics = std::make_unique<PublicsStream>(std::move(*PublicS)); if (auto EC = TempPublics->reload()) return std::move(EC); Publics = std::move(TempPublics); @@ -356,7 +356,7 @@ Expected<SymbolStream &> PDBFile::getPDBSymbolStream() { if (!SymbolS) return SymbolS.takeError(); - auto TempSymbols = llvm::make_unique<SymbolStream>(std::move(*SymbolS)); + auto TempSymbols = std::make_unique<SymbolStream>(std::move(*SymbolS)); if (auto EC = TempSymbols->reload()) return std::move(EC); Symbols = std::move(TempSymbols); @@ -370,7 +370,7 @@ Expected<PDBStringTable &> PDBFile::getStringTable() { if (!NS) return NS.takeError(); - auto N = llvm::make_unique<PDBStringTable>(); + auto N = std::make_unique<PDBStringTable>(); BinaryStreamReader Reader(**NS); if (auto EC = N->reload(Reader)) return std::move(EC); @@ -391,7 +391,7 @@ Expected<InjectedSourceStream &> PDBFile::getInjectedSourceStream() { if (!Strings) return Strings.takeError(); - auto IJ = llvm::make_unique<InjectedSourceStream>(std::move(*IJS)); + auto IJ = std::make_unique<InjectedSourceStream>(std::move(*IJS)); if (auto EC = IJ->reload(*Strings)) return std::move(EC); InjectedSources = std::move(IJ); diff --git a/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp b/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp index 8f5a048ea4b5..aa3288724390 100644 --- a/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp +++ b/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp @@ -22,7 +22,7 @@ #include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h" #include "llvm/Support/BinaryStream.h" #include "llvm/Support/BinaryStreamWriter.h" -#include "llvm/Support/JamCRC.h" +#include "llvm/Support/CRC.h" #include "llvm/Support/Path.h" #include "llvm/Support/xxhash.h" @@ -42,7 +42,7 @@ Error PDBFileBuilder::initialize(uint32_t BlockSize) { auto ExpectedMsf = MSFBuilder::create(Allocator, BlockSize); if (!ExpectedMsf) return ExpectedMsf.takeError(); - Msf = llvm::make_unique<MSFBuilder>(std::move(*ExpectedMsf)); + Msf = std::make_unique<MSFBuilder>(std::move(*ExpectedMsf)); return Error::success(); } @@ -50,25 +50,25 @@ MSFBuilder &PDBFileBuilder::getMsfBuilder() { return *Msf; } InfoStreamBuilder &PDBFileBuilder::getInfoBuilder() { if (!Info) - Info = llvm::make_unique<InfoStreamBuilder>(*Msf, NamedStreams); + Info = std::make_unique<InfoStreamBuilder>(*Msf, NamedStreams); return *Info; } DbiStreamBuilder &PDBFileBuilder::getDbiBuilder() { if (!Dbi) - Dbi = llvm::make_unique<DbiStreamBuilder>(*Msf); + Dbi = std::make_unique<DbiStreamBuilder>(*Msf); return *Dbi; } TpiStreamBuilder &PDBFileBuilder::getTpiBuilder() { if (!Tpi) - Tpi = llvm::make_unique<TpiStreamBuilder>(*Msf, StreamTPI); + Tpi = std::make_unique<TpiStreamBuilder>(*Msf, StreamTPI); return *Tpi; } TpiStreamBuilder &PDBFileBuilder::getIpiBuilder() { if (!Ipi) - Ipi = llvm::make_unique<TpiStreamBuilder>(*Msf, StreamIPI); + Ipi = std::make_unique<TpiStreamBuilder>(*Msf, StreamIPI); return *Ipi; } @@ -78,7 +78,7 @@ PDBStringTableBuilder &PDBFileBuilder::getStringTableBuilder() { GSIStreamBuilder &PDBFileBuilder::getGsiBuilder() { if (!Gsi) - Gsi = llvm::make_unique<GSIStreamBuilder>(*Msf); + Gsi = std::make_unique<GSIStreamBuilder>(*Msf); return *Gsi; } @@ -174,8 +174,7 @@ Error PDBFileBuilder::finalizeMsfLayout() { if (!InjectedSources.empty()) { for (const auto &IS : InjectedSources) { JamCRC CRC(0); - CRC.update(makeArrayRef(IS.Content->getBufferStart(), - IS.Content->getBufferSize())); + CRC.update(arrayRefFromStringRef(IS.Content->getBuffer())); SrcHeaderBlockEntry Entry; ::memset(&Entry, 0, sizeof(SrcHeaderBlockEntry)); diff --git a/lib/DebugInfo/PDB/Native/TpiHashing.cpp b/lib/DebugInfo/PDB/Native/TpiHashing.cpp index b21b82bf76fd..b71b2b158144 100644 --- a/lib/DebugInfo/PDB/Native/TpiHashing.cpp +++ b/lib/DebugInfo/PDB/Native/TpiHashing.cpp @@ -10,7 +10,7 @@ #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" #include "llvm/DebugInfo/PDB/Native/Hash.h" -#include "llvm/Support/JamCRC.h" +#include "llvm/Support/CRC.h" using namespace llvm; using namespace llvm::codeview; @@ -124,8 +124,6 @@ Expected<uint32_t> llvm::pdb::hashTypeRecord(const CVType &Rec) { // Run CRC32 over the bytes. This corresponds to `hashBufv8`. JamCRC JC(/*Init=*/0U); - ArrayRef<char> Bytes(reinterpret_cast<const char *>(Rec.data().data()), - Rec.data().size()); - JC.update(Bytes); + JC.update(Rec.data()); return JC.getCRC(); } diff --git a/lib/DebugInfo/PDB/Native/TpiStream.cpp b/lib/DebugInfo/PDB/Native/TpiStream.cpp index 8ee7f897b8bb..ac19db03fab2 100644 --- a/lib/DebugInfo/PDB/Native/TpiStream.cpp +++ b/lib/DebugInfo/PDB/Native/TpiStream.cpp @@ -112,7 +112,7 @@ Error TpiStream::reload() { HashStream = std::move(*HS); } - Types = llvm::make_unique<LazyRandomTypeCollection>( + Types = std::make_unique<LazyRandomTypeCollection>( TypeRecords, getNumTypeRecords(), getTypeIndexOffsets()); return Error::success(); } diff --git a/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp b/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp index 6b308453c2de..4f10f8524a9b 100644 --- a/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp +++ b/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp @@ -135,7 +135,7 @@ Error TpiStreamBuilder::finalizeMsfLayout() { reinterpret_cast<const uint8_t *>(HashBuffer.data()), calculateHashBufferSize()); HashValueStream = - llvm::make_unique<BinaryByteStream>(Bytes, llvm::support::little); + std::make_unique<BinaryByteStream>(Bytes, llvm::support::little); } return Error::success(); } diff --git a/lib/DebugInfo/PDB/PDBSymbolFunc.cpp b/lib/DebugInfo/PDB/PDBSymbolFunc.cpp index 7c3ba981fd6b..cb0329bc0ed7 100644 --- a/lib/DebugInfo/PDB/PDBSymbolFunc.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolFunc.cpp @@ -79,7 +79,7 @@ private: std::unique_ptr<IPDBEnumChildren<PDBSymbolData>> PDBSymbolFunc::getArguments() const { - return llvm::make_unique<FunctionArgEnumerator>(Session, *this); + return std::make_unique<FunctionArgEnumerator>(Session, *this); } void PDBSymbolFunc::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp index 292320a6fe6d..1373615522eb 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp @@ -63,7 +63,7 @@ private: std::unique_ptr<IPDBEnumSymbols> PDBSymbolTypeFunctionSig::getArguments() const { - return llvm::make_unique<FunctionArgEnumerator>(Session, *this); + return std::make_unique<FunctionArgEnumerator>(Session, *this); } void PDBSymbolTypeFunctionSig::dump(PDBSymDumper &Dumper) const { diff --git a/lib/DebugInfo/PDB/UDTLayout.cpp b/lib/DebugInfo/PDB/UDTLayout.cpp index acb1599480b0..a8e1d0a619ca 100644 --- a/lib/DebugInfo/PDB/UDTLayout.cpp +++ b/lib/DebugInfo/PDB/UDTLayout.cpp @@ -71,7 +71,7 @@ DataMemberLayoutItem::DataMemberLayoutItem( DataMember(std::move(Member)) { auto Type = DataMember->getType(); if (auto UDT = unique_dyn_cast<PDBSymbolTypeUDT>(Type)) { - UdtLayout = llvm::make_unique<ClassLayout>(std::move(UDT)); + UdtLayout = std::make_unique<ClassLayout>(std::move(UDT)); UsedBytes = UdtLayout->usedBytes(); } } @@ -84,7 +84,7 @@ VBPtrLayoutItem::VBPtrLayoutItem(const UDTLayoutBase &Parent, } const PDBSymbolData &DataMemberLayoutItem::getDataMember() { - return *dyn_cast<PDBSymbolData>(Symbol); + return *cast<PDBSymbolData>(Symbol); } bool DataMemberLayoutItem::hasUDTLayout() const { return UdtLayout != nullptr; } @@ -205,7 +205,7 @@ void UDTLayoutBase::initializeChildren(const PDBSymbol &Sym) { for (auto &Base : Bases) { uint32_t Offset = Base->getOffset(); // Non-virtual bases never get elided. - auto BL = llvm::make_unique<BaseClassLayout>(*this, Offset, false, + auto BL = std::make_unique<BaseClassLayout>(*this, Offset, false, std::move(Base)); AllBases.push_back(BL.get()); @@ -216,7 +216,7 @@ void UDTLayoutBase::initializeChildren(const PDBSymbol &Sym) { assert(VTables.size() <= 1); if (!VTables.empty()) { auto VTLayout = - llvm::make_unique<VTableLayoutItem>(*this, std::move(VTables[0])); + std::make_unique<VTableLayoutItem>(*this, std::move(VTables[0])); VTable = VTLayout.get(); @@ -224,7 +224,7 @@ void UDTLayoutBase::initializeChildren(const PDBSymbol &Sym) { } for (auto &Data : Members) { - auto DM = llvm::make_unique<DataMemberLayoutItem>(*this, std::move(Data)); + auto DM = std::make_unique<DataMemberLayoutItem>(*this, std::move(Data)); addChildToLayout(std::move(DM)); } @@ -236,7 +236,7 @@ void UDTLayoutBase::initializeChildren(const PDBSymbol &Sym) { int VBPO = VB->getVirtualBasePointerOffset(); if (!hasVBPtrAtOffset(VBPO)) { if (auto VBP = VB->getRawSymbol().getVirtualBaseTableType()) { - auto VBPL = llvm::make_unique<VBPtrLayoutItem>(*this, std::move(VBP), + auto VBPL = std::make_unique<VBPtrLayoutItem>(*this, std::move(VBP), VBPO, VBP->getLength()); VBPtr = VBPL.get(); addChildToLayout(std::move(VBPL)); @@ -250,7 +250,7 @@ void UDTLayoutBase::initializeChildren(const PDBSymbol &Sym) { uint32_t Offset = UsedBytes.find_last() + 1; bool Elide = (Parent != nullptr); auto BL = - llvm::make_unique<BaseClassLayout>(*this, Offset, Elide, std::move(VB)); + std::make_unique<BaseClassLayout>(*this, Offset, Elide, std::move(VB)); AllBases.push_back(BL.get()); // Only lay this virtual base out directly inside of *this* class if this diff --git a/lib/DebugInfo/Symbolize/DIPrinter.cpp b/lib/DebugInfo/Symbolize/DIPrinter.cpp index b2bfef251485..b1a80cbc4580 100644 --- a/lib/DebugInfo/Symbolize/DIPrinter.cpp +++ b/lib/DebugInfo/Symbolize/DIPrinter.cpp @@ -30,11 +30,6 @@ namespace llvm { namespace symbolize { -// By default, DILineInfo contains "<invalid>" for function/filename it -// cannot fetch. We replace it to "??" to make our output closer to addr2line. -static const char kDILineInfoBadString[] = "<invalid>"; -static const char kBadString[] = "??"; - // Prints source code around in the FileName the Line. void DIPrinter::printContext(const std::string &FileName, int64_t Line) { if (PrintSourceContext <= 0) @@ -68,16 +63,16 @@ void DIPrinter::printContext(const std::string &FileName, int64_t Line) { void DIPrinter::print(const DILineInfo &Info, bool Inlined) { if (PrintFunctionNames) { std::string FunctionName = Info.FunctionName; - if (FunctionName == kDILineInfoBadString) - FunctionName = kBadString; + if (FunctionName == DILineInfo::BadString) + FunctionName = DILineInfo::Addr2LineBadString; StringRef Delimiter = PrintPretty ? " at " : "\n"; StringRef Prefix = (PrintPretty && Inlined) ? " (inlined by) " : ""; OS << Prefix << FunctionName << Delimiter; } std::string Filename = Info.FileName; - if (Filename == kDILineInfoBadString) - Filename = kBadString; + if (Filename == DILineInfo::BadString) + Filename = DILineInfo::Addr2LineBadString; else if (Basenames) Filename = llvm::sys::path::filename(Filename); if (!Verbose) { @@ -115,8 +110,8 @@ DIPrinter &DIPrinter::operator<<(const DIInliningInfo &Info) { DIPrinter &DIPrinter::operator<<(const DIGlobal &Global) { std::string Name = Global.Name; - if (Name == kDILineInfoBadString) - Name = kBadString; + if (Name == DILineInfo::BadString) + Name = DILineInfo::Addr2LineBadString; OS << Name << "\n"; OS << Global.Start << " " << Global.Size << "\n"; return *this; diff --git a/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp b/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp index 2765bf44d504..b4d49d9ff958 100644 --- a/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp +++ b/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp @@ -43,20 +43,22 @@ getDILineInfoSpecifier(FunctionNameKind FNKind) { ErrorOr<std::unique_ptr<SymbolizableObjectFile>> SymbolizableObjectFile::create(const object::ObjectFile *Obj, - std::unique_ptr<DIContext> DICtx) { + std::unique_ptr<DIContext> DICtx, + bool UntagAddresses) { assert(DICtx); std::unique_ptr<SymbolizableObjectFile> res( - new SymbolizableObjectFile(Obj, std::move(DICtx))); + new SymbolizableObjectFile(Obj, std::move(DICtx), UntagAddresses)); std::unique_ptr<DataExtractor> OpdExtractor; uint64_t OpdAddress = 0; // Find the .opd (function descriptor) section if any, for big-endian // PowerPC64 ELF. if (Obj->getArch() == Triple::ppc64) { for (section_iterator Section : Obj->sections()) { - StringRef Name; - if (auto EC = Section->getName(Name)) - return EC; - if (Name == ".opd") { + Expected<StringRef> NameOrErr = Section->getName(); + if (!NameOrErr) + return errorToErrorCode(NameOrErr.takeError()); + + if (*NameOrErr == ".opd") { Expected<StringRef> E = Section->getContents(); if (!E) return errorToErrorCode(E.takeError()); @@ -103,8 +105,10 @@ SymbolizableObjectFile::create(const object::ObjectFile *Obj, } SymbolizableObjectFile::SymbolizableObjectFile(const ObjectFile *Obj, - std::unique_ptr<DIContext> DICtx) - : Module(Obj), DebugInfoContext(std::move(DICtx)) {} + std::unique_ptr<DIContext> DICtx, + bool UntagAddresses) + : Module(Obj), DebugInfoContext(std::move(DICtx)), + UntagAddresses(UntagAddresses) {} namespace { @@ -172,6 +176,12 @@ std::error_code SymbolizableObjectFile::addSymbol(const SymbolRef &Symbol, if (!SymbolAddressOrErr) return errorToErrorCode(SymbolAddressOrErr.takeError()); uint64_t SymbolAddress = *SymbolAddressOrErr; + if (UntagAddresses) { + // For kernel addresses, bits 56-63 need to be set, so we sign extend bit 55 + // into bits 56-63 instead of masking them out. + SymbolAddress &= (1ull << 56) - 1; + SymbolAddress = (int64_t(SymbolAddress) << 8) >> 8; + } if (OpdExtractor) { // For big-endian PowerPC64 ELF, symbols in the .opd section refer to // function descriptors. The first word of the descriptor is a pointer to @@ -179,10 +189,8 @@ std::error_code SymbolizableObjectFile::addSymbol(const SymbolRef &Symbol, // For the purposes of symbolization, pretend the symbol's address is that // of the function's code, not the descriptor. uint64_t OpdOffset = SymbolAddress - OpdAddress; - uint32_t OpdOffset32 = OpdOffset; - if (OpdOffset == OpdOffset32 && - OpdExtractor->isValidOffsetForAddress(OpdOffset32)) - SymbolAddress = OpdExtractor->getAddress(&OpdOffset32); + if (OpdExtractor->isValidOffsetForAddress(OpdOffset)) + SymbolAddress = OpdExtractor->getAddress(&OpdOffset); } Expected<StringRef> SymbolNameOrErr = Symbol.getName(); if (!SymbolNameOrErr) diff --git a/lib/DebugInfo/Symbolize/SymbolizableObjectFile.h b/lib/DebugInfo/Symbolize/SymbolizableObjectFile.h index 9cab94178c1b..b5b9793a44d9 100644 --- a/lib/DebugInfo/Symbolize/SymbolizableObjectFile.h +++ b/lib/DebugInfo/Symbolize/SymbolizableObjectFile.h @@ -31,7 +31,8 @@ namespace symbolize { class SymbolizableObjectFile : public SymbolizableModule { public: static ErrorOr<std::unique_ptr<SymbolizableObjectFile>> - create(const object::ObjectFile *Obj, std::unique_ptr<DIContext> DICtx); + create(const object::ObjectFile *Obj, std::unique_ptr<DIContext> DICtx, + bool UntagAddresses); DILineInfo symbolizeCode(object::SectionedAddress ModuleOffset, FunctionNameKind FNKind, @@ -70,6 +71,7 @@ private: const object::ObjectFile *Module; std::unique_ptr<DIContext> DebugInfoContext; + bool UntagAddresses; struct SymbolDesc { uint64_t Addr; @@ -85,7 +87,8 @@ private: std::vector<std::pair<SymbolDesc, StringRef>> Objects; SymbolizableObjectFile(const object::ObjectFile *Obj, - std::unique_ptr<DIContext> DICtx); + std::unique_ptr<DIContext> DICtx, + bool UntagAddresses); }; } // end namespace symbolize diff --git a/lib/DebugInfo/Symbolize/Symbolize.cpp b/lib/DebugInfo/Symbolize/Symbolize.cpp index 6a619f8f2f37..be79d9e637c1 100644 --- a/lib/DebugInfo/Symbolize/Symbolize.cpp +++ b/lib/DebugInfo/Symbolize/Symbolize.cpp @@ -35,19 +35,6 @@ #include <cassert> #include <cstring> -#if defined(_MSC_VER) -#include <Windows.h> - -// This must be included after windows.h. -#include <DbgHelp.h> -#pragma comment(lib, "dbghelp.lib") - -// Windows.h conflicts with our COFF header definitions. -#ifdef IMAGE_FILE_MACHINE_I386 -#undef IMAGE_FILE_MACHINE_I386 -#endif -#endif - namespace llvm { namespace symbolize { @@ -205,7 +192,7 @@ bool checkFileCRC(StringRef Path, uint32_t CRCHash) { MemoryBuffer::getFileOrSTDIN(Path); if (!MB) return false; - return CRCHash == llvm::crc32(0, MB.get()->getBuffer()); + return CRCHash == llvm::crc32(arrayRefFromStringRef(MB.get()->getBuffer())); } bool findDebugBinary(const std::string &OrigPath, @@ -259,7 +246,11 @@ bool getGNUDebuglinkContents(const ObjectFile *Obj, std::string &DebugName, return false; for (const SectionRef &Section : Obj->sections()) { StringRef Name; - Section.getName(Name); + if (Expected<StringRef> NameOrErr = Section.getName()) + Name = *NameOrErr; + else + consumeError(NameOrErr.takeError()); + Name = Name.substr(Name.find_first_not_of("._")); if (Name == "gnu_debuglink") { Expected<StringRef> ContentsOrErr = Section.getContents(); @@ -268,7 +259,7 @@ bool getGNUDebuglinkContents(const ObjectFile *Obj, std::string &DebugName, return false; } DataExtractor DE(*ContentsOrErr, Obj->isLittleEndian(), 0); - uint32_t Offset = 0; + uint64_t Offset = 0; if (const char *DebugNameStr = DE.getCStr(&Offset)) { // 4-byte align the offset. Offset = (Offset + 3) & ~0x3; @@ -397,7 +388,7 @@ LLVMSymbolizer::getOrCreateObject(const std::string &Path, return I->second.get(); Expected<std::unique_ptr<ObjectFile>> ObjOrErr = - UB->getObjectForArch(ArchName); + UB->getMachOObjectForArch(ArchName); if (!ObjOrErr) { ObjectForUBPathAndArch.emplace(std::make_pair(Path, ArchName), std::unique_ptr<ObjectFile>()); @@ -418,8 +409,8 @@ Expected<SymbolizableModule *> LLVMSymbolizer::createModuleInfo(const ObjectFile *Obj, std::unique_ptr<DIContext> Context, StringRef ModuleName) { - auto InfoOrErr = - SymbolizableObjectFile::create(Obj, std::move(Context)); + auto InfoOrErr = SymbolizableObjectFile::create(Obj, std::move(Context), + Opts.UntagAddresses); std::unique_ptr<SymbolizableModule> SymMod; if (InfoOrErr) SymMod = std::move(*InfoOrErr); @@ -530,21 +521,20 @@ LLVMSymbolizer::DemangleName(const std::string &Name, return Result; } -#if defined(_MSC_VER) if (!Name.empty() && Name.front() == '?') { // Only do MSVC C++ demangling on symbols starting with '?'. - char DemangledName[1024] = {0}; - DWORD result = ::UnDecorateSymbolName( - Name.c_str(), DemangledName, 1023, - UNDNAME_NO_ACCESS_SPECIFIERS | // Strip public, private, protected - UNDNAME_NO_ALLOCATION_LANGUAGE | // Strip __thiscall, __stdcall, etc - UNDNAME_NO_THROW_SIGNATURES | // Strip throw() specifications - UNDNAME_NO_MEMBER_TYPE | // Strip virtual, static, etc specifiers - UNDNAME_NO_MS_KEYWORDS | // Strip all MS extension keywords - UNDNAME_NO_FUNCTION_RETURNS); // Strip function return types - return (result == 0) ? Name : std::string(DemangledName); + int status = 0; + char *DemangledName = microsoftDemangle( + Name.c_str(), nullptr, nullptr, &status, + MSDemangleFlags(MSDF_NoAccessSpecifier | MSDF_NoCallingConvention | + MSDF_NoMemberType | MSDF_NoReturnType)); + if (status != 0) + return Name; + std::string Result = DemangledName; + free(DemangledName); + return Result; } -#endif + if (DbiModuleDescriptor && DbiModuleDescriptor->isWin32Module()) return std::string(demanglePE32ExternCFunc(Name)); return Name; |