19df3605dSDimitry Andric //===- DebugStringTableSubsection.cpp - CodeView String Table -------------===// 2148779dfSDimitry Andric // 3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6148779dfSDimitry Andric // 7148779dfSDimitry Andric //===----------------------------------------------------------------------===// 8148779dfSDimitry Andric 9ee2f195dSDimitry Andric #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" 109df3605dSDimitry Andric #include "llvm/ADT/StringRef.h" 119df3605dSDimitry Andric #include "llvm/DebugInfo/CodeView/CodeView.h" 12148779dfSDimitry Andric #include "llvm/Support/BinaryStreamReader.h" 13148779dfSDimitry Andric #include "llvm/Support/BinaryStreamWriter.h" 149df3605dSDimitry Andric #include "llvm/Support/Error.h" 159df3605dSDimitry Andric #include <algorithm> 169df3605dSDimitry Andric #include <cassert> 179df3605dSDimitry Andric #include <cstdint> 18148779dfSDimitry Andric 19148779dfSDimitry Andric using namespace llvm; 20148779dfSDimitry Andric using namespace llvm::codeview; 21148779dfSDimitry Andric DebugStringTableSubsectionRef()22ee2f195dSDimitry AndricDebugStringTableSubsectionRef::DebugStringTableSubsectionRef() 23ee2f195dSDimitry Andric : DebugSubsectionRef(DebugSubsectionKind::StringTable) {} 24148779dfSDimitry Andric initialize(BinaryStreamRef Contents)25ee2f195dSDimitry AndricError DebugStringTableSubsectionRef::initialize(BinaryStreamRef Contents) { 26148779dfSDimitry Andric Stream = Contents; 27148779dfSDimitry Andric return Error::success(); 28148779dfSDimitry Andric } 299df3605dSDimitry Andric initialize(BinaryStreamReader & Reader)307ab83427SDimitry AndricError DebugStringTableSubsectionRef::initialize(BinaryStreamReader &Reader) { 317ab83427SDimitry Andric return Reader.readStreamRef(Stream); 327ab83427SDimitry Andric } 33148779dfSDimitry Andric 34ee2f195dSDimitry Andric Expected<StringRef> getString(uint32_t Offset) const35ee2f195dSDimitry AndricDebugStringTableSubsectionRef::getString(uint32_t Offset) const { 36148779dfSDimitry Andric BinaryStreamReader Reader(Stream); 37148779dfSDimitry Andric Reader.setOffset(Offset); 38148779dfSDimitry Andric StringRef Result; 39148779dfSDimitry Andric if (auto EC = Reader.readCString(Result)) 40148779dfSDimitry Andric return std::move(EC); 41148779dfSDimitry Andric return Result; 42148779dfSDimitry Andric } 43148779dfSDimitry Andric DebugStringTableSubsection()44ee2f195dSDimitry AndricDebugStringTableSubsection::DebugStringTableSubsection() 45ee2f195dSDimitry Andric : DebugSubsection(DebugSubsectionKind::StringTable) {} 46ee2f195dSDimitry Andric insert(StringRef S)47ee2f195dSDimitry Andricuint32_t DebugStringTableSubsection::insert(StringRef S) { 48eb11fae6SDimitry Andric auto P = StringToId.insert({S, StringSize}); 49148779dfSDimitry Andric 50148779dfSDimitry Andric // If a given string didn't exist in the string table, we want to increment 51eb11fae6SDimitry Andric // the string table size and insert it into the reverse lookup. 52eb11fae6SDimitry Andric if (P.second) { 53eb11fae6SDimitry Andric IdToString.insert({P.first->getValue(), P.first->getKey()}); 54148779dfSDimitry Andric StringSize += S.size() + 1; // +1 for '\0' 55eb11fae6SDimitry Andric } 56eb11fae6SDimitry Andric 57148779dfSDimitry Andric return P.first->second; 58148779dfSDimitry Andric } 59148779dfSDimitry Andric calculateSerializedSize() const60ee2f195dSDimitry Andricuint32_t DebugStringTableSubsection::calculateSerializedSize() const { 61ee2f195dSDimitry Andric return StringSize; 62ee2f195dSDimitry Andric } 63148779dfSDimitry Andric commit(BinaryStreamWriter & Writer) const64ee2f195dSDimitry AndricError DebugStringTableSubsection::commit(BinaryStreamWriter &Writer) const { 657ab83427SDimitry Andric uint32_t Begin = Writer.getOffset(); 667ab83427SDimitry Andric uint32_t End = Begin + StringSize; 67148779dfSDimitry Andric 687c7aba6eSDimitry Andric // Write a null string at the beginning. 697c7aba6eSDimitry Andric if (auto EC = Writer.writeCString(StringRef())) 707c7aba6eSDimitry Andric return EC; 717c7aba6eSDimitry Andric 72eb11fae6SDimitry Andric for (auto &Pair : StringToId) { 73148779dfSDimitry Andric StringRef S = Pair.getKey(); 747ab83427SDimitry Andric uint32_t Offset = Begin + Pair.getValue(); 75148779dfSDimitry Andric Writer.setOffset(Offset); 76148779dfSDimitry Andric if (auto EC = Writer.writeCString(S)) 77148779dfSDimitry Andric return EC; 787ab83427SDimitry Andric assert(Writer.getOffset() <= End); 79148779dfSDimitry Andric } 80148779dfSDimitry Andric 817ab83427SDimitry Andric Writer.setOffset(End); 827c7aba6eSDimitry Andric assert((End - Begin) == StringSize); 83148779dfSDimitry Andric return Error::success(); 84148779dfSDimitry Andric } 85148779dfSDimitry Andric size() const86eb11fae6SDimitry Andricuint32_t DebugStringTableSubsection::size() const { return StringToId.size(); } 87148779dfSDimitry Andric sortedIds() const88eb11fae6SDimitry Andricstd::vector<uint32_t> DebugStringTableSubsection::sortedIds() const { 89eb11fae6SDimitry Andric std::vector<uint32_t> Result; 90eb11fae6SDimitry Andric Result.reserve(IdToString.size()); 91eb11fae6SDimitry Andric for (const auto &Entry : IdToString) 92eb11fae6SDimitry Andric Result.push_back(Entry.first); 93d8e91e46SDimitry Andric llvm::sort(Result); 94eb11fae6SDimitry Andric return Result; 95eb11fae6SDimitry Andric } 96eb11fae6SDimitry Andric getIdForString(StringRef S) const97eb11fae6SDimitry Andricuint32_t DebugStringTableSubsection::getIdForString(StringRef S) const { 98eb11fae6SDimitry Andric auto Iter = StringToId.find(S); 99eb11fae6SDimitry Andric assert(Iter != StringToId.end()); 100eb11fae6SDimitry Andric return Iter->second; 101eb11fae6SDimitry Andric } 102eb11fae6SDimitry Andric getStringForId(uint32_t Id) const103eb11fae6SDimitry AndricStringRef DebugStringTableSubsection::getStringForId(uint32_t Id) const { 104eb11fae6SDimitry Andric auto Iter = IdToString.find(Id); 105eb11fae6SDimitry Andric assert(Iter != IdToString.end()); 106d288ef4cSDimitry Andric return Iter->second; 107148779dfSDimitry Andric } 108