PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
ps2-irxgen.c
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright 2001-2022, ps2dev - http://www.ps2dev.org
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
11#include <stdio.h>
12#include <getopt.h>
13#include <string.h>
14#include <stdlib.h>
15#include <unistd.h>
16#include <assert.h>
17#include <ctype.h>
18
19#include "types.h"
20#include "elftypes.h"
21#include "irxtypes.h"
22
23/* Arrangement of ELF file after stripping
24 *
25 * ELF Header - 52 bytes
26 * Program Headers
27 * .text data
28 * .data data
29 * Section Headers
30 * Relocation data
31 * Section Header String Table
32 *
33 * When stripping the sections remove anything which isn't an allocated section or a relocation section.
34 * The section string section we will rebuild.
35 */
36
37static const char *g_outfile;
38static const char *g_infile;
39static unsigned char *g_elfdata = NULL;
40static struct ElfHeader g_elfhead = {0};
41static struct ElfSection *g_elfsections = NULL;
42static struct ElfSection *g_iopmod = NULL;
43static int g_out_sects = 2;
44static int g_alloc_size = 0;
45static int g_mem_size = 0;
46static int g_reloc_size = 0;
47static int g_str_size = 1;
48
49/* Base addresses in the Elf */
50static int g_phbase = 0;
51static int g_allocbase = 0;
52static int g_iopmodbase = 0;
53static int g_shbase = 0;
54static int g_relocbase = 0;
55static int g_shstrbase = 0;
56
57/* Specifies that the current usage is to print additional debugging information */
58static int g_verbose = 0;
59
60static struct option arg_opts[] =
61{
62 {"verbose", no_argument, NULL, 'v'},
63 { NULL, 0, NULL, 0 }
64};
65
66/* Process the arguments */
67int process_args(int argc, char **argv)
68{
69 int ch;
70
71 g_outfile = NULL;
72 g_infile = NULL;
73
74 ch = getopt_long(argc, argv, "v", arg_opts, NULL);
75 while(ch != -1)
76 {
77 switch(ch)
78 {
79 case 'v' : g_verbose = 1;
80 break;
81 default : break;
82 };
83
84 ch = getopt_long(argc, argv, "v", arg_opts, NULL);
85 }
86
87 argc -= optind;
88 argv += optind;
89
90 if(argc < 2)
91 {
92 return 0;
93 }
94
95 g_infile = argv[0];
96 g_outfile = argv[1];
97
98 if(g_verbose)
99 {
100 fprintf(stderr, "Loading %s, outputting to %s\n", g_infile, g_outfile);
101 }
102
103 return 1;
104}
105
106void print_help(void)
107{
108 fprintf(stderr, "Usage: ps2-irxgen [-v] infile.elf outfile.irx\n");
109 fprintf(stderr, "Options:\n");
110 fprintf(stderr, "-v, --verbose : Verbose output\n");
111}
112
113unsigned char *load_file(const char *file)
114{
115 unsigned char *data = NULL;
116
117 do
118 {
119 FILE *fp;
120
121 fp = fopen(file, "rb");
122 if(fp != NULL)
123 {
124 unsigned int size;
125
126 (void) fseek(fp, 0, SEEK_END);
127 size = ftell(fp);
128 rewind(fp);
129
130 if(size < sizeof(Elf32_Ehdr))
131 {
132 fprintf(stderr, "Error, invalid file size\n");
133 fclose(fp);
134 break;
135 }
136
137 data = (unsigned char *) malloc(size);
138 if(data == NULL)
139 {
140 fprintf(stderr, "Error, could not allocate memory for ELF\n");
141 fclose(fp);
142 break;
143 }
144
145 (void) fread(data, 1, size, fp);
146 fclose(fp);
147 }
148 else
149 {
150 fprintf(stderr, "Error, could not find file %s\n", file);
151 }
152 }
153 while(0);
154
155 return data;
156}
157
158/* Validate the ELF header */
159int validate_header(unsigned char *data)
160{
161 Elf32_Ehdr *head;
162 int ret = 0;
163
164 head = (Elf32_Ehdr*) data;
165
166 do
167 {
168 /* Read in the header structure */
169 g_elfhead.iMagic = LW(head->e_magic);
170 g_elfhead.iClass = head->e_class;
171 g_elfhead.iData = head->e_data;
172 g_elfhead.iIdver = head->e_idver;
173 g_elfhead.iType = LH(head->e_type);
174 g_elfhead.iMachine = LH(head->e_machine);
175 g_elfhead.iVersion = LW(head->e_version);
176 g_elfhead.iEntry = LW(head->e_entry);
177 g_elfhead.iPhoff = LW(head->e_phoff);
178 g_elfhead.iShoff = LW(head->e_shoff);
179 g_elfhead.iFlags = LW(head->e_flags);
180 g_elfhead.iEhsize = LH(head->e_ehsize);
181 g_elfhead.iPhentsize = LH(head->e_phentsize);
182 g_elfhead.iPhnum = LH(head->e_phnum);
183 g_elfhead.iShentsize = LH(head->e_shentsize);
184 g_elfhead.iShnum = LH(head->e_shnum);
185 g_elfhead.iShstrndx = LH(head->e_shstrndx);
186
187 if(g_verbose)
188 {
189 fprintf(stderr, "Magic %08X, Class %02X, Data %02X, Idver %02X\n", g_elfhead.iMagic,
190 g_elfhead.iClass, g_elfhead.iData, g_elfhead.iIdver);
191 fprintf(stderr, "Type %04X, Machine %04X, Version %08X, Entry %08X\n", g_elfhead.iType,
192 g_elfhead.iMachine, g_elfhead.iVersion, g_elfhead.iEntry);
193 fprintf(stderr, "Phoff %08X, Shoff %08X, Flags %08X, Ehsize %08X\n", g_elfhead.iPhoff,
194 g_elfhead.iShoff, g_elfhead.iFlags, g_elfhead.iEhsize);
195 fprintf(stderr, "Phentsize %04X, Phnum %04X\n", g_elfhead.iPhentsize, g_elfhead.iPhnum);
196 fprintf(stderr, "Shentsize %04X, Shnum %08X, Shstrndx %04X\n", g_elfhead.iShentsize,
197 g_elfhead.iShnum, g_elfhead.iShstrndx);
198 }
199
200 if(g_elfhead.iMagic != ELF_MAGIC)
201 {
202 fprintf(stderr, "Error, invalid magic in the header\n");
203 break;
204 }
205
206 if((g_elfhead.iType != ELF_EXEC_TYPE) && (g_elfhead.iType != ELF_IRX_TYPE))
207 {
208 fprintf(stderr, "Error, not EXEC type elf\n");
209 break;
210 }
211
212 if(g_elfhead.iMachine != ELF_MACHINE_MIPS)
213 {
214 fprintf(stderr, "Error, not MIPS type ELF\n");
215 break;
216 }
217
218 if(g_elfhead.iShnum < g_elfhead.iShstrndx)
219 {
220 fprintf(stderr, "Error, number of headers is less than section string index\n");
221 break;
222 }
223
224 ret = 1;
225 }
226 while(0);
227
228 return ret;
229}
230
231/* Load sections into ram */
232int load_sections(unsigned char *data)
233{
234 int ret = 0;
235
236 if(g_elfhead.iShnum > 0)
237 {
238 do
239 {
240 int i;
241 unsigned int load_addr = 0xFFFFFFFF;
242 int found_rel = 0;
243
244 g_elfsections = (struct ElfSection *) malloc(sizeof(struct ElfSection) * g_elfhead.iShnum);
245 if(g_elfsections == NULL)
246 {
247 fprintf(stderr, "Error, could not allocate memory for sections\n");
248 break;
249 }
250
251 memset(g_elfsections, 0, sizeof(struct ElfSection) * g_elfhead.iShnum);
252
253 for(i = 0; i < g_elfhead.iShnum; i++)
254 {
255 Elf32_Shdr *sect;
256
257 sect = (Elf32_Shdr *) (g_elfdata + g_elfhead.iShoff + (i * g_elfhead.iShentsize));
258
259 g_elfsections[i].iName = LW(sect->sh_name);
260 g_elfsections[i].iType = LW(sect->sh_type);
261 g_elfsections[i].iAddr = LW(sect->sh_addr);
262 g_elfsections[i].iFlags = LW(sect->sh_flags);
263 g_elfsections[i].iOffset = LW(sect->sh_offset);
264 g_elfsections[i].iSize = LW(sect->sh_size);
265 g_elfsections[i].iLink = LW(sect->sh_link);
266 g_elfsections[i].iInfo = LW(sect->sh_info);
267 g_elfsections[i].iAddralign = LW(sect->sh_addralign);
268 g_elfsections[i].iEntsize = LW(sect->sh_entsize);
269 g_elfsections[i].iIndex = i;
270
271 if(g_elfsections[i].iOffset != 0)
272 {
273 g_elfsections[i].pData = g_elfdata + g_elfsections[i].iOffset;
274 }
275
276 if(g_elfsections[i].iFlags & SHF_ALLOC)
277 {
278 g_elfsections[i].blOutput = 1;
279 if(g_elfsections[i].iAddr < load_addr)
280 {
281 load_addr = g_elfsections[i].iAddr;
282 }
283 }
284 }
285
286 /* Okay so we have loaded all the sections, lets find relocations and fix up the names */
287 for(i = 0; i < g_elfhead.iShnum; i++)
288 {
289 if(((g_elfsections[i].iType == SHT_REL))
290 && (g_elfsections[g_elfsections[i].iInfo].iFlags & SHF_ALLOC))
291 {
292 g_elfsections[i].pRef = &g_elfsections[g_elfsections[i].iInfo];
293 found_rel = 1;
294 g_elfsections[i].blOutput = 1;
295 }
296
297 strcpy(g_elfsections[i].szName, (char *) (g_elfsections[g_elfhead.iShstrndx].pData + g_elfsections[i].iName));
298 if(strcmp(g_elfsections[i].szName, PS2_MODULE_INFO_NAME) == 0)
299 {
300 g_elfsections[i].blOutput = 1;
301 g_iopmod = &g_elfsections[i];
302 g_iopmod->iType = SHT_LOPROC | SHT_LOPROC_IOPMOD;
303 }
304 }
305
306 if(g_verbose)
307 {
308 for(i = 0; i < g_elfhead.iShnum; i++)
309 {
310 fprintf(stderr, "\nSection %d: %s\n", i, g_elfsections[i].szName);
311 fprintf(stderr, "Name %08X, Type %08X, Flags %08X, Addr %08X\n",
312 g_elfsections[i].iName, g_elfsections[i].iType,
313 g_elfsections[i].iFlags, g_elfsections[i].iAddr);
314 fprintf(stderr, "Offset %08X, Size %08X, Link %08X, Info %08X\n",
315 g_elfsections[i].iOffset, g_elfsections[i].iSize,
316 g_elfsections[i].iLink, g_elfsections[i].iInfo);
317 fprintf(stderr, "Addralign %08X, Entsize %08X pData %p\n",
318 g_elfsections[i].iAddralign, g_elfsections[i].iEntsize,
319 g_elfsections[i].pData);
320 }
321
322 fprintf(stderr, "ELF Load Base address %08X\n", load_addr);
323 }
324
325 if(!found_rel)
326 {
327 fprintf(stderr, "Error, found no relocation sections\n");
328 break;
329 }
330
331 if(g_iopmod == NULL)
332 {
333 fprintf(stderr, "Error, found no iopmod sections\n");
334 break;
335 }
336
337 if(load_addr != 0)
338 {
339 fprintf(stderr, "Error, ELF not loaded to address 0 (%08X)\n", load_addr);
340 break;
341 }
342
343 ret = 1;
344 }
345 while(0);
346 }
347 else
348 {
349 fprintf(stderr, "Error, no sections in the ELF\n");
350 }
351
352 return ret;
353}
354
355int remove_weak_relocs(struct ElfSection *pReloc, struct ElfSection *pSymbol, struct ElfSection *pString)
356{
357 unsigned int iCount;
358 unsigned int iMaxSymbol;
359 void *pNewRel = NULL;
360 Elf32_Rel *pInRel;
361 Elf32_Rel *pOutRel;
362 Elf32_Sym *pSymData = (Elf32_Sym *) pSymbol->pData;
363 char *pStrData = NULL;
364 unsigned int iOutput;
365 unsigned int i;
366
367 if(pString != NULL)
368 {
369 pStrData = (char *) pString->pData;
370 }
371
372 iMaxSymbol = pSymbol->iSize / sizeof(Elf32_Sym);
373 iCount = pReloc->iSize / sizeof(Elf32_Rel);
374
375 pNewRel = malloc(pReloc->iSize);
376 if(pNewRel == NULL)
377 {
378 return 0;
379 }
380 pOutRel = (Elf32_Rel *) pNewRel;
381 pInRel = (Elf32_Rel *) pReloc->pData;
382 iOutput = 0;
383
384 if(g_verbose)
385 {
386 fprintf(stderr, "[%s] Processing %u relocations, %u symbols\n", pReloc->szName, iCount, iMaxSymbol);
387 }
388
389 for(i = 0; i < iCount; i++)
390 {
391 unsigned int iSymbol;
392
393 iSymbol = ELF32_R_SYM(LW(pInRel->r_info));
394 if(g_verbose)
395 {
396 fprintf(stderr, "Relocation %u - Symbol %x\n", iOutput, iSymbol);
397 }
398
399 if(iSymbol >= iMaxSymbol)
400 {
401 fprintf(stderr, "Warning: Ignoring relocation as cannot find matching symbol\n");
402 }
403 else
404 {
405 if(g_verbose)
406 {
407 if(pStrData != NULL)
408 {
409 fprintf(stderr, "Symbol %u - Name %s info %x ndx %x\n", iSymbol, &pStrData[pSymData[iSymbol].st_name],
410 pSymData[iSymbol].st_info, pSymData[iSymbol].st_shndx);
411 }
412 else
413 {
414 fprintf(stderr, "Symbol %u - Name %u info %x ndx %x\n", iSymbol, pSymData[iSymbol].st_name,
415 pSymData[iSymbol].st_info, pSymData[iSymbol].st_shndx);
416 }
417 }
418
419 /* We are keeping this relocation, copy it across */
420 *pOutRel = *pInRel;
421 pOutRel++;
422 iOutput++;
423 }
424
425 pInRel++;
426 }
427
428 /* If we deleted some relocations */
429 if(iOutput < iCount)
430 {
431 uint32_t iSize;
432
433 iSize = iOutput * sizeof(Elf32_Rel);
434 if(g_verbose)
435 {
436 fprintf(stderr, "Old relocation size %u, new %u\n", pReloc->iSize, iSize);
437 }
438 pReloc->iSize = iSize;
439 /* If size is zero then delete this section */
440 if(iSize == 0)
441 {
442 pReloc->blOutput = 0;
443 }
444 else
445 {
446 /* Copy across the new relocation data */
447 memcpy(pReloc->pData, pNewRel, pReloc->iSize);
448 }
449 }
450
451 free(pNewRel);
452
453 return 1;
454}
455
456/* Let's remove the weak relocations from the list */
457int process_relocs(void)
458{
459 int i;
460
461 for(i = 0; i < g_elfhead.iShnum; i++)
462 {
463 if((g_elfsections[i].blOutput) && (g_elfsections[i].iType == SHT_REL))
464 {
465 struct ElfSection *pReloc;
466
467 pReloc = &g_elfsections[i];
468 if((pReloc->iLink < g_elfhead.iShnum) && (g_elfsections[pReloc->iLink].iType == SHT_SYMTAB))
469 {
470 struct ElfSection *pStrings = NULL;
471 struct ElfSection *pSymbols;
472
473 pSymbols = &g_elfsections[pReloc->iLink];
474 if((pSymbols->iLink < g_elfhead.iShnum) && (g_elfsections[pSymbols->iLink].iType == SHT_STRTAB))
475 {
476 pStrings = &g_elfsections[pSymbols->iLink];
477 }
478
479 if(!remove_weak_relocs(pReloc, pSymbols, pStrings))
480 {
481 return 0;
482 }
483 }
484 else
485 {
486 if(g_verbose)
487 {
488 fprintf(stderr, "Ignoring relocation section %d, invalid link number\n", i);
489 }
490 }
491 }
492 }
493
494 return 1;
495}
496
497/* Reindex the sections we are keeping */
498void reindex_sections(void)
499{
500 int i;
501 int sect = 1;
502
503 for(i = 0; i < g_elfhead.iShnum; i++)
504 {
505 if(g_elfsections[i].blOutput)
506 {
507 g_elfsections[i].iIndex = sect++;
508 }
509 }
510}
511
512/* Load an ELF file */
513int load_elf(const char *elf)
514{
515 int ret = 0;
516
517 do
518 {
519 g_elfdata = load_file(elf);
520 if(g_elfdata == NULL)
521 {
522 break;
523 }
524
525 if(!validate_header(g_elfdata))
526 {
527 break;
528 }
529
530 if(!load_sections(g_elfdata))
531 {
532 break;
533 }
534
535 if(!process_relocs())
536 {
537 break;
538 }
539
540 reindex_sections();
541
542 ret = 1;
543 }
544 while(0);
545
546 return ret;
547}
548
549int calculate_outsize(void)
550{
551 /* out_sects starts at two for the null section and the section string table */
552 int out_sects = 2;
553 int alloc_size = 0;
554 int reloc_size = 0;
555 int mem_size = 0;
556 /* 1 for the NUL for the NULL section */
557 int str_size = 1;
558 int i;
559
560 /* Calculate how big our output file needs to be */
561 /* We have elf header + 2 PH + allocated data + iopmod section + section headers + relocation data */
562
563 /* Note that the ELF should be based from 0, we use this to calculate the alloc and mem sizes */
564
565 /* Skip null section */
566 for(i = 1; i < g_elfhead.iShnum; i++)
567 {
568 if(g_elfsections[i].blOutput)
569 {
570 if(g_elfsections[i].iType == SHT_PROGBITS)
571 {
572 unsigned int top_addr;
573
574 top_addr = g_elfsections[i].iAddr + g_elfsections[i].iSize;
575
576 if(top_addr > alloc_size)
577 {
578 alloc_size = top_addr;
579 }
580
581 if(top_addr > mem_size)
582 {
583 mem_size = top_addr;
584 }
585
586 str_size += strlen(g_elfsections[i].szName) + 1;
587 }
588 else if(g_elfsections[i].iType == SHT_REL)
589 {
590 reloc_size += g_elfsections[i].iSize;
591 str_size += strlen(g_elfsections[i].szName) + 1;
592 }
593 else
594 {
595 unsigned int top_addr;
596
597 top_addr = g_elfsections[i].iAddr + g_elfsections[i].iSize;
598
599 if(top_addr > mem_size)
600 {
601 mem_size = top_addr;
602 }
603
604 str_size += strlen(g_elfsections[i].szName) + 1;
605 }
606 out_sects++;
607 }
608 }
609
610 alloc_size = (alloc_size + 3) & ~3;
611 mem_size = (mem_size + 3) & ~3;
612 str_size = (str_size + 3) & ~3;
613 str_size += strlen(ELF_SH_STRTAB) + 1;
614
615 if(g_verbose)
616 {
617 fprintf(stderr, "Out_sects %d, alloc_size %d, reloc_size %d, str_size %d, mem_size %d\n",
618 out_sects, alloc_size, reloc_size, str_size, mem_size);
619 }
620
621 /* Save them for future use */
622 g_out_sects = out_sects;
623 g_alloc_size = alloc_size;
624 g_reloc_size = reloc_size;
625 g_mem_size = mem_size;
626 g_str_size = str_size;
627
628 /* Lets build the offsets */
629 g_phbase = sizeof(Elf32_Ehdr);
630 g_allocbase = g_phbase + (2 * sizeof(Elf32_Phdr));
631 /* The allocated data needs to be 16 byte aligned */
632 g_allocbase = (g_allocbase + 0xF) & ~0xF;
633 g_iopmodbase = (g_allocbase + g_alloc_size + 0x3) & ~0x3;
634 /* The allocated data needs to be 4 byte aligned */
635 g_iopmodbase = (g_iopmodbase + 0x3) & ~0x3;
636 g_shbase = g_iopmodbase + g_iopmod->iSize;
637 /* The allocated data needs to be 4 byte aligned */
638 g_shbase = (g_shbase + 0x3) & ~0x3;
639 g_relocbase = g_shbase + (g_out_sects * sizeof(Elf32_Shdr));
640 /* The allocated data needs to be 4 byte aligned */
641 g_relocbase = (g_relocbase + 0x3) & ~0x3;
642 g_shstrbase = g_relocbase + g_reloc_size;
643 /* The allocated data needs to be 4 byte aligned */
644 g_shstrbase = (g_shstrbase + 0x3) & ~0x3;
645
646 if(g_verbose)
647 {
648 fprintf(stderr, "PHBase %08X, AllocBase %08X, IopmodBase %08X, SHBase %08X\n", g_phbase, g_allocbase, g_iopmodbase, g_shbase);
649 fprintf(stderr, "Relocbase %08X, Shstrbase %08X\n", g_relocbase, g_shstrbase);
650 fprintf(stderr, "Total size %d\n", g_shstrbase + g_str_size);
651 }
652
653 return (g_shstrbase + g_str_size);
654}
655
656/* Output the ELF header */
657void output_header(unsigned char *data)
658{
659 Elf32_Ehdr *head;
660
661 head = (Elf32_Ehdr*) data;
662
663 SW(&head->e_magic, g_elfhead.iMagic);
664 head->e_class = g_elfhead.iClass;
665 head->e_data = g_elfhead.iData;
666 head->e_idver = g_elfhead.iIdver;
667 SH(&head->e_type, ELF_IRX_TYPE);
668 SH(&head->e_machine, g_elfhead.iMachine);
669 SW(&head->e_version, g_elfhead.iVersion);
670 SW(&head->e_entry, g_elfhead.iEntry);
671 SW(&head->e_phoff, g_phbase);
672 SW(&head->e_shoff, g_shbase);
673 SW(&head->e_flags, g_elfhead.iFlags);
674 SH(&head->e_ehsize, sizeof(Elf32_Ehdr));
675 SH(&head->e_phentsize, sizeof(Elf32_Phdr));
676 SH(&head->e_phnum, 2);
677 SH(&head->e_shentsize, sizeof(Elf32_Shdr));
678 SH(&head->e_shnum, g_out_sects);
679 SH(&head->e_shstrndx, g_out_sects-1);
680}
681
682/* Output the iopmod program header */
683void output_ph_iopmod(unsigned char *data)
684{
685 Elf32_Phdr *phdr;
686
687 phdr = (Elf32_Phdr*) data;
688
689 SW(&phdr->p_type, SHT_LOPROC | SHT_LOPROC_IOPMOD);
690 /* Starts after the program header */
691 SW(&phdr->p_offset, g_iopmodbase);
692 SW(&phdr->p_vaddr, 0);
693 SW(&phdr->p_paddr, 0);
694 SW(&phdr->p_filesz, g_iopmod->iSize);
695 SW(&phdr->p_memsz, 0);
696 SW(&phdr->p_flags, 4);
697 SW(&phdr->p_align, 0x4);
698}
699
700/* Output the program header */
701void output_ph(unsigned char *data)
702{
703 Elf32_Phdr *phdr;
704
705 phdr = (Elf32_Phdr*) data;
706
707 SW(&phdr->p_type, 1);
708 /* Starts after the program header */
709 SW(&phdr->p_offset, g_allocbase);
710 SW(&phdr->p_vaddr, 0);
711 SW(&phdr->p_paddr, 0);
712 SW(&phdr->p_filesz, g_alloc_size);
713 SW(&phdr->p_memsz, g_mem_size);
714 SW(&phdr->p_flags, 7);
715 SW(&phdr->p_align, 0x10);
716}
717
718/* Output the allocated sections */
719void output_alloc(unsigned char *data)
720{
721 int i;
722
723 for(i = 0; i < g_elfhead.iShnum; i++)
724 {
725 if((g_elfsections[i].blOutput) && (g_elfsections[i].iType == SHT_PROGBITS))
726 {
727 memcpy(&data[g_elfsections[i].iAddr], g_elfsections[i].pData, g_elfsections[i].iSize);
728 }
729 }
730}
731
732/* Output the iopmod section */
733void output_iopmod(unsigned char *data)
734{
735 memcpy(data, g_iopmod->pData, g_iopmod->iSize);
736}
737
738/* Output the section headers */
739void output_sh(unsigned char *data)
740{
741 unsigned int reloc_ofs;
742 unsigned int str_ofs;
743 Elf32_Shdr *shdr;
744 int i;
745
746 shdr = (Elf32_Shdr*) data;
747 /* For the NULL section */
748 shdr++;
749 memset(data, 0, g_out_sects * sizeof(Elf32_Shdr));
750
751 reloc_ofs = g_relocbase;
752 str_ofs = 1;
753
754 for(i = 1; i < g_elfhead.iShnum; i++)
755 {
756 if(g_elfsections[i].blOutput)
757 {
758 SW(&shdr->sh_name, str_ofs);
759 str_ofs += strlen(g_elfsections[i].szName) + 1;
760 SW(&shdr->sh_flags, g_elfsections[i].iFlags);
761 SW(&shdr->sh_addr, g_elfsections[i].iAddr);
762 SW(&shdr->sh_size, g_elfsections[i].iSize);
763 /* Note: this is safe set to zero for REL sections, despite the readelf warnings */
764 SW(&shdr->sh_link, 0);
765 SW(&shdr->sh_addralign, g_elfsections[i].iAddralign);
766 SW(&shdr->sh_entsize, g_elfsections[i].iEntsize);
767
768 if(g_elfsections[i].iType == SHT_REL)
769 {
770 SW(&shdr->sh_type, SHT_REL);
771 if (g_elfsections[i].pRef)
772 SW(&shdr->sh_info, g_elfsections[i].pRef->iIndex);
773 else
774 SW(&shdr->sh_info, 0);
775 SW(&shdr->sh_offset, reloc_ofs);
776 reloc_ofs += g_elfsections[i].iSize;
777 }
778 else if(g_elfsections[i].iType == SHT_PROGBITS)
779 {
780 SW(&shdr->sh_type, g_elfsections[i].iType);
781 SW(&shdr->sh_info, 0);
782 SW(&shdr->sh_offset, g_allocbase + g_elfsections[i].iAddr);
783 }
784 else if(&g_elfsections[i] == g_iopmod)
785 {
786 SW(&shdr->sh_type, g_elfsections[i].iType);
787 SW(&shdr->sh_info, 0);
788 SW(&shdr->sh_offset, g_iopmodbase);
789 }
790 else
791 {
792 SW(&shdr->sh_type, g_elfsections[i].iType);
793 SW(&shdr->sh_info, 0);
794 /* Point it to the end of the allocated section */
795 SW(&shdr->sh_offset, g_allocbase + g_alloc_size);
796 }
797
798 shdr++;
799 }
800 }
801
802 /* Fill in the shstrtab section */
803 SW(&shdr->sh_name, str_ofs);
804 SW(&shdr->sh_flags, 0);
805 SW(&shdr->sh_addr, 0);
806 SW(&shdr->sh_size, g_str_size);
807 SW(&shdr->sh_link, 0);
808 SW(&shdr->sh_addralign, 1);
809 SW(&shdr->sh_entsize, 0);
810 SW(&shdr->sh_type, SHT_STRTAB);
811 SW(&shdr->sh_info, 0);
812 SW(&shdr->sh_offset, g_shstrbase);
813}
814
815/* Output relocations */
816void output_relocs(unsigned char *data)
817{
818 int i;
819 unsigned char *pReloc;
820
821 pReloc = data;
822
823 for(i = 0; i < g_elfhead.iShnum; i++)
824 {
825 if((g_elfsections[i].blOutput) &&
826 ((g_elfsections[i].iType == SHT_REL)))
827 {
828 memcpy(pReloc, g_elfsections[i].pData, g_elfsections[i].iSize);
829 pReloc += g_elfsections[i].iSize;
830 }
831 }
832}
833
834/* Output the section header string table */
835void output_shstrtab(unsigned char *data)
836{
837 int i;
838 char *pData;
839
840 /* For the NULL section, memory should be zeroed anyway */
841 memset(data, 0, g_str_size);
842 pData = (char *) (data + 1);
843
844 for(i = 1; i < g_elfhead.iShnum; i++)
845 {
846 if(g_elfsections[i].blOutput)
847 {
848 if(g_verbose)
849 {
850 fprintf(stderr, "String %d: %s\n", i, g_elfsections[i].szName);
851 }
852
853 strcpy(pData, g_elfsections[i].szName);
854 pData += strlen(g_elfsections[i].szName) + 1;
855 }
856 }
857
858 strcpy(pData, ELF_SH_STRTAB);
859}
860
861/* Output a stripped irx file */
862int output_irx(const char *irxfile)
863{
864 do
865 {
866 int size;
867 unsigned char *data;
868 FILE *fp;
869
870 size = calculate_outsize();
871 data = (unsigned char *) malloc(size);
872 if(data == NULL)
873 {
874 fprintf(stderr, "Error, couldn't allocate output data\n");
875 break;
876 }
877
878 memset(data, 0, size);
879
880 output_header(data);
881 output_ph_iopmod(data + g_phbase);
882 output_ph(data + g_phbase + sizeof(Elf32_Phdr));
883 output_alloc(data + g_allocbase);
884 output_iopmod(data + g_iopmodbase);
885 output_sh(data + g_shbase);
886 output_relocs(data + g_relocbase);
887 output_shstrtab(data + g_shstrbase);
888
889 fp = fopen(irxfile, "wb");
890 if(fp != NULL)
891 {
892 fwrite(data, 1, size, fp);
893 fclose(fp);
894 }
895 else
896 {
897 fprintf(stderr, "Error, could not open output file %s\n", irxfile);
898 }
899
900 free(data);
901 }
902 while(0);
903
904 return 0;
905}
906
907/* Free allocated memory */
908void free_data(void)
909{
910 if(g_elfdata != NULL)
911 {
912 free(g_elfdata);
913 g_elfdata = NULL;
914 }
915
916 if(g_elfsections != NULL)
917 {
918 free(g_elfsections);
919 g_elfsections = NULL;
920 }
921}
922
923int main(int argc, char **argv)
924{
925 if(process_args(argc, argv))
926 {
927 if(load_elf(g_infile))
928 {
929 (void) output_irx(g_outfile);
930 free_data();
931 }
932 }
933 else
934 {
935 print_help();
936 }
937
938 return 0;
939}