123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- //===- CodeViewRecordIO.h ---------------------------------------*- 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
- //
- //===----------------------------------------------------------------------===//
- #ifndef LLVM_DEBUGINFO_CODEVIEW_CODEVIEWRECORDIO_H
- #define LLVM_DEBUGINFO_CODEVIEW_CODEVIEWRECORDIO_H
- #include "llvm/ADT/APSInt.h"
- #include "llvm/ADT/None.h"
- #include "llvm/ADT/Optional.h"
- #include "llvm/ADT/SmallVector.h"
- #include "llvm/ADT/StringRef.h"
- #include "llvm/DebugInfo/CodeView/CodeViewError.h"
- #include "llvm/DebugInfo/CodeView/TypeRecord.h"
- #include "llvm/Support/BinaryStreamReader.h"
- #include "llvm/Support/BinaryStreamWriter.h"
- #include "llvm/Support/Error.h"
- #include <cassert>
- #include <cstdint>
- #include <type_traits>
- namespace llvm {
- namespace codeview {
- class CodeViewRecordStreamer {
- public:
- virtual void EmitBytes(StringRef Data) = 0;
- virtual void EmitIntValue(uint64_t Value, unsigned Size) = 0;
- virtual void EmitBinaryData(StringRef Data) = 0;
- virtual ~CodeViewRecordStreamer() = default;
- };
- class CodeViewRecordIO {
- uint32_t getCurrentOffset() const {
- if (isWriting())
- return Writer->getOffset();
- else if (isReading())
- return Reader->getOffset();
- else
- return 0;
- }
- public:
- // deserializes records to structures
- explicit CodeViewRecordIO(BinaryStreamReader &Reader) : Reader(&Reader) {}
- // serializes records to buffer
- explicit CodeViewRecordIO(BinaryStreamWriter &Writer) : Writer(&Writer) {}
- // writes records to assembly file using MC library interface
- explicit CodeViewRecordIO(CodeViewRecordStreamer &Streamer)
- : Streamer(&Streamer) {}
- Error beginRecord(Optional<uint32_t> MaxLength);
- Error endRecord();
- Error mapInteger(TypeIndex &TypeInd);
- bool isStreaming() const {
- return (Streamer != nullptr) && (Reader == nullptr) && (Writer == nullptr);
- }
- bool isReading() const {
- return (Reader != nullptr) && (Streamer == nullptr) && (Writer == nullptr);
- }
- bool isWriting() const {
- return (Writer != nullptr) && (Streamer == nullptr) && (Reader == nullptr);
- }
- uint32_t maxFieldLength() const;
- template <typename T> Error mapObject(T &Value) {
- if (isStreaming()) {
- StringRef BytesSR =
- StringRef((reinterpret_cast<const char *>(&Value)), sizeof(Value));
- Streamer->EmitBytes(BytesSR);
- incrStreamedLen(sizeof(T));
- return Error::success();
- }
- if (isWriting())
- return Writer->writeObject(Value);
- const T *ValuePtr;
- if (auto EC = Reader->readObject(ValuePtr))
- return EC;
- Value = *ValuePtr;
- return Error::success();
- }
- template <typename T> Error mapInteger(T &Value) {
- if (isStreaming()) {
- Streamer->EmitIntValue((int)Value, sizeof(T));
- incrStreamedLen(sizeof(T));
- return Error::success();
- }
- if (isWriting())
- return Writer->writeInteger(Value);
- return Reader->readInteger(Value);
- }
- template <typename T> Error mapEnum(T &Value) {
- if (!isStreaming() && sizeof(Value) > maxFieldLength())
- return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
- using U = typename std::underlying_type<T>::type;
- U X;
- if (isWriting() || isStreaming())
- X = static_cast<U>(Value);
- if (auto EC = mapInteger(X))
- return EC;
- if (isReading())
- Value = static_cast<T>(X);
- return Error::success();
- }
- Error mapEncodedInteger(int64_t &Value);
- Error mapEncodedInteger(uint64_t &Value);
- Error mapEncodedInteger(APSInt &Value);
- Error mapStringZ(StringRef &Value);
- Error mapGuid(GUID &Guid);
- Error mapStringZVectorZ(std::vector<StringRef> &Value);
- template <typename SizeType, typename T, typename ElementMapper>
- Error mapVectorN(T &Items, const ElementMapper &Mapper) {
- SizeType Size;
- if (isStreaming()) {
- Size = static_cast<SizeType>(Items.size());
- Streamer->EmitIntValue(Size, sizeof(Size));
- incrStreamedLen(sizeof(Size)); // add 1 for the delimiter
- for (auto &X : Items) {
- if (auto EC = Mapper(*this, X))
- return EC;
- }
- } else if (isWriting()) {
- Size = static_cast<SizeType>(Items.size());
- if (auto EC = Writer->writeInteger(Size))
- return EC;
- for (auto &X : Items) {
- if (auto EC = Mapper(*this, X))
- return EC;
- }
- } else {
- if (auto EC = Reader->readInteger(Size))
- return EC;
- for (SizeType I = 0; I < Size; ++I) {
- typename T::value_type Item;
- if (auto EC = Mapper(*this, Item))
- return EC;
- Items.push_back(Item);
- }
- }
- return Error::success();
- }
- template <typename T, typename ElementMapper>
- Error mapVectorTail(T &Items, const ElementMapper &Mapper) {
- if (isStreaming() || isWriting()) {
- for (auto &Item : Items) {
- if (auto EC = Mapper(*this, Item))
- return EC;
- }
- } else {
- typename T::value_type Field;
- // Stop when we run out of bytes or we hit record padding bytes.
- while (!Reader->empty() && Reader->peek() < 0xf0 /* LF_PAD0 */) {
- if (auto EC = Mapper(*this, Field))
- return EC;
- Items.push_back(Field);
- }
- }
- return Error::success();
- }
- Error mapByteVectorTail(ArrayRef<uint8_t> &Bytes);
- Error mapByteVectorTail(std::vector<uint8_t> &Bytes);
- Error padToAlignment(uint32_t Align);
- Error skipPadding();
- uint64_t getStreamedLen() {
- if (isStreaming())
- return StreamedLen;
- return 0;
- }
- private:
- void emitEncodedSignedInteger(const int64_t &Value);
- void emitEncodedUnsignedInteger(const uint64_t &Value);
- Error writeEncodedSignedInteger(const int64_t &Value);
- Error writeEncodedUnsignedInteger(const uint64_t &Value);
- void incrStreamedLen(const uint64_t &Len) {
- if (isStreaming())
- StreamedLen += Len;
- }
- void resetStreamedLen() {
- if (isStreaming())
- StreamedLen = 4; // The record prefix is 4 bytes long
- }
- struct RecordLimit {
- uint32_t BeginOffset;
- Optional<uint32_t> MaxLength;
- Optional<uint32_t> bytesRemaining(uint32_t CurrentOffset) const {
- if (!MaxLength.hasValue())
- return None;
- assert(CurrentOffset >= BeginOffset);
- uint32_t BytesUsed = CurrentOffset - BeginOffset;
- if (BytesUsed >= *MaxLength)
- return 0;
- return *MaxLength - BytesUsed;
- }
- };
- SmallVector<RecordLimit, 2> Limits;
- BinaryStreamReader *Reader = nullptr;
- BinaryStreamWriter *Writer = nullptr;
- CodeViewRecordStreamer *Streamer = nullptr;
- uint64_t StreamedLen = 0;
- };
- } // end namespace codeview
- } // end namespace llvm
- #endif // LLVM_DEBUGINFO_CODEVIEW_CODEVIEWRECORDIO_H
|