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 <algorithm> |
18 | #include <cstdint> |
19 | #include <utility> |
20 | #include <vector> |
21 | |
22 | using namespace llvm; |
23 | using namespace llvm::codeview; |
24 | |
25 | Error VarStreamArrayExtractor<CrossModuleImportItem>:: |
26 | (BinaryStreamRef Stream, uint32_t &Len, |
27 | codeview::CrossModuleImportItem &Item) { |
28 | BinaryStreamReader Reader(Stream); |
29 | if (Reader.bytesRemaining() < sizeof(CrossModuleImport)) |
30 | return make_error<CodeViewError>( |
31 | Args: cv_error_code::insufficient_buffer, |
32 | Args: "Not enough bytes for a Cross Module Import Header!" ); |
33 | if (auto EC = Reader.readObject(Dest&: Item.Header)) |
34 | return EC; |
35 | if (Reader.bytesRemaining() < Item.Header->Count * sizeof(uint32_t)) |
36 | return make_error<CodeViewError>( |
37 | Args: cv_error_code::insufficient_buffer, |
38 | Args: "Not enough to read specified number of Cross Module References!" ); |
39 | if (auto EC = Reader.readArray(Array&: Item.Imports, NumItems: Item.Header->Count)) |
40 | return EC; |
41 | return Error::success(); |
42 | } |
43 | |
44 | Error DebugCrossModuleImportsSubsectionRef::initialize( |
45 | BinaryStreamReader Reader) { |
46 | return Reader.readArray(Array&: References, Size: Reader.bytesRemaining()); |
47 | } |
48 | |
49 | Error DebugCrossModuleImportsSubsectionRef::initialize(BinaryStreamRef Stream) { |
50 | BinaryStreamReader Reader(Stream); |
51 | return initialize(Reader); |
52 | } |
53 | |
54 | void DebugCrossModuleImportsSubsection::addImport(StringRef Module, |
55 | uint32_t ImportId) { |
56 | Strings.insert(S: Module); |
57 | std::vector<support::ulittle32_t> Targets = {support::ulittle32_t(ImportId)}; |
58 | auto Result = Mappings.insert(KV: std::make_pair(x&: Module, y&: Targets)); |
59 | if (!Result.second) |
60 | Result.first->getValue().push_back(x: Targets[0]); |
61 | } |
62 | |
63 | uint32_t DebugCrossModuleImportsSubsection::calculateSerializedSize() const { |
64 | uint32_t Size = 0; |
65 | for (const auto &Item : Mappings) { |
66 | Size += sizeof(CrossModuleImport); |
67 | Size += sizeof(support::ulittle32_t) * Item.second.size(); |
68 | } |
69 | return Size; |
70 | } |
71 | |
72 | Error DebugCrossModuleImportsSubsection::commit( |
73 | BinaryStreamWriter &Writer) const { |
74 | using T = decltype(&*Mappings.begin()); |
75 | std::vector<T> Ids; |
76 | Ids.reserve(n: Mappings.size()); |
77 | |
78 | for (const auto &M : Mappings) |
79 | Ids.push_back(x: &M); |
80 | |
81 | llvm::sort(C&: Ids, Comp: [this](const T &L1, const T &L2) { |
82 | return Strings.getIdForString(S: L1->getKey()) < |
83 | Strings.getIdForString(S: L2->getKey()); |
84 | }); |
85 | |
86 | for (const auto &Item : Ids) { |
87 | CrossModuleImport Imp; |
88 | Imp.ModuleNameOffset = Strings.getIdForString(S: Item->getKey()); |
89 | Imp.Count = Item->getValue().size(); |
90 | if (auto EC = Writer.writeObject(Obj: Imp)) |
91 | return EC; |
92 | if (auto EC = Writer.writeArray(Array: ArrayRef(Item->getValue()))) |
93 | return EC; |
94 | } |
95 | return Error::success(); |
96 | } |
97 | |