Compare commits
10 Commits
7b047655b6
...
b2e1427387
| Author | SHA1 | Date | |
|---|---|---|---|
| b2e1427387 | |||
| a45c22a4a1 | |||
| 330637851e | |||
| 0f7e15a28b | |||
| a9b9715499 | |||
| f2534d54a5 | |||
| bac5a060d2 | |||
| 8c6ce9d289 | |||
| beb5071601 | |||
| d5ab4e5f72 |
68
.github/workflows/build-linux.yml
vendored
68
.github/workflows/build-linux.yml
vendored
@@ -1,68 +0,0 @@
|
||||
name: Build (Linux)
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- .github/workflows/build-linux.yml
|
||||
- src/**
|
||||
- xmake.lua
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
mode: [debug, release]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# - name: Prepare works
|
||||
# run: |
|
||||
# mkdir ./.xmake-dest
|
||||
|
||||
- name: Restore build cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.xmake
|
||||
./.xmake-dest
|
||||
key: xmake-linux-${{ hashFiles('xmake.lua') }}
|
||||
restore-keys: |
|
||||
xmake-linux-
|
||||
|
||||
- name: Setup XMake
|
||||
uses: xmake-io/github-action-setup-xmake@v1
|
||||
with:
|
||||
xmake-version: '2.9.8'
|
||||
actions-cache-folder: './.xmake-dest'
|
||||
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
sudo apt install -y build-essential llvm-19-dev libclang-19-dev
|
||||
|
||||
# workaround to switch llvm version.
|
||||
sudo mv /usr/include/clang /usr/include/clang-compiler
|
||||
sudo ln -s /usr/lib/llvm-19/bin/llvm-config /usr/bin/llvm-config
|
||||
sudo ln -s /usr/include/llvm-19/llvm /usr/include/llvm
|
||||
sudo ln -s /usr/include/llvm-c-19/llvm-c /usr/include/llvm-c
|
||||
sudo ln -s /usr/lib/llvm-19/include/clang /usr/include/clang
|
||||
sudo ln -s /usr/lib/llvm-19/include/clang-c /usr/include/clang-c
|
||||
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
# c++23 <print> requires gcc 14.
|
||||
xmake f -a x64 -m ${{ matrix.mode }} -p linux --toolchain=gcc-14 -v -y
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
xmake -v -y
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: debuginfo-${{ matrix.mode }}-linux-x64-${{ github.sha }}
|
||||
path: |
|
||||
build/linux/x64/${{ matrix.mode }}
|
||||
88
.github/workflows/build.yml
vendored
Normal file
88
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
name: Build
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- .github/workflows/build.yml
|
||||
- src/**
|
||||
- xmake.lua
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
XMAKE_VERSION: "3.0.1"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
mode: [debug, release]
|
||||
plat:
|
||||
- os: linux
|
||||
toolchain: gcc-14 # c++23 <print> requires gcc 14.
|
||||
arch: x86_64
|
||||
runner: ubuntu-latest
|
||||
- os: linux
|
||||
toolchain: gcc-14
|
||||
arch: arm64
|
||||
runner: ubuntu-24.04-arm
|
||||
- os: macosx
|
||||
toolchain: xcode
|
||||
arch: arm64
|
||||
runner: macos-latest
|
||||
- os: windows
|
||||
toolchain: clang
|
||||
arch: x64
|
||||
runner: windows-latest
|
||||
|
||||
runs-on: ${{ matrix.plat.runner }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Restore xmake cache
|
||||
if: matrix.plat.os != 'windows'
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.xmake
|
||||
./.xmake-dest
|
||||
key: xmake-${{ matrix.plat.os }}-${{ matrix.plat.arch }}-${{ hashFiles('xmake.lua') }}
|
||||
restore-keys: |
|
||||
xmake-${{ matrix.plat.os }}-${{ matrix.plat.arch }}-
|
||||
|
||||
- name: Restore xmake cache (Windows)
|
||||
if: matrix.plat.os == 'windows'
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/AppData/Local/.xmake
|
||||
./.xmake-dest
|
||||
key: xmake-${{ matrix.plat.os }}-${{ matrix.plat.arch }}-${{ hashFiles('xmake.lua') }}
|
||||
restore-keys: |
|
||||
xmake-${{ matrix.plat.os }}-${{ matrix.plat.arch }}-
|
||||
|
||||
- name: Setup xmake
|
||||
uses: xmake-io/github-action-setup-xmake@v1
|
||||
with:
|
||||
xmake-version: ${{ env.XMAKE_VERSION }}
|
||||
actions-cache-folder: "./.xmake-dest"
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
xmake f -a ${{ matrix.plat.arch }} -m ${{ matrix.mode }} -p ${{ matrix.plat.os }} --toolchain=${{ matrix.plat.toolchain }} -vD -y
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
xmake -vD -y
|
||||
|
||||
- name: Cleanup
|
||||
run: |
|
||||
xrepo clean
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: debuginfo-${{ matrix.mode }}-${{ matrix.plat.os }}-${{ matrix.plat.arch }}-${{ github.sha }}
|
||||
path: |
|
||||
build/${{ matrix.plat.os }}/${{ matrix.plat.arch }}/${{ matrix.mode }}
|
||||
@@ -1,44 +1,3 @@
|
||||
babel==2.17.0
|
||||
backrefs==5.8
|
||||
cairocffi==1.7.1
|
||||
CairoSVG==2.7.1
|
||||
certifi==2025.1.31
|
||||
cffi==1.17.1
|
||||
charset-normalizer==3.4.1
|
||||
click==8.1.8
|
||||
colorama==0.4.6
|
||||
cssselect2==0.8.0
|
||||
defusedxml==0.7.1
|
||||
ghp-import==2.1.0
|
||||
gitdb==4.0.12
|
||||
GitPython==3.1.44
|
||||
idna==3.10
|
||||
Jinja2==3.1.6
|
||||
Markdown==3.7
|
||||
MarkupSafe==3.0.2
|
||||
mergedeep==1.3.4
|
||||
mkdocs==1.6.1
|
||||
mkdocs-get-deps==0.2.0
|
||||
mkdocs-material==9.6.17
|
||||
mkdocs-git-revision-date-localized-plugin==1.4.7
|
||||
mkdocs-git-committers-plugin-2==2.5.0
|
||||
mkdocs-git-revision-date-localized-plugin==1.4.1
|
||||
mkdocs-material==9.6.8
|
||||
mkdocs-material-extensions==1.3.1
|
||||
packaging==24.2
|
||||
paginate==0.5.7
|
||||
pathspec==0.12.1
|
||||
pillow==10.4.0
|
||||
platformdirs==4.3.6
|
||||
pycparser==2.22
|
||||
Pygments==2.19.1
|
||||
pymdown-extensions==10.14.3
|
||||
python-dateutil==2.9.0.post0
|
||||
pytz==2025.1
|
||||
PyYAML==6.0.2
|
||||
pyyaml_env_tag==0.1
|
||||
requests==2.32.3
|
||||
six==1.17.0
|
||||
smmap==5.0.2
|
||||
tinycss2==1.4.0
|
||||
urllib3==2.3.0
|
||||
watchdog==6.0.0
|
||||
webencodings==0.5.1
|
||||
|
||||
74
src/data_format/_pl/v1_12_0/blob_impl.cpp
Normal file
74
src/data_format/_pl/v1_12_0/blob_impl.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
#include "blob_impl.h"
|
||||
#include "entry_impl.h"
|
||||
|
||||
#define XXH_INLINE_ALL
|
||||
#include "xxhash.h"
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr uint64_t hash_qseed(uint64_t stored_seed) {
|
||||
constexpr auto v1 = 0x7ED55D16u;
|
||||
constexpr auto v2 = 0xC761C23Cu;
|
||||
constexpr auto v3 = 0x165667B1u;
|
||||
constexpr auto v4 = 0x160733E3u;
|
||||
constexpr auto v5 = 0x028FB93Bu;
|
||||
constexpr auto v6 = 0xB55A4F09uLL;
|
||||
|
||||
constexpr auto al = [](uint32_t a) {
|
||||
auto c1 = (0x1000 + 1) * a + v1;
|
||||
auto d1 = (0x20 + 1) * (c1 ^ (c1 >> 19) ^ v2);
|
||||
auto e1 = ((d1 + v3) << 9) ^ (d1 - v4);
|
||||
return e1 + 8 * e1 - v5;
|
||||
};
|
||||
|
||||
auto a1 = al(stored_seed >> 32);
|
||||
auto a2 = al(stored_seed);
|
||||
|
||||
auto b1 = v6 | 0xFFFFFFFF00000000uLL;
|
||||
|
||||
auto c1 = ((a1 & 0xFFFF0000) ^ ((a1 ^ b1) << 16)) << 16;
|
||||
auto c2 = a2 ^ ((a2 ^ v6 << 16) >> 16);
|
||||
|
||||
return c1 | c2;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace di::data_format::_pl::v1_12_0 {
|
||||
|
||||
void MagicBlobImpl::read(const fs::path& path) {
|
||||
StreamedIO::read(path);
|
||||
|
||||
m_stored_seed = eat<uint64_t>();
|
||||
m_query_seed = hash_qseed(m_stored_seed);
|
||||
|
||||
rva_t n_rva{};
|
||||
|
||||
while (next() != EOF) {
|
||||
auto flags = eat_varint<uint64_t>();
|
||||
auto rva = eat_varint<rva_t>();
|
||||
auto hash = eat<hash_t>();
|
||||
|
||||
// What is stored in the original format is not the RVA itself, but the
|
||||
// difference with the previous entry (in MagicBlob, RVA is sorted from
|
||||
// small to large)
|
||||
// But here, we still store the "real" RVA.
|
||||
n_rva += rva;
|
||||
rva = n_rva;
|
||||
|
||||
m_entries.emplace(
|
||||
hash,
|
||||
std::make_shared<MagicEntryImpl>(hash, rva, flags)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
MagicBlob::shared_entry_t MagicBlobImpl::query(std::string_view symbol) const {
|
||||
auto query_hash = XXH64(symbol.data(), symbol.size(), m_query_seed);
|
||||
if (m_entries.contains(query_hash)) {
|
||||
return m_entries.at(query_hash);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace di::data_format::_pl::v1_12_0
|
||||
31
src/data_format/_pl/v1_12_0/blob_impl.h
Normal file
31
src/data_format/_pl/v1_12_0/blob_impl.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include "data_format/magic_blob.h"
|
||||
|
||||
namespace di::data_format::_pl::v1_12_0 {
|
||||
|
||||
class MagicBlobImpl : public MagicBlob {
|
||||
public:
|
||||
using for_each_callback_t =
|
||||
std::function<void(hash_t, shared_entry_t const&)>;
|
||||
|
||||
void read(const fs::path& path) override;
|
||||
|
||||
shared_entry_t query(std::string_view symbol) const override;
|
||||
|
||||
void for_each(const for_each_callback_t& callback) const override {
|
||||
for (const auto& [hash, entry] : m_entries) callback(hash, entry);
|
||||
}
|
||||
|
||||
size_t count() const override { return m_entries.size(); }
|
||||
|
||||
private:
|
||||
std::unordered_map<hash_t, shared_entry_t> m_entries;
|
||||
|
||||
// MagicBlob uses a custom algorithm to transform the stored seed. When
|
||||
// querying, you should use m_query_seed.
|
||||
uint64_t m_stored_seed{};
|
||||
uint64_t m_query_seed{};
|
||||
};
|
||||
|
||||
} // namespace di::data_format::_pl::v1_12_0
|
||||
16
src/data_format/_pl/v1_12_0/entry_impl.cpp
Normal file
16
src/data_format/_pl/v1_12_0/entry_impl.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#include "entry_impl.h"
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
namespace di::data_format::_pl::v1_12_0 {
|
||||
|
||||
void MagicEntryImpl::to_json(nlohmann::json& json) const {
|
||||
MagicEntry::to_json(json);
|
||||
|
||||
json["is_function"] = is_function();
|
||||
json["_unk2"] = _unk2();
|
||||
json["is_verbose"] = is_verbose();
|
||||
json["_unk4"] = _unk4();
|
||||
}
|
||||
|
||||
} // namespace di::data_format::_pl::v1_12_0
|
||||
29
src/data_format/_pl/v1_12_0/entry_impl.h
Normal file
29
src/data_format/_pl/v1_12_0/entry_impl.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "data_format/type/magic_entry.h"
|
||||
|
||||
#include <nlohmann/json_fwd.hpp>
|
||||
|
||||
namespace di::data_format::_pl::v1_12_0 {
|
||||
|
||||
struct MagicEntryImpl : public MagicEntry {
|
||||
using flags_t = std::bitset<64>;
|
||||
|
||||
flags_t flags;
|
||||
|
||||
MagicEntryImpl(hash_t hash, rva_t rva, flags_t flags)
|
||||
: MagicEntry(hash, rva),
|
||||
flags(flags) {}
|
||||
|
||||
void to_json(nlohmann::json& json) const override;
|
||||
|
||||
constexpr bool is_function() const { return flags[0]; }
|
||||
constexpr bool _unk2() const { return flags[1]; }
|
||||
constexpr bool is_verbose() const { return flags[2]; }
|
||||
constexpr bool _unk4() const { return flags[3]; }
|
||||
};
|
||||
|
||||
// TODO
|
||||
// void from_json(const nlohmann::json& json, MagicEntry& entry);
|
||||
|
||||
} // namespace di::data_format::_pl::v1_12_0
|
||||
@@ -14,7 +14,7 @@ public:
|
||||
|
||||
void record(const std::string& symbol, rva_t rva, bool is_function);
|
||||
|
||||
constexpr void for_each(const for_each_callback_t& callback) const {
|
||||
DI_CONSTEXPR void for_each(const for_each_callback_t& callback) const {
|
||||
for (const auto& entity : m_entities) callback(entity);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,65 +1,13 @@
|
||||
#include "magic_blob.h"
|
||||
#include "data_format/magic_blob.h"
|
||||
|
||||
#define XXH_INLINE_ALL
|
||||
#include "xxhash.h"
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr uint64_t 立即抽卡(uint64_t 几连抽) {
|
||||
constexpr auto 神里绫华 = 0x7ED55D16u;
|
||||
constexpr auto 雷电将军 = 0xC761C23Cu;
|
||||
constexpr auto 八重神子 = 0x165667B1u;
|
||||
constexpr auto 荒泷一斗 = 0x160733E3u;
|
||||
constexpr auto 克洛琳德 = 0x028FB93Bu;
|
||||
constexpr auto 艾尔海森 = 0xB55A4F09uLL;
|
||||
|
||||
constexpr auto 静水流涌之辉 = [](uint32_t 优菈) {
|
||||
auto 可莉 = (0x1000 + 1) * 优菈 + 神里绫华;
|
||||
auto 托马 = (0x20 + 1) * (可莉 ^ (可莉 >> 19) ^ 雷电将军);
|
||||
auto 宵宫 = ((托马 + 八重神子) << 9) ^ (托马 - 荒泷一斗);
|
||||
return 宵宫 + 8 * 宵宫 - 克洛琳德;
|
||||
};
|
||||
|
||||
auto 甘雨 = 静水流涌之辉(几连抽 >> 32);
|
||||
auto 纳西妲 = 静水流涌之辉(几连抽);
|
||||
|
||||
auto 心海 = 艾尔海森 | 0xFFFFFFFF00000000uLL;
|
||||
|
||||
auto 原神 = ((甘雨 & 0xFFFF0000) ^ ((甘雨 ^ 心海) << 16)) << 16;
|
||||
auto 原魔 = 纳西妲 ^ ((纳西妲 ^ 艾尔海森 << 16) >> 16);
|
||||
|
||||
return 原神 | 原魔;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
#include "data_format/_pl/v1_12_0/blob_impl.h"
|
||||
|
||||
namespace di::data_format {
|
||||
|
||||
void MagicBlob::read(const fs::path& path) {
|
||||
StreamedIO::read(path);
|
||||
|
||||
m_stored_seed = eat<uint64_t>();
|
||||
m_query_seed = 立即抽卡(m_stored_seed);
|
||||
|
||||
rva_t n_rva{};
|
||||
|
||||
while (next() != EOF) {
|
||||
auto flags = eat_varint<uint64_t>();
|
||||
auto rva = eat_varint<rva_t>();
|
||||
auto hash = eat<hash_t>();
|
||||
|
||||
// see comments in magic_entry.h
|
||||
n_rva += rva;
|
||||
rva = n_rva;
|
||||
|
||||
m_entries.emplace(hash, std::make_unique<MagicEntry>(flags, rva));
|
||||
}
|
||||
}
|
||||
|
||||
MagicEntry const* MagicBlob::query(std::string_view symbol) const {
|
||||
auto query_hash = XXH64(symbol.data(), symbol.size(), m_query_seed);
|
||||
if (m_entries.contains(query_hash)) {
|
||||
return m_entries.at(query_hash).get();
|
||||
MagicBlob::blob_t MagicBlob::create(FormatVersion version) {
|
||||
switch (version) {
|
||||
case V1_12_0:
|
||||
return std::make_unique<_pl::v1_12_0::MagicBlobImpl>();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -7,25 +7,29 @@ namespace di::data_format {
|
||||
|
||||
class MagicBlob : public io::StreamedIO {
|
||||
public:
|
||||
using for_each_callback_t = std::function<void(hash_t, MagicEntry const&)>;
|
||||
enum FormatVersion {
|
||||
V1_12_0,
|
||||
};
|
||||
|
||||
void read(const fs::path& path) override;
|
||||
using blob_t = std::unique_ptr<MagicBlob>;
|
||||
using entry_t = std::unique_ptr<MagicEntry>;
|
||||
|
||||
void for_each(const for_each_callback_t& callback) const {
|
||||
for (const auto& [hash, entry] : m_entries) callback(hash, *entry);
|
||||
}
|
||||
using shared_blob_t = std::shared_ptr<const MagicBlob>;
|
||||
using shared_entry_t = std::shared_ptr<const MagicEntry>;
|
||||
|
||||
constexpr size_t count() const { return m_entries.size(); }
|
||||
using for_each_callback_t =
|
||||
std::function<void(hash_t, shared_entry_t const&)>;
|
||||
|
||||
MagicEntry const* query(std::string_view symbol) const;
|
||||
virtual void read(const fs::path& path) = 0;
|
||||
|
||||
private:
|
||||
std::unordered_map<hash_t, std::unique_ptr<MagicEntry>> m_entries;
|
||||
virtual shared_entry_t query(std::string_view symbol) const = 0;
|
||||
virtual void for_each(const for_each_callback_t& callback) const = 0;
|
||||
virtual size_t count() const = 0;
|
||||
|
||||
// MagicBlob uses a custom algorithm to transform the stored seed. When
|
||||
// querying, you should use m_query_seed.
|
||||
uint64_t m_stored_seed{};
|
||||
uint64_t m_query_seed{};
|
||||
static blob_t create(FormatVersion version);
|
||||
|
||||
protected:
|
||||
MagicBlob() = default;
|
||||
};
|
||||
|
||||
} // namespace di::data_format
|
||||
} // namespace di::data_format
|
||||
@@ -4,12 +4,9 @@
|
||||
|
||||
namespace di {
|
||||
|
||||
void to_json(nlohmann::json& json, const MagicEntry& entry) {
|
||||
json["rva"] = entry.rva;
|
||||
json["is_function"] = entry.is_function();
|
||||
json["_unk2"] = entry._unk2();
|
||||
json["is_verbose"] = entry.is_verbose();
|
||||
json["_unk4"] = entry._unk4();
|
||||
void MagicEntry::to_json(nlohmann::json& json) const {
|
||||
json["hash"] = hash;
|
||||
json["rva"] = rva;
|
||||
}
|
||||
|
||||
} // namespace di
|
||||
@@ -5,24 +5,12 @@
|
||||
namespace di {
|
||||
|
||||
struct MagicEntry {
|
||||
std::bitset<64> flags;
|
||||
// What is stored in the original format is not the RVA itself, but the
|
||||
// difference with the previous entry (in MagicBlob, RVA is sorted from
|
||||
// small to large)
|
||||
// But here, we still store the "real" RVA.
|
||||
rva_t rva;
|
||||
// Do not put the original hash in the entry yet.
|
||||
// hash_t hash;
|
||||
hash_t hash; // key
|
||||
rva_t rva; // value
|
||||
|
||||
constexpr bool is_function() const { return flags[0]; }
|
||||
constexpr bool _unk2() const { return flags[1]; }
|
||||
constexpr bool is_verbose() const { return flags[2]; }
|
||||
constexpr bool _unk4() const { return flags[3]; }
|
||||
MagicEntry(hash_t hash, rva_t rva) : hash(hash), rva(rva) {}
|
||||
|
||||
virtual void to_json(nlohmann::json& json) const;
|
||||
};
|
||||
|
||||
void to_json(nlohmann::json& json, const MagicEntry& entry);
|
||||
|
||||
// TODO
|
||||
// void from_json(const nlohmann::json& json, MagicEntry& entry);
|
||||
|
||||
} // namespace di
|
||||
|
||||
@@ -5,6 +5,12 @@
|
||||
namespace di {
|
||||
|
||||
struct TypedSymbol {
|
||||
#if __cpp_aggregate_paren_init < 201902L
|
||||
TypedSymbol(std::string_view name, DeclType type)
|
||||
: m_name(name),
|
||||
m_type(type) {}
|
||||
#endif
|
||||
|
||||
std::string m_name;
|
||||
DeclType m_type;
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ public:
|
||||
|
||||
constexpr size_t count() const { return m_data.size(); }
|
||||
|
||||
constexpr void for_each(const for_each_callback_t& callback) const {
|
||||
DI_CONSTEXPR void for_each(const for_each_callback_t& callback) const {
|
||||
for (const auto& entity : m_data) callback(entity);
|
||||
}
|
||||
|
||||
|
||||
12
src/nonstd.h
12
src/nonstd.h
@@ -13,6 +13,18 @@ constexpr auto underlying_value(T v) {
|
||||
return static_cast<std::underlying_type_t<decltype(v)>>(v);
|
||||
}
|
||||
|
||||
#if __cpp_constexpr >= 202211L // complete c++23 constexpr
|
||||
#define DI_CONSTEXPR constexpr
|
||||
#else
|
||||
#define DI_CONSTEXPR inline
|
||||
#endif
|
||||
|
||||
// a clang bug
|
||||
#if __clang_major__ < 19
|
||||
#undef DI_CONSTEXPR
|
||||
#define DI_CONSTEXPR inline
|
||||
#endif
|
||||
|
||||
// From:
|
||||
// https://stackoverflow.com/questions/7110301/generic-hash-for-tuples-in-unordered-map-unordered-set
|
||||
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
#include "data_format/raw_text.h"
|
||||
#include "data_format/typed_symbol_list.h"
|
||||
|
||||
#include <argparse/argparse.hpp>
|
||||
|
||||
#if DI_USE_NATIVE_SYMBOL_RESOLVER
|
||||
#include <pl/SymbolProvider.h>
|
||||
#else
|
||||
#include "data_format/magic_blob.h"
|
||||
#endif
|
||||
|
||||
#include <argparse/argparse.hpp>
|
||||
#include <magic_enum.hpp>
|
||||
|
||||
using namespace di;
|
||||
using namespace di::data_format;
|
||||
|
||||
@@ -20,6 +21,7 @@ using namespace di::data_format;
|
||||
std::vector<std::string> m_input_paths;
|
||||
std::string m_output_path;
|
||||
std::string m_magic_blob_path;
|
||||
std::string m_format_version;
|
||||
|
||||
std::optional<std::string> m_output_failed_path;
|
||||
} args;
|
||||
@@ -36,6 +38,15 @@ using namespace di::data_format;
|
||||
.help("Path to magic blob (for builtin-symbol-resolver only).")
|
||||
.default_value("bedrock_runtime_data")
|
||||
.store_into(args.m_magic_blob_path);
|
||||
|
||||
std::apply([&](auto&&... xs) {
|
||||
program.add_argument("--preloader-version")
|
||||
.help("Choose a compatible PreLoader version. (for builtin-symbol-resolver only).")
|
||||
.choices(xs...)
|
||||
.store_into(args.m_format_version)
|
||||
.required();
|
||||
}, magic_enum::enum_names<MagicBlob::FormatVersion>());
|
||||
|
||||
|
||||
program.add_argument("--output", "-o")
|
||||
.help("Path to output.")
|
||||
@@ -75,26 +86,43 @@ int main(int argc, char* argv[]) try {
|
||||
);
|
||||
|
||||
#if !DI_USE_NATIVE_SYMBOL_RESOLVER
|
||||
MagicBlob magic_blob;
|
||||
magic_blob.read(args.m_magic_blob_path);
|
||||
auto format_version =
|
||||
magic_enum::enum_cast<MagicBlob::FormatVersion>(args.m_format_version);
|
||||
assert(format_version.has_value());
|
||||
|
||||
std::println("{} entries loaded from magicblob.", magic_blob.count());
|
||||
auto magic_blob = MagicBlob::create(*format_version);
|
||||
if (!magic_blob) {
|
||||
std::println(
|
||||
"Format version: {} is not yet implemented.",
|
||||
args.m_format_version
|
||||
);
|
||||
}
|
||||
|
||||
magic_blob->read(args.m_magic_blob_path);
|
||||
|
||||
std::println("{} entries loaded from magicblob.", magic_blob->count());
|
||||
#endif
|
||||
|
||||
symlist.for_each([&](const TypedSymbol& symbol) {
|
||||
auto& sym = symbol.m_name;
|
||||
rva_t rva{};
|
||||
#if DI_USE_NATIVE_SYMBOL_RESOLVER
|
||||
auto address = pl::symbol_provider::pl_resolve_symbol_silent_n(
|
||||
sym.c_str(),
|
||||
sym.size()
|
||||
);
|
||||
// FIXME: broken because IMAGE_BASE is not handled.
|
||||
rva = static_cast<rva_t>(reinterpret_cast<uintptr_t>(
|
||||
pl::symbol_provider::pl_resolve_symbol_silent_n(
|
||||
sym.c_str(),
|
||||
sym.size()
|
||||
)
|
||||
));
|
||||
// TODO: imagebase...
|
||||
#else
|
||||
auto entry = magic_blob.query(sym);
|
||||
if (auto entry = magic_blob->query(sym)) {
|
||||
rva = entry->rva;
|
||||
}
|
||||
#endif
|
||||
if (entry) {
|
||||
if (rva) {
|
||||
bound_symbol_list
|
||||
.record(symbol.m_name, entry->rva, symbol.m_type.is_function());
|
||||
.record(symbol.m_name, rva, symbol.m_type.is_function());
|
||||
} else {
|
||||
failed_list.record(symbol.m_name);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "data_format/magic_blob.h"
|
||||
|
||||
#include <argparse/argparse.hpp>
|
||||
#include <magic_enum.hpp>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using namespace di;
|
||||
@@ -13,6 +14,8 @@ auto load_args(int argc, char* argv[]) {
|
||||
struct {
|
||||
std::string m_magic_blob_path;
|
||||
fs::path m_output_path;
|
||||
|
||||
std::string m_format_version;
|
||||
} args;
|
||||
|
||||
// clang-format off
|
||||
@@ -26,6 +29,14 @@ auto load_args(int argc, char* argv[]) {
|
||||
.help("Path to output symlist.")
|
||||
.required();
|
||||
|
||||
std::apply([&](auto&&... xs) {
|
||||
program.add_argument("--preloader-version")
|
||||
.help("Choose a compatible PreLoader version. (for builtin-symbol-resolver only).")
|
||||
.choices(xs...)
|
||||
.store_into(args.m_format_version)
|
||||
.required();
|
||||
}, magic_enum::enum_names<MagicBlob::FormatVersion>());
|
||||
|
||||
// clang-format on
|
||||
|
||||
program.parse_args(argc, argv);
|
||||
@@ -39,12 +50,23 @@ int main(int argc, char* argv[]) try {
|
||||
|
||||
auto args = load_args(argc, argv);
|
||||
|
||||
MagicBlob blob;
|
||||
blob.read(args.m_magic_blob_path);
|
||||
auto format_version =
|
||||
magic_enum::enum_cast<MagicBlob::FormatVersion>(args.m_format_version);
|
||||
assert(format_version.has_value());
|
||||
|
||||
auto magic_blob = MagicBlob::create(*format_version);
|
||||
if (!magic_blob) {
|
||||
std::println(
|
||||
"Format version: {} is not yet implemented.",
|
||||
args.m_format_version
|
||||
);
|
||||
}
|
||||
|
||||
magic_blob->read(args.m_magic_blob_path);
|
||||
|
||||
nlohmann::json data;
|
||||
blob.for_each([&data](hash_t hash, const MagicEntry& entry) {
|
||||
data[std::format("{:#x}", hash)] = entry;
|
||||
magic_blob->for_each([&data](hash_t hash, MagicBlob::shared_entry_t entry) {
|
||||
entry->to_json(data.emplace_back());
|
||||
});
|
||||
|
||||
std::ofstream ofs(args.m_output_path);
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include <argparse/argparse.hpp>
|
||||
|
||||
#include <llvm/DebugInfo/CodeView/SymbolRecord.h>
|
||||
|
||||
#include "data_format/typed_symbol_list.h"
|
||||
#include "object_file/pdb.h"
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ public:
|
||||
constexpr std::string category() const { return "exception.llvm"; }
|
||||
};
|
||||
|
||||
constexpr void check_llvm_result(Error err, std::string_view msg = "") {
|
||||
DI_CONSTEXPR void check_llvm_result(Error err, std::string_view msg = "") {
|
||||
if (err) {
|
||||
std::string err_detail;
|
||||
raw_string_ostream os(err_detail);
|
||||
@@ -30,7 +30,7 @@ constexpr void check_llvm_result(Error err, std::string_view msg = "") {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr T
|
||||
DI_CONSTEXPR T
|
||||
check_llvm_result(Expected<T> val_or_err, std::string_view msg = "") {
|
||||
if (val_or_err) return std::move(*val_or_err);
|
||||
else {
|
||||
@@ -43,7 +43,7 @@ check_llvm_result(Expected<T> val_or_err, std::string_view msg = "") {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr T&
|
||||
DI_CONSTEXPR T&
|
||||
check_llvm_result(Expected<T&> val_or_err, std::string_view msg = "") {
|
||||
if (val_or_err) return *val_or_err;
|
||||
else {
|
||||
|
||||
107
xmake.lua
107
xmake.lua
@@ -1,11 +1,17 @@
|
||||
add_rules('mode.debug', 'mode.release')
|
||||
|
||||
add_requires('argparse 3.1')
|
||||
add_requires('nlohmann_json 3.11.3')
|
||||
add_requires('argparse 3.2')
|
||||
add_requires('nlohmann_json 3.12.0')
|
||||
add_requires('xxhash 0.8.3')
|
||||
add_requires('boost 1.87.0')
|
||||
|
||||
add_requires('llvm')
|
||||
add_requires('libllvm 19.1.7')
|
||||
add_requires('magic_enum 0.9.7')
|
||||
add_requires('boost 1.88.0', {
|
||||
system = false,
|
||||
configs = {
|
||||
filesystem = false,
|
||||
stacktrace = true
|
||||
}
|
||||
})
|
||||
|
||||
--- options
|
||||
|
||||
@@ -24,36 +30,17 @@ option('symbol-resolver')
|
||||
option_end()
|
||||
|
||||
if is_config('symbol-resolver', 'native') then
|
||||
add_repositories('liteldev-repo https://github.com/LiteLDev/xmake-repo.git')
|
||||
add_requires('preloader 1.12.0')
|
||||
add_repositories("liteldev-free-repo https://github.com/liteldev-free/xmake-repo.git")
|
||||
add_requires('preloader 1.13.0')
|
||||
end
|
||||
|
||||
--- global settings
|
||||
|
||||
set_policy("build.optimization.lto", true)
|
||||
|
||||
set_languages('c23', 'c++23')
|
||||
set_warnings('all')
|
||||
|
||||
add_includedirs('src')
|
||||
|
||||
-- now use boost::stacktrace, due to MacOSX (libc++) compatibility issues.
|
||||
-- ~~workaround to fix std::stacktrace link problem~~
|
||||
--
|
||||
-- for gcc == 14
|
||||
-- see https://gcc.gnu.org/onlinedocs/gcc-14.2.0/libstdc++/manual/manual/using.html
|
||||
-- for gcc == 13
|
||||
-- see https://gcc.gnu.org/onlinedocs/gcc-13.2.0/libstdc++/manual/manual/using.html
|
||||
-- if is_plat('linux') then
|
||||
-- add_links('stdc++exp')
|
||||
-- end
|
||||
|
||||
if is_mode('debug') then
|
||||
add_defines('DI_DEBUG')
|
||||
|
||||
-- to fix llvm link problem
|
||||
-- see https://stackoverflow.com/questions/53805007/compilation-failing-on-enableabibreakingchecks
|
||||
add_defines('LLVM_DISABLE_ABI_BREAKING_CHECKS_ENFORCING=1')
|
||||
end
|
||||
|
||||
--- targets
|
||||
@@ -67,28 +54,53 @@ target('libdi')
|
||||
set_basename('di')
|
||||
|
||||
if is_plat('linux') then
|
||||
add_ldflags('$(shell llvm-config --libs)') -- xrepo llvm bug?
|
||||
end
|
||||
if is_plat('linux') or is_plat('macosx') then
|
||||
add_defines('BOOST_STACKTRACE_USE_ADDR2LINE=1')
|
||||
add_cxflags('-fPIC')
|
||||
end
|
||||
|
||||
add_packages('xxhash')
|
||||
add_packages(
|
||||
'xxhash',
|
||||
'nlohmann_json',
|
||||
'libllvm',
|
||||
'boost',
|
||||
'llvm'
|
||||
'nlohmann_json',
|
||||
{public = true}
|
||||
)
|
||||
|
||||
add_includedirs('src', {public = true})
|
||||
|
||||
-- now use boost::stacktrace, due to MacOSX (libc++) compatibility issues.
|
||||
-- ~~workaround to fix std::stacktrace link problem~~
|
||||
--
|
||||
-- for gcc == 14
|
||||
-- see https://gcc.gnu.org/onlinedocs/gcc-14.2.0/libstdc++/manual/manual/using.html
|
||||
-- for gcc == 13
|
||||
-- see https://gcc.gnu.org/onlinedocs/gcc-13.2.0/libstdc++/manual/manual/using.html
|
||||
-- if is_plat('linux') then
|
||||
-- add_links('stdc++exp')
|
||||
-- end
|
||||
|
||||
if is_plat('linux') or is_plat('macosx') then
|
||||
add_defines('BOOST_STACKTRACE_USE_ADDR2LINE=1', {public = true})
|
||||
end
|
||||
|
||||
-- workaround to fix boost problem
|
||||
-- see https://github.com/boostorg/stacktrace/issues/88
|
||||
if is_plat('macosx') then
|
||||
add_defines('_GNU_SOURCE', {public = true})
|
||||
end
|
||||
|
||||
-- to fix llvm link problem
|
||||
-- see https://stackoverflow.com/questions/53805007/compilation-failing-on-enableabibreakingchecks
|
||||
add_defines('LLVM_DISABLE_ABI_BREAKING_CHECKS_ENFORCING=1', {public = true})
|
||||
|
||||
target('askrva')
|
||||
set_kind('binary')
|
||||
add_deps('libdi')
|
||||
add_files('src/tools/askrva/**.cpp')
|
||||
set_pcxxheader('src/pch.h')
|
||||
|
||||
add_deps('libdi')
|
||||
add_packages(
|
||||
'argparse',
|
||||
'nlohmann_json'
|
||||
'magic_enum'
|
||||
)
|
||||
|
||||
if is_config('symbol-resolver', 'native') then
|
||||
@@ -98,43 +110,34 @@ target('askrva')
|
||||
|
||||
target('blob-extractor')
|
||||
set_kind('binary')
|
||||
add_deps('libdi')
|
||||
add_files('src/tools/blob-extractor/**.cpp')
|
||||
set_pcxxheader('src/pch.h')
|
||||
|
||||
add_deps('libdi')
|
||||
add_packages(
|
||||
'argparse',
|
||||
'nlohmann_json',
|
||||
'argparse'
|
||||
'magic_enum'
|
||||
)
|
||||
|
||||
target('dumpsym')
|
||||
set_kind('shared')
|
||||
add_deps('libdi')
|
||||
add_files('src/tools/dumpsym/**.cpp')
|
||||
set_pcxxheader('src/pch.h')
|
||||
|
||||
add_packages(
|
||||
'llvm'
|
||||
)
|
||||
add_deps('libdi')
|
||||
|
||||
target('extractsym')
|
||||
set_kind('binary')
|
||||
add_deps('libdi')
|
||||
add_files('src/tools/extractsym/**.cpp')
|
||||
set_pcxxheader('src/pch.h')
|
||||
|
||||
add_packages(
|
||||
'nlohmann_json',
|
||||
'argparse'
|
||||
)
|
||||
add_deps('libdi')
|
||||
add_packages('argparse')
|
||||
|
||||
target('makepdb')
|
||||
set_kind('binary')
|
||||
add_deps('libdi')
|
||||
add_files('src/tools/makepdb/**.cpp')
|
||||
set_pcxxheader('src/pch.h')
|
||||
|
||||
add_packages(
|
||||
'nlohmann_json',
|
||||
'argparse'
|
||||
)
|
||||
add_deps('libdi')
|
||||
add_packages('argparse')
|
||||
|
||||
Reference in New Issue
Block a user