Skip to content

Commit 7a9f922

Browse files
committed
Added missing defines and fixed linux loader
1 parent f5a88f7 commit 7a9f922

2 files changed

Lines changed: 82 additions & 39 deletions

File tree

src/port/scripting/loader.cpp

Lines changed: 73 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,27 @@
11
#include "loader.h"
22

3-
#if defined(__linux__)
4-
#define _GNU_SOURCE
5-
#endif
6-
73
#include <stdio.h>
84
#include <stdlib.h>
95
#include <string.h>
6+
#include <string>
7+
#include <stdexcept>
108

119
#if defined(_WIN32) || defined(__CYGWIN__)
1210
#include <windows.h>
1311
#else
1412
#include <dlfcn.h>
1513
#include <unistd.h>
16-
#endif
17-
18-
#if defined(__linux__)
19-
#include <sys/mman.h>
20-
#endif
21-
22-
#include <string>
23-
#include <stdexcept>
24-
25-
#if defined(_WIN32) || defined(__CYGWIN__)
26-
#include <windows.h>
27-
#elif defined(__linux__) || defined(__APPLE__)
2814
#include <unistd.h>
2915
#include <fcntl.h>
3016
#include <cerrno>
3117
#endif
3218

3319
#if defined(__linux__)
3420
#include <sys/mman.h>
21+
#include <sys/stat.h>
22+
#include <elf.h>
23+
#include <iostream>
24+
#include <fstream>
3525
#endif
3626

3727
std::string ModInstance::GenerateTempFile() {
@@ -50,27 +40,18 @@ std::string ModInstance::GenerateTempFile() {
5040

5141
return std::string(tempFileName);
5242

53-
#elif defined(__linux__)
54-
int fd = memfd_create("virtual_mod_lib", 0);
55-
if (fd == -1) {
56-
throw std::runtime_error("Failed to create memfd: " + std::to_string(errno));
57-
}
58-
59-
// IMPORTANT: We deliberately DO NOT close(fd) here!
60-
// A memfd only exists in RAM as long as an open file descriptor points to it.
61-
// If we closed it, the file would instantly vanish and the path would become invalid.
62-
char path[256];
63-
snprintf(path, sizeof(path), "/proc/self/fd/%d", fd);
64-
return std::string(path);
65-
66-
#elif defined(__APPLE__)
43+
#elif defined(__APPLE__) || defined(__linux__)
6744
char path_template[] = "/tmp/mod_lib_XXXXXX";
6845

6946
int fd = mkstemp(path_template);
7047
if (fd == -1) {
7148
throw std::runtime_error("Failed to create temporary file: " + std::to_string(errno));
7249
}
7350

51+
#ifdef __linux__
52+
fchmod(fd, 0755);
53+
#endif
54+
7455
// mkstemp creates a physical file on the hard drive.
7556
// We can safely close the FD now; the file will remain on disk for you to open later.
7657
close(fd);
@@ -81,6 +62,64 @@ std::string ModInstance::GenerateTempFile() {
8162
#endif
8263
}
8364

65+
#ifdef __linux__
66+
void FixELFHeader(const std::string& path) {
67+
// 1. Read the file into a buffer
68+
std::ifstream in(path, std::ios::binary | std::ios::ate);
69+
if (!in.is_open()) return;
70+
71+
std::streamsize size = in.tellg();
72+
in.seekg(0, std::ios::beg);
73+
74+
std::vector<uint8_t> buffer(size);
75+
if (!in.read(reinterpret_cast<char*>(buffer.data()), size)) return;
76+
in.close();
77+
78+
if (buffer.size() < sizeof(Elf64_Ehdr)) return;
79+
80+
// 2. ELF Surgery
81+
Elf64_Ehdr* header = reinterpret_cast<Elf64_Ehdr*>(buffer.data());
82+
83+
if (header->e_ident[EI_CLASS] == ELFCLASS64) {
84+
Elf64_Phdr* phdr = reinterpret_cast<Elf64_Phdr*>(buffer.data() + header->e_phoff);
85+
86+
bool patched = false;
87+
for (int i = 0; i < header->e_phnum; i++) {
88+
// Target PT_NOTE (0x4) OR PT_GNU_EH_FRAME (0x6474e550)
89+
// TCC doesn't give us a NOTE, so we hijack the EH_FRAME header.
90+
if (phdr[i].p_type == PT_NOTE || phdr[i].p_type == 0x6474e550) {
91+
phdr[i].p_type = PT_GNU_STACK; // Change to 0x6474e551
92+
phdr[i].p_flags = PF_R | PF_W; // Set to RW (No Execute)
93+
phdr[i].p_align = 0x10;
94+
patched = true;
95+
break;
96+
}
97+
}
98+
99+
if (!patched) {
100+
// Last resort: if we can't find either, we'll try to find any
101+
// non-critical segment that isn't LOAD (1) or DYNAMIC (2).
102+
for (int i = 0; i < header->e_phnum; i++) {
103+
if (phdr[i].p_type != PT_LOAD && phdr[i].p_type != PT_DYNAMIC) {
104+
phdr[i].p_type = PT_GNU_STACK;
105+
phdr[i].p_flags = PF_R | PF_W;
106+
break;
107+
}
108+
}
109+
}
110+
}
111+
112+
// 3. Write it back
113+
std::ofstream out(path, std::ios::binary | std::ios::trunc);
114+
if (!out.is_open()) return;
115+
out.write(reinterpret_cast<const char*>(buffer.data()), buffer.size());
116+
out.close();
117+
118+
// 4. Ensure permissions are set to allow execution of the file
119+
chmod(path.c_str(), 0755);
120+
}
121+
#endif
122+
84123
void ModInstance::Init(const std::string& path) {
85124
#if defined(_WIN32) || defined(__CYGWIN__)
86125
HMODULE handle = LoadLibraryA(path.c_str());
@@ -91,15 +130,10 @@ void ModInstance::Init(const std::string& path) {
91130
} else {
92131
throw std::runtime_error("Failed to load library: " + std::to_string(GetLastError()));
93132
}
94-
#elif defined(__linux__)
95-
void* handle = dlopen(path.c_str(), RTLD_NOW);
96-
if (handle) {
97-
this->mHandle = handle;
98-
return;
99-
} else {
100-
throw std::runtime_error("Failed to load library: " + std::string(dlerror()));
101-
}
102-
#elif defined(__APPLE__)
133+
#elif defined(__linux__) || defined(__APPLE__)
134+
#ifdef __linux__
135+
FixELFHeader(path);
136+
#endif
103137
void* handle = dlopen(path.c_str(), RTLD_NOW);
104138
if (handle) {
105139
this->mHandle = handle;

src/port/scripting/scripting.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,15 @@ void ScriptingLayer::Load(const std::string& path, const std::shared_ptr<Ship::A
4646
throw std::runtime_error("Failed to create tcc state");
4747
}
4848

49+
tcc_define_symbol(s, "VERSION_US", "1");
50+
tcc_define_symbol(s, "ENABLE_RUMBLE", "1");
51+
tcc_define_symbol(s, "F3D_OLD", "1");
52+
tcc_define_symbol(s, "F3D_GBI", "1");
53+
tcc_define_symbol(s, "GBI_FLOATS", "1");
54+
tcc_define_symbol(s, "_LANGUAGE_C", "1");
55+
tcc_define_symbol(s, "_USE_MATH_DEFINES", "1");
56+
tcc_define_symbol(s, "AVOID_UB", "1");
57+
4958
tcc_set_output_type(s, TCC_OUTPUT_DLL);
5059

5160
if (tcc_compile_string(s, reinterpret_cast<const char*>(raw.data())) == -1) {

0 commit comments

Comments
 (0)