37static const char *g_outfile;
38static const char *g_infile;
39static unsigned char *g_elfdata = 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;
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;
58static int g_verbose = 0;
60static struct option arg_opts[] =
62 {
"verbose", no_argument, NULL,
'v'},
67int process_args(
int argc,
char **argv)
74 ch = getopt_long(argc, argv,
"v", arg_opts, NULL);
79 case 'v' : g_verbose = 1;
84 ch = getopt_long(argc, argv,
"v", arg_opts, NULL);
100 fprintf(stderr,
"Loading %s, outputting to %s\n", g_infile, g_outfile);
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");
113unsigned char *load_file(
const char *file)
115 unsigned char *data = NULL;
121 fp = fopen(file,
"rb");
126 (void) fseek(fp, 0, SEEK_END);
130 if(size <
sizeof(Elf32_Ehdr))
132 fprintf(stderr,
"Error, invalid file size\n");
137 data = (
unsigned char *) malloc(size);
140 fprintf(stderr,
"Error, could not allocate memory for ELF\n");
145 (void) fread(data, 1, size, fp);
150 fprintf(stderr,
"Error, could not find file %s\n", file);
159int validate_header(
unsigned char *data)
164 head = (Elf32_Ehdr*) data;
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);
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);
200 if(g_elfhead.iMagic != ELF_MAGIC)
202 fprintf(stderr,
"Error, invalid magic in the header\n");
206 if((g_elfhead.iType != ELF_EXEC_TYPE) && (g_elfhead.iType != ELF_IRX_TYPE))
208 fprintf(stderr,
"Error, not EXEC type elf\n");
212 if(g_elfhead.iMachine != ELF_MACHINE_MIPS)
214 fprintf(stderr,
"Error, not MIPS type ELF\n");
218 if(g_elfhead.iShnum < g_elfhead.iShstrndx)
220 fprintf(stderr,
"Error, number of headers is less than section string index\n");
232int load_sections(
unsigned char *data)
236 if(g_elfhead.iShnum > 0)
241 unsigned int load_addr = 0xFFFFFFFF;
245 if(g_elfsections == NULL)
247 fprintf(stderr,
"Error, could not allocate memory for sections\n");
251 memset(g_elfsections, 0,
sizeof(
struct ElfSection) * g_elfhead.iShnum);
253 for(i = 0; i < g_elfhead.iShnum; i++)
257 sect = (Elf32_Shdr *) (g_elfdata + g_elfhead.iShoff + (i * g_elfhead.iShentsize));
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;
271 if(g_elfsections[i].iOffset != 0)
273 g_elfsections[i].pData = g_elfdata + g_elfsections[i].iOffset;
276 if(g_elfsections[i].iFlags & SHF_ALLOC)
278 g_elfsections[i].blOutput = 1;
279 if(g_elfsections[i].iAddr < load_addr)
281 load_addr = g_elfsections[i].iAddr;
287 for(i = 0; i < g_elfhead.iShnum; i++)
289 if(((g_elfsections[i].iType == SHT_REL))
290 && (g_elfsections[g_elfsections[i].iInfo].iFlags & SHF_ALLOC))
292 g_elfsections[i].pRef = &g_elfsections[g_elfsections[i].iInfo];
294 g_elfsections[i].blOutput = 1;
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)
300 g_elfsections[i].blOutput = 1;
301 g_iopmod = &g_elfsections[i];
302 g_iopmod->iType = SHT_LOPROC | SHT_LOPROC_IOPMOD;
308 for(i = 0; i < g_elfhead.iShnum; i++)
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);
322 fprintf(stderr,
"ELF Load Base address %08X\n", load_addr);
327 fprintf(stderr,
"Error, found no relocation sections\n");
333 fprintf(stderr,
"Error, found no iopmod sections\n");
339 fprintf(stderr,
"Error, ELF not loaded to address 0 (%08X)\n", load_addr);
349 fprintf(stderr,
"Error, no sections in the ELF\n");
358 unsigned int iMaxSymbol;
359 void *pNewRel = NULL;
362 Elf32_Sym *pSymData = (Elf32_Sym *) pSymbol->pData;
363 char *pStrData = NULL;
364 unsigned int iOutput;
369 pStrData = (
char *) pString->pData;
372 iMaxSymbol = pSymbol->iSize /
sizeof(Elf32_Sym);
373 iCount = pReloc->iSize /
sizeof(
Elf32_Rel);
375 pNewRel = malloc(pReloc->iSize);
386 fprintf(stderr,
"[%s] Processing %u relocations, %u symbols\n", pReloc->szName, iCount, iMaxSymbol);
389 for(i = 0; i < iCount; i++)
391 unsigned int iSymbol;
393 iSymbol = ELF32_R_SYM(LW(pInRel->r_info));
396 fprintf(stderr,
"Relocation %u - Symbol %x\n", iOutput, iSymbol);
399 if(iSymbol >= iMaxSymbol)
401 fprintf(stderr,
"Warning: Ignoring relocation as cannot find matching symbol\n");
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);
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);
436 fprintf(stderr,
"Old relocation size %u, new %u\n", pReloc->iSize, iSize);
438 pReloc->iSize = iSize;
442 pReloc->blOutput = 0;
447 memcpy(pReloc->pData, pNewRel, pReloc->iSize);
457int process_relocs(
void)
461 for(i = 0; i < g_elfhead.iShnum; i++)
463 if((g_elfsections[i].blOutput) && (g_elfsections[i].iType == SHT_REL))
467 pReloc = &g_elfsections[i];
468 if((pReloc->iLink < g_elfhead.iShnum) && (g_elfsections[pReloc->iLink].iType == SHT_SYMTAB))
473 pSymbols = &g_elfsections[pReloc->iLink];
474 if((pSymbols->iLink < g_elfhead.iShnum) && (g_elfsections[pSymbols->iLink].iType == SHT_STRTAB))
476 pStrings = &g_elfsections[pSymbols->iLink];
479 if(!remove_weak_relocs(pReloc, pSymbols, pStrings))
488 fprintf(stderr,
"Ignoring relocation section %d, invalid link number\n", i);
498void reindex_sections(
void)
503 for(i = 0; i < g_elfhead.iShnum; i++)
505 if(g_elfsections[i].blOutput)
507 g_elfsections[i].iIndex = sect++;
513int load_elf(
const char *elf)
519 g_elfdata = load_file(elf);
520 if(g_elfdata == NULL)
525 if(!validate_header(g_elfdata))
530 if(!load_sections(g_elfdata))
535 if(!process_relocs())
549int calculate_outsize(
void)
566 for(i = 1; i < g_elfhead.iShnum; i++)
568 if(g_elfsections[i].blOutput)
570 if(g_elfsections[i].iType == SHT_PROGBITS)
572 unsigned int top_addr;
574 top_addr = g_elfsections[i].iAddr + g_elfsections[i].iSize;
576 if(top_addr > alloc_size)
578 alloc_size = top_addr;
581 if(top_addr > mem_size)
586 str_size += strlen(g_elfsections[i].szName) + 1;
588 else if(g_elfsections[i].iType == SHT_REL)
590 reloc_size += g_elfsections[i].iSize;
591 str_size += strlen(g_elfsections[i].szName) + 1;
595 unsigned int top_addr;
597 top_addr = g_elfsections[i].iAddr + g_elfsections[i].iSize;
599 if(top_addr > mem_size)
604 str_size += strlen(g_elfsections[i].szName) + 1;
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;
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);
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;
629 g_phbase =
sizeof(Elf32_Ehdr);
630 g_allocbase = g_phbase + (2 *
sizeof(
Elf32_Phdr));
632 g_allocbase = (g_allocbase + 0xF) & ~0xF;
633 g_iopmodbase = (g_allocbase + g_alloc_size + 0x3) & ~0x3;
635 g_iopmodbase = (g_iopmodbase + 0x3) & ~0x3;
636 g_shbase = g_iopmodbase + g_iopmod->iSize;
638 g_shbase = (g_shbase + 0x3) & ~0x3;
639 g_relocbase = g_shbase + (g_out_sects *
sizeof(Elf32_Shdr));
641 g_relocbase = (g_relocbase + 0x3) & ~0x3;
642 g_shstrbase = g_relocbase + g_reloc_size;
644 g_shstrbase = (g_shstrbase + 0x3) & ~0x3;
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);
653 return (g_shstrbase + g_str_size);
657void output_header(
unsigned char *data)
661 head = (Elf32_Ehdr*) data;
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));
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);
683void output_ph_iopmod(
unsigned char *data)
689 SW(&phdr->p_type, SHT_LOPROC | SHT_LOPROC_IOPMOD);
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);
701void output_ph(
unsigned char *data)
707 SW(&phdr->p_type, 1);
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);
719void output_alloc(
unsigned char *data)
723 for(i = 0; i < g_elfhead.iShnum; i++)
725 if((g_elfsections[i].blOutput) && (g_elfsections[i].iType == SHT_PROGBITS))
727 memcpy(&data[g_elfsections[i].iAddr], g_elfsections[i].pData, g_elfsections[i].iSize);
733void output_iopmod(
unsigned char *data)
735 memcpy(data, g_iopmod->pData, g_iopmod->iSize);
739void output_sh(
unsigned char *data)
741 unsigned int reloc_ofs;
742 unsigned int str_ofs;
746 shdr = (Elf32_Shdr*) data;
749 memset(data, 0, g_out_sects *
sizeof(Elf32_Shdr));
751 reloc_ofs = g_relocbase;
754 for(i = 1; i < g_elfhead.iShnum; i++)
756 if(g_elfsections[i].blOutput)
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);
764 SW(&shdr->sh_link, 0);
765 SW(&shdr->sh_addralign, g_elfsections[i].iAddralign);
766 SW(&shdr->sh_entsize, g_elfsections[i].iEntsize);
768 if(g_elfsections[i].iType == SHT_REL)
770 SW(&shdr->sh_type, SHT_REL);
771 if (g_elfsections[i].pRef)
772 SW(&shdr->sh_info, g_elfsections[i].pRef->iIndex);
774 SW(&shdr->sh_info, 0);
775 SW(&shdr->sh_offset, reloc_ofs);
776 reloc_ofs += g_elfsections[i].iSize;
778 else if(g_elfsections[i].iType == SHT_PROGBITS)
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);
784 else if(&g_elfsections[i] == g_iopmod)
786 SW(&shdr->sh_type, g_elfsections[i].iType);
787 SW(&shdr->sh_info, 0);
788 SW(&shdr->sh_offset, g_iopmodbase);
792 SW(&shdr->sh_type, g_elfsections[i].iType);
793 SW(&shdr->sh_info, 0);
795 SW(&shdr->sh_offset, g_allocbase + g_alloc_size);
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);
816void output_relocs(
unsigned char *data)
819 unsigned char *pReloc;
823 for(i = 0; i < g_elfhead.iShnum; i++)
825 if((g_elfsections[i].blOutput) &&
826 ((g_elfsections[i].iType == SHT_REL)))
828 memcpy(pReloc, g_elfsections[i].pData, g_elfsections[i].iSize);
829 pReloc += g_elfsections[i].iSize;
835void output_shstrtab(
unsigned char *data)
841 memset(data, 0, g_str_size);
842 pData = (
char *) (data + 1);
844 for(i = 1; i < g_elfhead.iShnum; i++)
846 if(g_elfsections[i].blOutput)
850 fprintf(stderr,
"String %d: %s\n", i, g_elfsections[i].szName);
853 strcpy(pData, g_elfsections[i].szName);
854 pData += strlen(g_elfsections[i].szName) + 1;
858 strcpy(pData, ELF_SH_STRTAB);
862int output_irx(
const char *irxfile)
870 size = calculate_outsize();
871 data = (
unsigned char *) malloc(size);
874 fprintf(stderr,
"Error, couldn't allocate output data\n");
878 memset(data, 0, size);
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);
889 fp = fopen(irxfile,
"wb");
892 fwrite(data, 1, size, fp);
897 fprintf(stderr,
"Error, could not open output file %s\n", irxfile);
910 if(g_elfdata != NULL)
916 if(g_elfsections != NULL)
919 g_elfsections = NULL;
923int main(
int argc,
char **argv)
925 if(process_args(argc, argv))
927 if(load_elf(g_infile))
929 (void) output_irx(g_outfile);