18456b16eSEugene Zelenko //===- DebugCrossImpSubsection.cpp ----------------------------------------===// 2349c18f8SZachary Turner // 3349c18f8SZachary Turner // The LLVM Compiler Infrastructure 4349c18f8SZachary Turner // 5349c18f8SZachary Turner // This file is distributed under the University of Illinois Open Source 6349c18f8SZachary Turner // License. See LICENSE.TXT for details. 7349c18f8SZachary Turner // 8349c18f8SZachary Turner //===----------------------------------------------------------------------===// 9349c18f8SZachary Turner 10349c18f8SZachary Turner #include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h" 118456b16eSEugene Zelenko #include "llvm/ADT/ArrayRef.h" 12349c18f8SZachary Turner #include "llvm/DebugInfo/CodeView/CodeViewError.h" 13349c18f8SZachary Turner #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" 148456b16eSEugene Zelenko #include "llvm/Support/BinaryStreamReader.h" 158456b16eSEugene Zelenko #include "llvm/Support/BinaryStreamWriter.h" 168456b16eSEugene Zelenko #include "llvm/Support/Endian.h" 178456b16eSEugene Zelenko #include "llvm/Support/Error.h" 188456b16eSEugene Zelenko #include <algorithm> 198456b16eSEugene Zelenko #include <cstdint> 208456b16eSEugene Zelenko #include <utility> 218456b16eSEugene Zelenko #include <vector> 22349c18f8SZachary Turner 23349c18f8SZachary Turner using namespace llvm; 24349c18f8SZachary Turner using namespace llvm::codeview; 25349c18f8SZachary Turner 267e62cd17SZachary Turner Error VarStreamArrayExtractor<CrossModuleImportItem>:: 277e62cd17SZachary Turner operator()(BinaryStreamRef Stream, uint32_t &Len, 28349c18f8SZachary Turner codeview::CrossModuleImportItem &Item) { 29349c18f8SZachary Turner BinaryStreamReader Reader(Stream); 30349c18f8SZachary Turner if (Reader.bytesRemaining() < sizeof(CrossModuleImport)) 31349c18f8SZachary Turner return make_error<CodeViewError>( 32349c18f8SZachary Turner cv_error_code::insufficient_buffer, 33349c18f8SZachary Turner "Not enough bytes for a Cross Module Import Header!"); 34349c18f8SZachary Turner if (auto EC = Reader.readObject(Item.Header)) 35349c18f8SZachary Turner return EC; 36349c18f8SZachary Turner if (Reader.bytesRemaining() < Item.Header->Count * sizeof(uint32_t)) 37349c18f8SZachary Turner return make_error<CodeViewError>( 38349c18f8SZachary Turner cv_error_code::insufficient_buffer, 39349c18f8SZachary Turner "Not enough to read specified number of Cross Module References!"); 40349c18f8SZachary Turner if (auto EC = Reader.readArray(Item.Imports, Item.Header->Count)) 41349c18f8SZachary Turner return EC; 42349c18f8SZachary Turner return Error::success(); 43349c18f8SZachary Turner } 44349c18f8SZachary Turner 45349c18f8SZachary Turner Error DebugCrossModuleImportsSubsectionRef::initialize( 46349c18f8SZachary Turner BinaryStreamReader Reader) { 47349c18f8SZachary Turner return Reader.readArray(References, Reader.bytesRemaining()); 48349c18f8SZachary Turner } 49349c18f8SZachary Turner 50349c18f8SZachary Turner Error DebugCrossModuleImportsSubsectionRef::initialize(BinaryStreamRef Stream) { 51349c18f8SZachary Turner BinaryStreamReader Reader(Stream); 52349c18f8SZachary Turner return initialize(Reader); 53349c18f8SZachary Turner } 54349c18f8SZachary Turner 55349c18f8SZachary Turner void DebugCrossModuleImportsSubsection::addImport(StringRef Module, 56349c18f8SZachary Turner uint32_t ImportId) { 57349c18f8SZachary Turner Strings.insert(Module); 58349c18f8SZachary Turner std::vector<support::ulittle32_t> Targets = {support::ulittle32_t(ImportId)}; 59349c18f8SZachary Turner auto Result = Mappings.insert(std::make_pair(Module, Targets)); 60349c18f8SZachary Turner if (!Result.second) 61349c18f8SZachary Turner Result.first->getValue().push_back(Targets[0]); 62349c18f8SZachary Turner } 63349c18f8SZachary Turner 64349c18f8SZachary Turner uint32_t DebugCrossModuleImportsSubsection::calculateSerializedSize() const { 65349c18f8SZachary Turner uint32_t Size = 0; 66349c18f8SZachary Turner for (const auto &Item : Mappings) { 67349c18f8SZachary Turner Size += sizeof(CrossModuleImport); 68349c18f8SZachary Turner Size += sizeof(support::ulittle32_t) * Item.second.size(); 69349c18f8SZachary Turner } 70349c18f8SZachary Turner return Size; 71349c18f8SZachary Turner } 72349c18f8SZachary Turner 73349c18f8SZachary Turner Error DebugCrossModuleImportsSubsection::commit( 74349c18f8SZachary Turner BinaryStreamWriter &Writer) const { 75349c18f8SZachary Turner using T = decltype(&*Mappings.begin()); 76349c18f8SZachary Turner std::vector<T> Ids; 77349c18f8SZachary Turner Ids.reserve(Mappings.size()); 78349c18f8SZachary Turner 79349c18f8SZachary Turner for (const auto &M : Mappings) 80349c18f8SZachary Turner Ids.push_back(&M); 81349c18f8SZachary Turner 82349c18f8SZachary Turner std::sort(Ids.begin(), Ids.end(), [this](const T &L1, const T &L2) { 83*71d36ad9SZachary Turner return Strings.getIdForString(L1->getKey()) < 84*71d36ad9SZachary Turner Strings.getIdForString(L2->getKey()); 85349c18f8SZachary Turner }); 86349c18f8SZachary Turner 87349c18f8SZachary Turner for (const auto &Item : Ids) { 88349c18f8SZachary Turner CrossModuleImport Imp; 89*71d36ad9SZachary Turner Imp.ModuleNameOffset = Strings.getIdForString(Item->getKey()); 90349c18f8SZachary Turner Imp.Count = Item->getValue().size(); 91349c18f8SZachary Turner if (auto EC = Writer.writeObject(Imp)) 92349c18f8SZachary Turner return EC; 93349c18f8SZachary Turner if (auto EC = Writer.writeArray(makeArrayRef(Item->getValue()))) 94349c18f8SZachary Turner return EC; 95349c18f8SZachary Turner } 96349c18f8SZachary Turner return Error::success(); 97349c18f8SZachary Turner } 98