VoltMod
C++23 framework for CS2 server plugins
Loading...
Searching...
No Matches
Image.linux.cpp
Go to the documentation of this file.
2
3#include <algorithm>
4#include <dlfcn.h>
5#include <link.h>
6#include <string_view>
7#include <utility>
8#include <vector>
9
10namespace VoltMod
11{
12
13static std::string_view BaseName(std::string_view path)
14{
15 const size_t slash = path.rfind('/');
16 return slash == std::string_view::npos ? path : path.substr(slash + 1);
17}
18
20{
21 std::string_view Name; // basename to match, e.g. "libserver.so"
22 size_t BestSpan = 0; // largest span selects the real module
23 std::vector<ScanRange> Ranges; // PT_LOAD segments of the selected module
24 Image Module; // selected module mapping and path
25};
26
27// Multiple objects can share a basename. Match it exactly and keep the largest mapping to avoid
28// selecting a loader stub.
29static int DlIterateCallback(struct dl_phdr_info* info, size_t /*size*/, void* data)
30{
31 auto* scan = static_cast<ModuleScan*>(data);
32 if (!info->dlpi_name || BaseName(info->dlpi_name) != scan->Name)
33 {
34 return 0;
35 }
36
37 size_t span = 0;
38 std::vector<ScanRange> segments;
39 for (int i = 0; i < info->dlpi_phnum; ++i)
40 {
41 const auto& phdr = info->dlpi_phdr[i];
42 if (phdr.p_type != PT_LOAD || phdr.p_memsz == 0)
43 {
44 continue;
45 }
46
47 span = std::max(span, static_cast<size_t>(phdr.p_vaddr + phdr.p_memsz));
48 segments.push_back({reinterpret_cast<const uint8_t*>(info->dlpi_addr + phdr.p_vaddr), phdr.p_memsz});
49 }
50
51 if (span > scan->BestSpan)
52 {
53 scan->BestSpan = span;
54 scan->Ranges = std::move(segments);
55 // ELF symbol values are link-time addresses, so apply the loader's l_addr bias.
56 scan->Module = {reinterpret_cast<const uint8_t*>(info->dlpi_addr), span, info->dlpi_name};
57 }
58 return 0; // continue so the largest match wins
59}
60
61bool FindModuleAndRanges(std::string_view fileName, Image& module, std::vector<ScanRange>& ranges)
62{
65 if (scan.Ranges.empty())
66 {
67 return false;
68 }
69
70 module = std::move(scan.Module);
71 ranges = std::move(scan.Ranges);
72 return true;
73}
74
75} // namespace VoltMod
bool FindModuleAndRanges(std::string_view fileName, Image &module, std::vector< ScanRange > &ranges)
static std::string ReadFile(const std::filesystem::path &path)
Definition Loader.cpp:56
static std::string_view BaseName(std::string_view path)
static int DlIterateCallback(struct dl_phdr_info *info, size_t, void *data)
std::vector< ScanRange > Ranges
std::string_view Name