18456b16eSEugene Zelenko //===- DebugCrossImpSubsection.cpp ----------------------------------------===//
2349c18f8SZachary Turner //
3*2946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*2946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
5*2946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6349c18f8SZachary Turner //
7349c18f8SZachary Turner //===----------------------------------------------------------------------===//
8349c18f8SZachary Turner
9349c18f8SZachary Turner #include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h"
108456b16eSEugene Zelenko #include "llvm/ADT/ArrayRef.h"
11349c18f8SZachary Turner #include "llvm/DebugInfo/CodeView/CodeViewError.h"
12349c18f8SZachary Turner #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
138456b16eSEugene Zelenko #include "llvm/Support/BinaryStreamReader.h"
148456b16eSEugene Zelenko #include "llvm/Support/BinaryStreamWriter.h"
158456b16eSEugene Zelenko #include "llvm/Support/Endian.h"
168456b16eSEugene Zelenko #include "llvm/Support/Error.h"
178456b16eSEugene Zelenko #include <algorithm>
188456b16eSEugene Zelenko #include <cstdint>
198456b16eSEugene Zelenko #include <utility>
208456b16eSEugene Zelenko #include <vector>
21349c18f8SZachary Turner
22349c18f8SZachary Turner using namespace llvm;
23349c18f8SZachary Turner using namespace llvm::codeview;
24349c18f8SZachary Turner
257e62cd17SZachary Turner Error VarStreamArrayExtractor<CrossModuleImportItem>::
operator ()(BinaryStreamRef Stream,uint32_t & Len,codeview::CrossModuleImportItem & Item)267e62cd17SZachary Turner operator()(BinaryStreamRef Stream, uint32_t &Len,
27349c18f8SZachary Turner codeview::CrossModuleImportItem &Item) {
28349c18f8SZachary Turner BinaryStreamReader Reader(Stream);
29349c18f8SZachary Turner if (Reader.bytesRemaining() < sizeof(CrossModuleImport))
30349c18f8SZachary Turner return make_error<CodeViewError>(
31349c18f8SZachary Turner cv_error_code::insufficient_buffer,
32349c18f8SZachary Turner "Not enough bytes for a Cross Module Import Header!");
33349c18f8SZachary Turner if (auto EC = Reader.readObject(Item.Header))
34349c18f8SZachary Turner return EC;
35349c18f8SZachary Turner if (Reader.bytesRemaining() < Item.Header->Count * sizeof(uint32_t))
36349c18f8SZachary Turner return make_error<CodeViewError>(
37349c18f8SZachary Turner cv_error_code::insufficient_buffer,
38349c18f8SZachary Turner "Not enough to read specified number of Cross Module References!");
39349c18f8SZachary Turner if (auto EC = Reader.readArray(Item.Imports, Item.Header->Count))
40349c18f8SZachary Turner return EC;
41349c18f8SZachary Turner return Error::success();
42349c18f8SZachary Turner }
43349c18f8SZachary Turner
initialize(BinaryStreamReader Reader)44349c18f8SZachary Turner Error DebugCrossModuleImportsSubsectionRef::initialize(
45349c18f8SZachary Turner BinaryStreamReader Reader) {
46349c18f8SZachary Turner return Reader.readArray(References, Reader.bytesRemaining());
47349c18f8SZachary Turner }
48349c18f8SZachary Turner
initialize(BinaryStreamRef Stream)49349c18f8SZachary Turner Error DebugCrossModuleImportsSubsectionRef::initialize(BinaryStreamRef Stream) {
50349c18f8SZachary Turner BinaryStreamReader Reader(Stream);
51349c18f8SZachary Turner return initialize(Reader);
52349c18f8SZachary Turner }
53349c18f8SZachary Turner
addImport(StringRef Module,uint32_t ImportId)54349c18f8SZachary Turner void DebugCrossModuleImportsSubsection::addImport(StringRef Module,
55349c18f8SZachary Turner uint32_t ImportId) {
56349c18f8SZachary Turner Strings.insert(Module);
57349c18f8SZachary Turner std::vector<support::ulittle32_t> Targets = {support::ulittle32_t(ImportId)};
58349c18f8SZachary Turner auto Result = Mappings.insert(std::make_pair(Module, Targets));
59349c18f8SZachary Turner if (!Result.second)
60349c18f8SZachary Turner Result.first->getValue().push_back(Targets[0]);
61349c18f8SZachary Turner }
62349c18f8SZachary Turner
calculateSerializedSize() const63349c18f8SZachary Turner uint32_t DebugCrossModuleImportsSubsection::calculateSerializedSize() const {
64349c18f8SZachary Turner uint32_t Size = 0;
65349c18f8SZachary Turner for (const auto &Item : Mappings) {
66349c18f8SZachary Turner Size += sizeof(CrossModuleImport);
67349c18f8SZachary Turner Size += sizeof(support::ulittle32_t) * Item.second.size();
68349c18f8SZachary Turner }
69349c18f8SZachary Turner return Size;
70349c18f8SZachary Turner }
71349c18f8SZachary Turner
commit(BinaryStreamWriter & Writer) const72349c18f8SZachary Turner Error DebugCrossModuleImportsSubsection::commit(
73349c18f8SZachary Turner BinaryStreamWriter &Writer) const {
74349c18f8SZachary Turner using T = decltype(&*Mappings.begin());
75349c18f8SZachary Turner std::vector<T> Ids;
76349c18f8SZachary Turner Ids.reserve(Mappings.size());
77349c18f8SZachary Turner
78349c18f8SZachary Turner for (const auto &M : Mappings)
79349c18f8SZachary Turner Ids.push_back(&M);
80349c18f8SZachary Turner
810cac726aSFangrui Song llvm::sort(Ids, [this](const T &L1, const T &L2) {
8271d36ad9SZachary Turner return Strings.getIdForString(L1->getKey()) <
8371d36ad9SZachary Turner Strings.getIdForString(L2->getKey());
84349c18f8SZachary Turner });
85349c18f8SZachary Turner
86349c18f8SZachary Turner for (const auto &Item : Ids) {
87349c18f8SZachary Turner CrossModuleImport Imp;
8871d36ad9SZachary Turner Imp.ModuleNameOffset = Strings.getIdForString(Item->getKey());
89349c18f8SZachary Turner Imp.Count = Item->getValue().size();
90349c18f8SZachary Turner if (auto EC = Writer.writeObject(Imp))
91349c18f8SZachary Turner return EC;
92349c18f8SZachary Turner if (auto EC = Writer.writeArray(makeArrayRef(Item->getValue())))
93349c18f8SZachary Turner return EC;
94349c18f8SZachary Turner }
95349c18f8SZachary Turner return Error::success();
96349c18f8SZachary Turner }
97