Add support for the VS2017 built binaries.
There's 2 things that had to be fixed:
- There's a new flag value for the 32 bit offset fixups, we used to always see a flag value of 0 but it's now set to 0x2000 in the VS2017 binaries.
- Add a workaround for what seems to be a toolchain bug in VS2017, the PDB contain some invalid symbols, see https://developercommunity.visualstudio.com/content/problem/47386/invalid-symbols-when-using-rtti.html
With these 2 changes we fully support the VS2017 built binaries.
BUG=chromium:683729
Review-Url: https://codereview.chromium.org/2856933003
diff --git a/syzygy/pdb/pdb_data.cc b/syzygy/pdb/pdb_data.cc
index e825355..80fb655 100644
--- a/syzygy/pdb/pdb_data.cc
+++ b/syzygy/pdb/pdb_data.cc
@@ -30,8 +30,7 @@
case TYPE_OFFSET_32BIT:
case TYPE_OFFSET_8BIT: {
- // We've only ever seen offset fixups without flags.
- return flags == 0;
+ return (flags & ~FLAG_OFFSET_32BIT_VS2017) == 0;
}
default: {
diff --git a/syzygy/pdb/pdb_data.h b/syzygy/pdb/pdb_data.h
index c490591..406009d 100644
--- a/syzygy/pdb/pdb_data.h
+++ b/syzygy/pdb/pdb_data.h
@@ -289,6 +289,9 @@
};
enum Flags {
+ // Flag value that we observe for the TYPE_OFFSET_32BIT fixups produced by
+ // VS2017.
+ FLAG_OFFSET_32BIT_VS2017 = 0x2000,
FLAG_IS_DATA = 0x4000,
FLAG_REFERS_TO_CODE = 0x8000,
FLAG_UNKNOWN = 0x3fff,
diff --git a/syzygy/pe/decomposer.cc b/syzygy/pe/decomposer.cc
index 9314d45..1c81f4b 100644
--- a/syzygy/pe/decomposer.cc
+++ b/syzygy/pe/decomposer.cc
@@ -1792,6 +1792,7 @@
// Verify that the data symbol does not exceed the size of the block.
if (addr + length > block_addr + block->size()) {
+ base::StringPiece spname(name);
// The data symbol can exceed the size of the block in the case of data
// imports. For some reason the toolchain emits a global data symbol with
// type information equal to the type of the data *pointed* to by the import
@@ -1802,10 +1803,24 @@
// generated. This won't be part of the IAT, so we can't even filter based
// on that. Instead, we simply ignore global data symbols that exceed the
// block size.
- base::StringPiece spname(name);
- if (sym_tags.size() == 1 && spname.starts_with("_imp_")) {
+ bool is_imported_data_symbol = (sym_tags.size() == 1 &&
+ spname.starts_with("_imp_"));
+ // In VS2017 we've noticed that the size returned by IDiaSymbol::get_length
+ // function is invalid for the objects using RTTI in VS2017. This has been
+ // reported here:
+ // https://developercommunity.visualstudio.com/content/problem/47386/invalid-symbols-when-using-rtti.html
+ //
+ // In this situation the data symbol that we get always starts 4 bytes after
+ // the beginning of its parent block and has an identical size.
+ bool is_vtable_symbol = spname.ends_with("::`vftable'") &&
+ (addr - block_addr == 4) &&
+ length == block->size();
+ if (is_imported_data_symbol) {
VLOG(1) << "Encountered an imported data symbol \"" << name << "\" that "
<< "extends past its parent block \"" << block->name() << "\".";
+ } else if (is_vtable_symbol) {
+ VLOG(1) << "Encountered a vtable data symbol \"" << name << "\" that "
+ << "extends past its parent block \"" << block->name() << "\".";
} else {
LOG(ERROR) << "Received data symbol \"" << name << "\" that extends past "
<< "its parent block \"" << block->name() << "\".";