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(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(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({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({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(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(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(IdToString.size()); 90 for (const auto &Entry : IdToString) 91 Result.push_back(Entry.first); 92 llvm::sort(Result); 93 return Result; 94 } 95 96 uint32_t DebugStringTableSubsection::getIdForString(StringRef S) const { 97 auto Iter = StringToId.find(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(Id); 104 assert(Iter != IdToString.end()); 105 return Iter->second; 106 } 107