xref: /src/contrib/llvm-project/llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
101095a5dSDimitry Andric //===-- RecordSerialization.cpp -------------------------------------------===//
201095a5dSDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
601095a5dSDimitry Andric //
701095a5dSDimitry Andric //===----------------------------------------------------------------------===//
801095a5dSDimitry Andric //
901095a5dSDimitry Andric // Utilities for serializing and deserializing CodeView records.
1001095a5dSDimitry Andric //
1101095a5dSDimitry Andric //===----------------------------------------------------------------------===//
1201095a5dSDimitry Andric 
1301095a5dSDimitry Andric #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
1401095a5dSDimitry Andric #include "llvm/ADT/APInt.h"
1501095a5dSDimitry Andric #include "llvm/ADT/APSInt.h"
16145449b1SDimitry Andric #include "llvm/DebugInfo/CodeView/CVRecord.h"
17b915e9e0SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewError.h"
18044eb2f6SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
1971d5a254SDimitry Andric #include "llvm/Support/BinaryByteStream.h"
2001095a5dSDimitry Andric 
2101095a5dSDimitry Andric using namespace llvm;
2201095a5dSDimitry Andric using namespace llvm::codeview;
2301095a5dSDimitry Andric using namespace llvm::support;
2401095a5dSDimitry Andric 
2501095a5dSDimitry Andric /// Reinterpret a byte array as an array of characters. Does not interpret as
2601095a5dSDimitry Andric /// a C string, as StringRef has several helpers (split) that make that easy.
getBytesAsCharacters(ArrayRef<uint8_t> LeafData)2701095a5dSDimitry Andric StringRef llvm::codeview::getBytesAsCharacters(ArrayRef<uint8_t> LeafData) {
2801095a5dSDimitry Andric   return StringRef(reinterpret_cast<const char *>(LeafData.data()),
2901095a5dSDimitry Andric                    LeafData.size());
3001095a5dSDimitry Andric }
3101095a5dSDimitry Andric 
getBytesAsCString(ArrayRef<uint8_t> LeafData)3201095a5dSDimitry Andric StringRef llvm::codeview::getBytesAsCString(ArrayRef<uint8_t> LeafData) {
3301095a5dSDimitry Andric   return getBytesAsCharacters(LeafData).split('\0').first;
3401095a5dSDimitry Andric }
3501095a5dSDimitry Andric 
consume(BinaryStreamReader & Reader,APSInt & Num)3671d5a254SDimitry Andric Error llvm::codeview::consume(BinaryStreamReader &Reader, APSInt &Num) {
37b60736ecSDimitry Andric   // Used to avoid overload ambiguity on APInt constructor.
3801095a5dSDimitry Andric   bool FalseVal = false;
39b915e9e0SDimitry Andric   uint16_t Short;
40b915e9e0SDimitry Andric   if (auto EC = Reader.readInteger(Short))
41b915e9e0SDimitry Andric     return EC;
42b915e9e0SDimitry Andric 
4301095a5dSDimitry Andric   if (Short < LF_NUMERIC) {
4401095a5dSDimitry Andric     Num = APSInt(APInt(/*numBits=*/16, Short, /*isSigned=*/false),
4501095a5dSDimitry Andric                  /*isUnsigned=*/true);
46b915e9e0SDimitry Andric     return Error::success();
4701095a5dSDimitry Andric   }
4801095a5dSDimitry Andric 
49b915e9e0SDimitry Andric   switch (Short) {
50b915e9e0SDimitry Andric   case LF_CHAR: {
51b915e9e0SDimitry Andric     int8_t N;
52b915e9e0SDimitry Andric     if (auto EC = Reader.readInteger(N))
53b915e9e0SDimitry Andric       return EC;
54b915e9e0SDimitry Andric     Num = APSInt(APInt(8, N, true), false);
55b915e9e0SDimitry Andric     return Error::success();
56b915e9e0SDimitry Andric   }
57b915e9e0SDimitry Andric   case LF_SHORT: {
58b915e9e0SDimitry Andric     int16_t N;
59b915e9e0SDimitry Andric     if (auto EC = Reader.readInteger(N))
60b915e9e0SDimitry Andric       return EC;
61b915e9e0SDimitry Andric     Num = APSInt(APInt(16, N, true), false);
62b915e9e0SDimitry Andric     return Error::success();
63b915e9e0SDimitry Andric   }
64b915e9e0SDimitry Andric   case LF_USHORT: {
65b915e9e0SDimitry Andric     uint16_t N;
66b915e9e0SDimitry Andric     if (auto EC = Reader.readInteger(N))
67b915e9e0SDimitry Andric       return EC;
68b915e9e0SDimitry Andric     Num = APSInt(APInt(16, N, false), true);
69b915e9e0SDimitry Andric     return Error::success();
70b915e9e0SDimitry Andric   }
71b915e9e0SDimitry Andric   case LF_LONG: {
72b915e9e0SDimitry Andric     int32_t N;
73b915e9e0SDimitry Andric     if (auto EC = Reader.readInteger(N))
74b915e9e0SDimitry Andric       return EC;
75b915e9e0SDimitry Andric     Num = APSInt(APInt(32, N, true), false);
76b915e9e0SDimitry Andric     return Error::success();
77b915e9e0SDimitry Andric   }
78b915e9e0SDimitry Andric   case LF_ULONG: {
79b915e9e0SDimitry Andric     uint32_t N;
80b915e9e0SDimitry Andric     if (auto EC = Reader.readInteger(N))
81b915e9e0SDimitry Andric       return EC;
82b915e9e0SDimitry Andric     Num = APSInt(APInt(32, N, FalseVal), true);
83b915e9e0SDimitry Andric     return Error::success();
84b915e9e0SDimitry Andric   }
85b915e9e0SDimitry Andric   case LF_QUADWORD: {
86b915e9e0SDimitry Andric     int64_t N;
87b915e9e0SDimitry Andric     if (auto EC = Reader.readInteger(N))
88b915e9e0SDimitry Andric       return EC;
89b915e9e0SDimitry Andric     Num = APSInt(APInt(64, N, true), false);
90b915e9e0SDimitry Andric     return Error::success();
91b915e9e0SDimitry Andric   }
92b915e9e0SDimitry Andric   case LF_UQUADWORD: {
93b915e9e0SDimitry Andric     uint64_t N;
94b915e9e0SDimitry Andric     if (auto EC = Reader.readInteger(N))
95b915e9e0SDimitry Andric       return EC;
96b915e9e0SDimitry Andric     Num = APSInt(APInt(64, N, false), true);
97b915e9e0SDimitry Andric     return Error::success();
98b915e9e0SDimitry Andric   }
99b915e9e0SDimitry Andric   }
100b915e9e0SDimitry Andric   return make_error<CodeViewError>(cv_error_code::corrupt_record,
101b915e9e0SDimitry Andric                                    "Buffer contains invalid APSInt type");
102b915e9e0SDimitry Andric }
103b915e9e0SDimitry Andric 
consume(StringRef & Data,APSInt & Num)104b915e9e0SDimitry Andric Error llvm::codeview::consume(StringRef &Data, APSInt &Num) {
10501095a5dSDimitry Andric   ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());
106b1c73532SDimitry Andric   BinaryByteStream S(Bytes, llvm::endianness::little);
10771d5a254SDimitry Andric   BinaryStreamReader SR(S);
108b915e9e0SDimitry Andric   auto EC = consume(SR, Num);
109b915e9e0SDimitry Andric   Data = Data.take_back(SR.bytesRemaining());
11001095a5dSDimitry Andric   return EC;
11101095a5dSDimitry Andric }
11201095a5dSDimitry Andric 
11301095a5dSDimitry Andric /// Decode a numeric leaf value that is known to be a uint64_t.
consume_numeric(BinaryStreamReader & Reader,uint64_t & Num)11471d5a254SDimitry Andric Error llvm::codeview::consume_numeric(BinaryStreamReader &Reader,
11501095a5dSDimitry Andric                                       uint64_t &Num) {
11601095a5dSDimitry Andric   APSInt N;
117b915e9e0SDimitry Andric   if (auto EC = consume(Reader, N))
11801095a5dSDimitry Andric     return EC;
11901095a5dSDimitry Andric   if (N.isSigned() || !N.isIntN(64))
120b915e9e0SDimitry Andric     return make_error<CodeViewError>(cv_error_code::corrupt_record,
121b915e9e0SDimitry Andric                                      "Data is not a numeric value!");
12201095a5dSDimitry Andric   Num = N.getLimitedValue();
123b915e9e0SDimitry Andric   return Error::success();
12401095a5dSDimitry Andric }
12501095a5dSDimitry Andric 
consume(BinaryStreamReader & Reader,uint32_t & Item)12671d5a254SDimitry Andric Error llvm::codeview::consume(BinaryStreamReader &Reader, uint32_t &Item) {
127b915e9e0SDimitry Andric   return Reader.readInteger(Item);
12801095a5dSDimitry Andric }
12901095a5dSDimitry Andric 
consume(StringRef & Data,uint32_t & Item)130b915e9e0SDimitry Andric Error llvm::codeview::consume(StringRef &Data, uint32_t &Item) {
13101095a5dSDimitry Andric   ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());
132b1c73532SDimitry Andric   BinaryByteStream S(Bytes, llvm::endianness::little);
13371d5a254SDimitry Andric   BinaryStreamReader SR(S);
134b915e9e0SDimitry Andric   auto EC = consume(SR, Item);
135b915e9e0SDimitry Andric   Data = Data.take_back(SR.bytesRemaining());
13601095a5dSDimitry Andric   return EC;
13701095a5dSDimitry Andric }
13801095a5dSDimitry Andric 
consume(BinaryStreamReader & Reader,int32_t & Item)13971d5a254SDimitry Andric Error llvm::codeview::consume(BinaryStreamReader &Reader, int32_t &Item) {
140b915e9e0SDimitry Andric   return Reader.readInteger(Item);
14101095a5dSDimitry Andric }
14201095a5dSDimitry Andric 
consume(BinaryStreamReader & Reader,StringRef & Item)14371d5a254SDimitry Andric Error llvm::codeview::consume(BinaryStreamReader &Reader, StringRef &Item) {
144b915e9e0SDimitry Andric   if (Reader.empty())
145b915e9e0SDimitry Andric     return make_error<CodeViewError>(cv_error_code::corrupt_record,
146b915e9e0SDimitry Andric                                      "Null terminated string buffer is empty!");
14701095a5dSDimitry Andric 
14871d5a254SDimitry Andric   return Reader.readCString(Item);
14901095a5dSDimitry Andric }
150044eb2f6SDimitry Andric 
readSymbolFromStream(BinaryStreamRef Stream,uint32_t Offset)151044eb2f6SDimitry Andric Expected<CVSymbol> llvm::codeview::readSymbolFromStream(BinaryStreamRef Stream,
152044eb2f6SDimitry Andric                                                         uint32_t Offset) {
153044eb2f6SDimitry Andric   return readCVRecordFromStream<SymbolKind>(Stream, Offset);
154044eb2f6SDimitry Andric }
155