9 #define ELF_HEADER_SIZE 52
10 #define ELF_SECTION_HEADER_ENT_SIZE 40
11 #define ELF_PROGRAM_HEADER_ENT_SIZE 32
12 #define ELF_PRX_FLAGS (ELF_FLAGS_MIPS_ARCH2 | ELF_FLAGS_MACH_ALLEGREX | ELF_FLAGS_MACH_ALLEGREX)
13 #define PRX_MODULE_INFO_SIZE 52
15 extern int load_relocs (struct prx
*p
);
16 extern void free_relocs (struct prx
*p
);
17 extern void print_relocs (struct prx
*p
);
19 extern int load_module_info (struct prx
*p
);
20 extern void free_module_info (struct prx
*p
);
21 extern void print_module_info (struct prx
*p
);
24 static const uint8 valid_ident
[] = {
26 0x01, /* Elf class = ELFCLASS32 */
27 0x01, /* Elf data = ELFDATA2LSB */
28 0x01, /* Version = EV_CURRENT */
29 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* Padding */
32 uint32
read_uint32_le (const uint8
*bytes
)
42 uint16
read_uint16_le (const uint8
*bytes
)
50 void write_uint32_le (uint8
*bytes
, uint32 val
)
52 bytes
[0] = val
& 0xFF; val
>>= 8;
53 bytes
[1] = val
& 0xFF; val
>>= 8;
54 bytes
[2] = val
& 0xFF; val
>>= 8;
55 bytes
[3] = val
& 0xFF;
58 int prx_inside_prx (struct prx
*p
, uint32 offset
, uint32 size
)
60 if (offset
>= p
->size
|| size
> p
->size
||
61 size
> (p
->size
- offset
)) return 0;
65 int prx_inside_progfile (struct elf_program
*program
, uint32 vaddr
, uint32 size
)
67 if (vaddr
< program
->vaddr
|| size
> program
->filesz
) return 0;
69 vaddr
-= program
->vaddr
;
70 if (vaddr
>= program
->filesz
|| (program
->filesz
- vaddr
) < size
) return 0;
74 int prx_inside_progmem (struct elf_program
*program
, uint32 vaddr
, uint32 size
)
76 if (vaddr
< program
->vaddr
|| size
> program
->memsz
) return 0;
78 vaddr
-= program
->vaddr
;
79 if (vaddr
>= program
->memsz
|| (program
->memsz
- vaddr
) < size
) return 0;
84 int prx_inside_strprogfile (struct elf_program
*program
, uint32 vaddr
)
86 if (vaddr
< program
->vaddr
) return 0;
88 vaddr
-= program
->vaddr
;
89 if (vaddr
>= program
->filesz
) return 0;
91 while (vaddr
< program
->filesz
) {
92 if (!program
->data
[vaddr
]) return 1;
100 int check_section_header (struct prx
*p
, uint32 index
)
102 struct elf_section
*section
= &p
->sections
[index
];
104 switch (section
->type
) {
112 if (!prx_inside_prx (p
, section
->offset
, section
->size
)) {
113 error (__FILE__
": section is not inside ELF/PRX (section %d)", index
);
119 error (__FILE__
": invalid section type 0x$08X (section %d)", section
->type
, index
);
127 int check_program_header (struct prx
*p
, uint32 index
)
129 struct elf_program
*program
= &p
->programs
[index
];
130 if (!prx_inside_prx (p
, program
->offset
, program
->filesz
)) {
131 error (__FILE__
": program is not inside ELF/PRX (program %d)", index
);
135 if ((index
== 0) && program
->type
!= PT_LOAD
) {
136 error (__FILE__
": first program is not of the type LOAD");
140 switch (program
->type
) {
142 if (program
->filesz
> program
->memsz
) {
143 error (__FILE__
": program file size grater than than memory size (program %d)", index
);
149 if (program
->memsz
) {
150 error (__FILE__
": program type must not loaded (program %d)", index
);
155 error (__FILE__
": invalid program type 0x%08X (program %d)", program
->type
, index
);
163 int check_elf_header (struct prx
*p
)
167 if (memcmp (p
->ident
, valid_ident
, sizeof (valid_ident
))) {
168 error (__FILE__
": invalid identification for ELF/PRX");
172 if (p
->type
!= ELF_PRX_TYPE
) {
173 error (__FILE__
": not a PRX file (0x%04X)", p
->type
);
177 if (p
->machine
!= ELF_MACHINE_MIPS
) {
178 error (__FILE__
": machine is not MIPS (0x%04X)", p
->machine
);
182 if (p
->version
!= ELF_VERSION_CURRENT
) {
183 error (__FILE__
": version is not EV_CURRENT (0x%08X)", p
->version
);
187 if (p
->ehsize
!= ELF_HEADER_SIZE
) {
188 error (__FILE__
": wrong ELF header size (%u)", p
->ehsize
);
192 if ((p
->flags
& ELF_PRX_FLAGS
) != ELF_PRX_FLAGS
) {
193 error (__FILE__
": wrong ELF flags (0x%08X)", p
->flags
);
197 if (p
->phnum
&& p
->phentsize
!= ELF_PROGRAM_HEADER_ENT_SIZE
) {
198 error (__FILE__
": wrong ELF program header entity size (%u)", p
->phentsize
);
203 error (__FILE__
": PRX has no programs");
207 table_size
= p
->phentsize
;
208 table_size
*= (uint32
) p
->phnum
;
209 if (!prx_inside_prx (p
, p
->phoff
, table_size
)) {
210 error (__FILE__
": wrong ELF program header table offset/size");
214 if (p
->shnum
&& p
->shentsize
!= ELF_SECTION_HEADER_ENT_SIZE
) {
215 error (__FILE__
": wrong ELF section header entity size (%u)", p
->shentsize
);
219 table_size
= p
->shentsize
;
220 table_size
*= (uint32
) p
->shnum
;
221 if (!prx_inside_prx (p
, p
->shoff
, table_size
)) {
222 error (__FILE__
": wrong ELF section header table offset/size");
231 int load_sections (struct prx
*p
)
233 struct elf_section
*sections
;
238 if (p
->shnum
== 0) return 1;
240 sections
= xmalloc (p
->shnum
* sizeof (struct elf_section
));
241 p
->sections
= sections
;
244 for (idx
= 0; idx
< p
->shnum
; idx
++) {
246 sections
[idx
].idxname
= read_uint32_le (&p
->data
[offset
]);
247 sections
[idx
].type
= read_uint32_le (&p
->data
[offset
+4]);
248 sections
[idx
].flags
= read_uint32_le (&p
->data
[offset
+8]);
249 sections
[idx
].addr
= read_uint32_le (&p
->data
[offset
+12]);
250 sections
[idx
].offset
= read_uint32_le (&p
->data
[offset
+16]);
251 sections
[idx
].size
= read_uint32_le (&p
->data
[offset
+20]);
252 sections
[idx
].link
= read_uint32_le (&p
->data
[offset
+24]);
253 sections
[idx
].info
= read_uint32_le (&p
->data
[offset
+28]);
254 sections
[idx
].addralign
= read_uint32_le (&p
->data
[offset
+32]);
255 sections
[idx
].entsize
= read_uint32_le (&p
->data
[offset
+36]);
257 sections
[idx
].data
= &p
->data
[sections
[idx
].offset
];
259 if (!check_section_header (p
, idx
))
262 offset
+= p
->shentsize
;
265 if (p
->shstrndx
> 0) {
266 if (sections
[p
->shstrndx
].type
== SHT_STRTAB
) {
267 char *strings
= (char *) sections
[p
->shstrndx
].data
;
268 uint32 max_index
= sections
[p
->shstrndx
].size
;
271 if (strings
[max_index
- 1] != '\0') {
272 error (__FILE__
": string table section not terminated with null byte");
276 for (idx
= 0; idx
< p
->shnum
; idx
++) {
277 if (sections
[idx
].idxname
< max_index
) {
278 sections
[idx
].name
= &strings
[sections
[idx
].idxname
];
280 error (__FILE__
": invalid section name");
292 int load_programs (struct prx
*p
)
294 struct elf_program
*programs
;
298 programs
= xmalloc (p
->phnum
* sizeof (struct elf_program
));
299 p
->programs
= programs
;
302 for (idx
= 0; idx
< p
->phnum
; idx
++) {
303 programs
[idx
].type
= read_uint32_le (&p
->data
[offset
]);
304 programs
[idx
].offset
= read_uint32_le (&p
->data
[offset
+4]);
305 programs
[idx
].vaddr
= read_uint32_le (&p
->data
[offset
+8]);
306 programs
[idx
].paddr
= read_uint32_le (&p
->data
[offset
+12]);
307 programs
[idx
].filesz
= read_uint32_le (&p
->data
[offset
+16]);
308 programs
[idx
].memsz
= read_uint32_le (&p
->data
[offset
+20]);
309 programs
[idx
].flags
= read_uint32_le (&p
->data
[offset
+24]);
310 programs
[idx
].align
= read_uint32_le (&p
->data
[offset
+28]);
312 programs
[idx
].data
= &p
->data
[programs
[idx
].offset
];
314 if (!check_program_header (p
, idx
))
317 offset
+= p
->phentsize
;
323 struct prx
*prx_load (const char *path
)
328 elf_bytes
= read_file (path
, &elf_size
);
330 if (!elf_bytes
) return NULL
;
332 if (elf_size
< ELF_HEADER_SIZE
) {
333 error (__FILE__
": elf size too short");
334 free ((void *) elf_bytes
);
338 p
= xmalloc (sizeof (struct prx
));
339 memset (p
, 0, sizeof (struct prx
));
343 memcpy (p
->ident
, p
->data
, ELF_HEADER_IDENT
);
344 p
->type
= read_uint16_le (&p
->data
[ELF_HEADER_IDENT
]);
345 p
->machine
= read_uint16_le (&p
->data
[ELF_HEADER_IDENT
+2]);
347 p
->version
= read_uint32_le (&p
->data
[ELF_HEADER_IDENT
+4]);
348 p
->entry
= read_uint32_le (&p
->data
[ELF_HEADER_IDENT
+8]);
349 p
->phoff
= read_uint32_le (&p
->data
[ELF_HEADER_IDENT
+12]);
350 p
->shoff
= read_uint32_le (&p
->data
[ELF_HEADER_IDENT
+16]);
351 p
->flags
= read_uint32_le (&p
->data
[ELF_HEADER_IDENT
+20]);
352 p
->ehsize
= read_uint16_le (&p
->data
[ELF_HEADER_IDENT
+24]);
353 p
->phentsize
= read_uint16_le (&p
->data
[ELF_HEADER_IDENT
+26]);
354 p
->phnum
= read_uint16_le (&p
->data
[ELF_HEADER_IDENT
+28]);
355 p
->shentsize
= read_uint16_le (&p
->data
[ELF_HEADER_IDENT
+30]);
356 p
->shnum
= read_uint16_le (&p
->data
[ELF_HEADER_IDENT
+32]);
357 p
->shstrndx
= read_uint16_le (&p
->data
[ELF_HEADER_IDENT
+34]);
359 if (!check_elf_header (p
)) {
364 if (!load_sections (p
)) {
369 if (!load_programs (p
)) {
374 if (!load_relocs (p
)) {
379 if (!load_module_info (p
)) {
388 void free_sections (struct prx
*p
)
396 void free_programs (struct prx
*p
)
403 void prx_free (struct prx
*p
)
408 free_module_info (p
);
410 free ((void *) p
->data
);
416 void print_sections (struct prx
*p
)
419 struct elf_section
*section
;
420 const char *type
= "";
422 if (!p
->shnum
) return;
423 report ("\nSection Headers:\n");
424 report (" [Nr] Name Type Addr Off Size ES Flg Lk Inf Al\n");
426 for (idx
= 0; idx
< p
->shnum
; idx
++) {
427 section
= &p
->sections
[idx
];
428 switch (section
->type
) {
429 case SHT_NOBITS
: type
= "NOBITS"; break;
430 case SHT_PRXRELOC
: type
= "PRXRELOC"; break;
431 case SHT_STRTAB
: type
= "STRTAB"; break;
432 case SHT_PROGBITS
: type
= "PROGBITS"; break;
433 case SHT_NULL
: type
= "NULL"; break;
435 report (" [%2d] %-28s %-10s %08X %08X %08X %02d %s%s%s %2d %2d %2d\n",
436 idx
, section
->name
, type
, section
->addr
, section
->offset
, section
->size
,
437 section
->entsize
, (section
->flags
& SHF_ALLOC
) ? "A" : " ",
438 (section
->flags
& SHF_EXECINSTR
) ? "X" : " ", (section
->flags
& SHF_WRITE
) ? "W" : " ",
439 section
->link
, section
->info
, section
->addralign
);
444 void print_programs (struct prx
*p
)
447 struct elf_program
*program
;
448 const char *type
= "";
450 if (!p
->phnum
) return;
451 report ("\nProgram Headers:\n");
452 report (" Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align\n");
454 for (idx
= 0; idx
< p
->phnum
; idx
++) {
455 program
= &p
->programs
[idx
];
456 switch (program
->type
) {
457 case PT_LOAD
: type
= "LOAD"; break;
458 case PT_PRXRELOC
: type
= "REL"; break;
459 case PT_PRXRELOC2
: type
= "REL2"; break;
462 report (" %-5s 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X %s%s%s 0x%02X\n",
463 type
, program
->offset
, program
->vaddr
, program
->paddr
, program
->filesz
,
464 program
->memsz
, (program
->flags
& PF_X
) ? "X" : " ", (program
->flags
& PF_R
) ? "R" : " ",
465 (program
->flags
& PF_W
) ? "W" : " ", program
->align
);
469 void prx_print (struct prx
*p
, int prtrelocs
)
471 report ("ELF header:\n");
472 report (" Entry point address: 0x%08X\n", p
->entry
);
473 report (" Start of program headers: 0x%08X\n", p
->phoff
);
474 report (" Start of section headers: 0x%08X\n", p
->shoff
);
475 report (" Number of programs: %8d\n", p
->phnum
);
476 report (" Number of sections: %8d\n", p
->shnum
);
482 print_module_info (p
);
487 uint32
prx_translate (struct prx
*p
, uint32 vaddr
)
490 for (idx
= 0; idx
< p
->phnum
; idx
++) {
491 struct elf_program
*program
= &p
->programs
[idx
];
492 if (program
->type
!= PT_LOAD
) continue;
493 if (vaddr
>= program
->vaddr
&&
494 (vaddr
- program
->vaddr
) < program
->memsz
) {
495 vaddr
-= program
->vaddr
;
496 if (vaddr
< program
->filesz
)
497 return vaddr
+ program
->offset
;