xref: /freebsd/contrib/llvm-project/llvm/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp (revision ee67461e56828dd1f8de165947ba83f6d9148a87)
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(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(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({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({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(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(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(IdToString.size());
91    for (const auto &Entry : IdToString)
92      Result.push_back(Entry.first);
93    llvm::sort(Result);
94    return Result;
95  }
96  
97  uint32_t DebugStringTableSubsection::getIdForString(StringRef S) const {
98    auto Iter = StringToId.find(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(Id);
105    assert(Iter != IdToString.end());
106    return Iter->second;
107  }
108