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