xref: /freebsd/contrib/llvm-project/llvm/lib/DebugInfo/CodeView/DebugCrossImpSubsection.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
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