| //===- DebugCrossImpSubsection.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/DebugCrossImpSubsection.h" |
| #include "llvm/ADT/ArrayRef.h" |
| #include "llvm/DebugInfo/CodeView/CodeViewError.h" |
| #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" |
| #include "llvm/Support/BinaryStreamReader.h" |
| #include "llvm/Support/BinaryStreamWriter.h" |
| #include "llvm/Support/Endian.h" |
| #include "llvm/Support/Error.h" |
| #include <algorithm> |
| #include <cstdint> |
| #include <utility> |
| #include <vector> |
| |
| using namespace llvm; |
| using namespace llvm::codeview; |
| |
| Error VarStreamArrayExtractor<CrossModuleImportItem>:: |
| operator()(BinaryStreamRef Stream, uint32_t &Len, |
| codeview::CrossModuleImportItem &Item) { |
| BinaryStreamReader Reader(Stream); |
| if (Reader.bytesRemaining() < sizeof(CrossModuleImport)) |
| return make_error<CodeViewError>( |
| cv_error_code::insufficient_buffer, |
| "Not enough bytes for a Cross Module Import Header!"); |
| if (auto EC = Reader.readObject(Item.Header)) |
| return EC; |
| if (Reader.bytesRemaining() < Item.Header->Count * sizeof(uint32_t)) |
| return make_error<CodeViewError>( |
| cv_error_code::insufficient_buffer, |
| "Not enough to read specified number of Cross Module References!"); |
| if (auto EC = Reader.readArray(Item.Imports, Item.Header->Count)) |
| return EC; |
| return Error::success(); |
| } |
| |
| Error DebugCrossModuleImportsSubsectionRef::initialize( |
| BinaryStreamReader Reader) { |
| return Reader.readArray(References, Reader.bytesRemaining()); |
| } |
| |
| Error DebugCrossModuleImportsSubsectionRef::initialize(BinaryStreamRef Stream) { |
| BinaryStreamReader Reader(Stream); |
| return initialize(Reader); |
| } |
| |
| void DebugCrossModuleImportsSubsection::addImport(StringRef Module, |
| uint32_t ImportId) { |
| Strings.insert(Module); |
| std::vector<support::ulittle32_t> Targets = {support::ulittle32_t(ImportId)}; |
| auto Result = Mappings.insert(std::make_pair(Module, Targets)); |
| if (!Result.second) |
| Result.first->getValue().push_back(Targets[0]); |
| } |
| |
| uint32_t DebugCrossModuleImportsSubsection::calculateSerializedSize() const { |
| uint32_t Size = 0; |
| for (const auto &Item : Mappings) { |
| Size += sizeof(CrossModuleImport); |
| Size += sizeof(support::ulittle32_t) * Item.second.size(); |
| } |
| return Size; |
| } |
| |
| Error DebugCrossModuleImportsSubsection::commit( |
| BinaryStreamWriter &Writer) const { |
| using T = decltype(&*Mappings.begin()); |
| std::vector<T> Ids; |
| Ids.reserve(Mappings.size()); |
| |
| for (const auto &M : Mappings) |
| Ids.push_back(&M); |
| |
| llvm::sort(Ids, [this](const T &L1, const T &L2) { |
| return Strings.getIdForString(L1->getKey()) < |
| Strings.getIdForString(L2->getKey()); |
| }); |
| |
| for (const auto &Item : Ids) { |
| CrossModuleImport Imp; |
| Imp.ModuleNameOffset = Strings.getIdForString(Item->getKey()); |
| Imp.Count = Item->getValue().size(); |
| if (auto EC = Writer.writeObject(Imp)) |
| return EC; |
| if (auto EC = Writer.writeArray(makeArrayRef(Item->getValue()))) |
| return EC; |
| } |
| return Error::success(); |
| } |