llvm.org GIT mirror llvm / 87f3ec2
[llvm-pdbutil] Add the ability to dump raw bytes from the file. Normally we can only make sense of the content of a PDB in terms of streams and blocks, but in some cases it may be useful to dump bytes at a specific absolute file offset. For example, if you know that some interesting data is at a particular location and you want to see some surrounding data. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@306146 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 2 years ago
6 changed file(s) with 93 addition(s) and 26 deletion(s). Raw diff Collapse all Expand all
None ; RUN: llvm-pdbutil bytes -block-data=0 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK0 %s
1 ; RUN: llvm-pdbutil bytes -block-data=0-1 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK01 %s
2 ; RUN: llvm-pdbutil bytes -block-data=0-0x1 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK01 %s
3 ; RUN: not llvm-pdbutil bytes -block-data=0,1 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
4 ; RUN: not llvm-pdbutil bytes -block-data=0a1 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
5 ; RUN: not llvm-pdbutil bytes -block-data=0- %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
0 ; RUN: llvm-pdbutil bytes -block-range=0 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK0 %s
1 ; RUN: llvm-pdbutil bytes -block-range=0-1 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK01 %s
2 ; RUN: llvm-pdbutil bytes -block-range=0-0x1 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK01 %s
3 ; RUN: not llvm-pdbutil bytes -block-range=0,1 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
4 ; RUN: not llvm-pdbutil bytes -block-range=0a1 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
5 ; RUN: not llvm-pdbutil bytes -block-range=0- %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
66
77 BLOCK0: MSF Blocks
88 BLOCK0-NEXT: ============================================================
0 ; RUN: llvm-pdbutil bytes -byte-range=20-60 %p/Inputs/empty.pdb | FileCheck --check-prefix=VALID %s
1 ; RUN: not llvm-pdbutil bytes -byte-range=100-20 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=INVALID %s
2 ; RUN: not llvm-pdbutil bytes -byte-range=100000-200000 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=INVALID-RANGE %s
3
4
5 VALID: MSF Bytes
6 VALID-NEXT: ============================================================
7 VALID-NEXT: Bytes (
8 VALID-NEXT: 0014: 372E3030 0D0A1A44 53000000 00100000 02000000 19000000 88000000 00000000 |7.00...DS.......................|
9 VALID-NEXT: 0034: 18000000 00000000 00 |.........|
10 VALID-NEXT: )
11
12 INVALID: llvm-pdbutil: Invalid byte range specified. Max < Min
13
14 INVALID-RANGE: llvm-pdbutil: Invalid byte range specified. Requested byte larger than file size
9595 P.NewLine();
9696 }
9797
98 if (opts::bytes::DumpByteRange.hasValue()) {
99 auto &R = *opts::bytes::DumpByteRange;
100 uint32_t Max = R.Max.getValueOr(File.getFileSize());
101
102 if (Max < R.Min)
103 return make_error("Invalid byte range specified. Max < Min",
104 inconvertibleErrorCode());
105 if (Max >= File.getFileSize())
106 return make_error(
107 "Invalid byte range specified. Requested byte larger than file size",
108 inconvertibleErrorCode());
109
110 dumpByteRanges(R.Min, Max);
111 P.NewLine();
112 }
113
98114 if (!opts::bytes::DumpStreamData.empty()) {
99115 dumpStreamBytes();
100116 P.NewLine();
121137 }
122138 }
123139
140 void BytesOutputStyle::dumpByteRanges(uint32_t Min, uint32_t Max) {
141 printHeader(P, "MSF Bytes");
142
143 AutoIndent Indent(P);
144
145 BinaryStreamReader Reader(File.getMsfBuffer());
146 ArrayRef Data;
147 consumeError(Reader.skip(Min));
148 uint32_t Size = Max - Min + 1;
149 auto EC = Reader.readBytes(Data, Size);
150 assert(!EC);
151 consumeError(std::move(EC));
152 P.formatBinary("Bytes", Data, Min);
153 }
154
124155 void BytesOutputStyle::dumpStreamBytes() {
125156 if (StreamPurposes.empty())
126157 discoverStreamPurposes(File, StreamPurposes);
2828
2929 private:
3030 void dumpBlockRanges(uint32_t Min, uint32_t Max);
31 void dumpByteRanges(uint32_t Min, uint32_t Max);
3132 void dumpStreamBytes();
3233
3334 PDBFile &File;
266266 cl::OptionCategory FileOptions("Module & File Options");
267267
268268 namespace bytes {
269 llvm::Optional<BlockRange> DumpBlockRange;
269 llvm::Optional<NumberRange> DumpBlockRange;
270 llvm::Optional DumpByteRange;
271
272 cl::opt DumpBlockRangeOpt(
273 "block-range", cl::value_desc("start[-end]"),
274 cl::desc("Dump binary data from specified range of blocks."),
275 cl::sub(BytesSubcommand));
270276
271277 cl::opt
272 DumpBlockRangeOpt("block-data", cl::value_desc("start[-end]"),
273 cl::desc("Dump binary data from specified range."),
274 cl::sub(BytesSubcommand));
278 DumpByteRangeOpt("byte-range", cl::value_desc("start[-end]"),
279 cl::desc("Dump binary data from specified range of bytes"),
280 cl::sub(BytesSubcommand));
275281
276282 cl::list
277283 DumpStreamData("stream-data", cl::CommaSeparated, cl::ZeroOrMore,
902908 ExitOnErr(Builder.commit(OutFile));
903909 }
904910
905 static bool validateBlockRangeArgument() {
906 if (opts::bytes::DumpBlockRangeOpt.empty())
911 static bool parseRange(StringRef Str,
912 Optional &Parsed) {
913 if (Str.empty())
907914 return true;
908915
909916 llvm::Regex R("^([^-]+)(-([^-]+))?$");
910917 llvm::SmallVector Matches;
911 if (!R.match(opts::bytes::DumpBlockRangeOpt, &Matches))
918 if (!R.match(Str, &Matches))
912919 return false;
913920
914 opts::bytes::DumpBlockRange.emplace();
915 if (!to_integer(Matches[1], opts::bytes::DumpBlockRange->Min))
921 Parsed.emplace();
922 if (!to_integer(Matches[1], Parsed->Min))
916923 return false;
917924
918925 if (!Matches[3].empty()) {
919 opts::bytes::DumpBlockRange->Max.emplace();
920 if (!to_integer(Matches[3], *opts::bytes::DumpBlockRange->Max))
926 Parsed->Max.emplace();
927 if (!to_integer(Matches[3], *Parsed->Max))
921928 return false;
922929 }
923930 return true;
938945 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
939946
940947 cl::ParseCommandLineOptions(argv.size(), argv.data(), "LLVM PDB Dumper\n");
941 if (!validateBlockRangeArgument()) {
942 errs() << "Argument '" << opts::bytes::DumpBlockRangeOpt
943 << "' invalid format.\n";
944 errs().flush();
945 exit(1);
948
949 if (opts::BytesSubcommand) {
950 if (!parseRange(opts::bytes::DumpBlockRangeOpt,
951 opts::bytes::DumpBlockRange)) {
952 errs() << "Argument '" << opts::bytes::DumpBlockRangeOpt
953 << "' invalid format.\n";
954 errs().flush();
955 exit(1);
956 }
957 if (!parseRange(opts::bytes::DumpByteRangeOpt,
958 opts::bytes::DumpByteRange)) {
959 errs() << "Argument '" << opts::bytes::DumpByteRangeOpt
960 << "' invalid format.\n";
961 errs().flush();
962 exit(1);
963 }
946964 }
947965
948966 if (opts::DumpSubcommand) {
9292 }
9393
9494 namespace bytes {
95 struct BlockRange {
96 uint32_t Min;
97 llvm::Optional Max;
95 struct NumberRange {
96 uint64_t Min;
97 llvm::Optional Max;
9898 };
99 extern llvm::Optional DumpBlockRange;
99
100 extern llvm::Optional DumpBlockRange;
101 extern llvm::Optional DumpByteRange;
100102 extern llvm::cl::list DumpStreamData;
101103 } // namespace bytes
102104