10 #define ELF_HEADER_SIZE 52
11 #define ELF_SECTION_HEADER_ENT_SIZE 40
12 #define ELF_PROGRAM_HEADER_ENT_SIZE 32
13 #define ELF_PRX_FLAGS (ELF_FLAGS_MIPS_ARCH2 | ELF_FLAGS_MACH_ALLEGREX | ELF_FLAGS_MACH_ALLEGREX)
14 #define PRX_MODULE_INFO_SIZE 52
17 static const uint8 valid_ident
[] = {
19 0x01, /* Elf class = ELFCLASS32 */
20 0x01, /* Elf data = ELFDATA2LSB */
21 0x01, /* Version = EV_CURRENT */
22 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* Padding */
26 uint32
read_uint32_le (const uint8
*bytes
)
37 uint16
read_uint16_le (const uint8
*bytes
)
46 int inside_prx (struct prx
*p
, uint32 offset
, uint32 size
)
48 if (offset
>= p
->size
|| size
> p
->size
||
49 size
> (p
->size
- offset
)) return 0;
54 int inside_progfile (struct elf_program
*program
, uint32 vaddr
, uint32 size
)
56 if (vaddr
< program
->vaddr
|| size
> program
->filesz
) return 0;
58 vaddr
-= program
->vaddr
;
59 if (vaddr
>= program
->filesz
|| (program
->filesz
- vaddr
) < size
) return 0;
64 int inside_progmem (struct elf_program
*program
, uint32 vaddr
, uint32 size
)
66 if (vaddr
< program
->vaddr
|| size
> program
->memsz
) return 0;
68 vaddr
-= program
->vaddr
;
69 if (vaddr
>= program
->memsz
|| (program
->memsz
- vaddr
) < size
) return 0;
75 int inside_strprogfile (struct elf_program
*program
, uint32 vaddr
)
77 if (vaddr
< program
->vaddr
) return 0;
79 vaddr
-= program
->vaddr
;
80 if (vaddr
>= program
->filesz
) return 0;
82 while (vaddr
< program
->filesz
) {
83 if (!program
->data
[vaddr
]) return 1;
91 int check_section_header (struct prx
*p
, uint32 index
)
93 struct elf_section
*section
= &p
->sections
[index
];
95 switch (section
->type
) {
102 if (!inside_prx (p
, section
->offset
, section
->size
)) {
103 error (__FILE__
": section is not inside ELF/PRX (section %d)", index
);
108 error (__FILE__
": invalid section type 0x$08X (section %d)", section
->type
, index
);
116 int check_program_header (struct prx
*p
, uint32 index
)
118 struct elf_program
*program
= &p
->programs
[index
];
119 if (!inside_prx (p
, program
->offset
, program
->filesz
)) {
120 error (__FILE__
": program is not inside ELF/PRX (program %d)", index
);
124 if ((index
== 0) && program
->type
!= PT_LOAD
) {
125 error (__FILE__
": first program is not of the type LOAD");
129 switch (program
->type
) {
131 if (program
->filesz
> program
->memsz
) {
132 error (__FILE__
": program file size grater than than memory size (program %d)", index
);
137 if (program
->memsz
) {
138 error (__FILE__
": program type must not loaded (program %d)", index
);
143 error (__FILE__
": invalid program type 0x$08X (program %d)", program
->type
, index
);
151 int check_relocs (struct prx
*p
)
154 struct elf_program
*offsbase
;
155 struct elf_program
*addrbase
;
156 uint32 index
, lasthi
= -1, addend
;
160 for (index
= 0; index
< p
->relocnum
; index
++) {
161 r
= &p
->relocs
[index
];
162 if (r
->offsbase
>= p
->phnum
) {
163 error (__FILE__
": invalid offset base for relocation (%d)", r
->offsbase
);
167 if (r
->addrbase
>= p
->phnum
) {
168 error (__FILE__
": invalid address base for relocation (%d)", r
->offsbase
);
172 offsbase
= &p
->programs
[r
->offsbase
];
173 addrbase
= &p
->programs
[r
->addrbase
];
175 r
->vaddr
= r
->offset
+ offsbase
->vaddr
;
176 if (!inside_progfile (offsbase
, r
->vaddr
, 4)) {
177 error (__FILE__
": relocation points to invalid address (0x%08X)", r
->vaddr
);
181 addend
= read_uint32_le (&offsbase
->data
[r
->offset
]);
187 r
->target
= (addrbase
->vaddr
& 0xF0000000) | ((addend
& 0x3FFFFFF) << 2);
188 if (!inside_progfile (addrbase
, r
->target
, 8)) {
189 error (__FILE__
": mips26 relocation to invalid address at 0x%08X (0x%08X)", r
->vaddr
, r
->target
);
195 /*error (__FILE__ ": hi16 without a matching lo16 relocation at 0x%08X (now at 0x%08X)",
196 p->relocs[lasthi].vaddr, r->vaddr);
201 r
->target
= (addend
& 0xFFFF) << 16;
205 error (__FILE__
": lo16 without matching hi16");
208 struct prx_reloc
*last
= &p
->relocs
[lasthi
];
209 enum insn_type itype
;
212 itype
= allegrex_insn_type (addend
);
213 r
->target
= addend
& 0xFFFF;
214 if (/*itype != I_ORI &&*/ (r
->target
& 0x8000)) {
215 r
->target
|= ~0xFFFF;
217 r
->target
+= last
->target
+ addrbase
->vaddr
;
218 if (!inside_progmem (addrbase
, r
->target
, 1)) {
219 error (__FILE__
": invalid hi16/lo16 reference at 0x%08X (0x%08X) (matching hi: 0x%08X)", r
->vaddr
, r
->target
, last
->vaddr
);
227 if (!inside_progmem (addrbase
, r
->target
, 1)) {
228 error (__FILE__
": invalid mips32 reference at 0x%08X (0x%08X)", r
->vaddr
, r
->target
);
241 error (__FILE__
": invalid reference type %d", r
->type
);
251 int check_module_info (struct prx
*p
)
253 struct prx_modinfo
*info
= p
->modinfo
;
254 uint32 vaddr
, offset
;
256 if (info
->name
[27]) {
257 error (__FILE__
": module name is not null terminated\n");
261 if (info
->expvaddr
) {
262 if (info
->expvaddr
> info
->expvaddrbtm
) {
263 error (__FILE__
": exports bottom is above top (0x%08X - 0x%08X)", info
->expvaddr
, info
->expvaddrbtm
);
266 if (!inside_progfile (p
->programs
, info
->expvaddr
, info
->expvaddrbtm
- info
->expvaddr
)) {
267 error (__FILE__
": exports not inside the first program (0x%08X - 0x%08X)", info
->expvaddr
, info
->expvaddrbtm
);
270 info
->numexports
= 0;
271 offset
= prx_translate (p
, info
->expvaddr
);
272 for (vaddr
= info
->expvaddr
; vaddr
< info
->expvaddrbtm
; info
->numexports
++) {
274 size
= p
->data
[offset
+8];
276 error (__FILE__
": export size less than 4 words: %d", size
);
282 if (vaddr
!= info
->expvaddrbtm
) {
283 error (__FILE__
": invalid exports boundary");
288 if (info
->impvaddr
) {
289 if (info
->impvaddr
> info
->impvaddrbtm
) {
290 error (__FILE__
": imports bottom is above top (0x%08X - 0x%08X)", info
->impvaddr
, info
->impvaddrbtm
);
293 if (!inside_progfile (p
->programs
, info
->impvaddr
, info
->impvaddrbtm
- info
->impvaddr
)) {
294 error (__FILE__
": imports not inside the first program (0x%08X - 0x%08X)", info
->impvaddr
, info
->impvaddrbtm
);
297 info
->numimports
= 0;
298 offset
= prx_translate (p
, info
->impvaddr
);
299 for (vaddr
= info
->impvaddr
; vaddr
< info
->impvaddrbtm
; info
->numimports
++) {
302 size
= p
->data
[offset
+8];
303 nvars
= p
->data
[offset
+9];
305 error (__FILE__
": import size less than 5 words: %d", size
);
308 if (nvars
&& size
< 6) {
309 error (__FILE__
": import size less than 6 words: %d", size
);
315 if (vaddr
!= info
->impvaddrbtm
) {
316 error (__FILE__
": invalid imports boundary");
324 int check_module_import (struct prx
*p
, uint32 index
)
326 struct prx_import
*imp
= &p
->modinfo
->imports
[index
];
328 if (!inside_strprogfile (p
->programs
, imp
->namevaddr
)) {
329 error (__FILE__
": import name not inside first program");
333 if (!imp
->nfuncs
&& !imp
->nvars
) {
334 error (__FILE__
": no functions or variables imported");
338 if (!inside_progfile (p
->programs
, imp
->funcsvaddr
, 8 * imp
->nfuncs
)) {
339 error (__FILE__
": functions not inside the first program");
343 if (!inside_progfile (p
->programs
, imp
->nidsvaddr
, 4 * imp
->nfuncs
)) {
344 error (__FILE__
": nids not inside the first program");
349 if (!inside_progfile (p
->programs
, imp
->varsvaddr
, 8 * imp
->nvars
)) {
350 error (__FILE__
": variables not inside first program");
360 int check_module_export (struct prx
*p
, uint32 index
)
362 struct prx_export
*exp
= &p
->modinfo
->exports
[index
];
364 if (!inside_strprogfile (p
->programs
, exp
->namevaddr
)) {
365 error (__FILE__
": export name not inside first program");
369 if (!exp
->nfuncs
&& !exp
->nvars
) {
370 error (__FILE__
": no functions or variables exported");
374 if (!inside_progfile (p
->programs
, exp
->expvaddr
, 8 * (exp
->nfuncs
+ exp
->nvars
))) {
375 error (__FILE__
": functions and variables not inside the first program");
383 int check_elf_header (struct prx
*p
)
387 if (memcmp (p
->ident
, valid_ident
, sizeof (valid_ident
))) {
388 error (__FILE__
": invalid identification for ELF/PRX");
392 if (p
->type
!= ELF_PRX_TYPE
) {
393 error (__FILE__
": not a PRX file (0x%04X)", p
->type
);
397 if (p
->machine
!= ELF_MACHINE_MIPS
) {
398 error (__FILE__
": machine is not MIPS (0x%04X)", p
->machine
);
402 if (p
->version
!= ELF_VERSION_CURRENT
) {
403 error (__FILE__
": version is not EV_CURRENT (0x%08X)", p
->version
);
407 if (p
->ehsize
!= ELF_HEADER_SIZE
) {
408 error (__FILE__
": wrong ELF header size (%u)", p
->ehsize
);
412 if ((p
->flags
& ELF_PRX_FLAGS
) != ELF_PRX_FLAGS
) {
413 error (__FILE__
": wrong ELF flags (0x%08X)", p
->flags
);
417 if (p
->phnum
&& p
->phentsize
!= ELF_PROGRAM_HEADER_ENT_SIZE
) {
418 error (__FILE__
": wrong ELF program header entity size (%u)", p
->phentsize
);
423 error (__FILE__
": PRX has no programs");
427 table_size
= p
->phentsize
;
428 table_size
*= (uint32
) p
->phnum
;
429 if (!inside_prx (p
, p
->phoff
, table_size
)) {
430 error (__FILE__
": wrong ELF program header table offset/size");
434 if (p
->shnum
&& p
->shentsize
!= ELF_SECTION_HEADER_ENT_SIZE
) {
435 error (__FILE__
": wrong ELF section header entity size (%u)", p
->shentsize
);
439 table_size
= p
->shentsize
;
440 table_size
*= (uint32
) p
->shnum
;
441 if (!inside_prx (p
, p
->shoff
, table_size
)) {
442 error (__FILE__
": wrong ELF section header table offset/size");
451 int load_sections (struct prx
*p
)
453 struct elf_section
*sections
;
458 p
->secbyname
= hashtable_create (64, &hashtable_hash_string
, &hashtable_string_compare
);
459 if (p
->shnum
== 0) return 1;
461 sections
= xmalloc (p
->shnum
* sizeof (struct elf_section
));
462 p
->sections
= sections
;
465 for (idx
= 0; idx
< p
->shnum
; idx
++) {
467 sections
[idx
].idxname
= read_uint32_le (&p
->data
[offset
]);
468 sections
[idx
].type
= read_uint32_le (&p
->data
[offset
+4]);
469 sections
[idx
].flags
= read_uint32_le (&p
->data
[offset
+8]);
470 sections
[idx
].addr
= read_uint32_le (&p
->data
[offset
+12]);
471 sections
[idx
].offset
= read_uint32_le (&p
->data
[offset
+16]);
472 sections
[idx
].size
= read_uint32_le (&p
->data
[offset
+20]);
473 sections
[idx
].link
= read_uint32_le (&p
->data
[offset
+24]);
474 sections
[idx
].info
= read_uint32_le (&p
->data
[offset
+28]);
475 sections
[idx
].addralign
= read_uint32_le (&p
->data
[offset
+32]);
476 sections
[idx
].entsize
= read_uint32_le (&p
->data
[offset
+36]);
478 sections
[idx
].data
= &p
->data
[sections
[idx
].offset
];
480 if (!check_section_header (p
, idx
))
483 offset
+= p
->shentsize
;
486 if (p
->shstrndx
> 0) {
487 if (sections
[p
->shstrndx
].type
== SHT_STRTAB
) {
488 char *strings
= (char *) sections
[p
->shstrndx
].data
;
489 uint32 max_index
= sections
[p
->shstrndx
].size
;
492 if (strings
[max_index
- 1] != '\0') {
493 error (__FILE__
": string table section not terminated with null byte");
497 for (idx
= 0; idx
< p
->shnum
; idx
++) {
498 if (sections
[idx
].idxname
< max_index
) {
499 sections
[idx
].name
= &strings
[sections
[idx
].idxname
];
501 error (__FILE__
": invalid section name");
505 for (idx
= 0; idx
< p
->shnum
; idx
++) {
506 hashtable_insert (p
->secbyname
, (void *) sections
[idx
].name
, §ions
[idx
]);
516 int load_programs (struct prx
*p
)
518 struct elf_program
*programs
;
522 programs
= xmalloc (p
->phnum
* sizeof (struct elf_program
));
523 p
->programs
= programs
;
526 for (idx
= 0; idx
< p
->phnum
; idx
++) {
527 programs
[idx
].type
= read_uint32_le (&p
->data
[offset
]);
528 programs
[idx
].offset
= read_uint32_le (&p
->data
[offset
+4]);
529 programs
[idx
].vaddr
= read_uint32_le (&p
->data
[offset
+8]);
530 programs
[idx
].paddr
= read_uint32_le (&p
->data
[offset
+12]);
531 programs
[idx
].filesz
= read_uint32_le (&p
->data
[offset
+16]);
532 programs
[idx
].memsz
= read_uint32_le (&p
->data
[offset
+20]);
533 programs
[idx
].flags
= read_uint32_le (&p
->data
[offset
+24]);
534 programs
[idx
].align
= read_uint32_le (&p
->data
[offset
+28]);
536 programs
[idx
].data
= &p
->data
[programs
[idx
].offset
];
538 if (!check_program_header (p
, idx
))
541 offset
+= p
->phentsize
;
548 int load_relocs (struct prx
*p
)
551 for (i
= 0; i
< p
->shnum
; i
++) {
552 struct elf_section
*section
= &p
->sections
[i
];
553 if (section
->type
== SHT_PRXRELOC
) {
554 count
+= section
->size
>> 3;
558 if (!count
) return 1;
561 p
->relocs
= (struct prx_reloc
*) xmalloc (count
* sizeof (struct prx_reloc
));
564 for (i
= 0; i
< p
->shnum
; i
++) {
565 struct elf_section
*section
= &p
->sections
[i
];
566 if (section
->type
== SHT_PRXRELOC
) {
569 offset
= section
->offset
;
570 secsize
= section
->size
>> 3;
571 for (j
= 0; j
< secsize
; j
++) {
572 p
->relocs
[count
].offset
= read_uint32_le (&p
->data
[offset
]);
573 p
->relocs
[count
].type
= p
->data
[offset
+ 4];
574 p
->relocs
[count
].offsbase
= p
->data
[offset
+ 5];
575 p
->relocs
[count
].addrbase
= p
->data
[offset
+ 6];
576 p
->relocs
[count
].extra
= p
->data
[offset
+ 7];
584 if (!check_relocs (p
)) return 0;
590 int load_module_import (struct prx
*p
, struct prx_import
*imp
)
594 imp
->funcs
= (struct prx_function
*) xmalloc (imp
->nfuncs
* sizeof (struct prx_function
));
595 offset
= prx_translate (p
, imp
->nidsvaddr
);
596 for (i
= 0; i
< imp
->nfuncs
; i
++) {
597 struct prx_function
*f
= &imp
->funcs
[i
];
598 f
->nid
= read_uint32_le (&p
->data
[offset
+ 4 * i
]);
599 f
->vaddr
= imp
->funcsvaddr
+ 8 * i
;
605 imp
->vars
= (struct prx_variable
*) xmalloc (imp
->nvars
* sizeof (struct prx_variable
));
606 offset
= prx_translate (p
, imp
->varsvaddr
);
607 for (i
= 0; i
< imp
->nvars
; i
++) {
608 struct prx_variable
*v
= &imp
->vars
[i
];
609 v
->nid
= read_uint32_le (&p
->data
[offset
+ 8 * i
+ 4]);
610 v
->vaddr
= read_uint32_le (&p
->data
[offset
+ 8 * i
]);
618 int load_module_imports (struct prx
*p
)
620 uint32 i
= 0, offset
;
621 struct prx_modinfo
*info
= p
->modinfo
;
622 if (!info
->impvaddr
) return 1;
624 info
->imports
= (struct prx_import
*) xmalloc (info
->numimports
* sizeof (struct prx_import
));
625 memset (info
->imports
, 0, info
->numimports
* sizeof (struct prx_import
));
627 offset
= prx_translate (p
, info
->impvaddr
);
628 for (i
= 0; i
< info
->numimports
; i
++) {
629 struct prx_import
*imp
= &info
->imports
[i
];
630 imp
->namevaddr
= read_uint32_le (&p
->data
[offset
]);
631 imp
->flags
= read_uint32_le (&p
->data
[offset
+4]);
632 imp
->size
= p
->data
[offset
+8];
633 imp
->nvars
= p
->data
[offset
+9];
634 imp
->nfuncs
= read_uint16_le (&p
->data
[offset
+10]);
635 imp
->nidsvaddr
= read_uint32_le (&p
->data
[offset
+12]);
636 imp
->funcsvaddr
= read_uint32_le (&p
->data
[offset
+16]);
637 if (imp
->nvars
) imp
->varsvaddr
= read_uint32_le (&p
->data
[offset
+20]);
639 if (!check_module_import (p
, i
)) return 0;
642 imp
->name
= (const char *) &p
->data
[prx_translate (p
, imp
->namevaddr
)];
646 if (!load_module_import (p
, imp
)) return 0;
647 offset
+= imp
->size
<< 2;
653 const char *resolve_syslib_nid (uint32 nid
)
656 case 0xd3744be0: return "module_bootstart";
657 case 0x2f064fa6: return "module_reboot_before";
658 case 0xadf12745: return "module_reboot_phase";
659 case 0xd632acdb: return "module_start";
660 case 0xcee8593c: return "module_stop";
661 case 0xf01d73a7: return "module_info";
662 case 0x0f7c276c: return "module_start_thread_parameter";
663 case 0xcf0cc697: return "module_stop_thread_parameter";
669 int load_module_export (struct prx
*p
, struct prx_export
*exp
)
671 uint32 i
, offset
, disp
;
672 offset
= prx_translate (p
, exp
->expvaddr
);
673 disp
= 4 * (exp
->nfuncs
+ exp
->nvars
);
675 exp
->funcs
= (struct prx_function
*) xmalloc (exp
->nfuncs
* sizeof (struct prx_function
));
676 for (i
= 0; i
< exp
->nfuncs
; i
++) {
677 struct prx_function
*f
= &exp
->funcs
[i
];
678 f
->vaddr
= read_uint32_le (&p
->data
[offset
+ disp
]);
679 f
->nid
= read_uint32_le (&p
->data
[offset
]);
682 if (exp
->namevaddr
== 0) {
683 f
->name
= resolve_syslib_nid (f
->nid
);
689 exp
->vars
= (struct prx_variable
*) xmalloc (exp
->nvars
* sizeof (struct prx_variable
));
690 for (i
= 0; i
< exp
->nvars
; i
++) {
691 struct prx_variable
*v
= &exp
->vars
[i
];
692 v
->vaddr
= read_uint32_le (&p
->data
[offset
+ disp
]);
693 v
->nid
= read_uint32_le (&p
->data
[offset
]);
696 if (exp
->namevaddr
== 0) {
697 v
->name
= resolve_syslib_nid (v
->nid
);
705 int load_module_exports (struct prx
*p
)
707 uint32 i
= 0, offset
;
708 struct prx_modinfo
*info
= p
->modinfo
;
709 if (!info
->expvaddr
) return 1;
711 info
->exports
= (struct prx_export
*) xmalloc (info
->numexports
* sizeof (struct prx_export
));
712 memset (info
->exports
, 0, info
->numexports
* sizeof (struct prx_export
));
714 offset
= prx_translate (p
, info
->expvaddr
);
715 for (i
= 0; i
< info
->numexports
; i
++) {
716 struct prx_export
*exp
= &info
->exports
[i
];
717 exp
->namevaddr
= read_uint32_le (&p
->data
[offset
]);
718 exp
->flags
= read_uint32_le (&p
->data
[offset
+4]);
719 exp
->size
= p
->data
[offset
+8];
720 exp
->nvars
= p
->data
[offset
+9];
721 exp
->nfuncs
= read_uint16_le (&p
->data
[offset
+10]);
722 exp
->expvaddr
= read_uint32_le (&p
->data
[offset
+12]);
724 if (!check_module_export (p
, i
)) return 0;
727 exp
->name
= (const char *) &p
->data
[prx_translate (p
, exp
->namevaddr
)];
729 exp
->name
= "syslib";
731 if (!load_module_export (p
, exp
)) return 0;
732 offset
+= exp
->size
<< 2;
738 int load_module_info (struct prx
*p
)
740 struct prx_modinfo
*info
;
744 offset
= p
->programs
[0].paddr
& 0x7FFFFFFF;
746 error (__FILE__
": can't find module info for PRX");
750 info
= (struct prx_modinfo
*) xmalloc (sizeof (struct prx_modinfo
));
753 info
->attributes
= read_uint16_le (&p
->data
[offset
]);
754 info
->version
= read_uint16_le (&p
->data
[offset
+2]);
755 info
->name
= (const char *) &p
->data
[offset
+4];
756 info
->gp
= read_uint32_le (&p
->data
[offset
+32]);
757 info
->expvaddr
= read_uint32_le (&p
->data
[offset
+36]);
758 info
->expvaddrbtm
= read_uint32_le (&p
->data
[offset
+40]);
759 info
->impvaddr
= read_uint32_le (&p
->data
[offset
+44]);
760 info
->impvaddrbtm
= read_uint32_le (&p
->data
[offset
+48]);
762 info
->imports
= NULL
;
763 info
->exports
= NULL
;
765 if (!check_module_info (p
)) return 0;
767 if (!load_module_imports (p
)) return 0;
768 if (!load_module_exports (p
)) return 0;
774 struct prx
*prx_load (const char *path
)
779 elf_bytes
= read_file (path
, &elf_size
);
781 if (!elf_bytes
) return NULL
;
783 if (elf_size
< ELF_HEADER_SIZE
) {
784 error (__FILE__
": elf size too short");
785 free ((void *) elf_bytes
);
789 p
= xmalloc (sizeof (struct prx
));
790 memset (p
, 0, sizeof (struct prx
));
794 memcpy (p
->ident
, p
->data
, ELF_HEADER_IDENT
);
795 p
->type
= read_uint16_le (&p
->data
[ELF_HEADER_IDENT
]);
796 p
->machine
= read_uint16_le (&p
->data
[ELF_HEADER_IDENT
+2]);
798 p
->version
= read_uint32_le (&p
->data
[ELF_HEADER_IDENT
+4]);
799 p
->entry
= read_uint32_le (&p
->data
[ELF_HEADER_IDENT
+8]);
800 p
->phoff
= read_uint32_le (&p
->data
[ELF_HEADER_IDENT
+12]);
801 p
->shoff
= read_uint32_le (&p
->data
[ELF_HEADER_IDENT
+16]);
802 p
->flags
= read_uint32_le (&p
->data
[ELF_HEADER_IDENT
+20]);
803 p
->ehsize
= read_uint16_le (&p
->data
[ELF_HEADER_IDENT
+24]);
804 p
->phentsize
= read_uint16_le (&p
->data
[ELF_HEADER_IDENT
+26]);
805 p
->phnum
= read_uint16_le (&p
->data
[ELF_HEADER_IDENT
+28]);
806 p
->shentsize
= read_uint16_le (&p
->data
[ELF_HEADER_IDENT
+30]);
807 p
->shnum
= read_uint16_le (&p
->data
[ELF_HEADER_IDENT
+32]);
808 p
->shstrndx
= read_uint16_le (&p
->data
[ELF_HEADER_IDENT
+34]);
810 if (!check_elf_header (p
)) {
815 if (!load_sections (p
)) {
820 if (!load_programs (p
)) {
825 if (!load_relocs (p
)) {
830 if (!load_module_info (p
)) {
839 void free_sections (struct prx
*p
)
845 hashtable_free (p
->secbyname
, NULL
, NULL
);
850 void free_programs (struct prx
*p
)
858 void free_relocs (struct prx
*p
)
866 void free_module_import (struct prx_import
*imp
)
868 if (imp
->funcs
) free (imp
->funcs
);
869 if (imp
->vars
) free (imp
->vars
);
875 void free_module_imports (struct prx
*p
)
877 if (!p
->modinfo
) return;
878 if (p
->modinfo
->imports
) {
880 for (i
= 0; i
< p
->modinfo
->numimports
; i
++)
881 free_module_import (&p
->modinfo
->imports
[i
]);
882 free (p
->modinfo
->imports
);
884 p
->modinfo
->imports
= NULL
;
888 void free_module_export (struct prx_export
*exp
)
890 if (exp
->funcs
) free (exp
->funcs
);
891 if (exp
->vars
) free (exp
->vars
);
897 void free_module_exports (struct prx
*p
)
899 if (!p
->modinfo
) return;
900 if (p
->modinfo
->exports
) {
902 for (i
= 0; i
< p
->modinfo
->numexports
; i
++)
903 free_module_export (&p
->modinfo
->exports
[i
]);
904 free (p
->modinfo
->exports
);
906 p
->modinfo
->imports
= NULL
;
910 void free_module_info (struct prx
*p
)
912 free_module_imports (p
);
913 free_module_exports (p
);
919 void prx_free (struct prx
*p
)
924 free_module_info (p
);
926 free ((void *) p
->data
);
932 void print_sections (struct prx
*p
)
935 struct elf_section
*section
;
936 const char *type
= "";
938 if (!p
->shnum
) return;
939 report ("\nSection Headers:\n");
940 report (" [Nr] Name Type Addr Off Size ES Flg Lk Inf Al\n");
942 for (idx
= 0; idx
< p
->shnum
; idx
++) {
943 section
= &p
->sections
[idx
];
944 switch (section
->type
) {
945 case SHT_NOBITS
: type
= "NOBITS"; break;
946 case SHT_PRXRELOC
: type
= "PRXRELOC"; break;
947 case SHT_STRTAB
: type
= "STRTAB"; break;
948 case SHT_PROGBITS
: type
= "PROGBITS"; break;
949 case SHT_NULL
: type
= "NULL"; break;
951 report (" [%2d] %-28s %-10s %08X %08X %08X %02d %s%s%s %2d %2d %2d\n",
952 idx
, section
->name
, type
, section
->addr
, section
->offset
, section
->size
,
953 section
->entsize
, (section
->flags
& SHF_ALLOC
) ? "A" : " ",
954 (section
->flags
& SHF_EXECINSTR
) ? "X" : " ", (section
->flags
& SHF_WRITE
) ? "W" : " ",
955 section
->link
, section
->info
, section
->addralign
);
960 void print_programs (struct prx
*p
)
963 struct elf_program
*program
;
964 const char *type
= "";
966 if (!p
->phnum
) return;
967 report ("\nProgram Headers:\n");
968 report (" Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align\n");
970 for (idx
= 0; idx
< p
->phnum
; idx
++) {
971 program
= &p
->programs
[idx
];
972 switch (program
->type
) {
973 case PT_LOAD
: type
= "LOAD"; break;
974 case PT_PRX
: type
= "PRX"; break;
977 report (" %-5s 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X %s%s%s 0x%02X\n",
978 type
, program
->offset
, program
->vaddr
, program
->paddr
, program
->filesz
,
979 program
->memsz
, (program
->flags
& PF_X
) ? "X" : " ", (program
->flags
& PF_R
) ? "R" : " ",
980 (program
->flags
& PF_W
) ? "W" : " ", program
->align
);
985 void print_module_imports (struct prx
*p
)
988 struct prx_modinfo
*info
= p
->modinfo
;
989 report ("\nImports:\n");
990 for (idx
= 0; idx
< info
->numimports
; idx
++) {
991 struct prx_import
*imp
= &info
->imports
[idx
];
992 report (" %s\n", imp
->name
);
994 report (" Flags: 0x%08X\n", imp
->flags
);
995 report (" Size: %6d\n", imp
->size
);
996 report (" Num Variables: %6d\n", imp
->nvars
);
997 report (" Num Functions: %6d\n", imp
->nfuncs
);
998 report (" Nids: 0x%08X\n", imp
->nidsvaddr
);
999 report (" Functions: 0x%08X\n", imp
->funcsvaddr
);
1001 for (i
= 0; i
< imp
->nfuncs
; i
++) {
1002 struct prx_function
*f
= &imp
->funcs
[i
];
1003 report (" NID: 0x%08X VADDR: 0x%08X", f
->nid
, f
->vaddr
);
1005 report (" NAME: %s", f
->name
);
1009 report (" Variables: 0x%08X\n", imp
->varsvaddr
);
1010 for (i
= 0; i
< imp
->nvars
; i
++) {
1011 struct prx_variable
*v
= &imp
->vars
[i
];
1012 report (" NID: 0x%08X VADDR: 0x%08X", v
->nid
, v
->vaddr
);
1014 report (" NAME: %s", v
->name
);
1024 void print_module_exports (struct prx
*p
)
1027 struct prx_modinfo
*info
= p
->modinfo
;
1028 report ("\nExports:\n");
1029 for (idx
= 0; idx
< info
->numexports
; idx
++) {
1030 struct prx_export
*exp
= &info
->exports
[idx
];
1031 report (" %s\n", exp
->name
);
1033 report (" Flags: 0x%08X\n", exp
->flags
);
1034 report (" Size: %6d\n", exp
->size
);
1035 report (" Num Variables: %6d\n", exp
->nvars
);
1036 report (" Num Functions: %6d\n", exp
->nfuncs
);
1037 report (" Exports: 0x%08X\n", exp
->expvaddr
);
1039 report (" Functions:\n");
1040 for (i
= 0; i
< exp
->nfuncs
; i
++) {
1041 struct prx_function
*f
= &exp
->funcs
[i
];
1042 report (" NID: 0x%08X VADDR: 0x%08X", f
->nid
, f
->vaddr
);
1044 report (" NAME: %s", f
->name
);
1049 report (" Variables:\n");
1050 for (i
= 0; i
< exp
->nvars
; i
++) {
1051 struct prx_variable
*v
= &exp
->vars
[i
];
1052 report (" NID: 0x%08X VADDR: 0x%08X", v
->nid
, v
->vaddr
);
1054 report (" NAME: %s", v
->name
);
1063 void print_module_info (struct prx
*p
)
1065 struct prx_modinfo
*info
= p
->modinfo
;
1068 report ("\nModule info:\n");
1069 report (" Name: %31s\n", info
->name
);
1070 report (" Attributes: 0x%04X\n", info
->attributes
);
1071 report (" Version: 0x%04X\n", info
->version
);
1072 report (" GP: 0x%08X\n", info
->gp
);
1073 report (" Library entry: 0x%08X\n", info
->expvaddr
);
1074 report (" Library entry bottom: 0x%08X\n", info
->expvaddrbtm
);
1075 report (" Library stubs: 0x%08X\n", info
->impvaddr
);
1076 report (" Library stubs bottom: 0x%08X\n", info
->impvaddrbtm
);
1078 print_module_imports (p
);
1079 print_module_exports (p
);
1082 void prx_print (struct prx
*p
)
1084 report ("ELF header:\n");
1085 report (" Entry point address: 0x%08X\n", p
->entry
);
1086 report (" Start of program headers: 0x%08X\n", p
->phoff
);
1087 report (" Start of section headers: 0x%08X\n", p
->shoff
);
1088 report (" Number of programs: %8d\n", p
->phnum
);
1089 report (" Number of sections: %8d\n", p
->shnum
);
1093 print_module_info (p
);
1098 void prx_resolve_nids (struct prx
*p
, struct nidstable
*nids
)
1102 struct prx_modinfo
*info
= p
->modinfo
;
1103 for (i
= 0; i
< info
->numimports
; i
++) {
1104 struct prx_import
*imp
= &info
->imports
[i
];
1105 for (j
= 0; j
< imp
->nfuncs
; j
++) {
1106 struct prx_function
*f
= &imp
->funcs
[j
];
1107 name
= nids_find (nids
, imp
->name
, f
->nid
);
1108 if (name
) f
->name
= name
;
1110 for (j
= 0; j
< imp
->nvars
; j
++) {
1111 struct prx_variable
*v
= &imp
->vars
[j
];
1112 name
= nids_find (nids
, imp
->name
, v
->nid
);
1113 if (name
) v
->name
= name
;
1116 for (i
= 0; i
< info
->numexports
; i
++) {
1117 struct prx_export
*exp
= &info
->exports
[i
];
1118 for (j
= 0; j
< exp
->nfuncs
; j
++) {
1119 struct prx_function
*f
= &exp
->funcs
[j
];
1120 name
= nids_find (nids
, exp
->name
, f
->nid
);
1121 if (name
) f
->name
= name
;
1123 for (j
= 0; j
< exp
->nvars
; j
++) {
1124 struct prx_variable
*v
= &exp
->vars
[j
];
1125 name
= nids_find (nids
, exp
->name
, v
->nid
);
1126 if (name
) v
->name
= name
;
1131 uint32
prx_translate (struct prx
*p
, uint32 vaddr
)
1134 for (idx
= 0; idx
< p
->phnum
; idx
++) {
1135 struct elf_program
*program
= &p
->programs
[idx
];
1136 if (program
->type
!= PT_LOAD
) continue;
1137 if (vaddr
>= program
->vaddr
&&
1138 (vaddr
- program
->vaddr
) < program
->memsz
) {
1139 vaddr
-= program
->vaddr
;
1140 if (vaddr
< program
->filesz
)
1141 return vaddr
+ program
->offset
;