1*0b57cec5SDimitry Andric //===- DebugCrossImpSubsection.cpp ----------------------------------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric 9*0b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h" 10*0b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 11*0b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewError.h" 12*0b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" 13*0b57cec5SDimitry Andric #include "llvm/Support/BinaryStreamReader.h" 14*0b57cec5SDimitry Andric #include "llvm/Support/BinaryStreamWriter.h" 15*0b57cec5SDimitry Andric #include "llvm/Support/Endian.h" 16*0b57cec5SDimitry Andric #include "llvm/Support/Error.h" 17*0b57cec5SDimitry Andric #include <algorithm> 18*0b57cec5SDimitry Andric #include <cstdint> 19*0b57cec5SDimitry Andric #include <utility> 20*0b57cec5SDimitry Andric #include <vector> 21*0b57cec5SDimitry Andric 22*0b57cec5SDimitry Andric using namespace llvm; 23*0b57cec5SDimitry Andric using namespace llvm::codeview; 24*0b57cec5SDimitry Andric 25*0b57cec5SDimitry Andric Error VarStreamArrayExtractor<CrossModuleImportItem>:: 26*0b57cec5SDimitry Andric operator()(BinaryStreamRef Stream, uint32_t &Len, 27*0b57cec5SDimitry Andric codeview::CrossModuleImportItem &Item) { 28*0b57cec5SDimitry Andric BinaryStreamReader Reader(Stream); 29*0b57cec5SDimitry Andric if (Reader.bytesRemaining() < sizeof(CrossModuleImport)) 30*0b57cec5SDimitry Andric return make_error<CodeViewError>( 31*0b57cec5SDimitry Andric cv_error_code::insufficient_buffer, 32*0b57cec5SDimitry Andric "Not enough bytes for a Cross Module Import Header!"); 33*0b57cec5SDimitry Andric if (auto EC = Reader.readObject(Item.Header)) 34*0b57cec5SDimitry Andric return EC; 35*0b57cec5SDimitry Andric if (Reader.bytesRemaining() < Item.Header->Count * sizeof(uint32_t)) 36*0b57cec5SDimitry Andric return make_error<CodeViewError>( 37*0b57cec5SDimitry Andric cv_error_code::insufficient_buffer, 38*0b57cec5SDimitry Andric "Not enough to read specified number of Cross Module References!"); 39*0b57cec5SDimitry Andric if (auto EC = Reader.readArray(Item.Imports, Item.Header->Count)) 40*0b57cec5SDimitry Andric return EC; 41*0b57cec5SDimitry Andric return Error::success(); 42*0b57cec5SDimitry Andric } 43*0b57cec5SDimitry Andric 44*0b57cec5SDimitry Andric Error DebugCrossModuleImportsSubsectionRef::initialize( 45*0b57cec5SDimitry Andric BinaryStreamReader Reader) { 46*0b57cec5SDimitry Andric return Reader.readArray(References, Reader.bytesRemaining()); 47*0b57cec5SDimitry Andric } 48*0b57cec5SDimitry Andric 49*0b57cec5SDimitry Andric Error DebugCrossModuleImportsSubsectionRef::initialize(BinaryStreamRef Stream) { 50*0b57cec5SDimitry Andric BinaryStreamReader Reader(Stream); 51*0b57cec5SDimitry Andric return initialize(Reader); 52*0b57cec5SDimitry Andric } 53*0b57cec5SDimitry Andric 54*0b57cec5SDimitry Andric void DebugCrossModuleImportsSubsection::addImport(StringRef Module, 55*0b57cec5SDimitry Andric uint32_t ImportId) { 56*0b57cec5SDimitry Andric Strings.insert(Module); 57*0b57cec5SDimitry Andric std::vector<support::ulittle32_t> Targets = {support::ulittle32_t(ImportId)}; 58*0b57cec5SDimitry Andric auto Result = Mappings.insert(std::make_pair(Module, Targets)); 59*0b57cec5SDimitry Andric if (!Result.second) 60*0b57cec5SDimitry Andric Result.first->getValue().push_back(Targets[0]); 61*0b57cec5SDimitry Andric } 62*0b57cec5SDimitry Andric 63*0b57cec5SDimitry Andric uint32_t DebugCrossModuleImportsSubsection::calculateSerializedSize() const { 64*0b57cec5SDimitry Andric uint32_t Size = 0; 65*0b57cec5SDimitry Andric for (const auto &Item : Mappings) { 66*0b57cec5SDimitry Andric Size += sizeof(CrossModuleImport); 67*0b57cec5SDimitry Andric Size += sizeof(support::ulittle32_t) * Item.second.size(); 68*0b57cec5SDimitry Andric } 69*0b57cec5SDimitry Andric return Size; 70*0b57cec5SDimitry Andric } 71*0b57cec5SDimitry Andric 72*0b57cec5SDimitry Andric Error DebugCrossModuleImportsSubsection::commit( 73*0b57cec5SDimitry Andric BinaryStreamWriter &Writer) const { 74*0b57cec5SDimitry Andric using T = decltype(&*Mappings.begin()); 75*0b57cec5SDimitry Andric std::vector<T> Ids; 76*0b57cec5SDimitry Andric Ids.reserve(Mappings.size()); 77*0b57cec5SDimitry Andric 78*0b57cec5SDimitry Andric for (const auto &M : Mappings) 79*0b57cec5SDimitry Andric Ids.push_back(&M); 80*0b57cec5SDimitry Andric 81*0b57cec5SDimitry Andric llvm::sort(Ids, [this](const T &L1, const T &L2) { 82*0b57cec5SDimitry Andric return Strings.getIdForString(L1->getKey()) < 83*0b57cec5SDimitry Andric Strings.getIdForString(L2->getKey()); 84*0b57cec5SDimitry Andric }); 85*0b57cec5SDimitry Andric 86*0b57cec5SDimitry Andric for (const auto &Item : Ids) { 87*0b57cec5SDimitry Andric CrossModuleImport Imp; 88*0b57cec5SDimitry Andric Imp.ModuleNameOffset = Strings.getIdForString(Item->getKey()); 89*0b57cec5SDimitry Andric Imp.Count = Item->getValue().size(); 90*0b57cec5SDimitry Andric if (auto EC = Writer.writeObject(Imp)) 91*0b57cec5SDimitry Andric return EC; 92*0b57cec5SDimitry Andric if (auto EC = Writer.writeArray(makeArrayRef(Item->getValue()))) 93*0b57cec5SDimitry Andric return EC; 94*0b57cec5SDimitry Andric } 95*0b57cec5SDimitry Andric return Error::success(); 96*0b57cec5SDimitry Andric } 97