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