-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathresolve.h
309 lines (288 loc) · 11.6 KB
/
resolve.h
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
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
///
/// \file resolve.h
/// \brief Functions to resolve NIDs and syscalls
/// \defgroup resolve Executable Resolver
/// \brief Finds and resolves NIDs
/// @{
///
#ifndef UVL_RESOLVE
#define UVL_RESOLVE
#include "types.h"
/** \name Type of entry
* @{
*/
#define RESOLVE_TYPE_UNKNOWN 0 ///< Unknown type
#define RESOLVE_TYPE_FUNCTION 1 ///< Function call
#define RESOLVE_TYPE_SYSCALL 2 ///< Syscall
#define RESOLVE_TYPE_VARIABLE 3 ///< Imported variable
#define RESOLVE_TYPE_RELATIVE 4 ///< PC relative import
#define RESOLVE_TYPE_UNRESOLVED 5 ///< No resolve
/** @}*/
/** \name Supported ARM instruction types
* @{
*/
#define INSTRUCTION_UNKNOWN 0 ///< Unknown/unsupported instruction
#define INSTRUCTION_MOVW 1 ///< MOVW Rd, \#imm instruction
#define INSTRUCTION_MOVT 2 ///< MOVT Rd, \#imm instruction
#define INSTRUCTION_SYSCALL 3 ///< SVC \#imm instruction
#define INSTRUCTION_BRANCH 4 ///< BX Rn instruction
#define INSTRUCTION_ADR 5 ///< Relative addressing
#define INSTRUCTION_MVN 6 ///< MVN 0 (always invalid)
/** @}*/
#define STUB_FUNC_MAX_LEN 16 ///< Max size for a stub function in bytes
/** \name Search flags for importing loaded modules
* \sa uvl_resolve_all_loaded_modules
* @{
*/
#define RESOLVE_MOD_IMPS 0x1 ///< Add entry from import function stubs
#define RESOLVE_MOD_EXPS 0x2 ///< Add entry from exported information
#define RESOLVE_IMPS_SVC_ONLY 0x4 ///< Used with @c RESOLVE_MOD_IMPS but only add syscalls for import entries
#define RESOLVE_RELOAD_MOD 0x8 ///< Load module again to get unpoisoned import NID table
/** @}*/
/** \name Module infomation check
* @{
*/
#define MOD_INFO_VALID_ATTR 0x0000
#define MOD_INFO_VALID_VER 0x0101
/** @}*/
#define MAX_LOADED_MODS 128 ///< Maximum number of loaded modules
#define MAX_RESOLVE_ENTRIES 0x10000 ///< Maximum number of resolves
#define STUB_FUNC_SIZE 0x10 ///< Size of stub functions
#define UVL_LIBKERN_MAX_SIZE 0xE000 ///< Maximum size of sceLibKernel (for resolving loader)
/**
* \brief Resolve table entry
*
* This can represent either an unresolved entry
* from a homebrew or a resolved entry copied
* from a loaded module.
*/
typedef struct resolve_entry
{
u32_t nid; ///< NID of entry
u16_t type; ///< See defined "Type of entry"
u16_t reserved; ///< For future use
/**
* \brief Value of the entry
*/
union value
{
void* ptr; ///< A pointer value for unresolved pointing to where to write resolved value
u32_t value; ///< Any double-word value for resolved
void* func_ptr; ///< A pointer to stub function for unresolved or function to call for resolved
u32_t syscall; ///< A syscall number
} value;
} resolve_entry_t;
/**
* \brief SCE module information section
*
* Can be found in an ELF file or loaded in
* memory.
*/
typedef struct module_info // thanks roxfan
{
u16_t modattribute; // ??
u16_t modversion; // always 1,1?
char modname[27]; ///< Name of the module
u8_t type; // 6 = user-mode prx?
void *gp_value; // always 0 on ARM
u32_t ent_top; // beginning of the export list (sceModuleExports array)
u32_t ent_end; // end of same
u32_t stub_top; // beginning of the import list (sceModuleStubInfo array)
u32_t stub_end; // end of same
u32_t module_nid; // ID of the PRX? seems to be unused
u32_t field_38; // unused in samples
u32_t field_3C; // I suspect these may contain TLS info
u32_t field_40; //
u32_t mod_start; // module start function; can be 0 or -1; also present in exports
u32_t mod_stop; // module stop function
u32_t exidx_start; // ARM EABI style exception tables
u32_t exidx_end; //
u32_t extab_start; //
u32_t extab_end; //
} module_info_t;
/**
* \brief SCE module export table
*
* Can be found in an ELF file or loaded in
* memory.
*/
typedef struct module_exports // thanks roxfan
{
u16_t size; // size of this structure; 0x20 for Vita 1.x
u8_t lib_version[2]; //
u16_t attribute; // ?
u16_t num_functions; // number of exported functions
u32_t num_vars; // number of exported variables
u32_t num_tls_vars; // number of exported TLS variables? <-- pretty sure wrong // yifanlu
u32_t module_nid; // NID of this specific export list; one PRX can export several names
char *lib_name; // name of the export module
u32_t *nid_table; // array of 32-bit NIDs for the exports, first functions then vars
void **entry_table; // array of pointers to exported functions and then variables
} module_exports_t;
/**
* \brief SCE module import table (< 3.0 format)
*
* Can be found in an ELF file or loaded in
* memory.
*/
typedef struct module_imports_2x // thanks roxfan
{
u16_t size; // size of this structure; 0x34 for Vita 1.x
u16_t lib_version; //
u16_t attribute; //
u16_t num_functions; // number of imported functions
u16_t num_vars; // number of imported variables
u16_t num_tls_vars; // number of imported TLS variables
u32_t reserved1; // ?
u32_t module_nid; // NID of the module to link to
char *lib_name; // name of module
u32_t reserved2; // ?
u32_t *func_nid_table; // array of function NIDs (numFuncs)
void **func_entry_table; // parallel array of pointers to stubs; they're patched by the loader to jump to the final code
u32_t *var_nid_table; // NIDs of the imported variables (numVars)
void **var_entry_table; // array of pointers to "ref tables" for each variable
u32_t *tls_nid_table; // NIDs of the imported TLS variables (numTlsVars)
void **tls_entry_table; // array of pointers to ???
} module_imports_2x_t;
/**
* \brief SCE module import table (>= 3.x format)
*
* Can be found in an ELF file or loaded in
* memory.
*/
typedef struct module_imports_3x
{
u16_t size; // size of this structure; 0x24 for Vita 3.x
u16_t lib_version; //
u16_t attribute; //
u16_t num_functions; // number of imported functions
u16_t num_vars; // number of imported variables
u16_t unknown1;
u32_t module_nid; // NID of the module to link to
char *lib_name; // name of module
u32_t *func_nid_table; // array of function NIDs (numFuncs)
void **func_entry_table; // parallel array of pointers to stubs; they're patched by the loader to jump to the final code
u32_t *var_nid_table; // NIDs of the imported variables (numVars)
void **var_entry_table; // array of pointers to "ref tables" for each variable
} module_imports_3x_t;
/**
* \brief SCE module import table
*/
typedef union module_imports
{
u16_t size;
module_imports_2x_t old_version;
module_imports_3x_t new_version;
} module_imports_t;
#define IMP_GET_NEXT(imp) ((module_imports_t *)((char *)imp + imp->size))
#define IMP_GET_FUNC_COUNT(imp) (imp->size == sizeof (module_imports_3x_t) ? imp->new_version.num_functions : imp->old_version.num_functions)
#define IMP_GET_VARS_COUNT(imp) (imp->size == sizeof (module_imports_3x_t) ? imp->new_version.num_vars : imp->old_version.num_vars)
#define IMP_GET_NID(imp) (imp->size == sizeof (module_imports_3x_t) ? imp->new_version.module_nid : imp->old_version.module_nid)
#define IMP_GET_NAME(imp) (imp->size == sizeof (module_imports_3x_t) ? imp->new_version.lib_name : imp->old_version.lib_name)
#define IMP_GET_FUNC_TABLE(imp) (imp->size == sizeof (module_imports_3x_t) ? imp->new_version.func_nid_table : imp->old_version.func_nid_table)
#define IMP_GET_FUNC_ENTRIES(imp) (imp->size == sizeof (module_imports_3x_t) ? imp->new_version.func_entry_table : imp->old_version.func_entry_table)
#define IMP_GET_VARS_TABLE(imp) (imp->size == sizeof (module_imports_3x_t) ? imp->new_version.var_nid_table : imp->old_version.var_nid_table)
#define IMP_GET_VARS_ENTRIES(imp) (imp->size == sizeof (module_imports_3x_t) ? imp->new_version.var_entry_table : imp->old_version.var_entry_table)
/**
* \brief Either an SCE module import table or export table
*
* \sa module_imports
* \sa module_exports
*/
typedef union module_ports
{
u16_t
size; ///< Size of table
module_imports_t imports; ///< Import kind
module_exports_t exports; ///< Export kind
} module_ports_t;
/**
* \brief A segment of the module in memory
*/
typedef struct segment_info
{
u32_t size; // this structure size (0x18)
u32_t perms; // probably rwx in low bits
void *vaddr; // address in memory
u32_t memsz; // size in memory
u32_t flags; // meanig unknown
u32_t res; // unused?
} segment_info_t;
/**
* \brief Loaded module information
*
* Returned by @c sceKernelGetModuleInfo
*/
typedef struct loaded_module_info
{
u32_t size; // 0x1B8 for Vita 1.x
u32_t handle; // kernel module handle?
u32_t flags; // some bits. could be priority or whatnot
char module_name[28];
u32_t unkn_28;
void *module_start;
u32_t unkn_30;
void *module_stop;
void *exidx_start;
void *exidx_end;
u32_t unkn_40;
u32_t unkn_44;
void *tls_init_data;
u32_t tls_init_size;
u32_t tls_area_size;
char file_path[256]; //
segment_info_t segments[4];
u32_t type; // 6 = user-mode PRX?
} loaded_module_info_t;
/** \name Interacting with the resolve table
* @{
*/
int uvl_resolve_table_initialize ();
int uvl_resolve_table_destroy ();
int uvl_resolve_table_add (resolve_entry_t *entry);
resolve_entry_t *uvl_resolve_table_get (u32_t nid);
/** @}*/
/** \name Estimating syscalls
* @{
*/
resolve_entry_t *uvl_estimate_syscall (u32_t nid);
/** @}*/
/** \name Capturing and resolving stubs
* @{
*/
int uvl_resolve_import_stub_to_entry (void *stub, u32_t nid, resolve_entry_t *entry);
int uvl_resolve_entry_to_import_stub (resolve_entry_t *entry, void *stub);
/** @}*/
/** \name ARM instruction functions
* @{
*/
u32_t uvl_decode_arm_inst (u32_t cur_inst, u8_t *type);
u32_t uvl_encode_arm_inst (u8_t type, u16_t immed, u16_t reg);
/** @}*/
/** \name Bulk add to resolve table
* @{
*/
int uvl_resolve_add_imports (module_info_t *mod_info, module_imports_t *reload_imp_table, module_imports_t *imp_table, int syscalls_only);
int uvl_resolve_add_exports (module_exports_t *exp_table);
/** @}*/
/** \name Resolving entries
* @{
*/
int uvl_resolve_add_all_modules (int type);
int uvl_resolve_add_module (PsvUID modid, int type);
int uvl_resolve_imports (module_imports_t *import);
int uvl_resolve_loader (u32_t nid, void *libkernel_base, void *stub);
/** @}*/
module_info_t *uvl_find_module_info (loaded_module_info_t *m_mod_info);
// live resolving too slow
#if 0
/** \name Resolving entries
* @{
*/
u32_t uvl_encode_arm_inst (u8_t type, u16_t immed, u16_t reg);
int uvl_resolve_stub (u32_t nid, void *stub, char *lib_name);
int uvl_resolve_stub_from_module (u32_t nid, void *stub, char *lib_name, void *mod_start, module_info_t *mod_info);
/** @}*/
#endif
#endif
/// @}