67 lines
2.6 KiB
C++
67 lines
2.6 KiB
C++
#pragma once
|
|
|
|
#include <cstddef>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace hot_reload::detail
|
|
{
|
|
|
|
/**
|
|
* @brief One exported symbol found in a loaded module, already classified.
|
|
*/
|
|
struct ExportedSymbol
|
|
{
|
|
std::string name; /**< The symbol's real (possibly mangled) name. */
|
|
void* address = nullptr; /**< The symbol's runtime address. */
|
|
|
|
/**
|
|
* The single load-bearing safety gate behind the "only
|
|
* executable code changes" guarantee in `hot_reload.h`: false
|
|
* for anything not mechanically identified as code (a data
|
|
* object, a forwarder export, or a symbol kind this reader does
|
|
* not recognize at all). `Context` never patches a
|
|
* symbol where this is false, on either side of a reload.
|
|
*/
|
|
bool isFunction = false;
|
|
|
|
/**
|
|
* Compiled size in bytes if known, 0 if not. ELF gives this
|
|
* exactly (the symbol table's `st_size` field); PE gives no such
|
|
* field, so this holds a conservative estimate derived from the
|
|
* distance to the next exported function in the same section --
|
|
* see the file comment in `SymbolTable.cpp` for exactly what
|
|
* that heuristic can and cannot catch.
|
|
*/
|
|
std::size_t size = 0;
|
|
};
|
|
|
|
/**
|
|
* @brief Reads and classifies every exported, defined symbol in a loaded module.
|
|
*
|
|
* On POSIX this parses @p imagePath on disk (its ELF `.dynsym` /
|
|
* `.dynstr` / section-header table) and adds @p loadedBase as the
|
|
* runtime load bias. On Windows this ignores @p imagePath and reads
|
|
* directly from the already-mapped image at @p loadedBase (its PE
|
|
* export directory and section table) -- see the per-platform
|
|
* implementation blocks in `SymbolTable.cpp` for why each platform
|
|
* reads from a different place.
|
|
*
|
|
* A file that is truncated or otherwise corrupt in the parts this reader relies on (the
|
|
* section header table and the tables it points at) is treated like any other unparseable
|
|
* image: every offset and length read from the file is range-checked against the file's size
|
|
* before it is used, so a damaged image yields fewer (or no) symbols rather than an
|
|
* out-of-bounds read.
|
|
*
|
|
* @param imagePath Path to the module on disk (POSIX only -- see above).
|
|
* @param loadedBase The base address `dlopen()`/`LoadLibrary()` returned for it.
|
|
* @return Every exported symbol, classified via ExportedSymbol::isFunction.
|
|
* Empty (never throws) if the image could not be parsed as
|
|
* this platform's native format (including the rare case of
|
|
* a `.so` with its section header table deliberately
|
|
* stripped -- see the file comment in `SymbolTable.cpp`).
|
|
*/
|
|
std::vector<ExportedSymbol> readExportedSymbols(const std::string& imagePath, void* loadedBase);
|
|
|
|
}
|