Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(91)

Unified Diff: src/common/windows/pdb_source_line_writer.cc

Issue 1773183003: Windows dump_syms: Add dumping of x86_64 CFI from PDB files Base URL: https://chromium.googlesource.com/breakpad/breakpad.git@warning-fix
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/common/windows/pdb_source_line_writer.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/common/windows/pdb_source_line_writer.cc
diff --git a/src/common/windows/pdb_source_line_writer.cc b/src/common/windows/pdb_source_line_writer.cc
index f0edb721c07e86bd9658a984be55e6bf23749dbe..522ec1a125c42792107b20e8072d704c3989187f 100644
--- a/src/common/windows/pdb_source_line_writer.cc
+++ b/src/common/windows/pdb_source_line_writer.cc
@@ -37,6 +37,7 @@
#include <ImageHlp.h>
#include <stdio.h>
+#include <cassert>
#include <limits>
#include <set>
@@ -686,61 +687,32 @@ bool PDBSourceLineWriter::PrintFrameDataUsingPDB() {
return true;
}
-bool PDBSourceLineWriter::PrintFrameDataUsingEXE() {
- if (code_file_.empty() && !FindPEFile()) {
- fprintf(stderr, "Couldn't locate EXE or DLL file.\n");
- return false;
- }
-
- // Convert wchar to native charset because ImageLoad only takes
- // a PSTR as input.
- string code_file;
- if (!WindowsStringUtils::safe_wcstombs(code_file_, &code_file)) {
- return false;
- }
-
- AutoImage img(ImageLoad((PSTR)code_file.c_str(), NULL));
- if (!img) {
- fprintf(stderr, "Failed to load %s\n", code_file.c_str());
- return false;
- }
- PIMAGE_OPTIONAL_HEADER64 optional_header =
- &(reinterpret_cast<PIMAGE_NT_HEADERS64>(img->FileHeader))->OptionalHeader;
- if (optional_header->Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
- fprintf(stderr, "Not a PE32+ image\n");
- return false;
- }
-
- // Read Exception Directory
- DWORD exception_rva = optional_header->
- DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress;
- DWORD exception_size = optional_header->
- DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size;
+// Prints CFI from xdata/pdata
+//
+// Performing the translation of RVA to a real pointer is very different for a
+// XDATA/PDATA streams read from a PDB, and XDATA/PDATA found in the loaded
+// image of an executable, so we specialize this function for each case with
+// RvaToVaTraits
+//
+template <typename RvaToVaTraits>
+static bool PrintCFIFromXData(FILE *output, PVOID pdata, size_t pdata_size,
+ const typename RvaToVaTraits &t) {
PIMAGE_RUNTIME_FUNCTION_ENTRY funcs =
- static_cast<PIMAGE_RUNTIME_FUNCTION_ENTRY>(
- ImageRvaToVa(img->FileHeader,
- img->MappedAddress,
- exception_rva,
- &img->LastRvaSection));
- for (DWORD i = 0; i < exception_size / sizeof(*funcs); i++) {
+ static_cast<PIMAGE_RUNTIME_FUNCTION_ENTRY>(pdata);
+
+ for (size_t i = 0; i < pdata_size / sizeof(*funcs) ; i++) {
DWORD unwind_rva = funcs[i].UnwindInfoAddress;
// handle chaining
while (unwind_rva & 0x1) {
unwind_rva ^= 0x1;
PIMAGE_RUNTIME_FUNCTION_ENTRY chained_func =
static_cast<PIMAGE_RUNTIME_FUNCTION_ENTRY>(
- ImageRvaToVa(img->FileHeader,
- img->MappedAddress,
- unwind_rva,
- &img->LastRvaSection));
+ t.PDataRvaToVa(unwind_rva));
unwind_rva = chained_func->UnwindInfoAddress;
}
UnwindInfo *unwind_info = static_cast<UnwindInfo *>(
- ImageRvaToVa(img->FileHeader,
- img->MappedAddress,
- unwind_rva,
- &img->LastRvaSection));
+ t.XDataRvaToVa(unwind_rva));
DWORD stack_size = 8; // minimal stack size is 8 for RIP
DWORD rip_offset = 8;
@@ -795,33 +767,162 @@ bool PDBSourceLineWriter::PrintFrameDataUsingEXE() {
}
}
if (unwind_info->flags & UNW_FLAG_CHAININFO) {
+ // unwind_code[] is followed by an IMAGE_RUNTIME_FUNCTION_ENTRY
PIMAGE_RUNTIME_FUNCTION_ENTRY chained_func =
reinterpret_cast<PIMAGE_RUNTIME_FUNCTION_ENTRY>(
(unwind_info->unwind_code +
((unwind_info->count_of_codes + 1) & ~1)));
unwind_info = static_cast<UnwindInfo *>(
- ImageRvaToVa(img->FileHeader,
- img->MappedAddress,
- chained_func->UnwindInfoAddress,
- &img->LastRvaSection));
+ t.XDataRvaToVa(chained_func->UnwindInfoAddress));
} else {
unwind_info = NULL;
}
} while (unwind_info);
- fprintf(output_, "STACK CFI INIT %x %x .cfa: $rsp .ra: .cfa %d - ^\n",
+ fprintf(output, "STACK CFI INIT %x %x .cfa: $rsp .ra: .cfa %d - ^\n",
funcs[i].BeginAddress,
funcs[i].EndAddress - funcs[i].BeginAddress, rip_offset);
- fprintf(output_, "STACK CFI %x .cfa: $rsp %d +\n",
+ fprintf(output, "STACK CFI %x .cfa: $rsp %d +\n",
funcs[i].BeginAddress, stack_size);
}
return true;
}
+// In a LOADED_IMAGE, we can simply use ImageRvaToVa() to translate RVAs
+class ImageRvaToVaTraits {
+ public:
+ ImageRvaToVaTraits(PLOADED_IMAGE img)
+ : img_(img)
+ {
+ };
+
+ PVOID XDataRvaToVa(DWORD rva) const {
+ return ImageRvaToVa(img_->FileHeader,
+ img_->MappedAddress,
+ rva,
+ &img_->LastRvaSection);
+ };
+
+ PVOID PDataRvaToVa(DWORD rva) const {
+ return ImageRvaToVa(img_->FileHeader,
+ img_->MappedAddress,
+ rva,
+ &img_->LastRvaSection);
+ };
+
+ private:
+ PLOADED_IMAGE img_;
+};
+
+bool PDBSourceLineWriter::PrintFrameDataUsingEXE() {
+ if (code_file_.empty() && !FindPEFile()) {
+ fprintf(stderr, "Couldn't locate EXE or DLL file.\n");
+ return false;
+ }
+
+ // Convert wchar to native charset because ImageLoad only takes
+ // a PSTR as input.
+ string code_file;
+ if (!WindowsStringUtils::safe_wcstombs(code_file_, &code_file)) {
+ return false;
+ }
+
+ AutoImage img(ImageLoad((PSTR)code_file.c_str(), NULL));
+ if (!img) {
+ fprintf(stderr, "Failed to load %s\n", code_file.c_str());
+ return false;
+ }
+ PIMAGE_OPTIONAL_HEADER64 optional_header =
+ &(reinterpret_cast<PIMAGE_NT_HEADERS64>(img->FileHeader))->OptionalHeader;
+ if (optional_header->Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+ fprintf(stderr, "Not a PE32+ image\n");
+ return false;
+ }
+
+ // Read Exception Directory
+ DWORD exception_rva = optional_header->
+ DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress;
+ DWORD exception_size = optional_header->
+ DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size;
+
+ PVOID pdata = static_cast<PVOID>(
+ ImageRvaToVa(img->FileHeader,
+ img->MappedAddress,
+ exception_rva,
+ &img->LastRvaSection));
+
+ ImageRvaToVaTraits t(img);
+
+ return PrintCFIFromXData(output_, pdata, exception_size, t);
+}
+
+// We have the XDATA/PDATA streams from the PDB, along with their base RVAs
+// provided by IDiaImageData. It is assumed that all the RVAs we access lie
+// within the range of RVAs covered by the stream.
+class PdbRvaToVaTraits {
+ public:
+ PdbRvaToVaTraits(PVOID pdata, size_t pdata_size, DWORD pdata_base_rva,
+ PVOID xdata, size_t xdata_size, DWORD xdata_base_rva)
+ : pdata_(pdata), pdata_size_(pdata_size), pdata_base_rva_(pdata_base_rva),
+ xdata_(xdata), xdata_size_(xdata_size), xdata_base_rva_(xdata_base_rva)
+ {
+ };
+
+ PVOID XDataRvaToVa(DWORD rva) const {
+ assert(rva >= xdata_base_rva_);
+ assert(rva < xdata_base_rva_ + xdata_size_);
+
+ return rva - xdata_base_rva_ + static_cast<PBYTE>(xdata_);
+ };
+
+ PVOID PDataRvaToVa(DWORD rva) const {
+ assert(rva >= pdata_base_rva_);
+ assert(rva < pdata_base_rva_ + pdata_size_);
+
+ return rva - pdata_base_rva_ + static_cast<PBYTE>(pdata_);
+ };
+
+ private:
+ PVOID pdata_;
+ size_t pdata_size_;
+ DWORD pdata_base_rva_;
+ PVOID xdata_;
+ size_t xdata_size_;
+ DWORD xdata_base_rva_;
+};
+
+bool PDBSourceLineWriter::PrintFrameDataUsingPDBXData() {
+ static const wchar_t kPdataStreamName[] = L"PDATA";
+ static const wchar_t kXdataStreamName[] = L"XDATA";
+
+ std::vector<BYTE> pdata;
+ std::vector<BYTE> xdata;
+ DWORD pdata_base_rva;
+ DWORD xdata_base_rva;
+
+ if (FindAndLoadDebugStream(kPdataStreamName, session_, &pdata,
+ &pdata_base_rva) && pdata_base_rva &&
+ FindAndLoadDebugStream(kXdataStreamName, session_, &xdata,
+ &xdata_base_rva) && xdata_base_rva) {
+
+ PdbRvaToVaTraits t(&pdata[0], pdata.size(), pdata_base_rva,
+ &xdata[0], xdata.size(), xdata_base_rva);
+
+ return PrintCFIFromXData(output_, &pdata[0], pdata.size(), t);
+ }
+
+ return false;
+}
+
bool PDBSourceLineWriter::PrintFrameData() {
PDBModuleInfo info;
if (GetModuleInfo(&info) && info.cpu == L"x86_64") {
+ // Print CFI using .pdata/.xdata streams in PDB
+ if (PrintFrameDataUsingPDBXData())
+ return true;
+ // If they are not present, fall-back to reading the .pdata/.xdata from the
+ // corresponding PE/COFF executable, if we can find it.
return PrintFrameDataUsingEXE();
} else {
return PrintFrameDataUsingPDB();
« no previous file with comments | « src/common/windows/pdb_source_line_writer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698