Ficando cada vez melhor
[pspdecompiler.git] / module.c
blob43d04fe4af79ba245ec9ad43952eb469baa25806
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;
159 if (imp->nvars) {
160 imp->vars = (struct prx_variable *) xmalloc (imp->nvars * sizeof (struct prx_variable));
161 offset = prx_translate (p, imp->varsvaddr);
162 for (i = 0; i < imp->nvars; i++) {
163 struct prx_variable *v = &imp->vars[i];
164 v->nid = read_uint32_le (&p->data[offset + 8 * i + 4]);
165 v->vaddr = read_uint32_le (&p->data[offset + 8 * i]);
166 v->libname = imp->name;
167 v->name = NULL;
170 return 1;
173 static
174 int load_module_imports (struct prx *p)
176 uint32 i = 0, offset;
177 struct prx_modinfo *info = p->modinfo;
178 if (!info->impvaddr) return 1;
180 info->imports = (struct prx_import *) xmalloc (info->numimports * sizeof (struct prx_import));
181 memset (info->imports, 0, info->numimports * sizeof (struct prx_import));
183 offset = prx_translate (p, info->impvaddr);
184 for (i = 0; i < info->numimports; i++) {
185 struct prx_import *imp = &info->imports[i];
186 imp->namevaddr = read_uint32_le (&p->data[offset]);
187 imp->flags = read_uint32_le (&p->data[offset+4]);
188 imp->size = p->data[offset+8];
189 imp->nvars = p->data[offset+9];
190 imp->nfuncs = read_uint16_le (&p->data[offset+10]);
191 imp->nidsvaddr = read_uint32_le (&p->data[offset+12]);
192 imp->funcsvaddr = read_uint32_le (&p->data[offset+16]);
193 if (imp->nvars) imp->varsvaddr = read_uint32_le (&p->data[offset+20]);
195 if (!check_module_import (p, i)) return 0;
197 if (imp->namevaddr)
198 imp->name = (const char *) &p->data[prx_translate (p, imp->namevaddr)];
199 else
200 imp->name = NULL;
202 if (!load_module_import (p, imp)) return 0;
203 offset += imp->size << 2;
205 return 1;
208 static
209 const char *resolve_syslib_nid (uint32 nid)
211 switch (nid) {
212 case 0xd3744be0: return "module_bootstart";
213 case 0x2f064fa6: return "module_reboot_before";
214 case 0xadf12745: return "module_reboot_phase";
215 case 0xd632acdb: return "module_start";
216 case 0xcee8593c: return "module_stop";
217 case 0xf01d73a7: return "module_info";
218 case 0x0f7c276c: return "module_start_thread_parameter";
219 case 0xcf0cc697: return "module_stop_thread_parameter";
221 return NULL;
224 static
225 int load_module_export (struct prx *p, struct prx_export *exp)
227 uint32 i, offset, disp;
228 offset = prx_translate (p, exp->expvaddr);
229 disp = 4 * (exp->nfuncs + exp->nvars);
230 if (exp->nfuncs) {
231 exp->funcs = (struct prx_function *) xmalloc (exp->nfuncs * sizeof (struct prx_function));
232 for (i = 0; i < exp->nfuncs; i++) {
233 struct prx_function *f = &exp->funcs[i];
234 f->vaddr = read_uint32_le (&p->data[offset + disp]);
235 f->nid = read_uint32_le (&p->data[offset]);
236 f->name = NULL;
237 f->libname = exp->name;
238 f->numargs = -1;
239 offset += 4;
240 if (exp->namevaddr == 0) {
241 f->name = resolve_syslib_nid (f->nid);
246 if (exp->nvars) {
247 exp->vars = (struct prx_variable *) xmalloc (exp->nvars * sizeof (struct prx_variable));
248 for (i = 0; i < exp->nvars; i++) {
249 struct prx_variable *v = &exp->vars[i];
250 v->vaddr = read_uint32_le (&p->data[offset + disp]);
251 v->nid = read_uint32_le (&p->data[offset]);
252 v->name = NULL;
253 v->libname = exp->name;
254 offset += 4;
255 if (exp->namevaddr == 0) {
256 v->name = resolve_syslib_nid (v->nid);
260 return 1;
263 static
264 int load_module_exports (struct prx *p)
266 uint32 i = 0, offset;
267 struct prx_modinfo *info = p->modinfo;
268 if (!info->expvaddr) return 1;
270 info->exports = (struct prx_export *) xmalloc (info->numexports * sizeof (struct prx_export));
271 memset (info->exports, 0, info->numexports * sizeof (struct prx_export));
273 offset = prx_translate (p, info->expvaddr);
274 for (i = 0; i < info->numexports; i++) {
275 struct prx_export *exp = &info->exports[i];
276 exp->namevaddr = read_uint32_le (&p->data[offset]);
277 exp->flags = read_uint32_le (&p->data[offset+4]);
278 exp->size = p->data[offset+8];
279 exp->nvars = p->data[offset+9];
280 exp->nfuncs = read_uint16_le (&p->data[offset+10]);
281 exp->expvaddr = read_uint32_le (&p->data[offset+12]);
283 if (!check_module_export (p, i)) return 0;
285 if (exp->namevaddr)
286 exp->name = (const char *) &p->data[prx_translate (p, exp->namevaddr)];
287 else
288 exp->name = "syslib";
290 if (!load_module_export (p, exp)) return 0;
291 offset += exp->size << 2;
293 return 1;
296 int load_module_info (struct prx *p)
298 struct prx_modinfo *info;
299 uint32 offset;
300 p->modinfo = NULL;
301 if (p->phnum > 0)
302 offset = p->programs[0].paddr & 0x7FFFFFFF;
303 else {
304 error (__FILE__ ": can't find module info for PRX");
305 return 0;
308 info = (struct prx_modinfo *) xmalloc (sizeof (struct prx_modinfo));
309 p->modinfo = info;
311 info->attributes = read_uint16_le (&p->data[offset]);
312 info->version = read_uint16_le (&p->data[offset+2]);
313 info->name = (const char *) &p->data[offset+4];
314 info->gp = read_uint32_le (&p->data[offset+32]);
315 info->expvaddr = read_uint32_le (&p->data[offset+36]);
316 info->expvaddrbtm = read_uint32_le (&p->data[offset+40]);
317 info->impvaddr = read_uint32_le (&p->data[offset+44]);
318 info->impvaddrbtm = read_uint32_le (&p->data[offset+48]);
320 info->imports = NULL;
321 info->exports = NULL;
323 if (!check_module_info (p)) return 0;
325 if (!load_module_imports (p)) return 0;
326 if (!load_module_exports (p)) return 0;
328 return 1;
332 static
333 void free_module_import (struct prx_import *imp)
335 if (imp->funcs) free (imp->funcs);
336 if (imp->vars) free (imp->vars);
337 imp->funcs = NULL;
338 imp->vars = NULL;
341 static
342 void free_module_imports (struct prx *p)
344 if (!p->modinfo) return;
345 if (p->modinfo->imports) {
346 uint32 i;
347 for (i = 0; i < p->modinfo->numimports; i++)
348 free_module_import (&p->modinfo->imports[i]);
349 free (p->modinfo->imports);
351 p->modinfo->imports = NULL;
354 static
355 void free_module_export (struct prx_export *exp)
357 if (exp->funcs) free (exp->funcs);
358 if (exp->vars) free (exp->vars);
359 exp->funcs = NULL;
360 exp->vars = NULL;
363 static
364 void free_module_exports (struct prx *p)
366 if (!p->modinfo) return;
367 if (p->modinfo->exports) {
368 uint32 i;
369 for (i = 0; i < p->modinfo->numexports; i++)
370 free_module_export (&p->modinfo->exports[i]);
371 free (p->modinfo->exports);
373 p->modinfo->imports = NULL;
376 void free_module_info (struct prx *p)
378 free_module_imports (p);
379 free_module_exports (p);
380 if (p->modinfo)
381 free (p->modinfo);
382 p->modinfo = NULL;
386 static
387 void print_module_imports (struct prx *p)
389 uint32 idx, i;
390 struct prx_modinfo *info = p->modinfo;
391 report ("\nImports:\n");
392 for (idx = 0; idx < info->numimports; idx++) {
393 struct prx_import *imp = &info->imports[idx];
394 report (" %s\n", imp->name);
396 report (" Flags: 0x%08X\n", imp->flags);
397 report (" Size: %6d\n", imp->size);
398 report (" Num Variables: %6d\n", imp->nvars);
399 report (" Num Functions: %6d\n", imp->nfuncs);
400 report (" Nids: 0x%08X\n", imp->nidsvaddr);
401 report (" Functions: 0x%08X\n", imp->funcsvaddr);
403 for (i = 0; i < imp->nfuncs; i++) {
404 struct prx_function *f = &imp->funcs[i];
405 report (" NID: 0x%08X VADDR: 0x%08X", f->nid, f->vaddr);
406 if (f->name)
407 report (" NAME: %s", f->name);
408 report ("\n");
410 if (imp->nvars) {
411 report (" Variables: 0x%08X\n", imp->varsvaddr);
412 for (i = 0; i < imp->nvars; i++) {
413 struct prx_variable *v = &imp->vars[i];
414 report (" NID: 0x%08X VADDR: 0x%08X", v->nid, v->vaddr);
415 if (v->name)
416 report (" NAME: %s", v->name);
417 report ("\n");
421 report ("\n");
425 static
426 void print_module_exports (struct prx *p)
428 uint32 idx, i;
429 struct prx_modinfo *info = p->modinfo;
430 report ("\nExports:\n");
431 for (idx = 0; idx < info->numexports; idx++) {
432 struct prx_export *exp = &info->exports[idx];
433 report (" %s\n", exp->name);
435 report (" Flags: 0x%08X\n", exp->flags);
436 report (" Size: %6d\n", exp->size);
437 report (" Num Variables: %6d\n", exp->nvars);
438 report (" Num Functions: %6d\n", exp->nfuncs);
439 report (" Exports: 0x%08X\n", exp->expvaddr);
440 if (exp->nfuncs) {
441 report (" Functions:\n");
442 for (i = 0; i < exp->nfuncs; i++) {
443 struct prx_function *f = &exp->funcs[i];
444 report (" NID: 0x%08X VADDR: 0x%08X", f->nid, f->vaddr);
445 if (f->name)
446 report (" NAME: %s", f->name);
447 report ("\n");
450 if (exp->nvars) {
451 report (" Variables:\n");
452 for (i = 0; i < exp->nvars; i++) {
453 struct prx_variable *v = &exp->vars[i];
454 report (" NID: 0x%08X VADDR: 0x%08X", v->nid, v->vaddr);
455 if (v->name)
456 report (" NAME: %s", v->name);
457 report ("\n");
460 report ("\n");
464 void print_module_info (struct prx *p)
466 struct prx_modinfo *info = p->modinfo;
467 if (!info) return;
469 report ("\nModule info:\n");
470 report (" Name: %31s\n", info->name);
471 report (" Attributes: 0x%04X\n", info->attributes);
472 report (" Version: 0x%04X\n", info->version);
473 report (" GP: 0x%08X\n", info->gp);
474 report (" Library entry: 0x%08X\n", info->expvaddr);
475 report (" Library entry bottom: 0x%08X\n", info->expvaddrbtm);
476 report (" Library stubs: 0x%08X\n", info->impvaddr);
477 report (" Library stubs bottom: 0x%08X\n", info->impvaddrbtm);
479 print_module_imports (p);
480 print_module_exports (p);
484 void prx_resolve_nids (struct prx *p, struct nidstable *nids)
486 uint32 i, j;
487 struct nidinfo *ninfo;
488 struct prx_modinfo *info = p->modinfo;
490 for (i = 0; i < info->numimports; i++) {
491 struct prx_import *imp = &info->imports[i];
492 for (j = 0; j < imp->nfuncs; j++) {
493 struct prx_function *f = &imp->funcs[j];
494 ninfo = nids_find (nids, imp->name, f->nid);
495 if (ninfo) {
496 f->name = ninfo->name;
497 f->numargs = ninfo->numargs;
500 for (j = 0; j < imp->nvars; j++) {
501 struct prx_variable *v = &imp->vars[j];
502 ninfo = nids_find (nids, imp->name, v->nid);
503 if (ninfo) {
504 v->name = ninfo->name;
509 for (i = 0; i < info->numexports; i++) {
510 struct prx_export *exp = &info->exports[i];
511 for (j = 0; j < exp->nfuncs; j++) {
512 struct prx_function *f = &exp->funcs[j];
513 ninfo = nids_find (nids, exp->name, f->nid);
514 if (ninfo) {
515 f->name = ninfo->name;
516 f->numargs = ninfo->numargs;
519 for (j = 0; j < exp->nvars; j++) {
520 struct prx_variable *v = &exp->vars[j];
521 ninfo = nids_find (nids, exp->name, v->nid);
522 if (ninfo) {
523 v->name = ninfo->name;