mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:32:44 +01:00
[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. llvm-svn: 306146
This commit is contained in:
parent
dc91b9896c
commit
e26961f9a6
@ -1,9 +1,9 @@
|
||||
; RUN: llvm-pdbutil bytes -block-data=0 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK0 %s
|
||||
; RUN: llvm-pdbutil bytes -block-data=0-1 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK01 %s
|
||||
; RUN: llvm-pdbutil bytes -block-data=0-0x1 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK01 %s
|
||||
; RUN: not llvm-pdbutil bytes -block-data=0,1 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
|
||||
; RUN: not llvm-pdbutil bytes -block-data=0a1 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
|
||||
; RUN: not llvm-pdbutil bytes -block-data=0- %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
|
||||
; RUN: llvm-pdbutil bytes -block-range=0 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK0 %s
|
||||
; RUN: llvm-pdbutil bytes -block-range=0-1 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK01 %s
|
||||
; RUN: llvm-pdbutil bytes -block-range=0-0x1 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK01 %s
|
||||
; RUN: not llvm-pdbutil bytes -block-range=0,1 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
|
||||
; RUN: not llvm-pdbutil bytes -block-range=0a1 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
|
||||
; RUN: not llvm-pdbutil bytes -block-range=0- %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
|
||||
|
||||
BLOCK0: MSF Blocks
|
||||
BLOCK0-NEXT: ============================================================
|
||||
|
15
test/DebugInfo/PDB/pdbdump-raw-bytes.test
Normal file
15
test/DebugInfo/PDB/pdbdump-raw-bytes.test
Normal file
@ -0,0 +1,15 @@
|
||||
; RUN: llvm-pdbutil bytes -byte-range=20-60 %p/Inputs/empty.pdb | FileCheck --check-prefix=VALID %s
|
||||
; RUN: not llvm-pdbutil bytes -byte-range=100-20 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=INVALID %s
|
||||
; RUN: not llvm-pdbutil bytes -byte-range=100000-200000 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=INVALID-RANGE %s
|
||||
|
||||
|
||||
VALID: MSF Bytes
|
||||
VALID-NEXT: ============================================================
|
||||
VALID-NEXT: Bytes (
|
||||
VALID-NEXT: 0014: 372E3030 0D0A1A44 53000000 00100000 02000000 19000000 88000000 00000000 |7.00...DS.......................|
|
||||
VALID-NEXT: 0034: 18000000 00000000 00 |.........|
|
||||
VALID-NEXT: )
|
||||
|
||||
INVALID: llvm-pdbutil: Invalid byte range specified. Max < Min
|
||||
|
||||
INVALID-RANGE: llvm-pdbutil: Invalid byte range specified. Requested byte larger than file size
|
@ -96,6 +96,22 @@ Error BytesOutputStyle::dump() {
|
||||
P.NewLine();
|
||||
}
|
||||
|
||||
if (opts::bytes::DumpByteRange.hasValue()) {
|
||||
auto &R = *opts::bytes::DumpByteRange;
|
||||
uint32_t Max = R.Max.getValueOr(File.getFileSize());
|
||||
|
||||
if (Max < R.Min)
|
||||
return make_error<StringError>("Invalid byte range specified. Max < Min",
|
||||
inconvertibleErrorCode());
|
||||
if (Max >= File.getFileSize())
|
||||
return make_error<StringError>(
|
||||
"Invalid byte range specified. Requested byte larger than file size",
|
||||
inconvertibleErrorCode());
|
||||
|
||||
dumpByteRanges(R.Min, Max);
|
||||
P.NewLine();
|
||||
}
|
||||
|
||||
if (!opts::bytes::DumpStreamData.empty()) {
|
||||
dumpStreamBytes();
|
||||
P.NewLine();
|
||||
@ -122,6 +138,21 @@ void BytesOutputStyle::dumpBlockRanges(uint32_t Min, uint32_t Max) {
|
||||
}
|
||||
}
|
||||
|
||||
void BytesOutputStyle::dumpByteRanges(uint32_t Min, uint32_t Max) {
|
||||
printHeader(P, "MSF Bytes");
|
||||
|
||||
AutoIndent Indent(P);
|
||||
|
||||
BinaryStreamReader Reader(File.getMsfBuffer());
|
||||
ArrayRef<uint8_t> Data;
|
||||
consumeError(Reader.skip(Min));
|
||||
uint32_t Size = Max - Min + 1;
|
||||
auto EC = Reader.readBytes(Data, Size);
|
||||
assert(!EC);
|
||||
consumeError(std::move(EC));
|
||||
P.formatBinary("Bytes", Data, Min);
|
||||
}
|
||||
|
||||
void BytesOutputStyle::dumpStreamBytes() {
|
||||
if (StreamPurposes.empty())
|
||||
discoverStreamPurposes(File, StreamPurposes);
|
||||
|
@ -29,6 +29,7 @@ public:
|
||||
|
||||
private:
|
||||
void dumpBlockRanges(uint32_t Min, uint32_t Max);
|
||||
void dumpByteRanges(uint32_t Min, uint32_t Max);
|
||||
void dumpStreamBytes();
|
||||
|
||||
PDBFile &File;
|
||||
|
@ -267,12 +267,18 @@ cl::list<std::string> InputFilenames(cl::Positional,
|
||||
cl::OptionCategory FileOptions("Module & File Options");
|
||||
|
||||
namespace bytes {
|
||||
llvm::Optional<BlockRange> DumpBlockRange;
|
||||
llvm::Optional<NumberRange> DumpBlockRange;
|
||||
llvm::Optional<NumberRange> DumpByteRange;
|
||||
|
||||
cl::opt<std::string> DumpBlockRangeOpt(
|
||||
"block-range", cl::value_desc("start[-end]"),
|
||||
cl::desc("Dump binary data from specified range of blocks."),
|
||||
cl::sub(BytesSubcommand));
|
||||
|
||||
cl::opt<std::string>
|
||||
DumpBlockRangeOpt("block-data", cl::value_desc("start[-end]"),
|
||||
cl::desc("Dump binary data from specified range."),
|
||||
cl::sub(BytesSubcommand));
|
||||
DumpByteRangeOpt("byte-range", cl::value_desc("start[-end]"),
|
||||
cl::desc("Dump binary data from specified range of bytes"),
|
||||
cl::sub(BytesSubcommand));
|
||||
|
||||
cl::list<std::string>
|
||||
DumpStreamData("stream-data", cl::CommaSeparated, cl::ZeroOrMore,
|
||||
@ -903,22 +909,23 @@ static void mergePdbs() {
|
||||
ExitOnErr(Builder.commit(OutFile));
|
||||
}
|
||||
|
||||
static bool validateBlockRangeArgument() {
|
||||
if (opts::bytes::DumpBlockRangeOpt.empty())
|
||||
static bool parseRange(StringRef Str,
|
||||
Optional<opts::bytes::NumberRange> &Parsed) {
|
||||
if (Str.empty())
|
||||
return true;
|
||||
|
||||
llvm::Regex R("^([^-]+)(-([^-]+))?$");
|
||||
llvm::SmallVector<llvm::StringRef, 2> Matches;
|
||||
if (!R.match(opts::bytes::DumpBlockRangeOpt, &Matches))
|
||||
if (!R.match(Str, &Matches))
|
||||
return false;
|
||||
|
||||
opts::bytes::DumpBlockRange.emplace();
|
||||
if (!to_integer(Matches[1], opts::bytes::DumpBlockRange->Min))
|
||||
Parsed.emplace();
|
||||
if (!to_integer(Matches[1], Parsed->Min))
|
||||
return false;
|
||||
|
||||
if (!Matches[3].empty()) {
|
||||
opts::bytes::DumpBlockRange->Max.emplace();
|
||||
if (!to_integer(Matches[3], *opts::bytes::DumpBlockRange->Max))
|
||||
Parsed->Max.emplace();
|
||||
if (!to_integer(Matches[3], *Parsed->Max))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -939,11 +946,22 @@ int main(int argc_, const char *argv_[]) {
|
||||
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
|
||||
|
||||
cl::ParseCommandLineOptions(argv.size(), argv.data(), "LLVM PDB Dumper\n");
|
||||
if (!validateBlockRangeArgument()) {
|
||||
errs() << "Argument '" << opts::bytes::DumpBlockRangeOpt
|
||||
<< "' invalid format.\n";
|
||||
errs().flush();
|
||||
exit(1);
|
||||
|
||||
if (opts::BytesSubcommand) {
|
||||
if (!parseRange(opts::bytes::DumpBlockRangeOpt,
|
||||
opts::bytes::DumpBlockRange)) {
|
||||
errs() << "Argument '" << opts::bytes::DumpBlockRangeOpt
|
||||
<< "' invalid format.\n";
|
||||
errs().flush();
|
||||
exit(1);
|
||||
}
|
||||
if (!parseRange(opts::bytes::DumpByteRangeOpt,
|
||||
opts::bytes::DumpByteRange)) {
|
||||
errs() << "Argument '" << opts::bytes::DumpByteRangeOpt
|
||||
<< "' invalid format.\n";
|
||||
errs().flush();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (opts::DumpSubcommand) {
|
||||
|
@ -93,11 +93,13 @@ extern llvm::cl::opt<uint32_t> ClassRecursionDepth;
|
||||
}
|
||||
|
||||
namespace bytes {
|
||||
struct BlockRange {
|
||||
uint32_t Min;
|
||||
llvm::Optional<uint32_t> Max;
|
||||
struct NumberRange {
|
||||
uint64_t Min;
|
||||
llvm::Optional<uint64_t> Max;
|
||||
};
|
||||
extern llvm::Optional<BlockRange> DumpBlockRange;
|
||||
|
||||
extern llvm::Optional<NumberRange> DumpBlockRange;
|
||||
extern llvm::Optional<NumberRange> DumpByteRange;
|
||||
extern llvm::cl::list<std::string> DumpStreamData;
|
||||
} // namespace bytes
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user