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