update boost
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
|
||||
// Copyright 2015-2019 Antony Polukhin.
|
||||
// Copyright Antony Polukhin, 2015-2023.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include <boost/dll/detail/aggressive_ptr_cast.hpp>
|
||||
#include <boost/dll/detail/get_mem_fn_type.hpp>
|
||||
|
||||
#if defined(BOOST_MSVC) || defined(BOOST_MSVC_VER)
|
||||
#if defined(_MSC_VER) // MSVC, Clang-cl, and ICC on Windows
|
||||
# include <boost/dll/detail/demangling/msvc.hpp>
|
||||
#else
|
||||
# include <boost/dll/detail/demangling/itanium.hpp>
|
||||
@@ -117,7 +117,8 @@ struct destructor {
|
||||
{}
|
||||
};
|
||||
|
||||
#if defined(BOOST_MSVC) || defined(BOOST_MSVC_VER)
|
||||
#if defined(_MSC_VER) // MSVC, Clang-cl, and ICC on Windows
|
||||
|
||||
template<typename Signature, typename Lib>
|
||||
constructor<Signature> load_ctor(Lib & lib, const mangled_storage_impl::ctor_sym & ct) {
|
||||
typedef typename constructor<Signature>::standard_t standard_t;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#if defined(BOOST_MSVC) || defined(BOOST_MSVC_FULL_VER)
|
||||
#if defined(_MSC_VER) // MSVC, Clang-cl, and ICC on Windows
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
@@ -88,6 +88,102 @@ public:
|
||||
|
||||
namespace parser
|
||||
{
|
||||
//! declare
|
||||
template <typename... T>
|
||||
struct dummy;
|
||||
|
||||
template <typename T>
|
||||
std::string parse_type_helper(const mangled_storage_impl & ms, dummy<T>*);
|
||||
|
||||
template <typename... T, template <typename...> class Tn>
|
||||
std::string parse_type_helper(const mangled_storage_impl & ms, dummy<Tn<T...>>*);
|
||||
|
||||
template <typename... T, template <typename...> class Tn>
|
||||
std::string parse_type(const mangled_storage_impl & ms, dummy<Tn<T...>>*);
|
||||
|
||||
template <typename T>
|
||||
std::string parse_type(const mangled_storage_impl & ms, dummy<T>*);
|
||||
|
||||
template <typename T1, typename T2, typename... T3>
|
||||
std::string parse_type(const mangled_storage_impl & ms, dummy<T1, T2, T3...>*);
|
||||
|
||||
template <typename R, typename... Args>
|
||||
std::string parse_type(const mangled_storage_impl & ms, dummy<R(Args...)>*);
|
||||
|
||||
std::string parse_type(const mangled_storage_impl & ms, dummy<>*);
|
||||
|
||||
template<typename T>
|
||||
std::string
|
||||
type_name(const mangled_storage_impl &);
|
||||
|
||||
|
||||
//The purpose of this class template is to separate the pure type from the rule name from the target type
|
||||
template<typename T>
|
||||
struct pure_type
|
||||
{
|
||||
typedef T type;
|
||||
inline static std::string type_rule() { return ""; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct pure_type<T*>
|
||||
{
|
||||
typedef typename pure_type<T>::type type;
|
||||
inline static std::string type_rule()
|
||||
{
|
||||
return pure_type<T>::type_rule() + "*";
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct pure_type<T const>
|
||||
{
|
||||
typedef typename pure_type<T>::type type;
|
||||
inline static std::string type_rule()
|
||||
{
|
||||
return pure_type<T>::type_rule() + " const";
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct pure_type<T volatile>
|
||||
{
|
||||
typedef typename pure_type<T>::type type;
|
||||
inline static std::string type_rule()
|
||||
{
|
||||
return pure_type<T>::type_rule() + " volatile";
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct pure_type<T const volatile>
|
||||
{
|
||||
typedef typename pure_type<T>::type type;
|
||||
inline static std::string type_rule()
|
||||
{
|
||||
return pure_type<T>::type_rule() + " const volatile";
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct pure_type<T&>
|
||||
{
|
||||
typedef typename pure_type<T>::type type;
|
||||
inline static std::string type_rule()
|
||||
{
|
||||
return pure_type<T>::type_rule() + "&";
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct pure_type<T&&>
|
||||
{
|
||||
typedef typename pure_type<T>::type type;
|
||||
inline static std::string type_rule()
|
||||
{
|
||||
return pure_type<T>::type_rule() + "&&";
|
||||
}
|
||||
};
|
||||
|
||||
inline std::string const_rule_impl(true_type ) {return " const";}
|
||||
inline std::string const_rule_impl(false_type) {return "";}
|
||||
@@ -103,38 +199,22 @@ namespace parser
|
||||
inline std::string reference_rule_impl(true_type, false_type) {return "&" ;}
|
||||
inline std::string reference_rule_impl(false_type, true_type ) {return "&&";}
|
||||
|
||||
|
||||
template<typename T>
|
||||
std::string reference_rule() {using t_l = is_lvalue_reference<T>; using t_r = is_rvalue_reference<T>; return reference_rule_impl(t_l(), t_r());}
|
||||
|
||||
//it takes a string, because it may be overloaded.
|
||||
template<typename T>
|
||||
std::string type_rule(const std::string & type_name)
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
return type_name +
|
||||
const_rule<T>() +
|
||||
volatile_rule<T>() +
|
||||
reference_rule<T>();
|
||||
}
|
||||
|
||||
|
||||
template<typename Return, typename Arg>
|
||||
std::string arg_list(const mangled_storage_impl & ms, Return (*)(Arg))
|
||||
{
|
||||
using namespace std;
|
||||
auto str = ms.get_name<Arg>();
|
||||
return type_rule<Arg>(str);
|
||||
return type_name<Arg>(ms);
|
||||
}
|
||||
|
||||
template<typename Return, typename First, typename Second, typename ...Args>
|
||||
std::string arg_list(const mangled_storage_impl & ms, Return (*)(First, Second, Args...))
|
||||
{
|
||||
auto st = ms.get_name<First>();
|
||||
|
||||
using next_type = Return (*)(Second, Args...);
|
||||
return type_rule<First>(st) + ", " + arg_list(ms, next_type());
|
||||
return type_name<First>(ms) + ", " + arg_list(ms, next_type());
|
||||
}
|
||||
|
||||
template<typename Return>
|
||||
@@ -142,6 +222,70 @@ namespace parser
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
//! implement
|
||||
template <typename T>
|
||||
inline std::string parse_type_helper(const mangled_storage_impl & ms, dummy<T>*) {
|
||||
return ms.get_name<T>();
|
||||
}
|
||||
|
||||
template <typename... T, template <typename...> class Tn>
|
||||
inline std::string parse_type_helper(const mangled_storage_impl & ms, dummy<Tn<T...>>*) {
|
||||
using type = dummy<Tn<T...>>*;
|
||||
return parse_type(ms, type());
|
||||
}
|
||||
|
||||
template <typename R, typename... Args>
|
||||
inline std::string parse_type(const mangled_storage_impl & ms, dummy<R(*)(Args...)>*) {
|
||||
using args_type = dummy<Args...>*;
|
||||
using return_type = dummy<R>*;
|
||||
return parse_type(ms, return_type()) + " (*)(" + parse_type(ms, args_type()) + ")";
|
||||
}
|
||||
|
||||
template <typename R, typename... Args>
|
||||
inline std::string parse_type(const mangled_storage_impl & ms, dummy<R(Args...)>*) {
|
||||
using args_type = dummy<Args...>*;
|
||||
using return_type = dummy<R>*;
|
||||
return parse_type(ms, return_type()) + " (" + parse_type(ms, args_type()) + ")";
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline std::string parse_type(const mangled_storage_impl & ms, dummy<T>*) {
|
||||
using type = dummy<typename pure_type<T>::type>*;
|
||||
auto str = parse_type_helper(ms, type());
|
||||
return str + pure_type<T>::type_rule();
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename... T3>
|
||||
inline std::string parse_type(const mangled_storage_impl & ms, dummy<T1, T2, T3...>*) {
|
||||
using first_type = dummy<T1>*;
|
||||
using next_type = dummy<T2, T3...>*;
|
||||
return parse_type(ms, first_type()) + ", " + parse_type(ms, next_type());
|
||||
}
|
||||
|
||||
template <typename... T, template <typename...> class Tn>
|
||||
inline std::string parse_type(const mangled_storage_impl & ms, dummy<Tn<T...>>*) {
|
||||
using next_type = dummy<T...>*;
|
||||
std::string str = ms.get_name<Tn<T...>>();
|
||||
auto frist = str.find_first_of("<");
|
||||
std::string template_name = str.substr(0, frist);
|
||||
std::string args_name = parse_type(ms, next_type());
|
||||
char last_ch = args_name[args_name.size() - 1];
|
||||
return template_name + "<" + args_name + (last_ch == '>' ? " >" : ">");
|
||||
}
|
||||
|
||||
inline std::string parse_type(const mangled_storage_impl &, dummy<>*) {
|
||||
return "";
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline std::string
|
||||
type_name(const mangled_storage_impl &ms)
|
||||
{
|
||||
using namespace parser;
|
||||
using type = dummy<T>*;
|
||||
return parse_type(ms, type());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -180,11 +324,30 @@ std::string mangled_storage_impl::get_mem_fn(const std::string &name) const
|
||||
|
||||
std::string cname = get_name<Class>();
|
||||
|
||||
auto matcher = cname + "::" + name +
|
||||
const auto matcher = cname + "::" + name +
|
||||
'(' + parser::arg_list(*this, func_type()) + ')'
|
||||
+ const_rule<Class>() + volatile_rule<Class>();
|
||||
|
||||
auto found = std::find_if(storage_.begin(), storage_.end(), [&](const entry& e) {return e.demangled == matcher;});
|
||||
// Linux export table contains int MyClass::Func<float>(), but expected in import_mangled MyClass::Func<float>() without returned type.
|
||||
auto found = std::find_if(storage_.begin(), storage_.end(), [&matcher](const entry& e) {
|
||||
if (e.demangled == matcher) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto pos = e.demangled.rfind(matcher);
|
||||
if (pos == std::string::npos) {
|
||||
// Not found.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pos + matcher.size() != e.demangled.size()) {
|
||||
// There are some characters after the `matcher` string.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Double checking that we matched a full function name
|
||||
return e.demangled[pos - 1] == ' '; // `if (e.demangled == matcher)` makes sure that `pos > 0`
|
||||
});
|
||||
|
||||
if (found != storage_.end())
|
||||
return found->mangled;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
|
||||
// Copyright 2015-2019 Antony Polukhin.
|
||||
// Copyright Antony Polukhin, 2015-2023.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
@@ -16,9 +16,11 @@
|
||||
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/dll/detail/x_info_interface.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
namespace boost { namespace dll { namespace detail {
|
||||
|
||||
@@ -92,15 +94,14 @@ typedef Elf_Sym_template<boost::uint32_t> Elf32_Sym_;
|
||||
typedef Elf_Sym_template<boost::uint64_t> Elf64_Sym_;
|
||||
|
||||
template <class AddressOffsetT>
|
||||
class elf_info: public x_info_interface {
|
||||
std::ifstream& f_;
|
||||
|
||||
class elf_info {
|
||||
typedef boost::dll::detail::Elf_Ehdr_template<AddressOffsetT> header_t;
|
||||
typedef boost::dll::detail::Elf_Shdr_template<AddressOffsetT> section_t;
|
||||
typedef boost::dll::detail::Elf_Sym_template<AddressOffsetT> symbol_t;
|
||||
|
||||
BOOST_STATIC_CONSTANT(boost::uint32_t, SHT_SYMTAB_ = 2);
|
||||
BOOST_STATIC_CONSTANT(boost::uint32_t, SHT_STRTAB_ = 3);
|
||||
BOOST_STATIC_CONSTANT(boost::uint32_t, SHT_DYNSYM_ = 11);
|
||||
|
||||
BOOST_STATIC_CONSTANT(unsigned char, STB_LOCAL_ = 0); /* Local symbol */
|
||||
BOOST_STATIC_CONSTANT(unsigned char, STB_GLOBAL_ = 1); /* Global symbol */
|
||||
@@ -113,15 +114,15 @@ class elf_info: public x_info_interface {
|
||||
BOOST_STATIC_CONSTANT(unsigned char, STV_PROTECTED_ = 3); /* Not preemptible, not exported */
|
||||
|
||||
public:
|
||||
static bool parsing_supported(std::ifstream& f) {
|
||||
static bool parsing_supported(std::ifstream& fs) {
|
||||
const unsigned char magic_bytes[5] = {
|
||||
0x7f, 'E', 'L', 'F', sizeof(boost::uint32_t) == sizeof(AddressOffsetT) ? 1 : 2
|
||||
};
|
||||
|
||||
unsigned char ch;
|
||||
f.seekg(0);
|
||||
fs.seekg(0);
|
||||
for (std::size_t i = 0; i < sizeof(magic_bytes); ++i) {
|
||||
f >> ch;
|
||||
fs >> ch;
|
||||
if (ch != magic_bytes[i]) {
|
||||
return false;
|
||||
}
|
||||
@@ -130,97 +131,154 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
explicit elf_info(std::ifstream& f) BOOST_NOEXCEPT
|
||||
: f_(f)
|
||||
{}
|
||||
|
||||
std::vector<std::string> sections() {
|
||||
static std::vector<std::string> sections(std::ifstream& fs) {
|
||||
std::vector<std::string> ret;
|
||||
std::vector<char> names;
|
||||
sections_names_raw(names);
|
||||
|
||||
sections_names_raw(fs, names);
|
||||
|
||||
const char* name_begin = &names[0];
|
||||
const char* const name_end = name_begin + names.size();
|
||||
ret.reserve(header().e_shnum);
|
||||
ret.reserve(header(fs).e_shnum);
|
||||
do {
|
||||
ret.push_back(name_begin);
|
||||
name_begin += ret.back().size() + 1;
|
||||
if (*name_begin) {
|
||||
ret.push_back(name_begin);
|
||||
name_begin += ret.back().size() + 1;
|
||||
} else {
|
||||
++name_begin;
|
||||
}
|
||||
} while (name_begin != name_end);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
template <class T>
|
||||
inline void read_raw(T& value, std::size_t size = sizeof(T)) const {
|
||||
f_.read(reinterpret_cast<char*>(&value), size);
|
||||
template <class Integer>
|
||||
static void checked_seekg(std::ifstream& fs, Integer pos) {
|
||||
/* TODO: use cmp_less, cmp_greater
|
||||
if ((std::numeric_limits<std::streamoff>::max)() < pos) {
|
||||
boost::throw_exception(std::runtime_error("Integral overflow while getting info from ELF file"));
|
||||
}
|
||||
if ((std::numeric_limits<std::streamoff>::min)() > pos){
|
||||
boost::throw_exception(std::runtime_error("Integral underflow while getting info from ELF file"));
|
||||
}
|
||||
*/
|
||||
fs.seekg(static_cast<std::streamoff>(pos));
|
||||
}
|
||||
|
||||
inline header_t header() {
|
||||
template <class T>
|
||||
static void read_raw(std::ifstream& fs, T& value, std::size_t size = sizeof(T)) {
|
||||
fs.read(reinterpret_cast<char*>(&value), size);
|
||||
}
|
||||
|
||||
static header_t header(std::ifstream& fs) {
|
||||
header_t elf;
|
||||
|
||||
f_.seekg(0);
|
||||
read_raw(elf);
|
||||
fs.seekg(0);
|
||||
read_raw(fs, elf);
|
||||
|
||||
return elf;
|
||||
}
|
||||
|
||||
void sections_names_raw(std::vector<char>& sections) {
|
||||
const header_t elf = header();
|
||||
static void sections_names_raw(std::ifstream& fs, std::vector<char>& sections) {
|
||||
const header_t elf = header(fs);
|
||||
|
||||
section_t section_names_section;
|
||||
f_.seekg(elf.e_shoff + elf.e_shstrndx * sizeof(section_t));
|
||||
read_raw(section_names_section);
|
||||
checked_seekg(fs, elf.e_shoff + elf.e_shstrndx * sizeof(section_t));
|
||||
read_raw(fs, section_names_section);
|
||||
|
||||
sections.resize(static_cast<std::size_t>(section_names_section.sh_size));
|
||||
f_.seekg(section_names_section.sh_offset);
|
||||
read_raw(sections[0], static_cast<std::size_t>(section_names_section.sh_size));
|
||||
sections.resize(static_cast<std::size_t>(section_names_section.sh_size) + 1, '\0');
|
||||
checked_seekg(fs, section_names_section.sh_offset);
|
||||
read_raw(fs, sections[0], static_cast<std::size_t>(section_names_section.sh_size));
|
||||
}
|
||||
|
||||
void symbols_text(std::vector<symbol_t>& symbols, std::vector<char>& text) {
|
||||
const header_t elf = header();
|
||||
f_.seekg(elf.e_shoff);
|
||||
static void symbols_text(std::ifstream& fs, std::vector<symbol_t>& symbols, std::vector<char>& text) {
|
||||
std::vector<char> names;
|
||||
sections_names_raw(fs, names);
|
||||
symbols_text(fs, symbols, text, names);
|
||||
}
|
||||
|
||||
static void symbols_text(std::ifstream& fs, std::vector<symbol_t>& symbols, std::vector<char>& text, const std::vector<char>& names) {
|
||||
const header_t elf = header(fs);
|
||||
checked_seekg(fs, elf.e_shoff);
|
||||
|
||||
// ".dynsym" section may not have info on symbols that could be used while self loading an executable,
|
||||
// so we prefer ".symtab" section.
|
||||
AddressOffsetT symtab_size = 0;
|
||||
AddressOffsetT symtab_offset = 0;
|
||||
AddressOffsetT strtab_size = 0;
|
||||
AddressOffsetT strtab_offset = 0;
|
||||
|
||||
AddressOffsetT dynsym_size = 0;
|
||||
AddressOffsetT dynsym_offset = 0;
|
||||
AddressOffsetT dynstr_size = 0;
|
||||
AddressOffsetT dynstr_offset = 0;
|
||||
|
||||
for (std::size_t i = 0; i < elf.e_shnum; ++i) {
|
||||
section_t section;
|
||||
read_raw(section);
|
||||
read_raw(fs, section);
|
||||
if (section.sh_name >= names.size()) {
|
||||
continue;
|
||||
}
|
||||
const char* name = &names[section.sh_name];
|
||||
|
||||
if (section.sh_type == SHT_SYMTAB_) {
|
||||
symbols.resize(static_cast<std::size_t>(section.sh_size / sizeof(symbol_t)));
|
||||
|
||||
const std::ifstream::pos_type pos = f_.tellg();
|
||||
f_.seekg(section.sh_offset);
|
||||
read_raw(symbols[0], static_cast<std::size_t>(section.sh_size - (section.sh_size % sizeof(symbol_t))) );
|
||||
f_.seekg(pos);
|
||||
if (section.sh_type == SHT_SYMTAB_ && !std::strcmp(name, ".symtab")) {
|
||||
symtab_size = section.sh_size;
|
||||
symtab_offset = section.sh_offset;
|
||||
} else if (section.sh_type == SHT_STRTAB_) {
|
||||
text.resize(static_cast<std::size_t>(section.sh_size));
|
||||
|
||||
const std::ifstream::pos_type pos = f_.tellg();
|
||||
f_.seekg(section.sh_offset);
|
||||
read_raw(text[0], static_cast<std::size_t>(section.sh_size));
|
||||
f_.seekg(pos);
|
||||
if (!std::strcmp(name, ".dynstr")) {
|
||||
dynstr_size = section.sh_size;
|
||||
dynstr_offset = section.sh_offset;
|
||||
} else if (!std::strcmp(name, ".strtab")) {
|
||||
strtab_size = section.sh_size;
|
||||
strtab_offset = section.sh_offset;
|
||||
}
|
||||
} else if (section.sh_type == SHT_DYNSYM_ && !std::strcmp(name, ".dynsym")) {
|
||||
dynsym_size = section.sh_size;
|
||||
dynsym_offset = section.sh_offset;
|
||||
}
|
||||
}
|
||||
|
||||
if (!symtab_size || !strtab_size) {
|
||||
// ".symtab" stripped from the binary and we have to fallback to ".dynsym"
|
||||
symtab_size = dynsym_size;
|
||||
symtab_offset = dynsym_offset;
|
||||
strtab_size = dynstr_size;
|
||||
strtab_offset = dynstr_offset;
|
||||
}
|
||||
|
||||
if (!symtab_size || !strtab_size) {
|
||||
return;
|
||||
}
|
||||
|
||||
text.resize(static_cast<std::size_t>(strtab_size) + 1, '\0');
|
||||
checked_seekg(fs, strtab_offset);
|
||||
read_raw(fs, text[0], static_cast<std::size_t>(strtab_size));
|
||||
|
||||
symbols.resize(static_cast<std::size_t>(symtab_size / sizeof(symbol_t)));
|
||||
checked_seekg(fs, symtab_offset);
|
||||
read_raw(fs, symbols[0], static_cast<std::size_t>(symtab_size - (symtab_size % sizeof(symbol_t))) );
|
||||
}
|
||||
|
||||
static bool is_visible(const symbol_t& sym) BOOST_NOEXCEPT {
|
||||
const unsigned char visibility = (sym.st_other & 0x03);
|
||||
// `(sym.st_info >> 4) != STB_LOCAL_ && !!sym.st_size` check also workarounds the
|
||||
// GCC's issue https://sourceware.org/bugzilla/show_bug.cgi?id=13621
|
||||
return (sym.st_other & 0x03) == STV_DEFAULT_ && (sym.st_info >> 4) != STB_LOCAL_ && !!sym.st_size;
|
||||
return (visibility == STV_DEFAULT_ || visibility == STV_PROTECTED_)
|
||||
&& (sym.st_info >> 4) != STB_LOCAL_ && !!sym.st_size;
|
||||
}
|
||||
|
||||
public:
|
||||
std::vector<std::string> symbols() {
|
||||
static std::vector<std::string> symbols(std::ifstream& fs) {
|
||||
std::vector<std::string> ret;
|
||||
|
||||
std::vector<symbol_t> symbols;
|
||||
std::vector<char> text;
|
||||
symbols_text(symbols, text);
|
||||
symbols_text(fs, symbols, text);
|
||||
|
||||
ret.reserve(symbols.size());
|
||||
for (std::size_t i = 0; i < symbols.size(); ++i) {
|
||||
if (is_visible(symbols[i])) {
|
||||
ret.push_back(&text[0] + symbols[i].st_name);
|
||||
if (is_visible(symbols[i]) && symbols[i].st_name < text.size()) {
|
||||
ret.push_back(&text[symbols[i].st_name]);
|
||||
if (ret.back().empty()) {
|
||||
ret.pop_back(); // Do not show empty names
|
||||
}
|
||||
@@ -230,35 +288,34 @@ public:
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<std::string> symbols(const char* section_name) {
|
||||
static std::vector<std::string> symbols(std::ifstream& fs, const char* section_name) {
|
||||
std::vector<std::string> ret;
|
||||
|
||||
std::size_t index = 0;
|
||||
std::size_t ptrs_in_section_count = 0;
|
||||
{
|
||||
std::vector<char> names;
|
||||
sections_names_raw(names);
|
||||
|
||||
const header_t elf = header();
|
||||
std::vector<char> names;
|
||||
sections_names_raw(fs, names);
|
||||
|
||||
for (; index < elf.e_shnum; ++index) {
|
||||
section_t section;
|
||||
f_.seekg(elf.e_shoff + index * sizeof(section_t));
|
||||
read_raw(section);
|
||||
|
||||
if (!std::strcmp(&names[0] + section.sh_name, section_name)) {
|
||||
if (!section.sh_entsize) {
|
||||
section.sh_entsize = 1;
|
||||
}
|
||||
ptrs_in_section_count = static_cast<std::size_t>(section.sh_size / section.sh_entsize);
|
||||
break;
|
||||
const header_t elf = header(fs);
|
||||
|
||||
for (; index < elf.e_shnum; ++index) {
|
||||
section_t section;
|
||||
checked_seekg(fs, elf.e_shoff + index * sizeof(section_t));
|
||||
read_raw(fs, section);
|
||||
|
||||
if (!std::strcmp(&names.at(section.sh_name), section_name)) {
|
||||
if (!section.sh_entsize) {
|
||||
section.sh_entsize = 1;
|
||||
}
|
||||
}
|
||||
ptrs_in_section_count = static_cast<std::size_t>(section.sh_size / section.sh_entsize);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<symbol_t> symbols;
|
||||
std::vector<char> text;
|
||||
symbols_text(symbols, text);
|
||||
std::vector<char> text;
|
||||
symbols_text(fs, symbols, text, names);
|
||||
|
||||
if (ptrs_in_section_count < symbols.size()) {
|
||||
ret.reserve(ptrs_in_section_count);
|
||||
@@ -267,8 +324,8 @@ public:
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < symbols.size(); ++i) {
|
||||
if (symbols[i].st_shndx == index && is_visible(symbols[i])) {
|
||||
ret.push_back(&text[0] + symbols[i].st_name);
|
||||
if (symbols[i].st_shndx == index && is_visible(symbols[i]) && symbols[i].st_name < text.size()) {
|
||||
ret.push_back(&text[symbols[i].st_name]);
|
||||
if (ret.back().empty()) {
|
||||
ret.pop_back(); // Do not show empty names
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
|
||||
// Copyright 2015-2019 Antony Polukhin.
|
||||
// Copyright Antony Polukhin, 2015-2023.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
@@ -16,9 +16,10 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <string> // for std::getline
|
||||
#include <vector>
|
||||
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/dll/detail/x_info_interface.hpp>
|
||||
|
||||
namespace boost { namespace dll { namespace detail {
|
||||
|
||||
@@ -157,9 +158,7 @@ typedef nlist_template<boost::uint32_t> nlist_32_;
|
||||
typedef nlist_template<boost::uint64_t> nlist_64_;
|
||||
|
||||
template <class AddressOffsetT>
|
||||
class macho_info: public x_info_interface {
|
||||
std::ifstream& f_;
|
||||
|
||||
class macho_info {
|
||||
typedef boost::dll::detail::mach_header_template<AddressOffsetT> header_t;
|
||||
typedef boost::dll::detail::load_command_ load_command_t;
|
||||
typedef boost::dll::detail::segment_command_template<AddressOffsetT> segment_t;
|
||||
@@ -170,55 +169,51 @@ class macho_info: public x_info_interface {
|
||||
BOOST_STATIC_CONSTANT(boost::uint32_t, SEGMENT_CMD_NUMBER = (sizeof(AddressOffsetT) > 4 ? load_command_types::LC_SEGMENT_64_ : load_command_types::LC_SEGMENT_));
|
||||
|
||||
public:
|
||||
static bool parsing_supported(std::ifstream& f) {
|
||||
static bool parsing_supported(std::ifstream& fs) {
|
||||
static const uint32_t magic_bytes = (sizeof(AddressOffsetT) <= sizeof(uint32_t) ? 0xfeedface : 0xfeedfacf);
|
||||
|
||||
uint32_t magic;
|
||||
f.seekg(0);
|
||||
f.read(reinterpret_cast<char*>(&magic), sizeof(magic));
|
||||
fs.seekg(0);
|
||||
fs.read(reinterpret_cast<char*>(&magic), sizeof(magic));
|
||||
return (magic_bytes == magic);
|
||||
}
|
||||
|
||||
explicit macho_info(std::ifstream& f) BOOST_NOEXCEPT
|
||||
: f_(f)
|
||||
{}
|
||||
|
||||
private:
|
||||
template <class T>
|
||||
inline void read_raw(T& value, std::size_t size = sizeof(T)) const {
|
||||
f_.read(reinterpret_cast<char*>(&value), size);
|
||||
static void read_raw(std::ifstream& fs, T& value, std::size_t size = sizeof(T)) {
|
||||
fs.read(reinterpret_cast<char*>(&value), size);
|
||||
}
|
||||
|
||||
template <class F>
|
||||
void command_finder(uint32_t cmd_num, F callback_f) {
|
||||
const header_t h = header();
|
||||
static void command_finder(std::ifstream& fs, uint32_t cmd_num, F callback_f) {
|
||||
const header_t h = header(fs);
|
||||
load_command_t command;
|
||||
f_.seekg(sizeof(header_t));
|
||||
fs.seekg(sizeof(header_t));
|
||||
for (std::size_t i = 0; i < h.ncmds; ++i) {
|
||||
const std::ifstream::pos_type pos = f_.tellg();
|
||||
read_raw(command);
|
||||
const std::ifstream::pos_type pos = fs.tellg();
|
||||
read_raw(fs, command);
|
||||
if (command.cmd != cmd_num) {
|
||||
f_.seekg(pos + static_cast<std::ifstream::pos_type>(command.cmdsize));
|
||||
fs.seekg(pos + static_cast<std::ifstream::pos_type>(command.cmdsize));
|
||||
continue;
|
||||
}
|
||||
|
||||
f_.seekg(pos);
|
||||
callback_f(*this);
|
||||
f_.seekg(pos + static_cast<std::ifstream::pos_type>(command.cmdsize));
|
||||
fs.seekg(pos);
|
||||
callback_f(fs);
|
||||
fs.seekg(pos + static_cast<std::ifstream::pos_type>(command.cmdsize));
|
||||
}
|
||||
}
|
||||
|
||||
struct section_names_gather {
|
||||
std::vector<std::string>& ret;
|
||||
|
||||
void operator()(const macho_info& f) const {
|
||||
void operator()(std::ifstream& fs) const {
|
||||
segment_t segment;
|
||||
f.read_raw(segment);
|
||||
read_raw(fs, segment);
|
||||
|
||||
section_t section;
|
||||
ret.reserve(ret.size() + segment.nsects);
|
||||
for (std::size_t j = 0; j < segment.nsects; ++j) {
|
||||
f.read_raw(section);
|
||||
read_raw(fs, section);
|
||||
// `segname` goes right after the `sectname`.
|
||||
// Forcing `sectname` to end on '\0'
|
||||
section.segname[0] = '\0';
|
||||
@@ -234,16 +229,16 @@ private:
|
||||
std::vector<std::string>& ret;
|
||||
std::size_t section_index;
|
||||
|
||||
void operator()(const macho_info& f) const {
|
||||
void operator()(std::ifstream& fs) const {
|
||||
symbol_header_t symbh;
|
||||
f.read_raw(symbh);
|
||||
read_raw(fs, symbh);
|
||||
ret.reserve(ret.size() + symbh.nsyms);
|
||||
|
||||
nlist_t symbol;
|
||||
std::string symbol_name;
|
||||
for (std::size_t j = 0; j < symbh.nsyms; ++j) {
|
||||
f.f_.seekg(symbh.symoff + j * sizeof(nlist_t));
|
||||
f.read_raw(symbol);
|
||||
fs.seekg(symbh.symoff + j * sizeof(nlist_t));
|
||||
read_raw(fs, symbol);
|
||||
if (!symbol.n_strx) {
|
||||
continue; // Symbol has no name
|
||||
}
|
||||
@@ -256,8 +251,8 @@ private:
|
||||
continue; // Not in the required section
|
||||
}
|
||||
|
||||
f.f_.seekg(symbh.stroff + symbol.n_strx);
|
||||
getline(f.f_, symbol_name, '\0');
|
||||
fs.seekg(symbh.stroff + symbol.n_strx);
|
||||
std::getline(fs, symbol_name, '\0');
|
||||
if (symbol_name.empty()) {
|
||||
continue;
|
||||
}
|
||||
@@ -273,34 +268,34 @@ private:
|
||||
};
|
||||
|
||||
public:
|
||||
std::vector<std::string> sections() {
|
||||
static std::vector<std::string> sections(std::ifstream& fs) {
|
||||
std::vector<std::string> ret;
|
||||
section_names_gather f = { ret };
|
||||
command_finder(SEGMENT_CMD_NUMBER, f);
|
||||
command_finder(fs, SEGMENT_CMD_NUMBER, f);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
inline header_t header() {
|
||||
static header_t header(std::ifstream& fs) {
|
||||
header_t h;
|
||||
|
||||
f_.seekg(0);
|
||||
read_raw(h);
|
||||
fs.seekg(0);
|
||||
read_raw(fs, h);
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
public:
|
||||
std::vector<std::string> symbols() {
|
||||
static std::vector<std::string> symbols(std::ifstream& fs) {
|
||||
std::vector<std::string> ret;
|
||||
symbol_names_gather f = { ret, 0 };
|
||||
command_finder(load_command_types::LC_SYMTAB_, f);
|
||||
command_finder(fs, load_command_types::LC_SYMTAB_, f);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<std::string> symbols(const char* section_name) {
|
||||
static std::vector<std::string> symbols(std::ifstream& fs, const char* section_name) {
|
||||
// Not very optimal solution
|
||||
std::vector<std::string> ret = sections();
|
||||
std::vector<std::string> ret = sections(fs);
|
||||
std::vector<std::string>::iterator it = std::find(ret.begin(), ret.end(), section_name);
|
||||
if (it == ret.end()) {
|
||||
// No section with such name
|
||||
@@ -311,7 +306,7 @@ public:
|
||||
// section indexes start from 1
|
||||
symbol_names_gather f = { ret, static_cast<std::size_t>(1 + (it - ret.begin())) };
|
||||
ret.clear();
|
||||
command_finder(load_command_types::LC_SYMTAB_, f);
|
||||
command_finder(fs, load_command_types::LC_SYMTAB_, f);
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
|
||||
// Copyright 2015-2019 Antony Polukhin.
|
||||
// Copyright Antony Polukhin, 2015-2023.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
@@ -16,10 +16,11 @@
|
||||
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <string> // for std::getline
|
||||
#include <vector>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/dll/detail/x_info_interface.hpp>
|
||||
|
||||
namespace boost { namespace dll { namespace detail {
|
||||
|
||||
@@ -164,24 +165,22 @@ typedef IMAGE_NT_HEADERS_template<boost::dll::detail::ULONGLONG_> IMAGE_NT_HEAD
|
||||
|
||||
|
||||
template <class AddressOffsetT>
|
||||
class pe_info: public x_info_interface {
|
||||
std::ifstream& f_;
|
||||
|
||||
class pe_info {
|
||||
typedef IMAGE_NT_HEADERS_template<AddressOffsetT> header_t;
|
||||
typedef IMAGE_EXPORT_DIRECTORY_ exports_t;
|
||||
typedef IMAGE_SECTION_HEADER_ section_t;
|
||||
typedef IMAGE_DOS_HEADER_ dos_t;
|
||||
|
||||
template <class T>
|
||||
inline void read_raw(T& value, std::size_t size = sizeof(T)) const {
|
||||
f_.read(reinterpret_cast<char*>(&value), size);
|
||||
static void read_raw(std::ifstream& fs, T& value, std::size_t size = sizeof(T)) {
|
||||
fs.read(reinterpret_cast<char*>(&value), size);
|
||||
}
|
||||
|
||||
public:
|
||||
static bool parsing_supported(std::ifstream& f) {
|
||||
static bool parsing_supported(std::ifstream& fs) {
|
||||
dos_t dos;
|
||||
f.seekg(0);
|
||||
f.read(reinterpret_cast<char*>(&dos), sizeof(dos));
|
||||
fs.seekg(0);
|
||||
fs.read(reinterpret_cast<char*>(&dos), sizeof(dos));
|
||||
|
||||
// 'MZ' and 'ZM' according to Wikipedia
|
||||
if (dos.e_magic != 0x4D5A && dos.e_magic != 0x5A4D) {
|
||||
@@ -189,59 +188,61 @@ public:
|
||||
}
|
||||
|
||||
header_t h;
|
||||
f.seekg(dos.e_lfanew);
|
||||
f.read(reinterpret_cast<char*>(&h), sizeof(h));
|
||||
fs.seekg(dos.e_lfanew);
|
||||
fs.read(reinterpret_cast<char*>(&h), sizeof(h));
|
||||
|
||||
return h.Signature == 0x00004550 // 'PE00'
|
||||
&& h.OptionalHeader.Magic == (sizeof(boost::uint32_t) == sizeof(AddressOffsetT) ? 0x10B : 0x20B);
|
||||
}
|
||||
|
||||
|
||||
explicit pe_info(std::ifstream& f) BOOST_NOEXCEPT
|
||||
: f_(f)
|
||||
{}
|
||||
|
||||
private:
|
||||
inline header_t header() {
|
||||
static header_t header(std::ifstream& fs) {
|
||||
header_t h;
|
||||
|
||||
dos_t dos;
|
||||
f_.seekg(0);
|
||||
read_raw(dos);
|
||||
fs.seekg(0);
|
||||
read_raw(fs, dos);
|
||||
|
||||
f_.seekg(dos.e_lfanew);
|
||||
read_raw(h);
|
||||
fs.seekg(dos.e_lfanew);
|
||||
read_raw(fs, h);
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
inline exports_t exports(const header_t& h) {
|
||||
exports_t exports;
|
||||
|
||||
static exports_t exports(std::ifstream& fs, const header_t& h) {
|
||||
static const unsigned int IMAGE_DIRECTORY_ENTRY_EXPORT_ = 0;
|
||||
const std::size_t exp_virtual_address = h.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT_].VirtualAddress;
|
||||
exports_t exports;
|
||||
|
||||
const std::size_t real_offset = get_file_offset(exp_virtual_address, h);
|
||||
if (exp_virtual_address == 0) {
|
||||
// The virtual address can be 0 in case there are no exported symbols
|
||||
std::memset(&exports, 0, sizeof(exports));
|
||||
return exports;
|
||||
}
|
||||
|
||||
const std::size_t real_offset = get_file_offset(fs, exp_virtual_address, h);
|
||||
BOOST_ASSERT(real_offset);
|
||||
|
||||
f_.seekg(real_offset);
|
||||
read_raw(exports);
|
||||
fs.seekg(real_offset);
|
||||
read_raw(fs, exports);
|
||||
|
||||
return exports;
|
||||
}
|
||||
|
||||
std::size_t get_file_offset(std::size_t virtual_address, const header_t& h) {
|
||||
static std::size_t get_file_offset(std::ifstream& fs, std::size_t virtual_address, const header_t& h) {
|
||||
BOOST_ASSERT(virtual_address);
|
||||
|
||||
section_t image_section_header;
|
||||
|
||||
{ // f_.seekg to the beginning on section headers
|
||||
{ // fs.seekg to the beginning on section headers
|
||||
dos_t dos;
|
||||
f_.seekg(0);
|
||||
read_raw(dos);
|
||||
f_.seekg(dos.e_lfanew + sizeof(header_t));
|
||||
fs.seekg(0);
|
||||
read_raw(fs, dos);
|
||||
fs.seekg(dos.e_lfanew + sizeof(header_t));
|
||||
}
|
||||
|
||||
for (std::size_t i = 0;i < h.FileHeader.NumberOfSections;++i) {
|
||||
read_raw(image_section_header);
|
||||
read_raw(fs, image_section_header);
|
||||
if (virtual_address >= image_section_header.VirtualAddress
|
||||
&& virtual_address < image_section_header.VirtualAddress + image_section_header.SizeOfRawData)
|
||||
{
|
||||
@@ -253,10 +254,10 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
std::vector<std::string> sections() {
|
||||
static std::vector<std::string> sections(std::ifstream& fs) {
|
||||
std::vector<std::string> ret;
|
||||
|
||||
const header_t h = header();
|
||||
const header_t h = header(fs);
|
||||
ret.reserve(h.FileHeader.NumberOfSections);
|
||||
|
||||
// get names, e.g: .text .rdata .data .rsrc .reloc
|
||||
@@ -265,7 +266,7 @@ public:
|
||||
std::memset(name_helper, 0, sizeof(name_helper));
|
||||
for (std::size_t i = 0;i < h.FileHeader.NumberOfSections;++i) {
|
||||
// There is no terminating null character if the string is exactly eight characters long
|
||||
read_raw(image_section_header);
|
||||
read_raw(fs, image_section_header);
|
||||
std::memcpy(name_helper, image_section_header.Name, section_t::IMAGE_SIZEOF_SHORT_NAME_);
|
||||
|
||||
if (name_helper[0] != '/') {
|
||||
@@ -281,32 +282,37 @@ public:
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<std::string> symbols() {
|
||||
static std::vector<std::string> symbols(std::ifstream& fs) {
|
||||
std::vector<std::string> ret;
|
||||
|
||||
const header_t h = header();
|
||||
const exports_t exprt = exports(h);
|
||||
const header_t h = header(fs);
|
||||
const exports_t exprt = exports(fs, h);
|
||||
const std::size_t exported_symbols = exprt.NumberOfNames;
|
||||
const std::size_t fixed_names_addr = get_file_offset(exprt.AddressOfNames, h);
|
||||
|
||||
if (exported_symbols == 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
const std::size_t fixed_names_addr = get_file_offset(fs, exprt.AddressOfNames, h);
|
||||
|
||||
ret.reserve(exported_symbols);
|
||||
boost::dll::detail::DWORD_ name_offset;
|
||||
std::string symbol_name;
|
||||
for (std::size_t i = 0;i < exported_symbols;++i) {
|
||||
f_.seekg(fixed_names_addr + i * sizeof(name_offset));
|
||||
read_raw(name_offset);
|
||||
f_.seekg(get_file_offset(name_offset, h));
|
||||
getline(f_, symbol_name, '\0');
|
||||
fs.seekg(fixed_names_addr + i * sizeof(name_offset));
|
||||
read_raw(fs, name_offset);
|
||||
fs.seekg(get_file_offset(fs, name_offset, h));
|
||||
std::getline(fs, symbol_name, '\0');
|
||||
ret.push_back(symbol_name);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<std::string> symbols(const char* section_name) {
|
||||
static std::vector<std::string> symbols(std::ifstream& fs, const char* section_name) {
|
||||
std::vector<std::string> ret;
|
||||
|
||||
const header_t h = header();
|
||||
const header_t h = header(fs);
|
||||
|
||||
std::size_t section_begin_addr = 0;
|
||||
std::size_t section_end_addr = 0;
|
||||
@@ -317,7 +323,7 @@ public:
|
||||
std::memset(name_helper, 0, sizeof(name_helper));
|
||||
for (std::size_t i = 0;i < h.FileHeader.NumberOfSections;++i) {
|
||||
// There is no terminating null character if the string is exactly eight characters long
|
||||
read_raw(image_section_header);
|
||||
read_raw(fs, image_section_header);
|
||||
std::memcpy(name_helper, image_section_header.Name, section_t::IMAGE_SIZEOF_SHORT_NAME_);
|
||||
if (!std::strcmp(section_name, name_helper)) {
|
||||
section_begin_addr = image_section_header.PointerToRawData;
|
||||
@@ -330,11 +336,11 @@ public:
|
||||
return ret;
|
||||
}
|
||||
|
||||
const exports_t exprt = exports(h);
|
||||
const exports_t exprt = exports(fs, h);
|
||||
const std::size_t exported_symbols = exprt.NumberOfFunctions;
|
||||
const std::size_t fixed_names_addr = get_file_offset(exprt.AddressOfNames, h);
|
||||
const std::size_t fixed_ordinals_addr = get_file_offset(exprt.AddressOfNameOrdinals, h);
|
||||
const std::size_t fixed_functions_addr = get_file_offset(exprt.AddressOfFunctions, h);
|
||||
const std::size_t fixed_names_addr = get_file_offset(fs, exprt.AddressOfNames, h);
|
||||
const std::size_t fixed_ordinals_addr = get_file_offset(fs, exprt.AddressOfNameOrdinals, h);
|
||||
const std::size_t fixed_functions_addr = get_file_offset(fs, exprt.AddressOfFunctions, h);
|
||||
|
||||
ret.reserve(exported_symbols);
|
||||
boost::dll::detail::DWORD_ ptr;
|
||||
@@ -342,22 +348,22 @@ public:
|
||||
std::string symbol_name;
|
||||
for (std::size_t i = 0;i < exported_symbols;++i) {
|
||||
// getting ordinal
|
||||
f_.seekg(fixed_ordinals_addr + i * sizeof(ordinal));
|
||||
read_raw(ordinal);
|
||||
fs.seekg(fixed_ordinals_addr + i * sizeof(ordinal));
|
||||
read_raw(fs, ordinal);
|
||||
|
||||
// getting function addr
|
||||
f_.seekg(fixed_functions_addr + ordinal * sizeof(ptr));
|
||||
read_raw(ptr);
|
||||
ptr = static_cast<boost::dll::detail::DWORD_>( get_file_offset(ptr, h) );
|
||||
fs.seekg(fixed_functions_addr + ordinal * sizeof(ptr));
|
||||
read_raw(fs, ptr);
|
||||
ptr = static_cast<boost::dll::detail::DWORD_>( get_file_offset(fs, ptr, h) );
|
||||
|
||||
if (ptr >= section_end_addr || ptr < section_begin_addr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
f_.seekg(fixed_names_addr + i * sizeof(ptr));
|
||||
read_raw(ptr);
|
||||
f_.seekg(get_file_offset(ptr, h));
|
||||
getline(f_, symbol_name, '\0');
|
||||
fs.seekg(fixed_names_addr + i * sizeof(ptr));
|
||||
read_raw(fs, ptr);
|
||||
fs.seekg(get_file_offset(fs, ptr, h));
|
||||
std::getline(fs, symbol_name, '\0');
|
||||
ret.push_back(symbol_name);
|
||||
}
|
||||
|
||||
@@ -374,7 +380,7 @@ public:
|
||||
MSVCR110D.dll
|
||||
*/
|
||||
/*
|
||||
std::vector<std::string> depend_of(boost::dll::fs::error_code &ec) BOOST_NOEXCEPT {
|
||||
static std::vector<std::string> depend_of(boost::dll::fs::error_code &ec) BOOST_NOEXCEPT {
|
||||
std::vector<std::string> ret;
|
||||
|
||||
IMAGE_DOS_HEADER* image_dos_header = (IMAGE_DOS_HEADER*)native();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright 2014-2015 Renato Tegon Forti, Antony Polukhin.
|
||||
// Copyright 2016-2019 Antony Polukhin.
|
||||
// Copyright Antony Polukhin, 2016-2023.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
@@ -35,8 +35,8 @@ namespace boost { namespace dll { namespace detail {
|
||||
|
||||
// Iterate through all images currently in memory
|
||||
// https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/dyld.3.html
|
||||
const std::size_t count = _dyld_image_count(); // not thread safe: other thread my [un]load images
|
||||
for (std::size_t i = 0; i <= count; ++i) {
|
||||
const uint32_t count = _dyld_image_count(); // not thread safe: other thread my [un]load images
|
||||
for (uint32_t i = 0; i <= count; ++i) {
|
||||
// on last iteration `i` is equal to `count` which is out of range, so `_dyld_get_image_name`
|
||||
// will return NULL. `dlopen(NULL, RTLD_LAZY)` call will open the current executable.
|
||||
const char* image_name = _dyld_get_image_name(i);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
|
||||
// Copyright 2015-2019 Antony Polukhin.
|
||||
// Copyright Antony Polukhin, 2015-2023.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
|
||||
// Copyright 2015-2019 Antony Polukhin.
|
||||
// Copyright Antony Polukhin, 2015-2023.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
@@ -62,15 +62,16 @@ public:
|
||||
static boost::dll::fs::path decorate(const boost::dll::fs::path & sl) {
|
||||
boost::dll::fs::path actual_path = (
|
||||
std::strncmp(sl.filename().string().c_str(), "lib", 3)
|
||||
? boost::dll::fs::path((sl.has_parent_path() ? sl.parent_path() / L"lib" : L"lib").native() + sl.filename().native())
|
||||
? boost::dll::fs::path((sl.has_parent_path() ? sl.parent_path() / "lib" : "lib").native() + sl.filename().native())
|
||||
: sl
|
||||
);
|
||||
actual_path += suffix();
|
||||
return actual_path;
|
||||
}
|
||||
|
||||
void load(boost::dll::fs::path sl, load_mode::type mode, boost::dll::fs::error_code &ec) {
|
||||
void load(boost::dll::fs::path sl, load_mode::type portable_mode, boost::dll::fs::error_code &ec) {
|
||||
typedef int native_mode_t;
|
||||
native_mode_t native_mode = static_cast<native_mode_t>(portable_mode);
|
||||
unload();
|
||||
|
||||
// Do not allow opening NULL paths. User must use program_location() instead
|
||||
@@ -84,20 +85,20 @@ public:
|
||||
}
|
||||
|
||||
// Fixing modes
|
||||
if (!(mode & load_mode::rtld_now)) {
|
||||
mode |= load_mode::rtld_lazy;
|
||||
if (!(native_mode & load_mode::rtld_now)) {
|
||||
native_mode |= load_mode::rtld_lazy;
|
||||
}
|
||||
|
||||
if (!(mode & load_mode::rtld_global)) {
|
||||
mode |= load_mode::rtld_local;
|
||||
if (!(native_mode & load_mode::rtld_global)) {
|
||||
native_mode |= load_mode::rtld_local;
|
||||
}
|
||||
|
||||
#if BOOST_OS_LINUX || BOOST_OS_ANDROID
|
||||
if (!sl.has_parent_path() && !(mode & load_mode::search_system_folders)) {
|
||||
if (!sl.has_parent_path() && !(native_mode & load_mode::search_system_folders)) {
|
||||
sl = "." / sl;
|
||||
}
|
||||
#else
|
||||
if (!sl.is_absolute() && !(mode & load_mode::search_system_folders)) {
|
||||
if (!sl.is_absolute() && !(native_mode & load_mode::search_system_folders)) {
|
||||
boost::dll::fs::error_code current_path_ec;
|
||||
boost::dll::fs::path prog_loc = boost::dll::fs::current_path(current_path_ec);
|
||||
if (!current_path_ec) {
|
||||
@@ -107,14 +108,14 @@ public:
|
||||
}
|
||||
#endif
|
||||
|
||||
mode &= ~load_mode::search_system_folders;
|
||||
native_mode = static_cast<unsigned>(native_mode) & ~static_cast<unsigned>(load_mode::search_system_folders);
|
||||
|
||||
// Trying to open with appended decorations
|
||||
if (!!(mode & load_mode::append_decorations)) {
|
||||
mode &= ~load_mode::append_decorations;
|
||||
if (!!(native_mode & load_mode::append_decorations)) {
|
||||
native_mode = static_cast<unsigned>(native_mode) & ~static_cast<unsigned>(load_mode::append_decorations);
|
||||
|
||||
boost::dll::fs::path actual_path = decorate(sl);
|
||||
handle_ = dlopen(actual_path.c_str(), static_cast<native_mode_t>(mode));
|
||||
handle_ = dlopen(actual_path.c_str(), native_mode);
|
||||
if (handle_) {
|
||||
boost::dll::detail::reset_dlerror();
|
||||
return;
|
||||
@@ -131,7 +132,7 @@ public:
|
||||
}
|
||||
|
||||
// Opening by exactly specified path
|
||||
handle_ = dlopen(sl.c_str(), static_cast<native_mode_t>(mode));
|
||||
handle_ = dlopen(sl.c_str(), native_mode);
|
||||
if (handle_) {
|
||||
boost::dll::detail::reset_dlerror();
|
||||
return;
|
||||
@@ -153,7 +154,7 @@ public:
|
||||
// returned handle is for the main program.
|
||||
ec.clear();
|
||||
boost::dll::detail::reset_dlerror();
|
||||
handle_ = dlopen(NULL, static_cast<native_mode_t>(mode));
|
||||
handle_ = dlopen(NULL, native_mode);
|
||||
if (!handle_) {
|
||||
ec = boost::dll::fs::make_error_code(
|
||||
boost::dll::fs::errc::bad_file_descriptor
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
|
||||
// Copyright 2015-2019 Antony Polukhin.
|
||||
// Copyright Antony Polukhin, 2015-2023.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
#include <typeinfo>
|
||||
#include <cstring>
|
||||
#include <boost/dll/config.hpp>
|
||||
#if defined(BOOST_MSVC) || defined(BOOST_MSVC_VER)
|
||||
#if defined(_MSC_VER) // MSVC, Clang-cl, and ICC on Windows
|
||||
#include <boost/winapi/basic_types.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace dll { namespace detail {
|
||||
|
||||
#if defined(BOOST_MSVC) || defined(BOOST_MSVC_VER)
|
||||
#if defined(_MSC_VER) // MSVC, Clang-cl, and ICC on Windows
|
||||
|
||||
#if defined ( _WIN64 )
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
|
||||
// Copyright 2015-2019 Antony Polukhin.
|
||||
// Copyright Antony Polukhin, 2015-2023.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
@@ -31,27 +31,28 @@ namespace boost { namespace dll { namespace detail {
|
||||
BOOST_STATIC_CONSTANT(boost::winapi::DWORD_, ERROR_INSUFFICIENT_BUFFER_ = 0x7A);
|
||||
BOOST_STATIC_CONSTANT(boost::winapi::DWORD_, DEFAULT_PATH_SIZE_ = 260);
|
||||
|
||||
// On success, GetModuleFileNameW() doesn't reset last error to ERROR_SUCCESS. Resetting it manually.
|
||||
boost::winapi::GetLastError();
|
||||
|
||||
// If `handle` parameter is NULL, GetModuleFileName retrieves the path of the
|
||||
// executable file of the current process.
|
||||
boost::winapi::WCHAR_ path_hldr[DEFAULT_PATH_SIZE_];
|
||||
boost::winapi::GetModuleFileNameW(handle, path_hldr, DEFAULT_PATH_SIZE_);
|
||||
ec = boost::dll::detail::last_error_code();
|
||||
if (!ec) {
|
||||
const boost::winapi::DWORD_ ret = boost::winapi::GetModuleFileNameW(handle, path_hldr, DEFAULT_PATH_SIZE_);
|
||||
if (ret) {
|
||||
// On success, GetModuleFileNameW() doesn't reset last error to ERROR_SUCCESS. Resetting it manually.
|
||||
ec.clear();
|
||||
return boost::dll::fs::path(path_hldr);
|
||||
}
|
||||
|
||||
ec = boost::dll::detail::last_error_code();
|
||||
for (unsigned i = 2; i < 1025 && static_cast<boost::winapi::DWORD_>(ec.value()) == ERROR_INSUFFICIENT_BUFFER_; i *= 2) {
|
||||
std::wstring p(DEFAULT_PATH_SIZE_ * i, L'\0');
|
||||
const std::size_t size = boost::winapi::GetModuleFileNameW(handle, &p[0], DEFAULT_PATH_SIZE_ * i);
|
||||
ec = boost::dll::detail::last_error_code();
|
||||
|
||||
if (!ec) {
|
||||
if (size) {
|
||||
// On success, GetModuleFileNameW() doesn't reset last error to ERROR_SUCCESS. Resetting it manually.
|
||||
ec.clear();
|
||||
p.resize(size);
|
||||
return boost::dll::fs::path(p);
|
||||
}
|
||||
|
||||
ec = boost::dll::detail::last_error_code();
|
||||
}
|
||||
|
||||
// Error other than ERROR_INSUFFICIENT_BUFFER_ occurred or failed to allocate buffer big enough.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
|
||||
// Copyright 2015-2019 Antony Polukhin.
|
||||
// Copyright Antony Polukhin, 2015-2023.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
@@ -56,11 +56,12 @@ public:
|
||||
return actual_path;
|
||||
}
|
||||
|
||||
void load(boost::dll::fs::path sl, load_mode::type mode, boost::dll::fs::error_code &ec) {
|
||||
void load(boost::dll::fs::path sl, load_mode::type portable_mode, boost::dll::fs::error_code &ec) {
|
||||
typedef boost::winapi::DWORD_ native_mode_t;
|
||||
native_mode_t native_mode = static_cast<native_mode_t>(portable_mode);
|
||||
unload();
|
||||
|
||||
if (!sl.is_absolute() && !(mode & load_mode::search_system_folders)) {
|
||||
if (!sl.is_absolute() && !(native_mode & load_mode::search_system_folders)) {
|
||||
boost::dll::fs::error_code current_path_ec;
|
||||
boost::dll::fs::path prog_loc = boost::dll::fs::current_path(current_path_ec);
|
||||
|
||||
@@ -69,13 +70,13 @@ public:
|
||||
sl.swap(prog_loc);
|
||||
}
|
||||
}
|
||||
mode &= ~load_mode::search_system_folders;
|
||||
native_mode = static_cast<unsigned>(native_mode) & ~static_cast<unsigned>(load_mode::search_system_folders);
|
||||
|
||||
// Trying to open with appended decorations
|
||||
if (!!(mode & load_mode::append_decorations)) {
|
||||
mode &= ~load_mode::append_decorations;
|
||||
if (!!(native_mode & load_mode::append_decorations)) {
|
||||
native_mode = static_cast<unsigned>(native_mode) & ~static_cast<unsigned>(load_mode::append_decorations);
|
||||
|
||||
if (load_impl(decorate(sl), static_cast<native_mode_t>(mode), ec)) {
|
||||
if (load_impl(decorate(sl), native_mode, ec)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -85,7 +86,7 @@ public:
|
||||
? sl.parent_path() / L"lib"
|
||||
: L"lib"
|
||||
).native() + sl.filename().native() + suffix().native();
|
||||
if (load_impl(mingw_load_path, static_cast<native_mode_t>(mode), ec)) {
|
||||
if (load_impl(mingw_load_path, native_mode, ec)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -98,9 +99,9 @@ public:
|
||||
// we have some path. So we do not check for path, only for extension. We can not be sure that
|
||||
// such behavior remain across all platforms, so we add L"." by hand.
|
||||
if (sl.has_extension()) {
|
||||
handle_ = boost::winapi::LoadLibraryExW(sl.c_str(), 0, static_cast<native_mode_t>(mode));
|
||||
handle_ = boost::winapi::LoadLibraryExW(sl.c_str(), 0, native_mode);
|
||||
} else {
|
||||
handle_ = boost::winapi::LoadLibraryExW((sl.native() + L".").c_str(), 0, static_cast<native_mode_t>(mode));
|
||||
handle_ = boost::winapi::LoadLibraryExW((sl.native() + L".").c_str(), 0, native_mode);
|
||||
}
|
||||
|
||||
// LoadLibraryExW method is capable of self loading from program_location() path. No special actions
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
|
||||
// Copyright 2015-2019 Antony Polukhin.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_DLL_DETAIL_X_INFO_INTERFACE_HPP
|
||||
#define BOOST_DLL_DETAIL_X_INFO_INTERFACE_HPP
|
||||
|
||||
#include <boost/dll/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace boost { namespace dll { namespace detail {
|
||||
|
||||
class x_info_interface {
|
||||
public:
|
||||
virtual std::vector<std::string> sections() = 0;
|
||||
virtual std::vector<std::string> symbols() = 0;
|
||||
virtual std::vector<std::string> symbols(const char* section_name) = 0;
|
||||
|
||||
virtual ~x_info_interface() BOOST_NOEXCEPT {}
|
||||
};
|
||||
|
||||
}}} // namespace boost::dll::detail
|
||||
|
||||
#endif // BOOST_DLL_DETAIL_X_INFO_INTERFACE_HPP
|
||||
Reference in New Issue
Block a user