1 | //===- DebugStringTableSubsection.cpp - CodeView String Table -------------===// |
---|---|
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/DebugStringTableSubsection.h" |
10 | #include "llvm/ADT/StringRef.h" |
11 | #include "llvm/DebugInfo/CodeView/CodeView.h" |
12 | #include "llvm/Support/BinaryStreamReader.h" |
13 | #include "llvm/Support/BinaryStreamWriter.h" |
14 | #include "llvm/Support/Error.h" |
15 | #include <algorithm> |
16 | #include <cassert> |
17 | #include <cstdint> |
18 | |
19 | using namespace llvm; |
20 | using namespace llvm::codeview; |
21 | |
22 | DebugStringTableSubsectionRef::DebugStringTableSubsectionRef() |
23 | : DebugSubsectionRef(DebugSubsectionKind::StringTable) {} |
24 | |
25 | Error DebugStringTableSubsectionRef::initialize(BinaryStreamRef Contents) { |
26 | Stream = Contents; |
27 | return Error::success(); |
28 | } |
29 | |
30 | Error DebugStringTableSubsectionRef::initialize(BinaryStreamReader &Reader) { |
31 | return Reader.readStreamRef(Ref&: Stream); |
32 | } |
33 | |
34 | Expected<StringRef> |
35 | DebugStringTableSubsectionRef::getString(uint32_t Offset) const { |
36 | BinaryStreamReader Reader(Stream); |
37 | Reader.setOffset(Offset); |
38 | StringRef Result; |
39 | if (auto EC = Reader.readCString(Dest&: Result)) |
40 | return std::move(EC); |
41 | return Result; |
42 | } |
43 | |
44 | DebugStringTableSubsection::DebugStringTableSubsection() |
45 | : DebugSubsection(DebugSubsectionKind::StringTable) {} |
46 | |
47 | uint32_t DebugStringTableSubsection::insert(StringRef S) { |
48 | auto P = StringToId.insert(KV: {S, StringSize}); |
49 | |
50 | // If a given string didn't exist in the string table, we want to increment |
51 | // the string table size and insert it into the reverse lookup. |
52 | if (P.second) { |
53 | IdToString.insert(KV: {P.first->getValue(), P.first->getKey()}); |
54 | StringSize += S.size() + 1; // +1 for '\0' |
55 | } |
56 | |
57 | return P.first->second; |
58 | } |
59 | |
60 | uint32_t DebugStringTableSubsection::calculateSerializedSize() const { |
61 | return StringSize; |
62 | } |
63 | |
64 | Error DebugStringTableSubsection::commit(BinaryStreamWriter &Writer) const { |
65 | uint32_t Begin = Writer.getOffset(); |
66 | uint32_t End = Begin + StringSize; |
67 | |
68 | // Write a null string at the beginning. |
69 | if (auto EC = Writer.writeCString(Str: StringRef())) |
70 | return EC; |
71 | |
72 | for (auto &Pair : StringToId) { |
73 | StringRef S = Pair.getKey(); |
74 | uint32_t Offset = Begin + Pair.getValue(); |
75 | Writer.setOffset(Offset); |
76 | if (auto EC = Writer.writeCString(Str: S)) |
77 | return EC; |
78 | assert(Writer.getOffset() <= End); |
79 | } |
80 | |
81 | Writer.setOffset(End); |
82 | assert((End - Begin) == StringSize); |
83 | return Error::success(); |
84 | } |
85 | |
86 | uint32_t DebugStringTableSubsection::size() const { return StringToId.size(); } |
87 | |
88 | std::vector<uint32_t> DebugStringTableSubsection::sortedIds() const { |
89 | std::vector<uint32_t> Result; |
90 | Result.reserve(n: IdToString.size()); |
91 | for (const auto &Entry : IdToString) |
92 | Result.push_back(x: Entry.first); |
93 | llvm::sort(C&: Result); |
94 | return Result; |
95 | } |
96 | |
97 | uint32_t DebugStringTableSubsection::getIdForString(StringRef S) const { |
98 | auto Iter = StringToId.find(Key: S); |
99 | assert(Iter != StringToId.end()); |
100 | return Iter->second; |
101 | } |
102 | |
103 | StringRef DebugStringTableSubsection::getStringForId(uint32_t Id) const { |
104 | auto Iter = IdToString.find(Val: Id); |
105 | assert(Iter != IdToString.end()); |
106 | return Iter->second; |
107 | } |
108 |