aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/common/windows/omap.cc24
-rw-r--r--src/common/windows/omap_internal.h3
-rw-r--r--src/common/windows/pdb_source_line_writer.cc43
3 files changed, 69 insertions, 1 deletions
diff --git a/src/common/windows/omap.cc b/src/common/windows/omap.cc
index 554a57c2..ba3ce86b 100644
--- a/src/common/windows/omap.cc
+++ b/src/common/windows/omap.cc
@@ -449,6 +449,27 @@ void BuildEndpointIndexMap(ImageMap* image_map) {
}
}
+void BuildSubsequentRVAMap(const OmapData &omap_data,
+ std::map<DWORD, DWORD> *subsequent) {
+ assert(subsequent->empty());
+ const OmapFromTable &orig2tran =
+ reinterpret_cast<const OmapFromTable &>(omap_data.omap_from);
+
+ if (orig2tran.empty())
+ return;
+
+ for (size_t i = 0; i < orig2tran.size() - 1; ++i) {
+ // Expect that orig2tran is sorted.
+ if (orig2tran[i].rva_original >= orig2tran[i + 1].rva_original) {
+ fprintf(stderr, "OMAP 'from' table unexpectedly unsorted\n");
+ subsequent->clear();
+ return;
+ }
+ subsequent->insert(std::make_pair(orig2tran[i].rva_original,
+ orig2tran[i + 1].rva_original));
+ }
+}
+
// Clips the given mapped range.
void ClipMappedRangeOriginal(const AddressRange& clip_range,
MappedRange* mapped_range) {
@@ -576,6 +597,7 @@ void BuildImageMap(const OmapData& omap_data, ImageMap* image_map) {
BuildMapping(omap_data, &image_map->mapping);
BuildEndpointIndexMap(image_map);
+ BuildSubsequentRVAMap(omap_data, &image_map->subsequent_rva_block);
}
void MapAddressRange(const ImageMap& image_map,
@@ -691,4 +713,4 @@ void MapAddressRange(const ImageMap& image_map,
return;
}
-} // namespace google_breakpad \ No newline at end of file
+} // namespace google_breakpad
diff --git a/src/common/windows/omap_internal.h b/src/common/windows/omap_internal.h
index 3f904d7a..2a4713d9 100644
--- a/src/common/windows/omap_internal.h
+++ b/src/common/windows/omap_internal.h
@@ -35,6 +35,7 @@
#include <windows.h>
#include <dia2.h>
+#include <map>
#include <vector>
namespace google_breakpad {
@@ -130,6 +131,8 @@ struct ImageMap {
// an interval in |mapping| that contains the endpoint. Useful for doing
// interval intersection queries.
EndpointIndexMap endpoint_index_map;
+
+ std::map<DWORD, DWORD> subsequent_rva_block;
};
} // namespace google_breakpad
diff --git a/src/common/windows/pdb_source_line_writer.cc b/src/common/windows/pdb_source_line_writer.cc
index 01f4ce3b..c2e22e40 100644
--- a/src/common/windows/pdb_source_line_writer.cc
+++ b/src/common/windows/pdb_source_line_writer.cc
@@ -122,6 +122,16 @@ class AutoImage {
PLOADED_IMAGE img_;
};
+bool SymbolsMatch(IDiaSymbol* a, IDiaSymbol* b) {
+ DWORD a_section, a_offset, b_section, b_offset;
+ if (FAILED(a->get_addressSection(&a_section)) ||
+ FAILED(a->get_addressOffset(&a_offset)) ||
+ FAILED(b->get_addressSection(&b_section)) ||
+ FAILED(b->get_addressOffset(&b_offset)))
+ return false;
+ return a_section == b_section && a_offset == b_offset;
+}
+
bool CreateDiaDataSourceInstance(CComPtr<IDiaDataSource> &data_source) {
if (SUCCEEDED(data_source.CoCreateInstance(CLSID_DiaSource))) {
return true;
@@ -856,6 +866,39 @@ bool PDBSourceLineWriter::PrintCodePublicSymbol(IDiaSymbol *symbol) {
stack_param_size > 0 ? stack_param_size : 0,
name.m_str);
}
+
+ // Now walk the function in the original untranslated space, asking DIA
+ // what function is at that location, stepping through OMAP blocks. If
+ // we're still in the same function, emit another entry, because the
+ // symbol could have been split into multiple pieces. If we've gotten to
+ // another symbol in the original address space, then we're done for
+ // this symbol. See https://crbug.com/678874.
+ for (;;) {
+ // This steps to the next block in the original image. Simply doing
+ // rva++ would also be correct, but would emit tons of unnecessary
+ // entries.
+ rva = image_map_.subsequent_rva_block[rva];
+ if (rva == 0)
+ break;
+
+ CComPtr<IDiaSymbol> next_sym = NULL;
+ LONG displacement;
+ if (FAILED(session_->findSymbolByRVAEx(rva, SymTagPublicSymbol, &next_sym,
+ &displacement))) {
+ break;
+ }
+
+ if (!SymbolsMatch(symbol, next_sym))
+ break;
+
+ AddressRangeVector next_ranges;
+ MapAddressRange(image_map_, AddressRange(rva, 1), &next_ranges);
+ for (size_t i = 0; i < next_ranges.size(); ++i) {
+ fprintf(output_, "PUBLIC %x %x %ws\n", next_ranges[i].rva,
+ stack_param_size > 0 ? stack_param_size : 0, name.m_str);
+ }
+ }
+
return true;
}