Passo intermediario, ainda falta um longo caminho
[pspdecompiler.git] / module.c
blob6b68e3d2dd9eaf7ac2f3afcf77bd33ef5cd919a9
2 #include <stdlib.h>
3 #include <string.h>
5 #include "prx.h"
6 #include "utils.h"
8 static
9 int check_module_info (struct prx *p)
11 struct prx_modinfo *info = p->modinfo;
12 uint32 vaddr, offset;
14 if (info->name[27]) {
15 error (__FILE__ ": module name is not null terminated\n");
16 return 0;
19 if (info->expvaddr) {
20 if (info->expvaddr > info->expvaddrbtm) {
21 error (__FILE__ ": exports bottom is above top (0x%08X - 0x%08X)", info->expvaddr, info->expvaddrbtm);
22 return 0;
24 if (!prx_inside_progfile (p->programs, info->expvaddr, info->expvaddrbtm - info->expvaddr)) {
25 error (__FILE__ ": exports not inside the first program (0x%08X - 0x%08X)", info->expvaddr, info->expvaddrbtm);
26 return 0;
28 info->numexports = 0;
29 offset = prx_translate (p, info->expvaddr);
30 for (vaddr = info->expvaddr; vaddr < info->expvaddrbtm; info->numexports++) {
31 uint32 size;
32 size = p->data[offset+8];
33 if (size < 4) {
34 error (__FILE__ ": export size less than 4 words: %d", size);
35 return 0;
37 vaddr += size << 2;
38 offset += size << 2;
40 if (vaddr != info->expvaddrbtm) {
41 error (__FILE__ ": invalid exports boundary");
42 return 0;
46 if (info->impvaddr) {
47 if (info->impvaddr > info->impvaddrbtm) {
48 error (__FILE__ ": imports bottom is above top (0x%08X - 0x%08X)", info->impvaddr, info->impvaddrbtm);
49 return 0;
51 if (!prx_inside_progfile (p->programs, info->impvaddr, info->impvaddrbtm - info->impvaddr)) {
52 error (__FILE__ ": imports not inside the first program (0x%08X - 0x%08X)", info->impvaddr, info->impvaddrbtm);
53 return 0;
55 info->numimports = 0;
56 offset = prx_translate (p, info->impvaddr);
57 for (vaddr = info->impvaddr; vaddr < info->impvaddrbtm; info->numimports++) {
58 uint32 size;
59 uint8 nvars;
60 size = p->data[offset+8];
61 nvars = p->data[offset+9];
62 if (size < 5) {
63 error (__FILE__ ": import size less than 5 words: %d", size);
64 return 0;
66 if (nvars && size < 6) {
67 error (__FILE__ ": import size less than 6 words: %d", size);
68 return 0;
70 vaddr += size << 2;
71 offset += size << 2;
73 if (vaddr != info->impvaddrbtm) {
74 error (__FILE__ ": invalid imports boundary");
75 return 0;
78 return 1;
81 static
82 int check_module_import (struct prx *p, uint32 index)
84 struct prx_import *imp = &p->modinfo->imports[index];
86 if (!prx_inside_strprogfile (p->programs, imp->namevaddr)) {
87 error (__FILE__ ": import name not inside first program");
88 return 0;
91 if (!imp->nfuncs && !imp->nvars) {
92 error (__FILE__ ": no functions or variables imported");
93 return 0;
96 if (!prx_inside_progfile (p->programs, imp->funcsvaddr, 8 * imp->nfuncs)) {
97 error (__FILE__ ": functions not inside the first program");
98 return 0;
101 if (!prx_inside_progfile (p->programs, imp->nidsvaddr, 4 * imp->nfuncs)) {
102 error (__FILE__ ": nids not inside the first program");
103 return 0;
106 if (imp->nvars) {
107 if (!prx_inside_progfile (p->programs, imp->varsvaddr, 8 * imp->nvars)) {
108 error (__FILE__ ": variables not inside first program");
109 return 0;
114 return 1;
117 static
118 int check_module_export (struct prx *p, uint32 index)
120 struct prx_export *exp = &p->modinfo->exports[index];
122 if (!prx_inside_strprogfile (p->programs, exp->namevaddr)) {
123 error (__FILE__ ": export name not inside first program");
124 return 0;
127 if (!exp->nfuncs && !exp->nvars) {
128 error (__FILE__ ": no functions or variables exported");
129 return 0;
132 if (!prx_inside_progfile (p->programs, exp->expvaddr, 8 * (exp->nfuncs + exp->nvars))) {
133 error (__FILE__ ": functions and variables not inside the first program");
134 return 0;
137 return 1;
142 static
143 int load_module_import (struct prx *p, struct prx_import *imp)
145 uint32 i, offset;
146 if (imp->nfuncs) {
147 imp->funcs = (struct prx_function *) xmalloc (imp->nfuncs * sizeof (struct prx_function));
148 offset = prx_translate (p, imp->nidsvaddr);
149 for (i = 0; i < imp->nfuncs; i++) {
150 struct prx_function *f = &imp->funcs[i];
151 f->nid = read_uint32_le (&p->data[offset + 4 * i]);
152 f->vaddr = imp->funcsvaddr + 8 * i;
153 f->libname = imp->name;
154 f->name = NULL;
155 f->numargs = -1;
156 f->pfunc = NULL;
160 if (imp->nvars) {
161 imp->vars = (struct prx_variable *) xmalloc (imp->nvars * sizeof (struct prx_variable));
162 offset = prx_translate (p, imp->varsvaddr);
163 for (i = 0; i < imp->nvars; i++) {
164 struct prx_variable *v = &imp->vars[i];
165 v->nid = read_uint32_le (&p->data[offset + 8 * i + 4]);
166 v->vaddr = read_uint32_le (&p->data[offset + 8 * i]);
167 v->libname = imp->name;
168 v->name = NULL;
171 return 1;
174 static
175 int load_module_imports (struct prx *p)
177 uint32 i = 0, offset;
178 struct prx_modinfo *info = p->modinfo;
179 if (!info->impvaddr) return 1;
181 info->imports = (struct prx_import *) xmalloc (info->numimports * sizeof (struct prx_import));
182 memset (info->imports, 0, info->numimports * sizeof (struct prx_import));
184 offset = prx_translate (p, info->impvaddr);
185 for (i = 0; i < info->numimports; i++) {
186 struct prx_import *imp = &info->imports[i];
187 imp->namevaddr = read_uint32_le (&p->data[offset]);
188 imp->flags = read_uint32_le (&p->data[offset+4]);
189 imp->size = p->data[offset+8];
190 imp->nvars = p->data[offset+9];
191 imp->nfuncs = read_uint16_le (&p->data[offset+10]);
192 imp->nidsvaddr = read_uint32_le (&p->data[offset+12]);
193 imp->funcsvaddr = read_uint32_le (&p->data[offset+16]);
194 if (imp->nvars) imp->varsvaddr = read_uint32_le (&p->data[offset+20]);
196 if (!check_module_import (p, i)) return 0;
198 if (imp->namevaddr)
199 imp->name = (const char *) &p->data[prx_translate (p, imp->namevaddr)];
200 else
201 imp->name = NULL;
203 if (!load_module_import (p, imp)) return 0;
204 offset += imp->size << 2;
206 return 1;
209 static
210 const char *resolve_syslib_nid (uint32 nid)
212 switch (nid) {
213 case 0xd3744be0: return "module_bootstart";
214 case 0x2f064fa6: return "module_reboot_before";
215 case 0xadf12745: return "module_reboot_phase";
216 case 0xd632acdb: return "module_start";
217 case 0xcee8593c: return "module_stop";
218 case 0xf01d73a7: return "module_info";
219 case 0x0f7c276c: return "module_start_thread_parameter";
220 case 0xcf0cc697: return "module_stop_thread_parameter";
222 return NULL;
225 static
226 int load_module_export (struct prx *p, struct prx_export *exp)
228 uint32 i, offset, disp;
229 offset = prx_translate (p, exp->expvaddr);
230 disp = 4 * (exp->nfuncs + exp->nvars);
231 if (exp->nfuncs) {
232 exp->funcs = (struct prx_function *) xmalloc (exp->nfuncs * sizeof (struct prx_function));
233 for (i = 0; i < exp->nfuncs; i++) {
234 struct prx_function *f = &exp->funcs[i];
235 f->vaddr = read_uint32_le (&p->data[offset + disp]);
236 f->nid = read_uint32_le (&p->data[offset]);
237 f->name = NULL;
238 f->libname = exp->name;
239 f->numargs = -1;
240 f->pfunc = NULL;
241 offset += 4;
242 if (exp->namevaddr == 0) {
243 f->name = resolve_syslib_nid (f->nid);
248 if (exp->nvars) {
249 exp->vars = (struct prx_variable *) xmalloc (exp->nvars * sizeof (struct prx_variable));
250 for (i = 0; i < exp->nvars; i++) {
251 struct prx_variable *v = &exp->vars[i];
252 v->vaddr = read_uint32_le (&p->data[offset + disp]);
253 v->nid = read_uint32_le (&p->data[offset]);
254 v->name = NULL;
255 v->libname = exp->name;
256 offset += 4;
257 if (exp->namevaddr == 0) {
258 v->name = resolve_syslib_nid (v->nid);
262 return 1;
265 static
266 int load_module_exports (struct prx *p)
268 uint32 i = 0, offset;
269 struct prx_modinfo *info = p->modinfo;
270 if (!info->expvaddr) return 1;
272 info->exports = (struct prx_export *) xmalloc (info->numexports * sizeof (struct prx_export));
273 memset (info->exports, 0, info->numexports * sizeof (struct prx_export));
275 offset = prx_translate (p, info->expvaddr);
276 for (i = 0; i < info->numexports; i++) {
277 struct prx_export *exp = &info->exports[i];
278 exp->namevaddr = read_uint32_le (&p->data[offset]);
279 exp->flags = read_uint32_le (&p->data[offset+4]);
280 exp->size = p->data[offset+8];
281 exp->nvars = p->data[offset+9];
282 exp->nfuncs = read_uint16_le (&p->data[offset+10]);
283 exp->expvaddr = read_uint32_le (&p->data[offset+12]);
285 if (!check_module_export (p, i)) return 0;
287 if (exp->namevaddr)
288 exp->name = (const char *) &p->data[prx_translate (p, exp->namevaddr)];
289 else
290 exp->name = "syslib";
292 if (!load_module_export (p, exp)) return 0;
293 offset += exp->size << 2;
295 return 1;
298 int load_module_info (struct prx *p)
300 struct prx_modinfo *info;
301 uint32 offset;
302 p->modinfo = NULL;
303 if (p->phnum > 0)
304 offset = p->programs[0].paddr & 0x7FFFFFFF;
305 else {
306 error (__FILE__ ": can't find module info for PRX");
307 return 0;
310 info = (struct prx_modinfo *) xmalloc (sizeof (struct prx_modinfo));
311 p->modinfo = info;
313 info->attributes = read_uint16_le (&p->data[offset]);
314 info->version = read_uint16_le (&p->data[offset+2]);
315 info->name = (const char *) &p->data[offset+4];
316 info->gp = read_uint32_le (&p->data[offset+32]);
317 info->expvaddr = read_uint32_le (&p->data[offset+36]);
318 info->expvaddrbtm = read_uint32_le (&p->data[offset+40]);
319 info->impvaddr = read_uint32_le (&p->data[offset+44]);
320 info->impvaddrbtm = read_uint32_le (&p->data[offset+48]);
322 info->imports = NULL;
323 info->exports = NULL;
325 if (!check_module_info (p)) return 0;
327 if (!load_module_imports (p)) return 0;
328 if (!load_module_exports (p)) return 0;
330 return 1;
334 static
335 void free_module_import (struct prx_import *imp)
337 if (imp->funcs) free (imp->funcs);
338 if (imp->vars) free (imp->vars);
339 imp->funcs = NULL;
340 imp->vars = NULL;
343 static
344 void free_module_imports (struct prx *p)
346 if (!p->modinfo) return;
347 if (p->modinfo->imports) {
348 uint32 i;
349 for (i = 0; i < p->modinfo->numimports; i++)
350 free_module_import (&p->modinfo->imports[i]);
351 free (p->modinfo->imports);
353 p->modinfo->imports = NULL;
356 static
357 void free_module_export (struct prx_export *exp)
359 if (exp->funcs) free (exp->funcs);
360 if (exp->vars) free (exp->vars);
361 exp->funcs = NULL;
362 exp->vars = NULL;
365 static
366 void free_module_exports (struct prx *p)
368 if (!p->modinfo) return;
369 if (p->modinfo->exports) {
370 uint32 i;
371 for (i = 0; i < p->modinfo->numexports; i++)
372 free_module_export (&p->modinfo->exports[i]);
373 free (p->modinfo->exports);
375 p->modinfo->imports = NULL;
378 void free_module_info (struct prx *p)
380 free_module_imports (p);
381 free_module_exports (p);
382 if (p->modinfo)
383 free (p->modinfo);
384 p->modinfo = NULL;
388 static
389 void print_module_imports (struct prx *p)
391 uint32 idx, i;
392 struct prx_modinfo *info = p->modinfo;
393 report ("\nImports:\n");
394 for (idx = 0; idx < info->numimports; idx++) {
395 struct prx_import *imp = &info->imports[idx];
396 report (" %s\n", imp->name);
398 report (" Flags: 0x%08X\n", imp->flags);
399 report (" Size: %6d\n", imp->size);
400 report (" Num Variables: %6d\n", imp->nvars);
401 report (" Num Functions: %6d\n", imp->nfuncs);
402 report (" Nids: 0x%08X\n", imp->nidsvaddr);
403 report (" Functions: 0x%08X\n", imp->funcsvaddr);
405 for (i = 0; i < imp->nfuncs; i++) {
406 struct prx_function *f = &imp->funcs[i];
407 report (" NID: 0x%08X VADDR: 0x%08X", f->nid, f->vaddr);
408 if (f->name)
409 report (" NAME: %s", f->name);
410 report ("\n");
412 if (imp->nvars) {
413 report (" Variables: 0x%08X\n", imp->varsvaddr);
414 for (i = 0; i < imp->nvars; i++) {
415 struct prx_variable *v = &imp->vars[i];
416 report (" NID: 0x%08X VADDR: 0x%08X", v->nid, v->vaddr);
417 if (v->name)
418 report (" NAME: %s", v->name);
419 report ("\n");
423 report ("\n");
427 static
428 void print_module_exports (struct prx *p)
430 uint32 idx, i;
431 struct prx_modinfo *info = p->modinfo;
432 report ("\nExports:\n");
433 for (idx = 0; idx < info->numexports; idx++) {
434 struct prx_export *exp = &info->exports[idx];
435 report (" %s\n", exp->name);
437 report (" Flags: 0x%08X\n", exp->flags);
438 report (" Size: %6d\n", exp->size);
439 report (" Num Variables: %6d\n", exp->nvars);
440 report (" Num Functions: %6d\n", exp->nfuncs);
441 report (" Exports: 0x%08X\n", exp->expvaddr);
442 if (exp->nfuncs) {
443 report (" Functions:\n");
444 for (i = 0; i < exp->nfuncs; i++) {
445 struct prx_function *f = &exp->funcs[i];
446 report (" NID: 0x%08X VADDR: 0x%08X", f->nid, f->vaddr);
447 if (f->name)
448 report (" NAME: %s", f->name);
449 report ("\n");
452 if (exp->nvars) {
453 report (" Variables:\n");
454 for (i = 0; i < exp->nvars; i++) {
455 struct prx_variable *v = &exp->vars[i];
456 report (" NID: 0x%08X VADDR: 0x%08X", v->nid, v->vaddr);
457 if (v->name)
458 report (" NAME: %s", v->name);
459 report ("\n");
462 report ("\n");
466 void print_module_info (struct prx *p)
468 struct prx_modinfo *info = p->modinfo;
469 if (!info) return;
471 report ("\nModule info:\n");
472 report (" Name: %31s\n", info->name);
473 report (" Attributes: 0x%04X\n", info->attributes);
474 report (" Version: 0x%04X\n", info->version);
475 report (" GP: 0x%08X\n", info->gp);
476 report (" Library entry: 0x%08X\n", info->expvaddr);
477 report (" Library entry bottom: 0x%08X\n", info->expvaddrbtm);
478 report (" Library stubs: 0x%08X\n", info->impvaddr);
479 report (" Library stubs bottom: 0x%08X\n", info->impvaddrbtm);
481 print_module_imports (p);
482 print_module_exports (p);
486 void prx_resolve_nids (struct prx *p, struct nidstable *nids)
488 uint32 i, j;
489 struct nidinfo *ninfo;
490 struct prx_modinfo *info = p->modinfo;
492 for (i = 0; i < info->numimports; i++) {
493 struct prx_import *imp = &info->imports[i];
494 for (j = 0; j < imp->nfuncs; j++) {
495 struct prx_function *f = &imp->funcs[j];
496 ninfo = nids_find (nids, imp->name, f->nid);
497 if (ninfo) {
498 f->name = ninfo->name;
499 f->numargs = ninfo->numargs;
502 for (j = 0; j < imp->nvars; j++) {
503 struct prx_variable *v = &imp->vars[j];
504 ninfo = nids_find (nids, imp->name, v->nid);
505 if (ninfo) {
506 v->name = ninfo->name;
511 for (i = 0; i < info->numexports; i++) {
512 struct prx_export *exp = &info->exports[i];
513 for (j = 0; j < exp->nfuncs; j++) {
514 struct prx_function *f = &exp->funcs[j];
515 ninfo = nids_find (nids, exp->name, f->nid);
516 if (ninfo) {
517 f->name = ninfo->name;
518 f->numargs = ninfo->numargs;
521 for (j = 0; j < exp->nvars; j++) {
522 struct prx_variable *v = &exp->vars[j];
523 ninfo = nids_find (nids, exp->name, v->nid);
524 if (ninfo) {
525 v->name = ninfo->name;