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