aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorEgor Tensin <Egor.Tensin@gmail.com>2017-05-20 02:47:57 +0300
committerEgor Tensin <Egor.Tensin@gmail.com>2017-05-20 02:47:57 +0300
commitf4f39e74fae3c8b8d8fdb2f560e8a50777b6de1d (patch)
treea15a2c289e6d0f5fa8ccb2d71b1c4af24f0bd4b9
parentdon't load multiple PDBs with the same base (diff)
downloadwinapi-debug-f4f39e74fae3c8b8d8fdb2f560e8a50777b6de1d.tar.gz
winapi-debug-f4f39e74fae3c8b8d8fdb2f560e8a50777b6de1d.zip
don't load the same PDB twice
-rw-r--r--include/pdb/repo.hpp4
-rw-r--r--include/pdb/utils/file.hpp30
-rw-r--r--src/repo.cpp21
-rw-r--r--src/utils/file.cpp26
4 files changed, 77 insertions, 4 deletions
diff --git a/include/pdb/repo.hpp b/include/pdb/repo.hpp
index 239bd7e..aa5c3c3 100644
--- a/include/pdb/repo.hpp
+++ b/include/pdb/repo.hpp
@@ -9,10 +9,12 @@
#include "dbghelp.hpp"
#include "module.hpp"
#include "symbol.hpp"
+#include "utils/file.hpp"
#include <functional>
#include <map>
#include <string>
+#include <unordered_set>
namespace pdb
{
@@ -45,5 +47,7 @@ namespace pdb
std::map<Address, Module> online_modules;
std::map<Address, const Module&> offline_modules;
+
+ std::unordered_set<file::ID> module_ids;
};
}
diff --git a/include/pdb/utils/file.hpp b/include/pdb/utils/file.hpp
index 5b83f2b..50975aa 100644
--- a/include/pdb/utils/file.hpp
+++ b/include/pdb/utils/file.hpp
@@ -5,14 +5,44 @@
#pragma once
+#include <Windows.h>
+
#include <cstddef>
+#include <cstring>
+#include <functional>
#include <string>
+#include <type_traits>
namespace pdb
{
namespace file
{
std::size_t get_size(const std::string&);
+
+ struct ID
+ {
+ const FILE_ID_INFO raw;
+
+ bool operator==(const ID& other) const
+ {
+ static_assert(std::is_pod<FILE_ID_INFO>::value, "Can't memcmp if file IDs aren't PODs");
+ return 0 == std::memcmp(&raw, &other.raw, sizeof(FILE_ID_INFO));
+ }
+ };
+
+ ID query_id(const std::string&);
}
}
+
+namespace std
+{
+ template <>
+ struct hash<pdb::file::ID>
+ {
+ std::size_t operator()(const pdb::file::ID& id) const
+ {
+ return _Bitwise_hash<FILE_ID_INFO>{}(id.raw);
+ }
+ };
+}
diff --git a/src/repo.cpp b/src/repo.cpp
index 9a06481..02ca1db 100644
--- a/src/repo.cpp
+++ b/src/repo.cpp
@@ -6,6 +6,7 @@
#include "pdb/all.hpp"
#include <map>
+#include <sstream>
#include <stdexcept>
#include <string>
#include <utility>
@@ -41,11 +42,18 @@ namespace pdb
return it->second;
}
- std::string pdb_already_loaded(Address online_base)
+ std::string pdb_already_loaded(Address online_base, const std::string& path)
{
std::ostringstream oss;
- oss << "module with online base address " << format_address
- << " has already been loaded";
+ oss << "module with online base address " << format_address(online_base)
+ << " has already been loaded: " << path;
+ return oss.str();
+ }
+
+ std::string pdb_already_loaded(const std::string& path)
+ {
+ std::ostringstream oss;
+ oss << "module has already been loaded: " << path;
return oss.str();
}
}
@@ -53,13 +61,18 @@ namespace pdb
Address Repo::add_pdb(Address online_base, const std::string& path)
{
if (online_modules.find(online_base) != online_modules.cend())
- throw std::runtime_error{pdb_already_loaded(online_base)};
+ throw std::runtime_error{pdb_already_loaded(online_base, path)};
+
+ auto file_id = file::query_id(path);
+ if (module_ids.find(file_id) != module_ids.cend())
+ throw std::runtime_error{pdb_already_loaded(path)};
Module module{online_base, dbghelp.load_pdb(path)};
const auto offline_base = module.get_offline_base();
const auto it = online_modules.emplace(online_base, std::move(module));
offline_modules.emplace(offline_base, it.first->second);
+ module_ids.emplace(std::move(file_id));
return offline_base;
}
diff --git a/src/utils/file.cpp b/src/utils/file.cpp
index f013d90..dba8a38 100644
--- a/src/utils/file.cpp
+++ b/src/utils/file.cpp
@@ -44,5 +44,31 @@ namespace pdb
return result;
}
+
+ ID query_id(const std::string& path)
+ {
+ const Handle handle{CreateFileA(
+ path.c_str(),
+ FILE_READ_ATTRIBUTES,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL)};
+
+ if (handle.get() == INVALID_HANDLE_VALUE)
+ throw error::windows(GetLastError());
+
+ ID id;
+
+ if (!GetFileInformationByHandleEx(
+ handle.get(),
+ FileIdInfo,
+ &id,
+ sizeof(id)))
+ throw error::windows(GetLastError());
+
+ return id;
+ }
}
}