llvm.org GIT mirror llvm / 55ff94d
[llvm-pdbutil] Add an export subcommand. This command can dump the binary contents of a stream to a file. This is useful when you want to do side-by-side comparisons of a specific stream from two PDBs to examine the differences between them. You can export both of them to a file, then open them up side by side in a hex editor (for example), so as to eliminate any differences that might arise from the contents being on different blocks in the PDB. In subsequent patches I plan to improve the "explain" subcommand so that you can explain the contents of a binary file that isn't necessarily a full PDB, but one of these dumped streams, by telling the subcommand how to interpret the contents. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@329002 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 1 year, 5 months ago
7 changed file(s) with 86 addition(s) and 5 deletion(s). Raw diff Collapse all Expand all
5151
5252 BinarySubstreamRef getNamedStreamsBuffer() const;
5353
54 uint32_t getNamedStreamIndex(llvm::StringRef Name) const;
54 Expected getNamedStreamIndex(llvm::StringRef Name) const;
5555 StringMap named_streams() const;
5656
5757 private:
8585
8686 uint32_t InfoStream::getStreamSize() const { return Stream->getLength(); }
8787
88 uint32_t InfoStream::getNamedStreamIndex(llvm::StringRef Name) const {
88 Expected InfoStream::getNamedStreamIndex(llvm::StringRef Name) const {
8989 uint32_t Result;
9090 if (!NamedStreams.get(Name, Result))
91 return 0;
91 return make_error(raw_error_code::no_stream);
9292 return Result;
9393 }
9494
369369 if (!IS)
370370 return IS.takeError();
371371
372 uint32_t NameStreamIndex = IS->getNamedStreamIndex("/names");
372 Expected ExpectedNSI = IS->getNamedStreamIndex("/names");
373 if (!ExpectedNSI)
374 return ExpectedNSI.takeError();
375 uint32_t NameStreamIndex = *ExpectedNSI;
373376
374377 auto NS =
375378 safelyCreateIndexedStream(ContainerLayout, *Buffer, NameStreamIndex);
444447 auto IS = getPDBInfoStream();
445448 if (!IS)
446449 return false;
447 return IS->getNamedStreamIndex("/names") < getNumStreams();
450 Expected ExpectedNSI = IS->getNamedStreamIndex("/names");
451 if (!ExpectedNSI) {
452 consumeError(ExpectedNSI.takeError());
453 return false;
454 }
455 assert(*ExpectedNSI < getNumStreams());
456 return true;
448457 }
449458
450459 /// Wrapper around MappedBlockStream::createIndexedStream() that checks if a
0 ; RUN: llvm-pdbutil export -stream=2 -out=%t.tpi.bin %p/Inputs/InjectedSource.pdb
1 ; RUN: diff %t.tpi.bin %p/Inputs/tpi.bin
4949 #include "llvm/DebugInfo/PDB/IPDBSession.h"
5050 #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
5151 #include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h"
52 #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
5253 #include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
5354 #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
5455 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
113114
114115 cl::SubCommand ExplainSubcommand("explain",
115116 "Explain the meaning of a file offset");
117
118 cl::SubCommand ExportSubcommand("export",
119 "Write binary data from a stream to a file");
116120
117121 cl::OptionCategory TypeCategory("Symbol Type Options");
118122 cl::OptionCategory FilterCategory("Filtering and Sorting Options");
617621 cl::list Offsets("offset", cl::desc("The file offset to explain"),
618622 cl::sub(ExplainSubcommand), cl::OneOrMore);
619623 } // namespace explain
624
625 namespace exportstream {
626 cl::list InputFilename(cl::Positional,
627 cl::desc(""), cl::Required,
628 cl::sub(ExportSubcommand));
629 cl::opt OutputFile("out",
630 cl::desc("The file to write the stream to"),
631 cl::Required, cl::sub(ExportSubcommand));
632 cl::opt
633 Stream("stream", cl::Required,
634 cl::desc("The index or name of the stream whose contents to export"),
635 cl::sub(ExportSubcommand));
636 cl::opt ForceName("name",
637 cl::desc("Force the interpretation of -stream as a "
638 "string, even if it is a valid integer"),
639 cl::sub(ExportSubcommand), cl::Optional,
640 cl::init(false));
641 } // namespace exportstream
620642 }
621643
622644 static ExitOnError ExitOnErr;
10951117
10961118 ExitOnErr(O->dump());
10971119 }
1120 }
1121
1122 static void exportStream() {
1123 std::unique_ptr Session;
1124 PDBFile &File = loadPDB(opts::exportstream::InputFilename.front(), Session);
1125
1126 std::unique_ptr SourceStream;
1127 uint32_t Index = 0;
1128 bool Success = false;
1129 std::string OutFileName = opts::exportstream::OutputFile;
1130
1131 if (!opts::exportstream::ForceName) {
1132 // First try to parse it as an integer, if it fails fall back to treating it
1133 // as a named stream.
1134 if (to_integer(opts::exportstream::Stream, Index)) {
1135 if (Index >= File.getNumStreams()) {
1136 errs() << "Error: " << Index << " is not a valid stream index.\n";
1137 exit(1);
1138 }
1139 Success = true;
1140 outs() << "Dumping contents of stream index " << Index << " to file "
1141 << OutFileName << ".\n";
1142 }
1143 }
1144
1145 if (!Success) {
1146 InfoStream &IS = cantFail(File.getPDBInfoStream());
1147 Index = ExitOnErr(IS.getNamedStreamIndex(opts::exportstream::Stream));
1148 outs() << "Dumping contents of stream '" << opts::exportstream::Stream
1149 << "' (index " << Index << ") to file " << OutFileName << ".\n";
1150 }
1151
1152 SourceStream = MappedBlockStream::createIndexedStream(
1153 File.getMsfLayout(), File.getMsfBuffer(), Index, File.getAllocator());
1154 auto OutFile = ExitOnErr(
1155 FileOutputBuffer::create(OutFileName, SourceStream->getLength()));
1156 FileBufferByteStream DestStream(std::move(OutFile), llvm::support::little);
1157 BinaryStreamWriter Writer(DestStream);
1158 ExitOnErr(Writer.writeStreamRef(*SourceStream));
1159 ExitOnErr(DestStream.commit());
10981160 }
10991161
11001162 static bool parseRange(StringRef Str,
12731335 mergePdbs();
12741336 } else if (opts::ExplainSubcommand) {
12751337 explain();
1338 } else if (opts::ExportSubcommand) {
1339 exportStream();
12761340 }
12771341
12781342 outs().flush();
192192 extern llvm::cl::list InputFilename;
193193 extern llvm::cl::list Offsets;
194194 } // namespace explain
195
196 namespace exportstream {
197 extern llvm::cl::opt OutputFile;
198 extern llvm::cl::opt Stream;
199 extern llvm::cl::opt ForceName;
200 } // namespace exportstream
195201 }
196202
197203 #endif