-
Notifications
You must be signed in to change notification settings - Fork 45
/
Copy pathosx.lua
222 lines (180 loc) · 5.72 KB
/
osx.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
local ffi = require("ffi")
local log = require("log")
local format = string.format
local sub = string.sub
local cast = ffi.cast
local cdef = ffi.cdef
local load = ffi.load
local metatype = ffi.metatype
local new = ffi.new
local typeof = ffi.typeof
local sizeof = ffi.sizeof
local string = ffi.string
local errno = ffi.errno
local lshift = bit.lshift
local rshift = bit.rshift
local bswap = bit.bswap
local band = bit.band
local bor = bit.bor
local libc = ffi.C
cdef [[
static const int MAXCOMLEN = 16;
char *strerror(int errnum);
typedef struct task *task_t;
typedef task_t task_port_t;
typedef signed int pid_t;
typedef unsigned int uid_t;
typedef unsigned int gid_t;
typedef unsigned long uintptr_t;
typedef unsigned long long u_int64_t;
typedef uint32_t natural_t;
typedef uint32_t mach_port_t;
typedef uint64_t mach_vm_address_t;
typedef uint64_t mach_vm_size_t;
typedef mach_port_t vm_map_read_t;
typedef natural_t mach_msg_type_number_t;
typedef natural_t mach_port_t;
typedef int vm_region_flavor_t;
typedef int *vm_region_info_t;
typedef struct {
pid_t pid;
task_t task;
unsigned __int64 dolphin_base_addr;
unsigned __int64 dolphin_addr_size;
} MEMORY_STRUCT;
typedef struct proc_bsdinfo {
uint32_t pbi_flags; /* 64bit; emulated etc */
uint32_t pbi_status;
uint32_t pbi_xstatus;
uint32_t pbi_pid;
uint32_t pbi_ppid;
uid_t pbi_uid;
gid_t pbi_gid;
uid_t pbi_ruid;
gid_t pbi_rgid;
uid_t pbi_svuid;
gid_t pbi_svgid;
uint32_t rfu_1; /* reserved */
char pbi_comm[MAXCOMLEN];
char pbi_name[2*MAXCOMLEN]; /* empty if no name is registered */
uint32_t pbi_nfiles;
uint32_t pbi_pgid;
uint32_t pbi_pjobc;
uint32_t e_tdev; /* controlling tty dev */
uint32_t e_tpgid; /* tty process group id */
int32_t pbi_nice;
uint64_t pbi_start_tvsec;
uint64_t pbi_start_tvusec;
} proc_bsdinfo;
typedef struct proc_bsdshortinfo {
uint32_t pbsi_pid; /* process id */
uint32_t pbsi_ppid; /* process parent id */
uint32_t pbsi_pgid; /* process perp id */
uint32_t pbsi_status; /* p_stat value, SZOMB, SRUN, etc */
char pbsi_comm[MAXCOMLEN]; /* upto 16 characters of process name */
uint32_t pbsi_flags; /* 64bit; emulated etc */
uid_t pbsi_uid; /* current uid on process */
gid_t pbsi_gid; /* current gid on process */
uid_t pbsi_ruid; /* current ruid on process */
gid_t pbsi_rgid; /* current tgid on process */
uid_t pbsi_svuid; /* current svuid on process */
gid_t pbsi_svgid; /* current svgid on process */
uint32_t pbsi_rfu; /* reserved for future use*/
} proc_bsdshortinfo;
int proc_listpids(uint32_t type, uint32_t typeinfo, void *buffer, int buffersize); // , int32_t * retval
int proc_pidinfo(int pid, int flavor, uint64_t arg, void* buffer, uint32_t buffersize); // , int32_t * retval
int vm_read(uint32_t target_task, uintptr_t address, uintptr_t size, uintptr_t *data, uint32_t * dataCnt);
pid_t getpgid(pid_t pid);
int task_for_pid(mach_port_t task, pid_t pid, task_port_t *target);
mach_port_t mach_task_self(void);
int mach_vm_region(vm_map_read_t target_task, mach_vm_address_t *address, mach_vm_size_t *size, vm_region_flavor_t flavor, vm_region_info_t info, mach_msg_type_number_t *infoCnt, mach_port_t *object_name);
]]
local PROC_ALL_PIDS = 1
local PROC_PIDTBSDINFO = 3
local MEMORY = {}
MEMORY.__index = MEMORY
MEMORY.init = metatype("MEMORY_STRUCT", MEMORY)
MEMORY.task = new("task_t[1]")
function MEMORY:hasPermissions()
return true
end
local valid_process_names = {
["Dolphin"] = true,
["Slippi Dolphin"] = true,
["DolphinWx"] = true,
["DolphinQt2"] = true,
}
local PROC_BSDINFO_PTR = typeof("proc_bsdinfo[1]")
function MEMORY:findprocess()
if self:hasProcess() then return false end
local num_pids = libc.proc_listpids(PROC_ALL_PIDS, 0, nil, 0)
local pids = new("pid_t[?]", num_pids)
libc.proc_listpids(PROC_ALL_PIDS, 0, pids, sizeof(pids))
local proc = PROC_BSDINFO_PTR()[0]
for i=0, num_pids do
local pid = pids[i]
if pid ~= 0 then
local st = libc.proc_pidinfo(pid, PROC_PIDTBSDINFO, 0, proc, sizeof(PROC_BSDINFO_PTR))
if valid_process_names[string(proc.pbi_name)] then
self.pid = pid
log.debug("Found dolphin-emu process: /proc/%d", self.pid)
break
end
end
end
return self:hasProcess()
end
function MEMORY:isProcessActive()
if self.pid then
return libc.getpgid(self.pid) >= 0
end
return false
end
function MEMORY:hasProcess()
return self.pid ~= 0
end
function MEMORY:clearGamecubeRAMOffset()
self.dolphin_base_addr = 0
end
function MEMORY:hasGamecubeRAMOffset()
return self.dolphin_base_addr ~= 0
end
function MEMORY:getGamecubeRAMOffset()
return tonumber(self.dolphin_base_addr)
end
function MEMORY:getGamecubeRAMSize()
return tonumber(self.dolphin_addr_size)
end
function MEMORY:close()
if self:hasProcess() then
self.pid = 0
self.dolphin_base_addr = 0
end
end
function MEMORY:__gc()
self:close()
end
function MEMORY:findGamecubeRAMOffset()
if self:hasProcess() then
local err = libc.task_for_pid(libc.mach_task_self(), self.pid, self.task)
if error == 0 then
log.info("task_for_pid SUCCESS: valid permissions")
else
log.warn("task_for_pid FAILED: invalid permissions")
end
if error ~= 0 then
return false
end
-- while libc.mach_vm_region(self.task, regionAddr, size, VM_REGION_EXTENDED_INFO, regInfo, cnt, obj) == 0 do
-- TODO: Scan all memory regions..
-- end
end
return false
end
function MEMORY:read(addr, output, size)
return false
end
function MEMORY:write(addr, input, size)
return false
end
return MEMORY