Skip to content

Commit

Permalink
Fix parsing of COFF debug sections
Browse files Browse the repository at this point in the history
  • Loading branch information
crosire committed Dec 11, 2019
1 parent cb5f139 commit 168a4cf
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 25 deletions.
50 changes: 31 additions & 19 deletions source/blink.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -340,30 +340,42 @@ std::string blink::application::build_compile_command_line(const std::filesystem
SetFilePointer(file, section->PointerToRawData, nullptr, FILE_BEGIN);
ReadFile(file, debug_data.data(), section->SizeOfRawData, &read, nullptr);

// Replace command-line with the one in the debug section
cmdline.clear();

// Skip header in front of CodeView records (version, ...)
stream_reader stream(std::move(debug_data));
stream.skip(4 * 3);
stream.skip(4); // Skip 32-bit signature (this should be CV_SIGNATURE_C13, aka 4)

parse_code_view_records(stream, [&](uint16_t tag) {
if (tag != 0x113d) // S_ENVBLOCK
return; // Skip all records that are not about the compiler environment
stream.skip(1);
while (stream.tell() < stream.size() && *stream.data() != '\0')
while (stream.tell() < stream.size() && cmdline.empty())
{
// CV_DebugSSubsectionHeader_t
const auto subsection_type = stream.read<uint32_t>();
const auto subsection_length = stream.read<uint32_t>();
if (subsection_type != 0xf1 /*DEBUG_S_SYMBOLS*/)
{
const auto key = stream.read_string();
const std::string value(stream.read_string());

if (key == "cwd")
cmdline += "cd /D \"" + value + "\"\n";
else if (key == "cl") // Add compiler directories to path, so that 'mspdbcore.dll' is found
cmdline += "set PATH=%PATH%;" + value + "\\..\\..\\x86;" + value + "\\..\\..\\x64\n\"" + value + "\" ";
else if (key == "cmd")
cmdline += value;
stream.skip(subsection_length);
stream.align(4);
continue;
}
});

parse_code_view_records(stream, subsection_length, [&](uint16_t tag) {
if (tag != 0x113d) // S_ENVBLOCK
return; // Skip all records that are not about the compiler environment
stream.skip(1);
while (stream.tell() < stream.size() && *stream.data() != '\0')
{
const auto key = stream.read_string();
const std::string value(stream.read_string());

if (key == "cwd")
cmdline += "cd /D \"" + value + "\"\n";
else if (key == "cl") // Add compiler directories to path, so that 'mspdbcore.dll' is found
cmdline += "set PATH=%PATH%;" + value + "\\..\\..\\x86;" + value + "\\..\\..\\x64\n\"" + value + "\" ";
else if (key == "cmd")
cmdline += value;
}
});

stream.align(4); // Subsection headers are 4-byte aligned
}
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions source/pdb_reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ void blink::pdb_reader::read_symbol_table(uint8_t *image_base, std::unordered_ma
// Read symbol table records in CodeView format
stream = msf_reader::stream(header.symbol_record_stream);

parse_code_view_records(stream, [&](uint16_t tag) {
parse_code_view_records(stream, stream.size(), [&](uint16_t tag) {
if (tag != 0x110E) // S_PUB32
return; // Skip all records that are not about public symbols

Expand Down Expand Up @@ -242,9 +242,9 @@ void blink::pdb_reader::read_object_files(std::vector<std::filesystem::path> &ob

// Look up current working directory in symbol stream https://llvm.org/docs/PDB/ModiStream.html
stream_reader stream(msf_reader::stream(info.symbol_stream));
stream.skip(4); // Skip 32-bit signature
parse_code_view_records(stream, [&](uint16_t tag) {
stream.skip(4); // Skip 32-bit signature (this should be CV_SIGNATURE_C13, aka 4)

parse_code_view_records(stream, info.symbol_byte_size - 4, [&](uint16_t tag) {
if (tag == 0x113d) // S_ENVBLOCK
{
stream.skip(1);
Expand Down
6 changes: 4 additions & 2 deletions source/pdb_reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,10 +184,12 @@ namespace blink
/// Helper function that parses a CodeView stream and calls a callback function for every record in it
/// </summary>
template <typename L>
void parse_code_view_records(stream_reader &stream, L callback, size_t alignment = 1)
void parse_code_view_records(stream_reader &stream, size_t length, L callback, size_t alignment = 1)
{
const size_t end = stream.tell() + length;

// A list of records in CodeView format
while (stream.tell() < stream.size())
while (stream.tell() < end)
{
// Each records starts with 2 bytes containing the size of the record after this element
const auto size = stream.read<uint16_t>();
Expand Down

0 comments on commit 168a4cf

Please sign in to comment.