97 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			97 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===- DebugSubsectionRecord.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/CodeView/DebugSubsectionRecord.h"
 | |
| #include "llvm/DebugInfo/CodeView/CodeView.h"
 | |
| #include "llvm/DebugInfo/CodeView/DebugSubsection.h"
 | |
| #include "llvm/Support/BinaryStreamReader.h"
 | |
| #include "llvm/Support/BinaryStreamWriter.h"
 | |
| #include "llvm/Support/Error.h"
 | |
| #include "llvm/Support/MathExtras.h"
 | |
| #include <algorithm>
 | |
| #include <cassert>
 | |
| #include <cstdint>
 | |
| 
 | |
| using namespace llvm;
 | |
| using namespace llvm::codeview;
 | |
| 
 | |
| DebugSubsectionRecord::DebugSubsectionRecord() = default;
 | |
| 
 | |
| DebugSubsectionRecord::DebugSubsectionRecord(DebugSubsectionKind Kind,
 | |
|                                              BinaryStreamRef Data,
 | |
|                                              CodeViewContainer Container)
 | |
|     : Container(Container), Kind(Kind), Data(Data) {}
 | |
| 
 | |
| Error DebugSubsectionRecord::initialize(BinaryStreamRef Stream,
 | |
|                                         DebugSubsectionRecord &Info,
 | |
|                                         CodeViewContainer Container) {
 | |
|   const DebugSubsectionHeader *Header;
 | |
|   BinaryStreamReader Reader(Stream);
 | |
|   if (auto EC = Reader.readObject(Header))
 | |
|     return EC;
 | |
| 
 | |
|   DebugSubsectionKind Kind =
 | |
|       static_cast<DebugSubsectionKind>(uint32_t(Header->Kind));
 | |
|   if (auto EC = Reader.readStreamRef(Info.Data, Header->Length))
 | |
|     return EC;
 | |
|   Info.Container = Container;
 | |
|   Info.Kind = Kind;
 | |
|   return Error::success();
 | |
| }
 | |
| 
 | |
| uint32_t DebugSubsectionRecord::getRecordLength() const {
 | |
|   return sizeof(DebugSubsectionHeader) + Data.getLength();
 | |
| }
 | |
| 
 | |
| DebugSubsectionKind DebugSubsectionRecord::kind() const { return Kind; }
 | |
| 
 | |
| BinaryStreamRef DebugSubsectionRecord::getRecordData() const { return Data; }
 | |
| 
 | |
| DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder(
 | |
|     std::shared_ptr<DebugSubsection> Subsection, CodeViewContainer Container)
 | |
|     : Subsection(std::move(Subsection)), Container(Container) {}
 | |
| 
 | |
| DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder(
 | |
|     const DebugSubsectionRecord &Contents, CodeViewContainer Container)
 | |
|     : Contents(Contents), Container(Container) {}
 | |
| 
 | |
| uint32_t DebugSubsectionRecordBuilder::calculateSerializedLength() {
 | |
|   uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize()
 | |
|                                  : Contents.getRecordData().getLength();
 | |
|   // The length of the entire subsection is always padded to 4 bytes,
 | |
|   // regardless of the container kind.
 | |
|   return sizeof(DebugSubsectionHeader) + alignTo(DataSize, 4);
 | |
| }
 | |
| 
 | |
| Error DebugSubsectionRecordBuilder::commit(BinaryStreamWriter &Writer) const {
 | |
|   assert(Writer.getOffset() % alignOf(Container) == 0 &&
 | |
|          "Debug Subsection not properly aligned");
 | |
| 
 | |
|   DebugSubsectionHeader Header;
 | |
|   Header.Kind = uint32_t(Subsection ? Subsection->kind() : Contents.kind());
 | |
|   // The value written into the Header's Length field is only padded to the
 | |
|   // container's alignment
 | |
|   uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize()
 | |
|                                  : Contents.getRecordData().getLength();
 | |
|   Header.Length = alignTo(DataSize, alignOf(Container));
 | |
| 
 | |
|   if (auto EC = Writer.writeObject(Header))
 | |
|     return EC;
 | |
|   if (Subsection) {
 | |
|     if (auto EC = Subsection->commit(Writer))
 | |
|       return EC;
 | |
|   } else {
 | |
|     if (auto EC = Writer.writeStreamRef(Contents.getRecordData()))
 | |
|       return EC;
 | |
|   }
 | |
|   if (auto EC = Writer.padToAlignment(4))
 | |
|     return EC;
 | |
| 
 | |
|   return Error::success();
 | |
| }
 |