Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===- CVRecord.h -----------------------------------------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8.  
  9. #ifndef LLVM_DEBUGINFO_CODEVIEW_CVRECORD_H
  10. #define LLVM_DEBUGINFO_CODEVIEW_CVRECORD_H
  11.  
  12. #include "llvm/ADT/ArrayRef.h"
  13. #include "llvm/DebugInfo/CodeView/CodeView.h"
  14. #include "llvm/DebugInfo/CodeView/CodeViewError.h"
  15. #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
  16. #include "llvm/Support/BinaryStreamReader.h"
  17. #include "llvm/Support/BinaryStreamRef.h"
  18. #include "llvm/Support/Endian.h"
  19. #include "llvm/Support/Error.h"
  20. #include <cstdint>
  21.  
  22. namespace llvm {
  23.  
  24. namespace codeview {
  25.  
  26. /// CVRecord is a fat pointer (base + size pair) to a symbol or type record.
  27. /// Carrying the size separately instead of trusting the size stored in the
  28. /// record prefix provides some extra safety and flexibility.
  29. template <typename Kind> class CVRecord {
  30. public:
  31.   CVRecord() = default;
  32.  
  33.   CVRecord(ArrayRef<uint8_t> Data) : RecordData(Data) {}
  34.  
  35.   CVRecord(const RecordPrefix *P, size_t Size)
  36.       : RecordData(reinterpret_cast<const uint8_t *>(P), Size) {}
  37.  
  38.   bool valid() const { return kind() != Kind(0); }
  39.  
  40.   uint32_t length() const { return RecordData.size(); }
  41.  
  42.   Kind kind() const {
  43.     if (RecordData.size() < sizeof(RecordPrefix))
  44.       return Kind(0);
  45.     return static_cast<Kind>(static_cast<uint16_t>(
  46.         reinterpret_cast<const RecordPrefix *>(RecordData.data())->RecordKind));
  47.   }
  48.  
  49.   ArrayRef<uint8_t> data() const { return RecordData; }
  50.  
  51.   StringRef str_data() const {
  52.     return StringRef(reinterpret_cast<const char *>(RecordData.data()),
  53.                      RecordData.size());
  54.   }
  55.  
  56.   ArrayRef<uint8_t> content() const {
  57.     return RecordData.drop_front(sizeof(RecordPrefix));
  58.   }
  59.  
  60.   ArrayRef<uint8_t> RecordData;
  61. };
  62.  
  63. // There are two kinds of codeview records: type and symbol records.
  64. using CVType = CVRecord<TypeLeafKind>;
  65. using CVSymbol = CVRecord<SymbolKind>;
  66.  
  67. template <typename Record, typename Func>
  68. Error forEachCodeViewRecord(ArrayRef<uint8_t> StreamBuffer, Func F) {
  69.   while (!StreamBuffer.empty()) {
  70.     if (StreamBuffer.size() < sizeof(RecordPrefix))
  71.       return make_error<CodeViewError>(cv_error_code::corrupt_record);
  72.  
  73.     const RecordPrefix *Prefix =
  74.         reinterpret_cast<const RecordPrefix *>(StreamBuffer.data());
  75.  
  76.     size_t RealLen = Prefix->RecordLen + 2;
  77.     if (StreamBuffer.size() < RealLen)
  78.       return make_error<CodeViewError>(cv_error_code::corrupt_record);
  79.  
  80.     ArrayRef<uint8_t> Data = StreamBuffer.take_front(RealLen);
  81.     StreamBuffer = StreamBuffer.drop_front(RealLen);
  82.  
  83.     Record R(Data);
  84.     if (auto EC = F(R))
  85.       return EC;
  86.   }
  87.   return Error::success();
  88. }
  89.  
  90. /// Read a complete record from a stream at a random offset.
  91. template <typename Kind>
  92. inline Expected<CVRecord<Kind>> readCVRecordFromStream(BinaryStreamRef Stream,
  93.                                                        uint32_t Offset) {
  94.   const RecordPrefix *Prefix = nullptr;
  95.   BinaryStreamReader Reader(Stream);
  96.   Reader.setOffset(Offset);
  97.  
  98.   if (auto EC = Reader.readObject(Prefix))
  99.     return std::move(EC);
  100.   if (Prefix->RecordLen < 2)
  101.     return make_error<CodeViewError>(cv_error_code::corrupt_record);
  102.  
  103.   Reader.setOffset(Offset);
  104.   ArrayRef<uint8_t> RawData;
  105.   if (auto EC = Reader.readBytes(RawData, Prefix->RecordLen + sizeof(uint16_t)))
  106.     return std::move(EC);
  107.   return codeview::CVRecord<Kind>(RawData);
  108. }
  109.  
  110. } // end namespace codeview
  111.  
  112. template <typename Kind>
  113. struct VarStreamArrayExtractor<codeview::CVRecord<Kind>> {
  114.   Error operator()(BinaryStreamRef Stream, uint32_t &Len,
  115.                    codeview::CVRecord<Kind> &Item) {
  116.     auto ExpectedRec = codeview::readCVRecordFromStream<Kind>(Stream, 0);
  117.     if (!ExpectedRec)
  118.       return ExpectedRec.takeError();
  119.     Item = *ExpectedRec;
  120.     Len = ExpectedRec->length();
  121.     return Error::success();
  122.   }
  123. };
  124.  
  125. namespace codeview {
  126. using CVSymbolArray = VarStreamArray<CVSymbol>;
  127. using CVTypeArray = VarStreamArray<CVType>;
  128. using CVTypeRange = iterator_range<CVTypeArray::Iterator>;
  129. } // namespace codeview
  130.  
  131. } // end namespace llvm
  132.  
  133. #endif // LLVM_DEBUGINFO_CODEVIEW_CVRECORD_H
  134.