Added patchcompile module handling
This commit is contained in:
parent
447431ae45
commit
30be283e15
@ -48,12 +48,15 @@ static bool global_target_cmp(const TARGET& a, const TARGET& b) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::size_t accumulate_global_target(TARGET&& target) {
|
static std::size_t accumulate_global_target(TARGET&& target, bool& was_new) {
|
||||||
|
was_new = false;
|
||||||
for (const auto& [guid, gtarget] : targets) {
|
for (const auto& [guid, gtarget] : targets) {
|
||||||
if (global_target_cmp(gtarget, target))
|
if (global_target_cmp(gtarget, target))
|
||||||
return guid;
|
return guid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
was_new = true;
|
||||||
|
|
||||||
std::size_t guid = next_global_target_uid++;
|
std::size_t guid = next_global_target_uid++;
|
||||||
targets.emplace(guid, std::move(target));
|
targets.emplace(guid, std::move(target));
|
||||||
return guid;
|
return guid;
|
||||||
@ -75,7 +78,7 @@ dpin <symbol> <offset> <level> <target uid>
|
|||||||
dpin <symbol> <offset> <level> <target uid>
|
dpin <symbol> <offset> <level> <target uid>
|
||||||
...
|
...
|
||||||
*/
|
*/
|
||||||
static bool accumulate_file(const fs::path& path) {
|
static bool accumulate_file(const fs::path& path, bool no_new_targets) {
|
||||||
std::ifstream infile(path);
|
std::ifstream infile(path);
|
||||||
if (!infile)
|
if (!infile)
|
||||||
return false;
|
return false;
|
||||||
@ -169,7 +172,14 @@ static bool accumulate_file(const fs::path& path) {
|
|||||||
fit++;
|
fit++;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t global_target_uid = accumulate_global_target(std::move(target));
|
bool was_new = false;
|
||||||
|
std::size_t global_target_uid = accumulate_global_target(std::move(target), was_new);
|
||||||
|
|
||||||
|
if (no_new_targets && was_new) {
|
||||||
|
std::cerr << "Encountered new target but --no-new-targets is set!" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
cu.local_targets.emplace(local_uid, global_target_uid);
|
cu.local_targets.emplace(local_uid, global_target_uid);
|
||||||
continue;
|
continue;
|
||||||
} else if (type == "ipin") {
|
} else if (type == "ipin") {
|
||||||
@ -223,7 +233,7 @@ static bool accumulate_file(const fs::path& path) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool accumulate(const std::vector<std::string>& spslr_files) {
|
bool accumulate(const std::vector<std::string>& spslr_files, bool no_new_targets) {
|
||||||
for (const std::string& spslr_file : spslr_files) {
|
for (const std::string& spslr_file : spslr_files) {
|
||||||
fs::path p { spslr_file };
|
fs::path p { spslr_file };
|
||||||
|
|
||||||
@ -237,7 +247,7 @@ bool accumulate(const std::vector<std::string>& spslr_files) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!accumulate_file(p)) {
|
if (!accumulate_file(p, no_new_targets)) {
|
||||||
std::cerr << "Failed to parse metadata file " << p << "!" << std::endl;
|
std::cerr << "Failed to parse metadata file " << p << "!" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -245,3 +255,116 @@ bool accumulate(const std::vector<std::string>& spslr_files) {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool dump_target_map(const std::string& path) {
|
||||||
|
std::filesystem::path p{path};
|
||||||
|
if (p.has_parent_path()) {
|
||||||
|
std::error_code ec;
|
||||||
|
std::filesystem::create_directories(p.parent_path(), ec);
|
||||||
|
if (ec) {
|
||||||
|
std::cerr << "Failed to create target-map directory: " << ec.message() << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ofstream out(p);
|
||||||
|
if (!out)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
out << "SPSLR_TARGETS 1\n";
|
||||||
|
|
||||||
|
for (const auto& [uid, t] : targets) {
|
||||||
|
out << "target " << t.name << " " << uid << " " << t.size << " " << t.fields.size() << "\n";
|
||||||
|
|
||||||
|
for (const auto& [off, f] : t.fields) {
|
||||||
|
(void)off;
|
||||||
|
out << "f " << f.offset << " " << f.size << " " << f.alignment << " " << f.flags << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return !!out;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool load_target_map(const std::string& path) {
|
||||||
|
std::ifstream in(path);
|
||||||
|
if (!in)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::string magic;
|
||||||
|
std::size_t version = 0;
|
||||||
|
if (!(in >> magic >> version) || magic != "SPSLR_TARGETS" || version != 1) {
|
||||||
|
std::cerr << "Invalid target map header\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
std::getline(in, line); // consume rest of header line
|
||||||
|
|
||||||
|
std::size_t max_uid = 0;
|
||||||
|
bool have_any = false;
|
||||||
|
|
||||||
|
while (std::getline(in, line)) {
|
||||||
|
if (line.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::istringstream iss(line);
|
||||||
|
std::string tag;
|
||||||
|
iss >> tag;
|
||||||
|
|
||||||
|
if (tag != "target") {
|
||||||
|
std::cerr << "Expected target entry in target map\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
TARGET t{};
|
||||||
|
std::size_t uid = 0;
|
||||||
|
std::size_t field_count = 0;
|
||||||
|
|
||||||
|
if (!(iss >> t.name >> uid >> t.size >> field_count)) {
|
||||||
|
std::cerr << "Malformed target entry in target map\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < field_count; ++i) {
|
||||||
|
std::string fline;
|
||||||
|
if (!std::getline(in, fline)) {
|
||||||
|
std::cerr << "Missing field entry in target map\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::istringstream fiss(fline);
|
||||||
|
std::string ftag;
|
||||||
|
FIELD f{};
|
||||||
|
|
||||||
|
if (!(fiss >> ftag) || ftag != "f" || !(fiss >> f.offset >> f.size >> f.alignment >> f.flags)) {
|
||||||
|
std::cerr << "Malformed field entry in target map\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
f.idx = i;
|
||||||
|
if (t.fields.contains(f.offset)) {
|
||||||
|
std::cerr << "Duplicate field offset in target map\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
t.fields.emplace(f.offset, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targets.contains(uid)) {
|
||||||
|
std::cerr << "Duplicate target uid in target map\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
targets.emplace(uid, std::move(t));
|
||||||
|
|
||||||
|
if (!have_any || uid > max_uid) {
|
||||||
|
max_uid = uid;
|
||||||
|
have_any = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (have_any)
|
||||||
|
next_global_target_uid = (max_uid + 1);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -49,4 +49,6 @@ struct CU {
|
|||||||
extern std::unordered_map<std::size_t, TARGET> targets;
|
extern std::unordered_map<std::size_t, TARGET> targets;
|
||||||
extern std::unordered_map<std::string, CU> units;
|
extern std::unordered_map<std::string, CU> units;
|
||||||
|
|
||||||
bool accumulate(const std::vector<std::string>& spslr_files);
|
bool accumulate(const std::vector<std::string>& spslr_files, bool no_new_targets);
|
||||||
|
bool dump_target_map(const std::string& path);
|
||||||
|
bool load_target_map(const std::string& path);
|
||||||
|
|||||||
@ -101,6 +101,13 @@ static bool emit_header(std::ostream& out) {
|
|||||||
return !!out;
|
return !!out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool emit_module_header(std::ostream& out) {
|
||||||
|
// Shared objects with read-only relocations cause warnings
|
||||||
|
out << ".section .data.rel.ro.spslr,\"aw\",@progbits\n";
|
||||||
|
out << ".balign 8\n";
|
||||||
|
return !!out;
|
||||||
|
}
|
||||||
|
|
||||||
static bool emit_u32_object(std::ostream& out, const char* name, uint32_t value) {
|
static bool emit_u32_object(std::ostream& out, const char* name, uint32_t value) {
|
||||||
out << ".globl " << name << "\n";
|
out << ".globl " << name << "\n";
|
||||||
out << ".type " << name << ", @object\n";
|
out << ".type " << name << ", @object\n";
|
||||||
@ -112,6 +119,9 @@ static bool emit_u32_object(std::ostream& out, const char* name, uint32_t value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool emit_targets(std::ostream& out, const std::vector<TARGET_REC>& targets) {
|
static bool emit_targets(std::ostream& out, const std::vector<TARGET_REC>& targets) {
|
||||||
|
if (!emit_u32_object(out, "spslr_target_cnt", static_cast<uint32_t>(targets.size())))
|
||||||
|
return false;
|
||||||
|
|
||||||
out << ".globl spslr_targets\n";
|
out << ".globl spslr_targets\n";
|
||||||
out << ".type spslr_targets, @object\n";
|
out << ".type spslr_targets, @object\n";
|
||||||
out << ".balign 4\n";
|
out << ".balign 4\n";
|
||||||
@ -128,6 +138,9 @@ static bool emit_targets(std::ostream& out, const std::vector<TARGET_REC>& targe
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool emit_target_fields(std::ostream& out, const std::vector<TARGET_FIELD_REC>& fields) {
|
static bool emit_target_fields(std::ostream& out, const std::vector<TARGET_FIELD_REC>& fields) {
|
||||||
|
if (!emit_u32_object(out, "spslr_target_field_cnt", static_cast<uint32_t>(fields.size())))
|
||||||
|
return false;
|
||||||
|
|
||||||
out << ".globl spslr_target_fields\n";
|
out << ".globl spslr_target_fields\n";
|
||||||
out << ".type spslr_target_fields, @object\n";
|
out << ".type spslr_target_fields, @object\n";
|
||||||
out << ".balign 4\n";
|
out << ".balign 4\n";
|
||||||
@ -145,6 +158,9 @@ static bool emit_target_fields(std::ostream& out, const std::vector<TARGET_FIELD
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool emit_ipins(std::ostream& out, const std::vector<IPIN_REC>& ipins) {
|
static bool emit_ipins(std::ostream& out, const std::vector<IPIN_REC>& ipins) {
|
||||||
|
if (!emit_u32_object(out, "spslr_ipin_cnt", static_cast<uint32_t>(ipins.size())))
|
||||||
|
return false;
|
||||||
|
|
||||||
out << ".globl spslr_ipins\n";
|
out << ".globl spslr_ipins\n";
|
||||||
out << ".type spslr_ipins, @object\n";
|
out << ".type spslr_ipins, @object\n";
|
||||||
out << ".balign 8\n";
|
out << ".balign 8\n";
|
||||||
@ -161,6 +177,9 @@ static bool emit_ipins(std::ostream& out, const std::vector<IPIN_REC>& ipins) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool emit_ipin_ops(std::ostream& out, const std::vector<IPIN_OP_REC>& ops) {
|
static bool emit_ipin_ops(std::ostream& out, const std::vector<IPIN_OP_REC>& ops) {
|
||||||
|
if (!emit_u32_object(out, "spslr_ipin_op_cnt", static_cast<uint32_t>(ops.size())))
|
||||||
|
return false;
|
||||||
|
|
||||||
out << ".globl spslr_ipin_ops\n";
|
out << ".globl spslr_ipin_ops\n";
|
||||||
out << ".type spslr_ipin_ops, @object\n";
|
out << ".type spslr_ipin_ops, @object\n";
|
||||||
out << ".balign 4\n";
|
out << ".balign 4\n";
|
||||||
@ -177,6 +196,9 @@ static bool emit_ipin_ops(std::ostream& out, const std::vector<IPIN_OP_REC>& ops
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool emit_dpins(std::ostream& out, const std::vector<DPIN_REC>& dpins) {
|
static bool emit_dpins(std::ostream& out, const std::vector<DPIN_REC>& dpins) {
|
||||||
|
if (!emit_u32_object(out, "spslr_dpin_cnt", static_cast<uint32_t>(dpins.size())))
|
||||||
|
return false;
|
||||||
|
|
||||||
out << ".globl spslr_dpins\n";
|
out << ".globl spslr_dpins\n";
|
||||||
out << ".type spslr_dpins, @object\n";
|
out << ".type spslr_dpins, @object\n";
|
||||||
out << ".balign 8\n";
|
out << ".balign 8\n";
|
||||||
@ -193,37 +215,45 @@ static bool emit_dpins(std::ostream& out, const std::vector<DPIN_REC>& dpins) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool emit_patcher_program_asm(std::ostream& out) {
|
bool emit_patcher_program_asm(std::ostream& out, bool is_module) {
|
||||||
if (!emit_header(out))
|
if (!is_module) {
|
||||||
return false;
|
if (!emit_header(out))
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (!emit_module_header(out))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Important: target UID == index in spslr_targets[] for the new interface.
|
// Important: target UID == index in spslr_targets[] for the new interface.
|
||||||
std::vector<TARGET_REC> target_recs(targets.size());
|
std::vector<TARGET_REC> target_recs(targets.size());
|
||||||
std::vector<TARGET_FIELD_REC> field_recs;
|
std::vector<TARGET_FIELD_REC> field_recs;
|
||||||
field_recs.reserve(64);
|
|
||||||
|
|
||||||
for (uint32_t uid = 0; uid < static_cast<uint32_t>(targets.size()); ++uid) {
|
if (!is_module) {
|
||||||
if (!targets.contains(uid))
|
field_recs.reserve(64);
|
||||||
return false;
|
|
||||||
|
|
||||||
const TARGET& target = targets.at(uid);
|
for (uint32_t uid = 0; uid < static_cast<uint32_t>(targets.size()); ++uid) {
|
||||||
|
if (!targets.contains(uid))
|
||||||
|
return false;
|
||||||
|
|
||||||
TARGET_REC trec{};
|
const TARGET& target = targets.at(uid);
|
||||||
trec.size = static_cast<uint32_t>(target.size);
|
|
||||||
trec.fieldoff = static_cast<uint32_t>(field_recs.size());
|
|
||||||
trec.fieldcnt = static_cast<uint32_t>(target.fields.size());
|
|
||||||
|
|
||||||
for (const auto& [off, field] : target.fields) {
|
TARGET_REC trec{};
|
||||||
(void)off;
|
trec.size = static_cast<uint32_t>(target.size);
|
||||||
field_recs.push_back(TARGET_FIELD_REC{
|
trec.fieldoff = static_cast<uint32_t>(field_recs.size());
|
||||||
.offset = static_cast<uint32_t>(field.offset),
|
trec.fieldcnt = static_cast<uint32_t>(target.fields.size());
|
||||||
.size = static_cast<uint32_t>(field.size),
|
|
||||||
.alignment = static_cast<uint32_t>(field.alignment),
|
for (const auto& [off, field] : target.fields) {
|
||||||
.flags = static_cast<uint32_t>(field.flags),
|
(void)off;
|
||||||
});
|
field_recs.push_back(TARGET_FIELD_REC{
|
||||||
|
.offset = static_cast<uint32_t>(field.offset),
|
||||||
|
.size = static_cast<uint32_t>(field.size),
|
||||||
|
.alignment = static_cast<uint32_t>(field.alignment),
|
||||||
|
.flags = static_cast<uint32_t>(field.flags),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
target_recs[uid] = trec;
|
||||||
}
|
}
|
||||||
|
|
||||||
target_recs[uid] = trec;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<IPIN_REC> ipin_recs;
|
std::vector<IPIN_REC> ipin_recs;
|
||||||
@ -289,28 +319,17 @@ bool emit_patcher_program_asm(std::ostream& out) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!emit_u32_object(out, "spslr_target_cnt", static_cast<uint32_t>(target_recs.size())))
|
if (!is_module) {
|
||||||
return false;
|
if (!emit_targets(out, target_recs))
|
||||||
if (!emit_targets(out, target_recs))
|
return false;
|
||||||
return false;
|
if (!emit_target_fields(out, field_recs))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!emit_u32_object(out, "spslr_target_field_cnt", static_cast<uint32_t>(field_recs.size())))
|
|
||||||
return false;
|
|
||||||
if (!emit_target_fields(out, field_recs))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!emit_u32_object(out, "spslr_ipin_cnt", static_cast<uint32_t>(ipin_recs.size())))
|
|
||||||
return false;
|
|
||||||
if (!emit_ipins(out, ipin_recs))
|
if (!emit_ipins(out, ipin_recs))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!emit_u32_object(out, "spslr_ipin_op_cnt", static_cast<uint32_t>(ipin_ops.size())))
|
|
||||||
return false;
|
|
||||||
if (!emit_ipin_ops(out, ipin_ops))
|
if (!emit_ipin_ops(out, ipin_ops))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!emit_u32_object(out, "spslr_dpin_cnt", static_cast<uint32_t>(dpin_recs.size())))
|
|
||||||
return false;
|
|
||||||
if (!emit_dpins(out, dpin_recs))
|
if (!emit_dpins(out, dpin_recs))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
bool emit_patcher_program_asm(std::ostream& out);
|
bool emit_patcher_program_asm(std::ostream& out, bool is_module);
|
||||||
|
|||||||
@ -14,58 +14,91 @@ Notes:
|
|||||||
Between CUs, types with the same name HAVE TO HAVE the same layout -> randomized together
|
Between CUs, types with the same name HAVE TO HAVE the same layout -> randomized together
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
struct OPTIONS {
|
||||||
|
std::string out_file;
|
||||||
|
std::string load_targets_file;
|
||||||
|
std::string dump_targets_file;
|
||||||
|
std::vector<std::string> spslr_files;
|
||||||
|
bool no_new_targets = false;
|
||||||
|
bool is_module = false;
|
||||||
|
};
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
static option long_options[] = {
|
static option long_options[] = {
|
||||||
{ "help", no_argument, 0, 0 },
|
{ "help", no_argument, 0, 0 },
|
||||||
{ "out", required_argument, 0, 0 },
|
{ "out", required_argument, 0, 0 },
|
||||||
|
{ "load-targets", required_argument, 0, 0 },
|
||||||
|
{ "dump-targets", required_argument, 0, 0 },
|
||||||
|
{ "no-new-targets", no_argument, 0, 0 },
|
||||||
|
{ "module", no_argument, 0, 0 },
|
||||||
{ 0, 0, 0, 0 }
|
{ 0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
OPTIONS opts{};
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
std::vector<std::string> spslr_files;
|
|
||||||
std::string out_file;
|
|
||||||
|
|
||||||
while ((c = getopt_long(argc, argv, "h:o:", long_options, &option_index)) == 0) {
|
while ((c = getopt_long(argc, argv, "h:o:", long_options, &option_index)) == 0) {
|
||||||
const option& opt = long_options[option_index];
|
const option& opt = long_options[option_index];
|
||||||
std::string optname { opt.name };
|
std::string optname { opt.name };
|
||||||
|
|
||||||
if (optname == "help") {
|
if (optname == "help") {
|
||||||
std::cout << "To use spslr_patchcompile, supply these arguments:" << std::endl;
|
std::cout
|
||||||
std::cout << " --out=<file> (the compiled asm file to be written)" << std::endl;
|
<< "Usage:\n"
|
||||||
std::cout << " <file>... (one or more .spslr metadata files)" << std::endl;
|
<< " spslr_patchcompile --out=<file> [options] <file>...\n\n"
|
||||||
|
<< "Options:\n"
|
||||||
|
<< " --read-targets=<file>\n"
|
||||||
|
<< " --emit-targets=<file>\n"
|
||||||
|
<< " --no-new-targets\n"
|
||||||
|
<< " --module\n";
|
||||||
return 0;
|
return 0;
|
||||||
} else if (optname == "out") {
|
} else if (optname == "out") {
|
||||||
out_file = std::string{ optarg };
|
opts.out_file = optarg;
|
||||||
|
} else if (optname == "load-targets") {
|
||||||
|
opts.load_targets_file = optarg;
|
||||||
|
} else if (optname == "dump-targets") {
|
||||||
|
opts.dump_targets_file = optarg;
|
||||||
|
} else if (optname == "no-new-targets") {
|
||||||
|
opts.no_new_targets = true;
|
||||||
|
} else if (optname == "module") {
|
||||||
|
opts.is_module = true;
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "Invalid option, try \"--help\"!" << std::endl;
|
std::cerr << "Invalid option, try \"--help\"!\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (out_file.empty()) {
|
|
||||||
std::cerr << "Missing output file path, supply it via --out=<file>!" << std::endl;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = optind; i < argc; ++i)
|
for (int i = optind; i < argc; ++i)
|
||||||
spslr_files.emplace_back(argv[i]);
|
opts.spslr_files.emplace_back(argv[i]);
|
||||||
|
|
||||||
if (spslr_files.empty()) {
|
if (opts.out_file.empty()) {
|
||||||
std::cerr << "Missing spslr files! Pass one or more .spslr files as positional arguments." << std::endl;
|
std::cerr << "Missing output file path, supply it via --out=<file>!\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!accumulate(spslr_files)) {
|
if (opts.spslr_files.empty()) {
|
||||||
|
std::cerr << "Missing spslr files! Pass one or more .spslr metadata files as positional arguments.\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.no_new_targets && opts.load_targets_file.empty()) {
|
||||||
|
std::cerr << "--no-new-targets requires --load-targets\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!opts.load_targets_file.empty()) {
|
||||||
|
if (!load_target_map(opts.load_targets_file)) {
|
||||||
|
std::cerr << "Failed to load target map: " << opts.load_targets_file << "\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!accumulate(opts.spslr_files, opts.no_new_targets)) {
|
||||||
std::cerr << "Failed to accumulate data from spslr directory!" << std::endl;
|
std::cerr << "Failed to accumulate data from spslr directory!" << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Gathered a total of " << targets.size() << " distinct targets from "
|
std::filesystem::path out_path { opts.out_file };
|
||||||
<< units.size() << " compilation units!" << std::endl;
|
|
||||||
|
|
||||||
std::filesystem::path out_path { out_file };
|
|
||||||
if (out_path.has_parent_path()) {
|
if (out_path.has_parent_path()) {
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
std::filesystem::create_directories(out_path.parent_path(), ec);
|
std::filesystem::create_directories(out_path.parent_path(), ec);
|
||||||
@ -83,11 +116,18 @@ int main(int argc, char** argv) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!emit_patcher_program_asm(out)) {
|
if (!emit_patcher_program_asm(out, opts.is_module)) {
|
||||||
std::cerr << "Failed to write emit patcher program!" << std::endl;
|
std::cerr << "Failed to write emit patcher program!" << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!opts.dump_targets_file.empty()) {
|
||||||
|
if (!dump_target_map(opts.dump_targets_file)) {
|
||||||
|
std::cerr << "Failed to write target map: " << opts.dump_targets_file << "\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,22 @@
|
|||||||
#ifndef SPSLR_SELFPATCH_H
|
#ifndef SPSLR_SELFPATCH_H
|
||||||
#define SPSLR_SELFPATCH_H
|
#define SPSLR_SELFPATCH_H
|
||||||
|
|
||||||
|
#define SPSLR_MODULE_SYM_IPIN_CNT "spslr_ipin_cnt"
|
||||||
|
#define SPSLR_MODULE_SYM_IPINS "spslr_ipins"
|
||||||
|
#define SPSLR_MODULE_SYM_IPIN_OP_CNT "spslr_ipin_op_cnt"
|
||||||
|
#define SPSLR_MODULE_SYM_IPIN_OPS "spslr_ipin_ops"
|
||||||
|
#define SPSLR_MODULE_SYM_DPIN_CNT "spslr_dpin_cnt"
|
||||||
|
#define SPSLR_MODULE_SYM_DPINS "spslr_dpins"
|
||||||
|
|
||||||
|
struct spslr_module {
|
||||||
|
const void* ipin_cnt;
|
||||||
|
const void* ipins;
|
||||||
|
const void* ipin_op_cnt;
|
||||||
|
const void* ipin_ops;
|
||||||
|
const void* dpin_cnt;
|
||||||
|
const void* dpins;
|
||||||
|
};
|
||||||
|
|
||||||
void spslr_selfpatch(void);
|
void spslr_selfpatch(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -32,17 +32,25 @@ endforeach()
|
|||||||
set(SUBJECT_SPSLR_ASM "${CMAKE_CURRENT_BINARY_DIR}/subject_spslr_program.S")
|
set(SUBJECT_SPSLR_ASM "${CMAKE_CURRENT_BINARY_DIR}/subject_spslr_program.S")
|
||||||
set(SUBJECT_SPSLR_OBJ "${CMAKE_CURRENT_BINARY_DIR}/subject_spslr_program.o")
|
set(SUBJECT_SPSLR_OBJ "${CMAKE_CURRENT_BINARY_DIR}/subject_spslr_program.o")
|
||||||
|
|
||||||
|
set(SUBJECT_TARGET_MAP "${CMAKE_CURRENT_BINARY_DIR}/subject.spslr_targets")
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT "${SUBJECT_SPSLR_ASM}"
|
OUTPUT "${SUBJECT_SPSLR_ASM}" "${SUBJECT_TARGET_MAP}"
|
||||||
COMMAND $<TARGET_FILE:spslr_patchcompile>
|
COMMAND $<TARGET_FILE:spslr_patchcompile>
|
||||||
--out=${SUBJECT_SPSLR_ASM}
|
--out=${SUBJECT_SPSLR_ASM}
|
||||||
|
--dump-targets=${SUBJECT_TARGET_MAP}
|
||||||
${SUBJECT_SPSLR_FILES}
|
${SUBJECT_SPSLR_FILES}
|
||||||
DEPENDS
|
DEPENDS
|
||||||
spslr_patchcompile
|
spslr_patchcompile
|
||||||
$<TARGET_OBJECTS:subject_objs>
|
subject_objs
|
||||||
|
${SUBJECT_SPSLR_FILES}
|
||||||
VERBATIM
|
VERBATIM
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_custom_target(subject_spslr_metadata
|
||||||
|
DEPENDS "${SUBJECT_SPSLR_ASM}" "${SUBJECT_TARGET_MAP}"
|
||||||
|
)
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT "${SUBJECT_SPSLR_OBJ}"
|
OUTPUT "${SUBJECT_SPSLR_OBJ}"
|
||||||
COMMAND ${CMAKE_C_COMPILER}
|
COMMAND ${CMAKE_C_COMPILER}
|
||||||
@ -104,10 +112,15 @@ add_custom_command(
|
|||||||
OUTPUT "${MODULE_SPSLR_ASM}"
|
OUTPUT "${MODULE_SPSLR_ASM}"
|
||||||
COMMAND $<TARGET_FILE:spslr_patchcompile>
|
COMMAND $<TARGET_FILE:spslr_patchcompile>
|
||||||
--out=${MODULE_SPSLR_ASM}
|
--out=${MODULE_SPSLR_ASM}
|
||||||
|
--load-targets=${SUBJECT_TARGET_MAP}
|
||||||
|
--no-new-targets
|
||||||
|
--module
|
||||||
${MODULE_SPSLR_FILES}
|
${MODULE_SPSLR_FILES}
|
||||||
DEPENDS
|
DEPENDS
|
||||||
spslr_patchcompile
|
spslr_patchcompile
|
||||||
$<TARGET_OBJECTS:spslr_module_objs>
|
subject_spslr_metadata
|
||||||
|
spslr_module_objs
|
||||||
|
${MODULE_SPSLR_FILES}
|
||||||
VERBATIM
|
VERBATIM
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -22,6 +22,37 @@ struct task_struct global = { .pid = 42, .comm = "main_global", .arrfun = {
|
|||||||
|
|
||||||
EXPORT_SYMBOL(global);
|
EXPORT_SYMBOL(global);
|
||||||
|
|
||||||
|
static int fetch_module_spslr_symbols(void* handle, struct spslr_module* mod) {
|
||||||
|
if (!handle || !mod)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
mod->ipin_cnt = dlsym(handle, SPSLR_MODULE_SYM_IPIN_CNT);
|
||||||
|
if (!mod->ipin_cnt)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
mod->ipins = dlsym(handle, SPSLR_MODULE_SYM_IPINS);
|
||||||
|
if (!mod->ipins)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
mod->ipin_op_cnt = dlsym(handle, SPSLR_MODULE_SYM_IPIN_OP_CNT);
|
||||||
|
if (!mod->ipin_op_cnt)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
mod->ipin_ops = dlsym(handle, SPSLR_MODULE_SYM_IPIN_OPS);
|
||||||
|
if (!mod->ipin_ops)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
mod->dpin_cnt = dlsym(handle, SPSLR_MODULE_SYM_DPIN_CNT);
|
||||||
|
if (!mod->dpin_cnt)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
mod->dpins = dlsym(handle, SPSLR_MODULE_SYM_DPINS);
|
||||||
|
if (!mod->dpins)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int do_module_test_access_pid(const char *path, const struct task_struct *t) {
|
static int do_module_test_access_pid(const char *path, const struct task_struct *t) {
|
||||||
typedef int (*module_test_access_fn)(const struct task_struct *t);
|
typedef int (*module_test_access_fn)(const struct task_struct *t);
|
||||||
|
|
||||||
@ -33,6 +64,15 @@ static int do_module_test_access_pid(const char *path, const struct task_struct
|
|||||||
|
|
||||||
dlerror();
|
dlerror();
|
||||||
|
|
||||||
|
struct spslr_module mod;
|
||||||
|
if (fetch_module_spslr_symbols(handle, &mod) < 0) {
|
||||||
|
fprintf(stderr, "failed to fetch spslr symbols in test module\n");
|
||||||
|
dlclose(handle);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO -> Patch module
|
||||||
|
|
||||||
module_test_access_fn fn = (module_test_access_fn)dlsym(handle, "module_test_access_pid");
|
module_test_access_fn fn = (module_test_access_fn)dlsym(handle, "module_test_access_pid");
|
||||||
|
|
||||||
const char *err = dlerror();
|
const char *err = dlerror();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user