From 5e534c7fb357a157793e9a47c8a00880bdb18799 Mon Sep 17 00:00:00 2001 From: Zachary Turner Date: Fri, 15 Jul 2016 22:17:08 +0000 Subject: [PATCH] [pdb] Round trip the NameMap data structure to YAML. llvm-svn: 275628 --- .../llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h | 2 + llvm/include/llvm/DebugInfo/PDB/Raw/NameMap.h | 4 +- .../llvm/DebugInfo/PDB/Raw/NameMapBuilder.h | 7 ++++ llvm/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp | 8 ++++ llvm/lib/DebugInfo/PDB/Raw/NameMap.cpp | 44 ++++++++++++++++++++-- llvm/lib/DebugInfo/PDB/Raw/NameMapBuilder.cpp | 30 +++++++++++++-- llvm/test/DebugInfo/PDB/pdbdump-yaml.test | 7 ++++ llvm/tools/llvm-pdbdump/PdbYaml.cpp | 7 ++++ llvm/tools/llvm-pdbdump/PdbYaml.h | 11 ++++++ llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp | 6 +++ llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp | 3 ++ 11 files changed, 121 insertions(+), 8 deletions(-) diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h b/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h index 872f300..e9869bb 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h @@ -33,6 +33,8 @@ public: void setAge(uint32_t A); void setGuid(PDB_UniqueId G); + NameMapBuilder &getNamedStreamsBuilder(); + uint32_t calculateSerializedLength() const; Expected> build(PDBFile &File); diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/NameMap.h b/llvm/include/llvm/DebugInfo/PDB/Raw/NameMap.h index 0bd34db..8a9b0d1 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/NameMap.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/NameMap.h @@ -21,8 +21,10 @@ class StreamReader; class StreamWriter; } namespace pdb { - +class NameMapBuilder; class NameMap { + friend NameMapBuilder; + public: NameMap(); diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h b/llvm/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h index 698e767..bf49bfd 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h @@ -10,6 +10,7 @@ #ifndef LLVM_DEBUGINFO_PDB_RAW_PDBNAMEMAPBUILDER_H #define LLVM_DEBUGINFO_PDB_RAW_PDBNAMEMAPBUILDER_H +#include "llvm/ADT/StringMap.h" #include "llvm/Support/Error.h" #include @@ -23,9 +24,15 @@ class NameMapBuilder { public: NameMapBuilder(); + void addMapping(StringRef Name, uint32_t Mapping); + Expected> build(); uint32_t calculateSerializedLength() const; + +private: + StringMap Map; + uint32_t StringDataBytes = 0; }; } // end namespace pdb diff --git a/llvm/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp b/llvm/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp index 5a0e835..7be9cc3 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp +++ b/llvm/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp @@ -28,6 +28,10 @@ void InfoStreamBuilder::setAge(uint32_t A) { Age = A; } void InfoStreamBuilder::setGuid(PDB_UniqueId G) { Guid = G; } +NameMapBuilder &InfoStreamBuilder::getNamedStreamsBuilder() { + return NamedStreams; +} + uint32_t InfoStreamBuilder::calculateSerializedLength() const { return sizeof(InfoStream::HeaderInfo) + NamedStreams.calculateSerializedLength(); @@ -55,5 +59,9 @@ Expected> InfoStreamBuilder::build(PDBFile &File) { Info->Signature = *Sig; Info->Age = *Age; Info->Guid = *Guid; + auto NS = NamedStreams.build(); + if (!NS) + return NS.takeError(); + Info->NamedStreams = **NS; return std::move(Info); } diff --git a/llvm/lib/DebugInfo/PDB/Raw/NameMap.cpp b/llvm/lib/DebugInfo/PDB/Raw/NameMap.cpp index 3638380..b8a4eb7 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/NameMap.cpp +++ b/llvm/lib/DebugInfo/PDB/Raw/NameMap.cpp @@ -146,20 +146,56 @@ Error NameMap::load(codeview::StreamReader &Stream) { } Error NameMap::commit(codeview::StreamWriter &Writer) { - if (auto EC = Writer.writeInteger(0U)) // Number of bytes in table + // The first field is the number of bytes of string data. So add + // up the length of all strings plus a null terminator for each + // one. + uint32_t NumBytes = 0; + for (auto B = Mapping.begin(), E = Mapping.end(); B != E; ++B) { + NumBytes += B->getKeyLength() + 1; + } + + if (auto EC = Writer.writeInteger(NumBytes)) // Number of bytes of string data return EC; + // Now all of the string data itself. + for (auto B = Mapping.begin(), E = Mapping.end(); B != E; ++B) { + if (auto EC = Writer.writeZeroString(B->getKey())) + return EC; + } - if (auto EC = Writer.writeInteger(0U)) // Hash Size + if (auto EC = Writer.writeInteger(Mapping.size())) // Hash Size return EC; - if (auto EC = Writer.writeInteger(0U)) // Max Number of Strings + if (auto EC = Writer.writeInteger(Mapping.size())) // Max Number of Strings return EC; - if (auto EC = Writer.writeInteger(0U)) // Num Present Words + if (auto EC = Writer.writeInteger(Mapping.size())) // Num Present Words return EC; + // For each entry in the mapping, write a bit mask which represents a bucket + // to store it in. We don't use this, so the value we write isn't important + // to us, it just has to be there. + for (auto B = Mapping.begin(), E = Mapping.end(); B != E; ++B) { + if (auto EC = Writer.writeInteger(1U)) + return EC; + } + if (auto EC = Writer.writeInteger(0U)) // Num Deleted Words return EC; + + // Mappings of each word. + uint32_t OffsetSoFar = 0; + for (auto B = Mapping.begin(), E = Mapping.end(); B != E; ++B) { + // This is a list of key value pairs where the key is the offset into the + // strings buffer, and the value is a stream number. Write each pair. + if (auto EC = Writer.writeInteger(OffsetSoFar)) + return EC; + + if (auto EC = Writer.writeInteger(B->second)) + return EC; + + OffsetSoFar += B->getKeyLength() + 1; + } + return Error::success(); } diff --git a/llvm/lib/DebugInfo/PDB/Raw/NameMapBuilder.cpp b/llvm/lib/DebugInfo/PDB/Raw/NameMapBuilder.cpp index fe033c3..41c6c2c 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/NameMapBuilder.cpp +++ b/llvm/lib/DebugInfo/PDB/Raw/NameMapBuilder.cpp @@ -10,17 +10,41 @@ #include "llvm/DebugInfo/PDB/Raw/NameMapBuilder.h" #include "llvm/DebugInfo/PDB/Raw/NameMap.h" +#include "llvm/Support/Endian.h" using namespace llvm; using namespace llvm::pdb; NameMapBuilder::NameMapBuilder() {} +void NameMapBuilder::addMapping(StringRef Name, uint32_t Mapping) { + StringDataBytes += Name.size() + 1; + Map.insert({Name, Mapping}); +} + Expected> NameMapBuilder::build() { - return llvm::make_unique(); + auto Result = llvm::make_unique(); + Result->Mapping = Map; + return std::move(Result); } uint32_t NameMapBuilder::calculateSerializedLength() const { - // For now we write an empty name map, nothing else. - return 5 * sizeof(uint32_t); + uint32_t TotalLength = 0; + + TotalLength += sizeof(support::ulittle32_t); // StringDataBytes value + TotalLength += StringDataBytes; // actual string data + + TotalLength += sizeof(support::ulittle32_t); // Hash Size + TotalLength += sizeof(support::ulittle32_t); // Max Number of Strings + TotalLength += sizeof(support::ulittle32_t); // Num Present Words + // One bitmask word for each present entry + TotalLength += Map.size() * sizeof(support::ulittle32_t); + TotalLength += sizeof(support::ulittle32_t); // Num Deleted Words + + // For each present word, which we are treating as equivalent to the number of + // entries in the table, we have a pair of integers. An offset into the + // string data, and a corresponding stream number. + TotalLength += Map.size() * 2 * sizeof(support::ulittle32_t); + + return TotalLength; } diff --git a/llvm/test/DebugInfo/PDB/pdbdump-yaml.test b/llvm/test/DebugInfo/PDB/pdbdump-yaml.test index e0029d8..c90ae4c 100644 --- a/llvm/test/DebugInfo/PDB/pdbdump-yaml.test +++ b/llvm/test/DebugInfo/PDB/pdbdump-yaml.test @@ -74,6 +74,13 @@ ; YAML-NEXT: Guid: '{0B355641-86A0-A249-896F-9988FAE52FF0}' ; YAML-NEXT: Signature: 1424295906 ; YAML-NEXT: Version: VC70 +; YAML-NEXT: NamedStreams: +; YAML-NEXT: - Name: /names +; YAML-NEXT: StreamNum: 13 +; YAML-NEXT: - Name: /LinkInfo +; YAML-NEXT: StreamNum: 5 +; YAML-NEXT: - Name: /src/headerblock +; YAML-NEXT: StreamNum: 9 ; YAML-NEXT: ... ; NO-HEADERS: --- diff --git a/llvm/tools/llvm-pdbdump/PdbYaml.cpp b/llvm/tools/llvm-pdbdump/PdbYaml.cpp index 6525e3c..ac8e856 100644 --- a/llvm/tools/llvm-pdbdump/PdbYaml.cpp +++ b/llvm/tools/llvm-pdbdump/PdbYaml.cpp @@ -142,6 +142,7 @@ void MappingTraits::mapping(IO &IO, PdbInfoStream &Obj) { IO.mapRequired("Guid", Obj.Guid); IO.mapRequired("Signature", Obj.Signature); IO.mapRequired("Version", Obj.Version); + IO.mapRequired("NamedStreams", Obj.NamedStreams); } void MappingTraits::mapping(IO &IO, PdbDbiStream &Obj) { @@ -153,3 +154,9 @@ void MappingTraits::mapping(IO &IO, PdbDbiStream &Obj) { IO.mapRequired("Flags", Obj.Flags); IO.mapRequired("MachineType", Obj.MachineType); } + +void MappingTraits::mapping(IO &IO, + NamedStreamMapping &Obj) { + IO.mapRequired("Name", Obj.StreamName); + IO.mapRequired("StreamNum", Obj.StreamNumber); +} diff --git a/llvm/tools/llvm-pdbdump/PdbYaml.h b/llvm/tools/llvm-pdbdump/PdbYaml.h index 8a964a3..a7389af 100644 --- a/llvm/tools/llvm-pdbdump/PdbYaml.h +++ b/llvm/tools/llvm-pdbdump/PdbYaml.h @@ -38,11 +38,17 @@ struct StreamBlockList { std::vector Blocks; }; +struct NamedStreamMapping { + StringRef StreamName; + uint32_t StreamNumber; +}; + struct PdbInfoStream { PdbRaw_ImplVer Version; uint32_t Signature; uint32_t Age; PDB_UniqueId Guid; + std::vector NamedStreams; }; struct PdbDbiStream { @@ -92,10 +98,15 @@ template <> struct MappingTraits { template <> struct MappingTraits { static void mapping(IO &IO, pdb::yaml::PdbDbiStream &Obj); }; + +template <> struct MappingTraits { + static void mapping(IO &IO, pdb::yaml::NamedStreamMapping &Obj); +}; } } LLVM_YAML_IS_SEQUENCE_VECTOR(uint32_t) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::NamedStreamMapping) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::StreamBlockList) #endif // LLVM_TOOLS_LLVMPDBDUMP_PDBYAML_H diff --git a/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp b/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp index e216ab9..3385be9 100644 --- a/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp +++ b/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp @@ -106,6 +106,12 @@ Error YAMLOutputStyle::dumpPDBStream() { Obj.PdbStream->Guid = InfoS.getGuid(); Obj.PdbStream->Signature = InfoS.getSignature(); Obj.PdbStream->Version = InfoS.getVersion(); + for (auto &NS : InfoS.named_streams()) { + yaml::NamedStreamMapping Mapping; + Mapping.StreamName = NS.getKey(); + Mapping.StreamNumber = NS.getValue(); + Obj.PdbStream->NamedStreams.push_back(Mapping); + } return Error::success(); } diff --git a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp index 467b5bf..62f215d 100644 --- a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp +++ b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp @@ -361,6 +361,9 @@ static void yamlToPdb(StringRef Path) { InfoBuilder.setGuid(YamlObj.PdbStream->Guid); InfoBuilder.setSignature(YamlObj.PdbStream->Signature); InfoBuilder.setVersion(YamlObj.PdbStream->Version); + for (auto &NM : YamlObj.PdbStream->NamedStreams) + InfoBuilder.getNamedStreamsBuilder().addMapping(NM.StreamName, + NM.StreamNumber); } if (YamlObj.DbiStream.hasValue()) { -- 2.7.4