Hlide problem solved (i believe)
[pspdecompiler.git] / module.c
blob5715fa3c0a9c25cd965adf3197a2909fcfdb55f1
1 /**
2 * Author: Humberto Naves (hsnaves@gmail.com)
3 */
5 #include <stdlib.h>
6 #include <string.h>
8 #include "prx.h"
9 #include "utils.h"
11 static
12 int check_module_info (struct prx *p)
14 struct prx_modinfo *info = p->modinfo;
15 uint32 vaddr, offset;
17 if (info->name[27]) {
18 error (__FILE__ ": module name is not null terminated\n");
19 return 0;
22 if (info->expvaddr) {
23 if (info->expvaddr > info->expvaddrbtm) {
24 error (__FILE__ ": exports bottom is above top (0x%08X - 0x%08X)", info->expvaddr, info->expvaddrbtm);
25 return 0;
27 if (!prx_inside_progfile (p->programs, info->expvaddr, info->expvaddrbtm - info->expvaddr)) {
28 error (__FILE__ ": exports not inside the first program (0x%08X - 0x%08X)", info->expvaddr, info->expvaddrbtm);
29 return 0;
31 info->numexports = 0;
32 offset = prx_translate (p, info->expvaddr);
33 for (vaddr = info->expvaddr; vaddr < info->expvaddrbtm; info->numexports++) {
34 uint32 size;
35 size = p->data[offset+8];
36 if (size < 4) {
37 error (__FILE__ ": export size less than 4 words: %d", size);
38 return 0;
40 vaddr += size << 2;
41 offset += size << 2;
43 if (vaddr != info->expvaddrbtm) {
44 error (__FILE__ ": invalid exports boundary");
45 return 0;
49 if (info->impvaddr) {
50 if (info->impvaddr > info->impvaddrbtm) {
51 error (__FILE__ ": imports bottom is above top (0x%08X - 0x%08X)", info->impvaddr, info->impvaddrbtm);
52 return 0;
54 if (!prx_inside_progfile (p->programs, info->impvaddr, info->impvaddrbtm - info->impvaddr)) {
55 error (__FILE__ ": imports not inside the first program (0x%08X - 0x%08X)", info->impvaddr, info->impvaddrbtm);
56 return 0;
58 info->numimports = 0;
59 offset = prx_translate (p, info->impvaddr);
60 for (vaddr = info->impvaddr; vaddr < info->impvaddrbtm; info->numimports++) {
61 uint32 size;
62 uint8 nvars;
63 size = p->data[offset+8];
64 nvars = p->data[offset+9];
65 if (size < 5) {
66 error (__FILE__ ": import size less than 5 words: %d", size);
67 return 0;
69 if (nvars && size < 6) {
70 error (__FILE__ ": import size less than 6 words: %d", size);
71 return 0;
73 vaddr += size << 2;
74 offset += size << 2;
76 if (vaddr != info->impvaddrbtm) {
77 error (__FILE__ ": invalid imports boundary");
78 return 0;
81 return 1;
84 static
85 int check_module_import (struct prx *p, uint32 index)
87 struct prx_import *imp = &p->modinfo->imports[index];
89 if (!prx_inside_strprogfile (p->programs, imp->namevaddr)) {
90 error (__FILE__ ": import name not inside first program");
91 return 0;
94 if (!imp->nfuncs && !imp->nvars) {
95 error (__FILE__ ": no functions or variables imported");
96 return 0;
99 if (!prx_inside_progfile (p->programs, imp->funcsvaddr, 8 * imp->nfuncs)) {
100 error (__FILE__ ": functions not inside the first program");
101 return 0;
104 if (!prx_inside_progfile (p->programs, imp->nidsvaddr, 4 * imp->nfuncs)) {
105 error (__FILE__ ": nids not inside the first program");
106 return 0;
109 if (imp->nvars) {
110 if (!prx_inside_progfile (p->programs, imp->varsvaddr, 8 * imp->nvars)) {
111 error (__FILE__ ": variables not inside first program");
112 return 0;
117 return 1;
120 static
121 int check_module_export (struct prx *p, uint32 index)
123 struct prx_export *exp = &p->modinfo->exports[index];
125 if (!prx_inside_strprogfile (p->programs, exp->namevaddr)) {
126 error (__FILE__ ": export name not inside first program");
127 return 0;
130 if (!exp->nfuncs && !exp->nvars) {
131 error (__FILE__ ": no functions or variables exported");
132 return 0;
135 if (!prx_inside_progfile (p->programs, exp->expvaddr, 8 * (exp->nfuncs + exp->nvars))) {
136 error (__FILE__ ": functions and variables not inside the first program");
137 return 0;
140 return 1;
145 static
146 int load_module_import (struct prx *p, struct prx_import *imp)
148 uint32 i, offset;
149 if (imp->nfuncs) {
150 imp->funcs = (struct prx_function *) xmalloc (imp->nfuncs * sizeof (struct prx_function));
151 offset = prx_translate (p, imp->nidsvaddr);
152 for (i = 0; i < imp->nfuncs; i++) {
153 struct prx_function *f = &imp->funcs[i];
154 f->nid = read_uint32_le (&p->data[offset + 4 * i]);
155 f->vaddr = imp->funcsvaddr + 8 * i;
156 f->libname = imp->name;
157 f->name = NULL;
158 f->numargs = -1;
159 f->pfunc = NULL;
163 if (imp->nvars) {
164 imp->vars = (struct prx_variable *) xmalloc (imp->nvars * sizeof (struct prx_variable));
165 offset = prx_translate (p, imp->varsvaddr);
166 for (i = 0; i < imp->nvars; i++) {
167 struct prx_variable *v = &imp->vars[i];
168 v->nid = read_uint32_le (&p->data[offset + 8 * i + 4]);
169 v->vaddr = read_uint32_le (&p->data[offset + 8 * i]);
170 v->libname = imp->name;
171 v->name = NULL;
174 return 1;
177 static
178 int load_module_imports (struct prx *p)
180 uint32 i = 0, offset;
181 struct prx_modinfo *info = p->modinfo;
182 if (!info->impvaddr) return 1;
184 info->imports = (struct prx_import *) xmalloc (info->numimports * sizeof (struct prx_import));
185 memset (info->imports, 0, info->numimports * sizeof (struct prx_import));
187 offset = prx_translate (p, info->impvaddr);
188 for (i = 0; i < info->numimports; i++) {
189 struct prx_import *imp = &info->imports[i];
190 imp->namevaddr = read_uint32_le (&p->data[offset]);
191 imp->flags = read_uint32_le (&p->data[offset+4]);
192 imp->size = p->data[offset+8];
193 imp->nvars = p->data[offset+9];
194 imp->nfuncs = read_uint16_le (&p->data[offset+10]);
195 imp->nidsvaddr = read_uint32_le (&p->data[offset+12]);
196 imp->funcsvaddr = read_uint32_le (&p->data[offset+16]);
197 if (imp->nvars) imp->varsvaddr = read_uint32_le (&p->data[offset+20]);
199 if (!check_module_import (p, i)) return 0;
201 if (imp->namevaddr)
202 imp->name = (const char *) &p->data[prx_translate (p, imp->namevaddr)];
203 else
204 imp->name = NULL;
206 if (!load_module_import (p, imp)) return 0;
207 offset += imp->size << 2;
209 return 1;
212 static
213 const char *resolve_syslib_nid (uint32 nid)
215 switch (nid) {
216 case 0xd3744be0: return "module_bootstart";
217 case 0x2f064fa6: return "module_reboot_before";
218 case 0xadf12745: return "module_reboot_phase";
219 case 0xd632acdb: return "module_start";
220 case 0xcee8593c: return "module_stop";
221 case 0xf01d73a7: return "module_info";
222 case 0x0f7c276c: return "module_start_thread_parameter";
223 case 0xcf0cc697: return "module_stop_thread_parameter";
225 return NULL;
228 static
229 int load_module_export (struct prx *p, struct prx_export *exp)
231 uint32 i, offset, disp;
232 offset = prx_translate (p, exp->expvaddr);
233 disp = 4 * (exp->nfuncs + exp->nvars);
234 if (exp->nfuncs) {
235 exp->funcs = (struct prx_function *) xmalloc (exp->nfuncs * sizeof (struct prx_function));
236 for (i = 0; i < exp->nfuncs; i++) {
237 struct prx_function *f = &exp->funcs[i];
238 f->vaddr = read_uint32_le (&p->data[offset + disp]);
239 f->nid = read_uint32_le (&p->data[offset]);
240 f->name = NULL;
241 f->libname = exp->name;
242 f->numargs = -1;
243 f->pfunc = NULL;
244 offset += 4;
245 if (exp->namevaddr == 0) {
246 f->name = resolve_syslib_nid (f->nid);
251 if (exp->nvars) {
252 exp->vars = (struct prx_variable *) xmalloc (exp->nvars * sizeof (struct prx_variable));
253 for (i = 0; i < exp->nvars; i++) {
254 struct prx_variable *v = &exp->vars[i];
255 v->vaddr = read_uint32_le (&p->data[offset + disp]);
256 v->nid = read_uint32_le (&p->data[offset]);
257 v->name = NULL;
258 v->libname = exp->name;
259 offset += 4;
260 if (exp->namevaddr == 0) {
261 v->name = resolve_syslib_nid (v->nid);
265 return 1;
268 static
269 int load_module_exports (struct prx *p)
271 uint32 i = 0, offset;
272 struct prx_modinfo *info = p->modinfo;
273 if (!info->expvaddr) return 1;
275 info->exports = (struct prx_export *) xmalloc (info->numexports * sizeof (struct prx_export));
276 memset (info->exports, 0, info->numexports * sizeof (struct prx_export));
278 offset = prx_translate (p, info->expvaddr);
279 for (i = 0; i < info->numexports; i++) {
280 struct prx_export *exp = &info->exports[i];
281 exp->namevaddr = read_uint32_le (&p->data[offset]);
282 exp->flags = read_uint32_le (&p->data[offset+4]);
283 exp->size = p->data[offset+8];
284 exp->nvars = p->data[offset+9];
285 exp->nfuncs = read_uint16_le (&p->data[offset+10]);
286 exp->expvaddr = read_uint32_le (&p->data[offset+12]);
288 if (!check_module_export (p, i)) return 0;
290 if (exp->namevaddr)
291 exp->name = (const char *) &p->data[prx_translate (p, exp->namevaddr)];
292 else
293 exp->name = "syslib";
295 if (!load_module_export (p, exp)) return 0;
296 offset += exp->size << 2;
298 return 1;
301 int load_module_info (struct prx *p)
303 struct prx_modinfo *info;
304 uint32 offset;
305 p->modinfo = NULL;
306 if (p->phnum > 0)
307 offset = p->programs[0].paddr & 0x7FFFFFFF;
308 else {
309 error (__FILE__ ": can't find module info for PRX");
310 return 0;
313 info = (struct prx_modinfo *) xmalloc (sizeof (struct prx_modinfo));
314 p->modinfo = info;
316 info->attributes = read_uint16_le (&p->data[offset]);
317 info->version = read_uint16_le (&p->data[offset+2]);
318 info->name = (const char *) &p->data[offset+4];
319 info->gp = read_uint32_le (&p->data[offset+32]);
320 info->expvaddr = read_uint32_le (&p->data[offset+36]);
321 info->expvaddrbtm = read_uint32_le (&p->data[offset+40]);
322 info->impvaddr = read_uint32_le (&p->data[offset+44]);
323 info->impvaddrbtm = read_uint32_le (&p->data[offset+48]);
325 info->imports = NULL;
326 info->exports = NULL;
328 if (!check_module_info (p)) return 0;
330 if (!load_module_imports (p)) return 0;
331 if (!load_module_exports (p)) return 0;
333 return 1;
337 static
338 void free_module_import (struct prx_import *imp)
340 if (imp->funcs) free (imp->funcs);
341 if (imp->vars) free (imp->vars);
342 imp->funcs = NULL;
343 imp->vars = NULL;
346 static
347 void free_module_imports (struct prx *p)
349 if (!p->modinfo) return;
350 if (p->modinfo->imports) {
351 uint32 i;
352 for (i = 0; i < p->modinfo->numimports; i++)
353 free_module_import (&p->modinfo->imports[i]);
354 free (p->modinfo->imports);
356 p->modinfo->imports = NULL;
359 static
360 void free_module_export (struct prx_export *exp)
362 if (exp->funcs) free (exp->funcs);
363 if (exp->vars) free (exp->vars);
364 exp->funcs = NULL;
365 exp->vars = NULL;
368 static
369 void free_module_exports (struct prx *p)
371 if (!p->modinfo) return;
372 if (p->modinfo->exports) {
373 uint32 i;
374 for (i = 0; i < p->modinfo->numexports; i++)
375 free_module_export (&p->modinfo->exports[i]);
376 free (p->modinfo->exports);
378 p->modinfo->imports = NULL;
381 void free_module_info (struct prx *p)
383 free_module_imports (p);
384 free_module_exports (p);
385 if (p->modinfo)
386 free (p->modinfo);
387 p->modinfo = NULL;
391 static
392 void print_module_imports (struct prx *p)
394 uint32 idx, i;
395 struct prx_modinfo *info = p->modinfo;
396 report ("\nImports:\n");
397 for (idx = 0; idx < info->numimports; idx++) {
398 struct prx_import *imp = &info->imports[idx];
399 report (" %s\n", imp->name);
401 report (" Flags: 0x%08X\n", imp->flags);
402 report (" Size: %6d\n", imp->size);
403 report (" Num Variables: %6d\n", imp->nvars);
404 report (" Num Functions: %6d\n", imp->nfuncs);
405 report (" Nids: 0x%08X\n", imp->nidsvaddr);
406 report (" Functions: 0x%08X\n", imp->funcsvaddr);
408 for (i = 0; i < imp->nfuncs; i++) {
409 struct prx_function *f = &imp->funcs[i];
410 report (" NID: 0x%08X VADDR: 0x%08X", f->nid, f->vaddr);
411 if (f->name)
412 report (" NAME: %s", f->name);
413 report ("\n");
415 if (imp->nvars) {
416 report (" Variables: 0x%08X\n", imp->varsvaddr);
417 for (i = 0; i < imp->nvars; i++) {
418 struct prx_variable *v = &imp->vars[i];
419 report (" NID: 0x%08X VADDR: 0x%08X", v->nid, v->vaddr);
420 if (v->name)
421 report (" NAME: %s", v->name);
422 report ("\n");
426 report ("\n");
430 static
431 void print_module_exports (struct prx *p)
433 uint32 idx, i;
434 struct prx_modinfo *info = p->modinfo;
435 report ("\nExports:\n");
436 for (idx = 0; idx < info->numexports; idx++) {
437 struct prx_export *exp = &info->exports[idx];
438 report (" %s\n", exp->name);
440 report (" Flags: 0x%08X\n", exp->flags);
441 report (" Size: %6d\n", exp->size);
442 report (" Num Variables: %6d\n", exp->nvars);
443 report (" Num Functions: %6d\n", exp->nfuncs);
444 report (" Exports: 0x%08X\n", exp->expvaddr);
445 if (exp->nfuncs) {
446 report (" Functions:\n");
447 for (i = 0; i < exp->nfuncs; i++) {
448 struct prx_function *f = &exp->funcs[i];
449 report (" NID: 0x%08X VADDR: 0x%08X", f->nid, f->vaddr);
450 if (f->name)
451 report (" NAME: %s", f->name);
452 report ("\n");
455 if (exp->nvars) {
456 report (" Variables:\n");
457 for (i = 0; i < exp->nvars; i++) {
458 struct prx_variable *v = &exp->vars[i];
459 report (" NID: 0x%08X VADDR: 0x%08X", v->nid, v->vaddr);
460 if (v->name)
461 report (" NAME: %s", v->name);
462 report ("\n");
465 report ("\n");
469 void print_module_info (struct prx *p)
471 struct prx_modinfo *info = p->modinfo;
472 if (!info) return;
474 report ("\nModule info:\n");
475 report (" Name: %31s\n", info->name);
476 report (" Attributes: 0x%04X\n", info->attributes);
477 report (" Version: 0x%04X\n", info->version);
478 report (" GP: 0x%08X\n", info->gp);
479 report (" Library entry: 0x%08X\n", info->expvaddr);
480 report (" Library entry bottom: 0x%08X\n", info->expvaddrbtm);
481 report (" Library stubs: 0x%08X\n", info->impvaddr);
482 report (" Library stubs bottom: 0x%08X\n", info->impvaddrbtm);
484 print_module_imports (p);
485 print_module_exports (p);
489 void prx_resolve_nids (struct prx *p, struct nidstable *nids)
491 uint32 i, j;
492 struct nidinfo *ninfo;
493 struct prx_modinfo *info = p->modinfo;
495 for (i = 0; i < info->numimports; i++) {
496 struct prx_import *imp = &info->imports[i];
497 for (j = 0; j < imp->nfuncs; j++) {
498 struct prx_function *f = &imp->funcs[j];
499 ninfo = nids_find (nids, imp->name, f->nid);
500 if (ninfo) {
501 f->name = ninfo->name;
502 f->numargs = ninfo->numargs;
505 for (j = 0; j < imp->nvars; j++) {
506 struct prx_variable *v = &imp->vars[j];
507 ninfo = nids_find (nids, imp->name, v->nid);
508 if (ninfo) {
509 v->name = ninfo->name;
514 for (i = 0; i < info->numexports; i++) {
515 struct prx_export *exp = &info->exports[i];
516 for (j = 0; j < exp->nfuncs; j++) {
517 struct prx_function *f = &exp->funcs[j];
518 ninfo = nids_find (nids, exp->name, f->nid);
519 if (ninfo) {
520 f->name = ninfo->name;
521 f->numargs = ninfo->numargs;
524 for (j = 0; j < exp->nvars; j++) {
525 struct prx_variable *v = &exp->vars[j];
526 ninfo = nids_find (nids, exp->name, v->nid);
527 if (ninfo) {
528 v->name = ninfo->name;