10b57cec5SDimitry Andric //===- TypeIndexDiscovery.cpp -----------------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
9e8d8bef9SDimitry Andric #include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
10e8d8bef9SDimitry Andric #include "llvm/DebugInfo/CodeView/TypeRecord.h"
110b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
120b57cec5SDimitry Andric #include "llvm/Support/Endian.h"
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric using namespace llvm;
150b57cec5SDimitry Andric using namespace llvm::codeview;
160b57cec5SDimitry Andric
getMethodKind(uint16_t Attrs)170b57cec5SDimitry Andric static inline MethodKind getMethodKind(uint16_t Attrs) {
180b57cec5SDimitry Andric Attrs &= uint16_t(MethodOptions::MethodKindMask);
190b57cec5SDimitry Andric Attrs >>= 2;
200b57cec5SDimitry Andric return MethodKind(Attrs);
210b57cec5SDimitry Andric }
220b57cec5SDimitry Andric
isIntroVirtual(uint16_t Attrs)230b57cec5SDimitry Andric static inline bool isIntroVirtual(uint16_t Attrs) {
240b57cec5SDimitry Andric MethodKind MK = getMethodKind(Attrs);
250b57cec5SDimitry Andric return MK == MethodKind::IntroducingVirtual ||
260b57cec5SDimitry Andric MK == MethodKind::PureIntroducingVirtual;
270b57cec5SDimitry Andric }
280b57cec5SDimitry Andric
getPointerMode(uint32_t Attrs)290b57cec5SDimitry Andric static inline PointerMode getPointerMode(uint32_t Attrs) {
300b57cec5SDimitry Andric return static_cast<PointerMode>((Attrs >> PointerRecord::PointerModeShift) &
310b57cec5SDimitry Andric PointerRecord::PointerModeMask);
320b57cec5SDimitry Andric }
330b57cec5SDimitry Andric
isMemberPointer(uint32_t Attrs)340b57cec5SDimitry Andric static inline bool isMemberPointer(uint32_t Attrs) {
350b57cec5SDimitry Andric PointerMode Mode = getPointerMode(Attrs);
360b57cec5SDimitry Andric return Mode == PointerMode::PointerToDataMember ||
370b57cec5SDimitry Andric Mode == PointerMode::PointerToMemberFunction;
380b57cec5SDimitry Andric }
390b57cec5SDimitry Andric
getEncodedIntegerLength(ArrayRef<uint8_t> Data)400b57cec5SDimitry Andric static inline uint32_t getEncodedIntegerLength(ArrayRef<uint8_t> Data) {
410b57cec5SDimitry Andric uint16_t N = support::endian::read16le(Data.data());
420b57cec5SDimitry Andric if (N < LF_NUMERIC)
430b57cec5SDimitry Andric return 2;
440b57cec5SDimitry Andric
450b57cec5SDimitry Andric assert(N <= LF_UQUADWORD);
460b57cec5SDimitry Andric
470b57cec5SDimitry Andric constexpr uint32_t Sizes[] = {
480b57cec5SDimitry Andric 1, // LF_CHAR
490b57cec5SDimitry Andric 2, // LF_SHORT
500b57cec5SDimitry Andric 2, // LF_USHORT
510b57cec5SDimitry Andric 4, // LF_LONG
520b57cec5SDimitry Andric 4, // LF_ULONG
530b57cec5SDimitry Andric 4, // LF_REAL32
540b57cec5SDimitry Andric 8, // LF_REAL64
550b57cec5SDimitry Andric 10, // LF_REAL80
560b57cec5SDimitry Andric 16, // LF_REAL128
570b57cec5SDimitry Andric 8, // LF_QUADWORD
580b57cec5SDimitry Andric 8, // LF_UQUADWORD
590b57cec5SDimitry Andric };
600b57cec5SDimitry Andric
610b57cec5SDimitry Andric return 2 + Sizes[N - LF_NUMERIC];
620b57cec5SDimitry Andric }
630b57cec5SDimitry Andric
getCStringLength(ArrayRef<uint8_t> Data)640b57cec5SDimitry Andric static inline uint32_t getCStringLength(ArrayRef<uint8_t> Data) {
650b57cec5SDimitry Andric const char *S = reinterpret_cast<const char *>(Data.data());
660b57cec5SDimitry Andric return strlen(S) + 1;
670b57cec5SDimitry Andric }
680b57cec5SDimitry Andric
handleMethodOverloadList(ArrayRef<uint8_t> Content,SmallVectorImpl<TiReference> & Refs)690b57cec5SDimitry Andric static void handleMethodOverloadList(ArrayRef<uint8_t> Content,
700b57cec5SDimitry Andric SmallVectorImpl<TiReference> &Refs) {
710b57cec5SDimitry Andric uint32_t Offset = 0;
720b57cec5SDimitry Andric
730b57cec5SDimitry Andric while (!Content.empty()) {
740b57cec5SDimitry Andric // Array of:
750b57cec5SDimitry Andric // 0: Attrs
760b57cec5SDimitry Andric // 2: Padding
770b57cec5SDimitry Andric // 4: TypeIndex
780b57cec5SDimitry Andric // if (isIntroVirtual())
790b57cec5SDimitry Andric // 8: VFTableOffset
800b57cec5SDimitry Andric
810b57cec5SDimitry Andric // At least 8 bytes are guaranteed. 4 extra bytes come iff function is an
820b57cec5SDimitry Andric // intro virtual.
830b57cec5SDimitry Andric uint32_t Len = 8;
840b57cec5SDimitry Andric
850b57cec5SDimitry Andric uint16_t Attrs = support::endian::read16le(Content.data());
860b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
870b57cec5SDimitry Andric
880b57cec5SDimitry Andric if (LLVM_UNLIKELY(isIntroVirtual(Attrs)))
890b57cec5SDimitry Andric Len += 4;
900b57cec5SDimitry Andric Offset += Len;
910b57cec5SDimitry Andric Content = Content.drop_front(Len);
920b57cec5SDimitry Andric }
930b57cec5SDimitry Andric }
940b57cec5SDimitry Andric
handleBaseClass(ArrayRef<uint8_t> Data,uint32_t Offset,SmallVectorImpl<TiReference> & Refs)950b57cec5SDimitry Andric static uint32_t handleBaseClass(ArrayRef<uint8_t> Data, uint32_t Offset,
960b57cec5SDimitry Andric SmallVectorImpl<TiReference> &Refs) {
970b57cec5SDimitry Andric // 0: Kind
980b57cec5SDimitry Andric // 2: Padding
990b57cec5SDimitry Andric // 4: TypeIndex
1000b57cec5SDimitry Andric // 8: Encoded Integer
1010b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
1020b57cec5SDimitry Andric return 8 + getEncodedIntegerLength(Data.drop_front(8));
1030b57cec5SDimitry Andric }
1040b57cec5SDimitry Andric
handleEnumerator(ArrayRef<uint8_t> Data,uint32_t Offset,SmallVectorImpl<TiReference> & Refs)1050b57cec5SDimitry Andric static uint32_t handleEnumerator(ArrayRef<uint8_t> Data, uint32_t Offset,
1060b57cec5SDimitry Andric SmallVectorImpl<TiReference> &Refs) {
1070b57cec5SDimitry Andric // 0: Kind
1080b57cec5SDimitry Andric // 2: Padding
1090b57cec5SDimitry Andric // 4: Encoded Integer
1100b57cec5SDimitry Andric // <next>: Name
1110b57cec5SDimitry Andric uint32_t Size = 4 + getEncodedIntegerLength(Data.drop_front(4));
1120b57cec5SDimitry Andric return Size + getCStringLength(Data.drop_front(Size));
1130b57cec5SDimitry Andric }
1140b57cec5SDimitry Andric
handleDataMember(ArrayRef<uint8_t> Data,uint32_t Offset,SmallVectorImpl<TiReference> & Refs)1150b57cec5SDimitry Andric static uint32_t handleDataMember(ArrayRef<uint8_t> Data, uint32_t Offset,
1160b57cec5SDimitry Andric SmallVectorImpl<TiReference> &Refs) {
1170b57cec5SDimitry Andric // 0: Kind
1180b57cec5SDimitry Andric // 2: Padding
1190b57cec5SDimitry Andric // 4: TypeIndex
1200b57cec5SDimitry Andric // 8: Encoded Integer
1210b57cec5SDimitry Andric // <next>: Name
1220b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
1230b57cec5SDimitry Andric uint32_t Size = 8 + getEncodedIntegerLength(Data.drop_front(8));
1240b57cec5SDimitry Andric return Size + getCStringLength(Data.drop_front(Size));
1250b57cec5SDimitry Andric }
1260b57cec5SDimitry Andric
handleOverloadedMethod(ArrayRef<uint8_t> Data,uint32_t Offset,SmallVectorImpl<TiReference> & Refs)1270b57cec5SDimitry Andric static uint32_t handleOverloadedMethod(ArrayRef<uint8_t> Data, uint32_t Offset,
1280b57cec5SDimitry Andric SmallVectorImpl<TiReference> &Refs) {
1290b57cec5SDimitry Andric // 0: Kind
1300b57cec5SDimitry Andric // 2: Padding
1310b57cec5SDimitry Andric // 4: TypeIndex
1320b57cec5SDimitry Andric // 8: Name
1330b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
1340b57cec5SDimitry Andric return 8 + getCStringLength(Data.drop_front(8));
1350b57cec5SDimitry Andric }
1360b57cec5SDimitry Andric
handleOneMethod(ArrayRef<uint8_t> Data,uint32_t Offset,SmallVectorImpl<TiReference> & Refs)1370b57cec5SDimitry Andric static uint32_t handleOneMethod(ArrayRef<uint8_t> Data, uint32_t Offset,
1380b57cec5SDimitry Andric SmallVectorImpl<TiReference> &Refs) {
1390b57cec5SDimitry Andric // 0: Kind
1400b57cec5SDimitry Andric // 2: Attributes
1410b57cec5SDimitry Andric // 4: Type
1420b57cec5SDimitry Andric // if (isIntroVirtual)
1430b57cec5SDimitry Andric // 8: VFTableOffset
1440b57cec5SDimitry Andric // <next>: Name
1450b57cec5SDimitry Andric uint32_t Size = 8;
1460b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
1470b57cec5SDimitry Andric
1480b57cec5SDimitry Andric uint16_t Attrs = support::endian::read16le(Data.drop_front(2).data());
1490b57cec5SDimitry Andric if (LLVM_UNLIKELY(isIntroVirtual(Attrs)))
1500b57cec5SDimitry Andric Size += 4;
1510b57cec5SDimitry Andric
1520b57cec5SDimitry Andric return Size + getCStringLength(Data.drop_front(Size));
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric
handleNestedType(ArrayRef<uint8_t> Data,uint32_t Offset,SmallVectorImpl<TiReference> & Refs)1550b57cec5SDimitry Andric static uint32_t handleNestedType(ArrayRef<uint8_t> Data, uint32_t Offset,
1560b57cec5SDimitry Andric SmallVectorImpl<TiReference> &Refs) {
1570b57cec5SDimitry Andric // 0: Kind
1580b57cec5SDimitry Andric // 2: Padding
1590b57cec5SDimitry Andric // 4: TypeIndex
1600b57cec5SDimitry Andric // 8: Name
1610b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
1620b57cec5SDimitry Andric return 8 + getCStringLength(Data.drop_front(8));
1630b57cec5SDimitry Andric }
1640b57cec5SDimitry Andric
handleStaticDataMember(ArrayRef<uint8_t> Data,uint32_t Offset,SmallVectorImpl<TiReference> & Refs)1650b57cec5SDimitry Andric static uint32_t handleStaticDataMember(ArrayRef<uint8_t> Data, uint32_t Offset,
1660b57cec5SDimitry Andric SmallVectorImpl<TiReference> &Refs) {
1670b57cec5SDimitry Andric // 0: Kind
1680b57cec5SDimitry Andric // 2: Padding
1690b57cec5SDimitry Andric // 4: TypeIndex
1700b57cec5SDimitry Andric // 8: Name
1710b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
1720b57cec5SDimitry Andric return 8 + getCStringLength(Data.drop_front(8));
1730b57cec5SDimitry Andric }
1740b57cec5SDimitry Andric
handleVirtualBaseClass(ArrayRef<uint8_t> Data,uint32_t Offset,bool IsIndirect,SmallVectorImpl<TiReference> & Refs)1750b57cec5SDimitry Andric static uint32_t handleVirtualBaseClass(ArrayRef<uint8_t> Data, uint32_t Offset,
1760b57cec5SDimitry Andric bool IsIndirect,
1770b57cec5SDimitry Andric SmallVectorImpl<TiReference> &Refs) {
1780b57cec5SDimitry Andric // 0: Kind
1790b57cec5SDimitry Andric // 2: Attrs
1800b57cec5SDimitry Andric // 4: TypeIndex
1810b57cec5SDimitry Andric // 8: TypeIndex
1820b57cec5SDimitry Andric // 12: Encoded Integer
1830b57cec5SDimitry Andric // <next>: Encoded Integer
1840b57cec5SDimitry Andric uint32_t Size = 12;
1850b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, Offset + 4, 2});
1860b57cec5SDimitry Andric Size += getEncodedIntegerLength(Data.drop_front(Size));
1870b57cec5SDimitry Andric Size += getEncodedIntegerLength(Data.drop_front(Size));
1880b57cec5SDimitry Andric return Size;
1890b57cec5SDimitry Andric }
1900b57cec5SDimitry Andric
handleVFPtr(ArrayRef<uint8_t> Data,uint32_t Offset,SmallVectorImpl<TiReference> & Refs)1910b57cec5SDimitry Andric static uint32_t handleVFPtr(ArrayRef<uint8_t> Data, uint32_t Offset,
1920b57cec5SDimitry Andric SmallVectorImpl<TiReference> &Refs) {
1930b57cec5SDimitry Andric // 0: Kind
1940b57cec5SDimitry Andric // 2: Padding
1950b57cec5SDimitry Andric // 4: TypeIndex
1960b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
1970b57cec5SDimitry Andric return 8;
1980b57cec5SDimitry Andric }
1990b57cec5SDimitry Andric
handleListContinuation(ArrayRef<uint8_t> Data,uint32_t Offset,SmallVectorImpl<TiReference> & Refs)2000b57cec5SDimitry Andric static uint32_t handleListContinuation(ArrayRef<uint8_t> Data, uint32_t Offset,
2010b57cec5SDimitry Andric SmallVectorImpl<TiReference> &Refs) {
2020b57cec5SDimitry Andric // 0: Kind
2030b57cec5SDimitry Andric // 2: Padding
2040b57cec5SDimitry Andric // 4: TypeIndex
2050b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
2060b57cec5SDimitry Andric return 8;
2070b57cec5SDimitry Andric }
2080b57cec5SDimitry Andric
handleFieldList(ArrayRef<uint8_t> Content,SmallVectorImpl<TiReference> & Refs)2090b57cec5SDimitry Andric static void handleFieldList(ArrayRef<uint8_t> Content,
2100b57cec5SDimitry Andric SmallVectorImpl<TiReference> &Refs) {
2110b57cec5SDimitry Andric uint32_t Offset = 0;
2120b57cec5SDimitry Andric uint32_t ThisLen = 0;
2130b57cec5SDimitry Andric while (!Content.empty()) {
2140b57cec5SDimitry Andric TypeLeafKind Kind =
2150b57cec5SDimitry Andric static_cast<TypeLeafKind>(support::endian::read16le(Content.data()));
2160b57cec5SDimitry Andric switch (Kind) {
2170b57cec5SDimitry Andric case LF_BCLASS:
2180b57cec5SDimitry Andric ThisLen = handleBaseClass(Content, Offset, Refs);
2190b57cec5SDimitry Andric break;
2200b57cec5SDimitry Andric case LF_ENUMERATE:
2210b57cec5SDimitry Andric ThisLen = handleEnumerator(Content, Offset, Refs);
2220b57cec5SDimitry Andric break;
2230b57cec5SDimitry Andric case LF_MEMBER:
2240b57cec5SDimitry Andric ThisLen = handleDataMember(Content, Offset, Refs);
2250b57cec5SDimitry Andric break;
2260b57cec5SDimitry Andric case LF_METHOD:
2270b57cec5SDimitry Andric ThisLen = handleOverloadedMethod(Content, Offset, Refs);
2280b57cec5SDimitry Andric break;
2290b57cec5SDimitry Andric case LF_ONEMETHOD:
2300b57cec5SDimitry Andric ThisLen = handleOneMethod(Content, Offset, Refs);
2310b57cec5SDimitry Andric break;
2320b57cec5SDimitry Andric case LF_NESTTYPE:
2330b57cec5SDimitry Andric ThisLen = handleNestedType(Content, Offset, Refs);
2340b57cec5SDimitry Andric break;
2350b57cec5SDimitry Andric case LF_STMEMBER:
2360b57cec5SDimitry Andric ThisLen = handleStaticDataMember(Content, Offset, Refs);
2370b57cec5SDimitry Andric break;
2380b57cec5SDimitry Andric case LF_VBCLASS:
2390b57cec5SDimitry Andric case LF_IVBCLASS:
2400b57cec5SDimitry Andric ThisLen =
2410b57cec5SDimitry Andric handleVirtualBaseClass(Content, Offset, Kind == LF_VBCLASS, Refs);
2420b57cec5SDimitry Andric break;
2430b57cec5SDimitry Andric case LF_VFUNCTAB:
2440b57cec5SDimitry Andric ThisLen = handleVFPtr(Content, Offset, Refs);
2450b57cec5SDimitry Andric break;
2460b57cec5SDimitry Andric case LF_INDEX:
2470b57cec5SDimitry Andric ThisLen = handleListContinuation(Content, Offset, Refs);
2480b57cec5SDimitry Andric break;
2490b57cec5SDimitry Andric default:
2500b57cec5SDimitry Andric return;
2510b57cec5SDimitry Andric }
2520b57cec5SDimitry Andric Content = Content.drop_front(ThisLen);
2530b57cec5SDimitry Andric Offset += ThisLen;
2540b57cec5SDimitry Andric if (!Content.empty()) {
2550b57cec5SDimitry Andric uint8_t Pad = Content.front();
2560b57cec5SDimitry Andric if (Pad >= LF_PAD0) {
2570b57cec5SDimitry Andric uint32_t Skip = Pad & 0x0F;
2580b57cec5SDimitry Andric Content = Content.drop_front(Skip);
2590b57cec5SDimitry Andric Offset += Skip;
2600b57cec5SDimitry Andric }
2610b57cec5SDimitry Andric }
2620b57cec5SDimitry Andric }
2630b57cec5SDimitry Andric }
2640b57cec5SDimitry Andric
handlePointer(ArrayRef<uint8_t> Content,SmallVectorImpl<TiReference> & Refs)2650b57cec5SDimitry Andric static void handlePointer(ArrayRef<uint8_t> Content,
2660b57cec5SDimitry Andric SmallVectorImpl<TiReference> &Refs) {
2670b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, 0, 1});
2680b57cec5SDimitry Andric
2690b57cec5SDimitry Andric uint32_t Attrs = support::endian::read32le(Content.drop_front(4).data());
2700b57cec5SDimitry Andric if (isMemberPointer(Attrs))
2710b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, 8, 1});
2720b57cec5SDimitry Andric }
2730b57cec5SDimitry Andric
discoverTypeIndices(ArrayRef<uint8_t> Content,TypeLeafKind Kind,SmallVectorImpl<TiReference> & Refs)2740b57cec5SDimitry Andric static void discoverTypeIndices(ArrayRef<uint8_t> Content, TypeLeafKind Kind,
2750b57cec5SDimitry Andric SmallVectorImpl<TiReference> &Refs) {
2760b57cec5SDimitry Andric uint32_t Count;
2770b57cec5SDimitry Andric // FIXME: In the future it would be nice if we could avoid hardcoding these
2780b57cec5SDimitry Andric // values. One idea is to define some structures representing these types
2790b57cec5SDimitry Andric // that would allow the use of offsetof().
2800b57cec5SDimitry Andric switch (Kind) {
2810b57cec5SDimitry Andric case TypeLeafKind::LF_FUNC_ID:
2820b57cec5SDimitry Andric Refs.push_back({TiRefKind::IndexRef, 0, 1});
2830b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, 4, 1});
2840b57cec5SDimitry Andric break;
2850b57cec5SDimitry Andric case TypeLeafKind::LF_MFUNC_ID:
2860b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, 0, 2});
2870b57cec5SDimitry Andric break;
2880b57cec5SDimitry Andric case TypeLeafKind::LF_STRING_ID:
2890b57cec5SDimitry Andric Refs.push_back({TiRefKind::IndexRef, 0, 1});
2900b57cec5SDimitry Andric break;
2910b57cec5SDimitry Andric case TypeLeafKind::LF_SUBSTR_LIST:
2920b57cec5SDimitry Andric Count = support::endian::read32le(Content.data());
2930b57cec5SDimitry Andric if (Count > 0)
2940b57cec5SDimitry Andric Refs.push_back({TiRefKind::IndexRef, 4, Count});
2950b57cec5SDimitry Andric break;
2960b57cec5SDimitry Andric case TypeLeafKind::LF_BUILDINFO:
2970b57cec5SDimitry Andric Count = support::endian::read16le(Content.data());
2980b57cec5SDimitry Andric if (Count > 0)
2990b57cec5SDimitry Andric Refs.push_back({TiRefKind::IndexRef, 2, Count});
3000b57cec5SDimitry Andric break;
3010b57cec5SDimitry Andric case TypeLeafKind::LF_UDT_SRC_LINE:
3020b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, 0, 1});
3030b57cec5SDimitry Andric Refs.push_back({TiRefKind::IndexRef, 4, 1});
3040b57cec5SDimitry Andric break;
3050b57cec5SDimitry Andric case TypeLeafKind::LF_UDT_MOD_SRC_LINE:
3060b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, 0, 1});
3070b57cec5SDimitry Andric break;
3080b57cec5SDimitry Andric case TypeLeafKind::LF_MODIFIER:
3090b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, 0, 1});
3100b57cec5SDimitry Andric break;
3110b57cec5SDimitry Andric case TypeLeafKind::LF_PROCEDURE:
3120b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, 0, 1});
3130b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, 8, 1});
3140b57cec5SDimitry Andric break;
3150b57cec5SDimitry Andric case TypeLeafKind::LF_MFUNCTION:
3160b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, 0, 3});
3170b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, 16, 1});
3180b57cec5SDimitry Andric break;
3190b57cec5SDimitry Andric case TypeLeafKind::LF_ARGLIST:
3200b57cec5SDimitry Andric Count = support::endian::read32le(Content.data());
3210b57cec5SDimitry Andric if (Count > 0)
3220b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, 4, Count});
3230b57cec5SDimitry Andric break;
3240b57cec5SDimitry Andric case TypeLeafKind::LF_ARRAY:
3250b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, 0, 2});
3260b57cec5SDimitry Andric break;
3270b57cec5SDimitry Andric case TypeLeafKind::LF_CLASS:
3280b57cec5SDimitry Andric case TypeLeafKind::LF_STRUCTURE:
3290b57cec5SDimitry Andric case TypeLeafKind::LF_INTERFACE:
3300b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, 4, 3});
3310b57cec5SDimitry Andric break;
3320b57cec5SDimitry Andric case TypeLeafKind::LF_UNION:
3330b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, 4, 1});
3340b57cec5SDimitry Andric break;
3350b57cec5SDimitry Andric case TypeLeafKind::LF_ENUM:
3360b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, 4, 2});
3370b57cec5SDimitry Andric break;
3380b57cec5SDimitry Andric case TypeLeafKind::LF_BITFIELD:
3390b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, 0, 1});
3400b57cec5SDimitry Andric break;
3410b57cec5SDimitry Andric case TypeLeafKind::LF_VFTABLE:
3420b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, 0, 2});
3430b57cec5SDimitry Andric break;
3440b57cec5SDimitry Andric case TypeLeafKind::LF_VTSHAPE:
3450b57cec5SDimitry Andric break;
3460b57cec5SDimitry Andric case TypeLeafKind::LF_METHODLIST:
3470b57cec5SDimitry Andric handleMethodOverloadList(Content, Refs);
3480b57cec5SDimitry Andric break;
3490b57cec5SDimitry Andric case TypeLeafKind::LF_FIELDLIST:
3500b57cec5SDimitry Andric handleFieldList(Content, Refs);
3510b57cec5SDimitry Andric break;
3520b57cec5SDimitry Andric case TypeLeafKind::LF_POINTER:
3530b57cec5SDimitry Andric handlePointer(Content, Refs);
3540b57cec5SDimitry Andric break;
3550b57cec5SDimitry Andric default:
3560b57cec5SDimitry Andric break;
3570b57cec5SDimitry Andric }
3580b57cec5SDimitry Andric }
3590b57cec5SDimitry Andric
discoverTypeIndices(ArrayRef<uint8_t> Content,SymbolKind Kind,SmallVectorImpl<TiReference> & Refs)3600b57cec5SDimitry Andric static bool discoverTypeIndices(ArrayRef<uint8_t> Content, SymbolKind Kind,
3610b57cec5SDimitry Andric SmallVectorImpl<TiReference> &Refs) {
3620b57cec5SDimitry Andric uint32_t Count;
3630b57cec5SDimitry Andric // FIXME: In the future it would be nice if we could avoid hardcoding these
3640b57cec5SDimitry Andric // values. One idea is to define some structures representing these types
3650b57cec5SDimitry Andric // that would allow the use of offsetof().
3660b57cec5SDimitry Andric switch (Kind) {
3670b57cec5SDimitry Andric case SymbolKind::S_GPROC32_ID:
3680b57cec5SDimitry Andric case SymbolKind::S_LPROC32_ID:
3690b57cec5SDimitry Andric case SymbolKind::S_LPROC32_DPC:
3700b57cec5SDimitry Andric case SymbolKind::S_LPROC32_DPC_ID:
3710b57cec5SDimitry Andric Refs.push_back({TiRefKind::IndexRef, 24, 1}); // LF_FUNC_ID
3720b57cec5SDimitry Andric break;
3730b57cec5SDimitry Andric case SymbolKind::S_GPROC32:
3740b57cec5SDimitry Andric case SymbolKind::S_LPROC32:
3750b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, 24, 1}); // Type
3760b57cec5SDimitry Andric break;
3770b57cec5SDimitry Andric case SymbolKind::S_UDT:
3780b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, 0, 1}); // UDT
3790b57cec5SDimitry Andric break;
3800b57cec5SDimitry Andric case SymbolKind::S_GDATA32:
3810b57cec5SDimitry Andric case SymbolKind::S_LDATA32:
3820b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
3830b57cec5SDimitry Andric break;
3840b57cec5SDimitry Andric case SymbolKind::S_BUILDINFO:
3850b57cec5SDimitry Andric Refs.push_back({TiRefKind::IndexRef, 0, 1}); // Compile flags
3860b57cec5SDimitry Andric break;
3870b57cec5SDimitry Andric case SymbolKind::S_LTHREAD32:
3880b57cec5SDimitry Andric case SymbolKind::S_GTHREAD32:
3890b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
3900b57cec5SDimitry Andric break;
3910b57cec5SDimitry Andric case SymbolKind::S_FILESTATIC:
3920b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
3930b57cec5SDimitry Andric break;
3940b57cec5SDimitry Andric case SymbolKind::S_LOCAL:
3950b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
3960b57cec5SDimitry Andric break;
3970b57cec5SDimitry Andric case SymbolKind::S_REGISTER:
3980b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
3990b57cec5SDimitry Andric break;
4000b57cec5SDimitry Andric case SymbolKind::S_CONSTANT:
4010b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
4020b57cec5SDimitry Andric break;
4030b57cec5SDimitry Andric case SymbolKind::S_BPREL32:
4040b57cec5SDimitry Andric case SymbolKind::S_REGREL32:
4050b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, 4, 1}); // Type
4060b57cec5SDimitry Andric break;
4070b57cec5SDimitry Andric case SymbolKind::S_CALLSITEINFO:
4080b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, 8, 1}); // Call signature
4090b57cec5SDimitry Andric break;
4100b57cec5SDimitry Andric case SymbolKind::S_CALLERS:
4110b57cec5SDimitry Andric case SymbolKind::S_CALLEES:
4120b57cec5SDimitry Andric case SymbolKind::S_INLINEES:
4130b57cec5SDimitry Andric // The record is a count followed by an array of type indices.
4140b57cec5SDimitry Andric Count = *reinterpret_cast<const ulittle32_t *>(Content.data());
4150b57cec5SDimitry Andric Refs.push_back({TiRefKind::IndexRef, 4, Count}); // Callees
4160b57cec5SDimitry Andric break;
4170b57cec5SDimitry Andric case SymbolKind::S_INLINESITE:
4180b57cec5SDimitry Andric Refs.push_back({TiRefKind::IndexRef, 8, 1}); // ID of inlinee
4190b57cec5SDimitry Andric break;
4200b57cec5SDimitry Andric case SymbolKind::S_HEAPALLOCSITE:
4210b57cec5SDimitry Andric Refs.push_back({TiRefKind::TypeRef, 8, 1}); // UDT allocated
4220b57cec5SDimitry Andric break;
4230b57cec5SDimitry Andric
4240b57cec5SDimitry Andric // Defranges don't have types, just registers and code offsets.
4250b57cec5SDimitry Andric case SymbolKind::S_DEFRANGE_REGISTER:
4260b57cec5SDimitry Andric case SymbolKind::S_DEFRANGE_REGISTER_REL:
4270b57cec5SDimitry Andric case SymbolKind::S_DEFRANGE_FRAMEPOINTER_REL:
4280b57cec5SDimitry Andric case SymbolKind::S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE:
4290b57cec5SDimitry Andric case SymbolKind::S_DEFRANGE_SUBFIELD_REGISTER:
4300b57cec5SDimitry Andric case SymbolKind::S_DEFRANGE_SUBFIELD:
4310b57cec5SDimitry Andric break;
4320b57cec5SDimitry Andric
4330b57cec5SDimitry Andric // No type references.
4340b57cec5SDimitry Andric case SymbolKind::S_LABEL32:
4350b57cec5SDimitry Andric case SymbolKind::S_OBJNAME:
4360b57cec5SDimitry Andric case SymbolKind::S_COMPILE:
4370b57cec5SDimitry Andric case SymbolKind::S_COMPILE2:
4380b57cec5SDimitry Andric case SymbolKind::S_COMPILE3:
4390b57cec5SDimitry Andric case SymbolKind::S_ENVBLOCK:
4400b57cec5SDimitry Andric case SymbolKind::S_BLOCK32:
4410b57cec5SDimitry Andric case SymbolKind::S_FRAMEPROC:
4420b57cec5SDimitry Andric case SymbolKind::S_THUNK32:
4430b57cec5SDimitry Andric case SymbolKind::S_FRAMECOOKIE:
4440b57cec5SDimitry Andric case SymbolKind::S_UNAMESPACE:
4455f757f3fSDimitry Andric case SymbolKind::S_ARMSWITCHTABLE:
4460b57cec5SDimitry Andric break;
4470b57cec5SDimitry Andric // Scope ending symbols.
4480b57cec5SDimitry Andric case SymbolKind::S_END:
4490b57cec5SDimitry Andric case SymbolKind::S_INLINESITE_END:
4500b57cec5SDimitry Andric case SymbolKind::S_PROC_ID_END:
4510b57cec5SDimitry Andric break;
4520b57cec5SDimitry Andric default:
4530b57cec5SDimitry Andric return false; // Unknown symbol.
4540b57cec5SDimitry Andric }
4550b57cec5SDimitry Andric return true;
4560b57cec5SDimitry Andric }
4570b57cec5SDimitry Andric
discoverTypeIndices(const CVType & Type,SmallVectorImpl<TiReference> & Refs)4580b57cec5SDimitry Andric void llvm::codeview::discoverTypeIndices(const CVType &Type,
4590b57cec5SDimitry Andric SmallVectorImpl<TiReference> &Refs) {
4600b57cec5SDimitry Andric ::discoverTypeIndices(Type.content(), Type.kind(), Refs);
4610b57cec5SDimitry Andric }
4620b57cec5SDimitry Andric
resolveTypeIndexReferences(ArrayRef<uint8_t> RecordData,ArrayRef<TiReference> Refs,SmallVectorImpl<TypeIndex> & Indices)4630b57cec5SDimitry Andric static void resolveTypeIndexReferences(ArrayRef<uint8_t> RecordData,
4640b57cec5SDimitry Andric ArrayRef<TiReference> Refs,
4650b57cec5SDimitry Andric SmallVectorImpl<TypeIndex> &Indices) {
4660b57cec5SDimitry Andric Indices.clear();
4670b57cec5SDimitry Andric
4680b57cec5SDimitry Andric if (Refs.empty())
4690b57cec5SDimitry Andric return;
4700b57cec5SDimitry Andric
4710b57cec5SDimitry Andric RecordData = RecordData.drop_front(sizeof(RecordPrefix));
4720b57cec5SDimitry Andric
4735f757f3fSDimitry Andric BinaryStreamReader Reader(RecordData, llvm::endianness::little);
4740b57cec5SDimitry Andric for (const auto &Ref : Refs) {
4750b57cec5SDimitry Andric Reader.setOffset(Ref.Offset);
4760b57cec5SDimitry Andric FixedStreamArray<TypeIndex> Run;
4770b57cec5SDimitry Andric cantFail(Reader.readArray(Run, Ref.Count));
4780b57cec5SDimitry Andric Indices.append(Run.begin(), Run.end());
4790b57cec5SDimitry Andric }
4800b57cec5SDimitry Andric }
4810b57cec5SDimitry Andric
discoverTypeIndices(const CVType & Type,SmallVectorImpl<TypeIndex> & Indices)4820b57cec5SDimitry Andric void llvm::codeview::discoverTypeIndices(const CVType &Type,
4830b57cec5SDimitry Andric SmallVectorImpl<TypeIndex> &Indices) {
4840b57cec5SDimitry Andric return discoverTypeIndices(Type.RecordData, Indices);
4850b57cec5SDimitry Andric }
4860b57cec5SDimitry Andric
discoverTypeIndices(ArrayRef<uint8_t> RecordData,SmallVectorImpl<TypeIndex> & Indices)4870b57cec5SDimitry Andric void llvm::codeview::discoverTypeIndices(ArrayRef<uint8_t> RecordData,
4880b57cec5SDimitry Andric SmallVectorImpl<TypeIndex> &Indices) {
4890b57cec5SDimitry Andric SmallVector<TiReference, 4> Refs;
4900b57cec5SDimitry Andric discoverTypeIndices(RecordData, Refs);
4910b57cec5SDimitry Andric resolveTypeIndexReferences(RecordData, Refs, Indices);
4920b57cec5SDimitry Andric }
4930b57cec5SDimitry Andric
discoverTypeIndices(ArrayRef<uint8_t> RecordData,SmallVectorImpl<TiReference> & Refs)4940b57cec5SDimitry Andric void llvm::codeview::discoverTypeIndices(ArrayRef<uint8_t> RecordData,
4950b57cec5SDimitry Andric SmallVectorImpl<TiReference> &Refs) {
4960b57cec5SDimitry Andric const RecordPrefix *P =
4970b57cec5SDimitry Andric reinterpret_cast<const RecordPrefix *>(RecordData.data());
4980b57cec5SDimitry Andric TypeLeafKind K = static_cast<TypeLeafKind>(uint16_t(P->RecordKind));
4990b57cec5SDimitry Andric ::discoverTypeIndices(RecordData.drop_front(sizeof(RecordPrefix)), K, Refs);
5000b57cec5SDimitry Andric }
5010b57cec5SDimitry Andric
discoverTypeIndicesInSymbol(const CVSymbol & Sym,SmallVectorImpl<TiReference> & Refs)5020b57cec5SDimitry Andric bool llvm::codeview::discoverTypeIndicesInSymbol(
5030b57cec5SDimitry Andric const CVSymbol &Sym, SmallVectorImpl<TiReference> &Refs) {
5040b57cec5SDimitry Andric SymbolKind K = Sym.kind();
5050b57cec5SDimitry Andric return ::discoverTypeIndices(Sym.content(), K, Refs);
5060b57cec5SDimitry Andric }
5070b57cec5SDimitry Andric
discoverTypeIndicesInSymbol(ArrayRef<uint8_t> RecordData,SmallVectorImpl<TiReference> & Refs)5080b57cec5SDimitry Andric bool llvm::codeview::discoverTypeIndicesInSymbol(
5090b57cec5SDimitry Andric ArrayRef<uint8_t> RecordData, SmallVectorImpl<TiReference> &Refs) {
5100b57cec5SDimitry Andric const RecordPrefix *P =
5110b57cec5SDimitry Andric reinterpret_cast<const RecordPrefix *>(RecordData.data());
5120b57cec5SDimitry Andric SymbolKind K = static_cast<SymbolKind>(uint16_t(P->RecordKind));
5130b57cec5SDimitry Andric return ::discoverTypeIndices(RecordData.drop_front(sizeof(RecordPrefix)), K,
5140b57cec5SDimitry Andric Refs);
5150b57cec5SDimitry Andric }
5160b57cec5SDimitry Andric
discoverTypeIndicesInSymbol(ArrayRef<uint8_t> RecordData,SmallVectorImpl<TypeIndex> & Indices)5170b57cec5SDimitry Andric bool llvm::codeview::discoverTypeIndicesInSymbol(
5180b57cec5SDimitry Andric ArrayRef<uint8_t> RecordData, SmallVectorImpl<TypeIndex> &Indices) {
5190b57cec5SDimitry Andric SmallVector<TiReference, 2> Refs;
5200b57cec5SDimitry Andric if (!discoverTypeIndicesInSymbol(RecordData, Refs))
5210b57cec5SDimitry Andric return false;
5220b57cec5SDimitry Andric resolveTypeIndexReferences(RecordData, Refs, Indices);
5230b57cec5SDimitry Andric return true;
5240b57cec5SDimitry Andric }
525