Files
pspsdk/tools/psp-prxgen.c
ryancaicse 0ba656ab48 Fix resource leaks in psp-prxgen.c
Fix resource leaks in psp-prxgen.c
2022-02-07 15:12:52 +08:00

941 lines
21 KiB
C

/*
* PSP Software Development Kit - https://github.com/pspdev
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* psp-prxgen.c - Simple program to build a PRX file (and strip at the same time)
*
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
*
*/
#include <stdio.h>
#include <getopt.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <ctype.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "types.h"
#include "elftypes.h"
#include "prxtypes.h"
/* Arrangement of ELF file after stripping
*
* ELF Header - 52 bytes
* Program Headers
* .text data
* .data data
* Section Headers
* Relocation data
* Section Header String Table
*
* When stripping the sections remove anything which isn't an allocated section or a relocation section.
* The section string section we will rebuild.
*/
static const char *g_outfile;
static const char *g_infile;
static unsigned char *g_elfdata = NULL;
static struct ElfHeader g_elfhead = {0};
static struct ElfSection *g_elfsections = NULL;
static struct ElfSection *g_modinfo = NULL;
static int g_out_sects = 2;
static int g_alloc_size = 0;
static int g_mem_size = 0;
static int g_reloc_size = 0;
static int g_str_size = 1;
/* Base addresses in the Elf */
static int g_phbase = 0;
static int g_allocbase = 0;
static int g_shbase = 0;
static int g_relocbase = 0;
static int g_shstrbase = 0;
/* Specifies that the current usage is to the print the pspsdk path */
static int g_verbose = 0;
static struct option arg_opts[] =
{
{"verbose", no_argument, NULL, 'v'},
{ NULL, 0, NULL, 0 }
};
/* Process the arguments */
int process_args(int argc, char **argv)
{
int ch;
g_outfile = NULL;
g_infile = NULL;
ch = getopt_long(argc, argv, "v", arg_opts, NULL);
while(ch != -1)
{
switch(ch)
{
case 'v' : g_verbose = 1;
break;
default : break;
};
ch = getopt_long(argc, argv, "v", arg_opts, NULL);
}
argc -= optind;
argv += optind;
if(argc < 2)
{
return 0;
}
g_infile = argv[0];
g_outfile = argv[1];
if(g_verbose)
{
fprintf(stderr, "Loading %s, outputting to %s\n", g_infile, g_outfile);
}
return 1;
}
void print_help(void)
{
fprintf(stderr, "Usage: psp-prxgen [-v] infile.elf outfile.prx\n");
fprintf(stderr, "Options:\n");
fprintf(stderr, "-v, --verbose : Verbose output\n");
}
unsigned char *load_file(const char *file)
{
FILE *fp;
unsigned int size;
unsigned char *data = NULL;
do
{
fp = fopen(file, "rb");
if(fp != NULL)
{
(void) fseek(fp, 0, SEEK_END);
size = ftell(fp);
rewind(fp);
if(size < sizeof(Elf32_Ehdr))
{
fprintf(stderr, "Error, invalid file size\n");
fclose(fp);
break;
}
data = (unsigned char *) malloc(size);
if(data == NULL)
{
fprintf(stderr, "Error, could not allocate memory for ELF\n");
fclose(fp);
break;
}
(void) fread(data, 1, size, fp);
fclose(fp);
}
else
{
fprintf(stderr, "Error, could not find file %s\n", file);
}
}
while(0);
return data;
}
/* Validate the ELF header */
int validate_header(unsigned char *data)
{
Elf32_Ehdr *head;
int ret = 0;
head = (Elf32_Ehdr*) data;
do
{
/* Read in the header structure */
g_elfhead.iMagic = LW(head->e_magic);
g_elfhead.iClass = head->e_class;
g_elfhead.iData = head->e_data;
g_elfhead.iIdver = head->e_idver;
g_elfhead.iType = LH(head->e_type);
g_elfhead.iMachine = LH(head->e_machine);
g_elfhead.iVersion = LW(head->e_version);
g_elfhead.iEntry = LW(head->e_entry);
g_elfhead.iPhoff = LW(head->e_phoff);
g_elfhead.iShoff = LW(head->e_shoff);
g_elfhead.iFlags = LW(head->e_flags);
g_elfhead.iEhsize = LH(head->e_ehsize);
g_elfhead.iPhentsize = LH(head->e_phentsize);
g_elfhead.iPhnum = LH(head->e_phnum);
g_elfhead.iShentsize = LH(head->e_shentsize);
g_elfhead.iShnum = LH(head->e_shnum);
g_elfhead.iShstrndx = LH(head->e_shstrndx);
if(g_verbose)
{
fprintf(stderr, "Magic %08X, Class %02X, Data %02X, Idver %02X\n", g_elfhead.iMagic,
g_elfhead.iClass, g_elfhead.iData, g_elfhead.iIdver);
fprintf(stderr, "Type %04X, Machine %04X, Version %08X, Entry %08X\n", g_elfhead.iType,
g_elfhead.iMachine, g_elfhead.iVersion, g_elfhead.iEntry);
fprintf(stderr, "Phoff %08X, Shoff %08X, Flags %08X, Ehsize %08X\n", g_elfhead.iPhoff,
g_elfhead.iShoff, g_elfhead.iFlags, g_elfhead.iEhsize);
fprintf(stderr, "Phentsize %04X, Phnum %04X\n", g_elfhead.iPhentsize, g_elfhead.iPhnum);
fprintf(stderr, "Shentsize %04X, Shnum %08X, Shstrndx %04X\n", g_elfhead.iShentsize,
g_elfhead.iShnum, g_elfhead.iShstrndx);
}
if(g_elfhead.iMagic != ELF_MAGIC)
{
fprintf(stderr, "Error, invalid magic in the header\n");
break;
}
if((g_elfhead.iType != ELF_EXEC_TYPE) && (g_elfhead.iType != ELF_PRX_TYPE))
{
fprintf(stderr, "Error, not EXEC type elf\n");
break;
}
if(g_elfhead.iMachine != ELF_MACHINE_MIPS)
{
fprintf(stderr, "Error, not MIPS type ELF\n");
break;
}
if(g_elfhead.iShnum < g_elfhead.iShstrndx)
{
fprintf(stderr, "Error, number of headers is less than section string index\n");
break;
}
ret = 1;
}
while(0);
return ret;
}
/* Load sections into ram */
int load_sections(unsigned char *data)
{
int ret = 0;
int found_rel = 0;
unsigned int load_addr = 0xFFFFFFFF;
if(g_elfhead.iShnum > 0)
{
do
{
Elf32_Shdr *sect;
int i;
g_elfsections = (struct ElfSection *) malloc(sizeof(struct ElfSection) * g_elfhead.iShnum);
if(g_elfsections == NULL)
{
fprintf(stderr, "Error, could not allocate memory for sections\n");
break;
}
memset(g_elfsections, 0, sizeof(struct ElfSection) * g_elfhead.iShnum);
for(i = 0; i < g_elfhead.iShnum; i++)
{
sect = (Elf32_Shdr *) (g_elfdata + g_elfhead.iShoff + (i * g_elfhead.iShentsize));
g_elfsections[i].iName = LW(sect->sh_name);
g_elfsections[i].iType = LW(sect->sh_type);
g_elfsections[i].iAddr = LW(sect->sh_addr);
g_elfsections[i].iFlags = LW(sect->sh_flags);
g_elfsections[i].iOffset = LW(sect->sh_offset);
g_elfsections[i].iSize = LW(sect->sh_size);
g_elfsections[i].iLink = LW(sect->sh_link);
g_elfsections[i].iInfo = LW(sect->sh_info);
g_elfsections[i].iAddralign = LW(sect->sh_addralign);
g_elfsections[i].iEntsize = LW(sect->sh_entsize);
g_elfsections[i].iIndex = i;
if(g_elfsections[i].iOffset != 0)
{
g_elfsections[i].pData = g_elfdata + g_elfsections[i].iOffset;
}
if(g_elfsections[i].iFlags & SHF_ALLOC)
{
g_elfsections[i].blOutput = 1;
if(g_elfsections[i].iAddr < load_addr)
{
load_addr = g_elfsections[i].iAddr;
}
}
}
/* Okay so we have loaded all the sections, lets find relocations and fix up the names */
for(i = 0; i < g_elfhead.iShnum; i++)
{
if(((g_elfsections[i].iType == SHT_REL) || (g_elfsections[i].iType == SHT_PRXRELOC))
&& (g_elfsections[g_elfsections[i].iInfo].iFlags & SHF_ALLOC))
{
g_elfsections[i].pRef = &g_elfsections[g_elfsections[i].iInfo];
found_rel = 1;
g_elfsections[i].blOutput = 1;
}
strcpy(g_elfsections[i].szName, (char *) (g_elfsections[g_elfhead.iShstrndx].pData + g_elfsections[i].iName));
if(strcmp(g_elfsections[i].szName, PSP_MODULE_INFO_NAME) == 0)
{
g_modinfo = &g_elfsections[i];
}
else if(strcmp(g_elfsections[i].szName, PSP_MODULE_REMOVE_REL) == 0)
{
/* Don't output .rel.lib.stub relocations */
g_elfsections[i].blOutput = 0;
}
}
if(g_verbose)
{
for(i = 0; i < g_elfhead.iShnum; i++)
{
fprintf(stderr, "\nSection %d: %s\n", i, g_elfsections[i].szName);
fprintf(stderr, "Name %08X, Type %08X, Flags %08X, Addr %08X\n",
g_elfsections[i].iName, g_elfsections[i].iType,
g_elfsections[i].iFlags, g_elfsections[i].iAddr);
fprintf(stderr, "Offset %08X, Size %08X, Link %08X, Info %08X\n",
g_elfsections[i].iOffset, g_elfsections[i].iSize,
g_elfsections[i].iLink, g_elfsections[i].iInfo);
fprintf(stderr, "Addralign %08X, Entsize %08X pData %p\n",
g_elfsections[i].iAddralign, g_elfsections[i].iEntsize,
g_elfsections[i].pData);
}
fprintf(stderr, "ELF Load Base address %08X\n", load_addr);
}
if(g_modinfo == NULL)
{
fprintf(stderr, "Error, no sceModuleInfo section found\n");
break;
}
if(!found_rel)
{
fprintf(stderr, "Error, found no relocation sections\n");
break;
}
if(load_addr != 0)
{
fprintf(stderr, "Error, ELF not loaded to address 0 (%08X)\n", load_addr);
break;
}
ret = 1;
}
while(0);
}
else
{
fprintf(stderr, "Error, no sections in the ELF\n");
}
return ret;
}
int remove_weak_relocs(struct ElfSection *pReloc, struct ElfSection *pSymbol, struct ElfSection *pString)
{
int iCount;
int iMaxSymbol;
void *pNewRel = NULL;
Elf32_Rel *pInRel;
Elf32_Rel *pOutRel;
Elf32_Sym *pSymData = (Elf32_Sym *) pSymbol->pData;
char *pStrData = NULL;
int iOutput;
int i;
if(pString != NULL)
{
pStrData = (char *) pString->pData;
}
iMaxSymbol = pSymbol->iSize / sizeof(Elf32_Sym);
iCount = pReloc->iSize / sizeof(Elf32_Rel);
pNewRel = malloc(pReloc->iSize);
if(pNewRel == NULL)
{
return 0;
}
pOutRel = (Elf32_Rel *) pNewRel;
pInRel = (Elf32_Rel *) pReloc->pData;
iOutput = 0;
if(g_verbose)
{
fprintf(stderr, "[%s] Processing %d relocations, %d symbols\n", pReloc->szName, iCount, iMaxSymbol);
}
for(i = 0; i < iCount; i++)
{
int iSymbol;
iSymbol = ELF32_R_SYM(LW(pInRel->r_info));
if(g_verbose)
{
fprintf(stderr, "Relocation %d - Symbol %x\n", iOutput, iSymbol);
}
if(iSymbol >= iMaxSymbol)
{
fprintf(stderr, "Warning: Ignoring relocation as cannot find matching symbol\n");
}
else
{
if(g_verbose)
{
if(pStrData != NULL)
{
fprintf(stderr, "Symbol %d - Name %s info %x ndx %x\n", iSymbol, &pStrData[pSymData[iSymbol].st_name],
pSymData[iSymbol].st_info, pSymData[iSymbol].st_shndx);
}
else
{
fprintf(stderr, "Symbol %d - Name %d info %x ndx %x\n", iSymbol, pSymData[iSymbol].st_name,
pSymData[iSymbol].st_info, pSymData[iSymbol].st_shndx);
}
}
/* Remove PC16 relocations (unsupported by PSP, and useless) */
if(LH(pSymData[iSymbol].st_shndx) == 0 || ELF32_R_TYPE(LW(pInRel->r_info)) == R_MIPS_PC16 || ELF32_R_TYPE(LW(pInRel->r_info)) == R_MIPS_GPREL16)
{
if(g_verbose)
{
fprintf(stderr, "Deleting relocation\n");
}
}
else
{
/* We are keeping this relocation, copy it across */
*pOutRel = *pInRel;
pOutRel++;
iOutput++;
}
}
pInRel++;
}
/* If we deleted some relocations */
if(iOutput < iCount)
{
int iSize;
iSize = iOutput * sizeof(Elf32_Rel);
if(g_verbose)
{
fprintf(stderr, "Old relocation size %d, new %d\n", pReloc->iSize, iSize);
}
pReloc->iSize = iSize;
/* If size is zero then delete this section */
if(iSize == 0)
{
pReloc->blOutput = 0;
}
else
{
/* Copy across the new relocation data */
memcpy(pReloc->pData, pNewRel, pReloc->iSize);
}
}
free(pNewRel);
return 1;
}
/* Let's remove the weak relocations from the list */
int process_relocs(void)
{
int i;
for(i = 0; i < g_elfhead.iShnum; i++)
{
if((g_elfsections[i].blOutput) && (g_elfsections[i].iType == SHT_REL))
{
struct ElfSection *pReloc;
pReloc = &g_elfsections[i];
if((pReloc->iLink < g_elfhead.iShnum) && (g_elfsections[pReloc->iLink].iType == SHT_SYMTAB))
{
struct ElfSection *pStrings = NULL;
struct ElfSection *pSymbols;
pSymbols = &g_elfsections[pReloc->iLink];
if((pSymbols->iLink < g_elfhead.iShnum) && (g_elfsections[pSymbols->iLink].iType == SHT_STRTAB))
{
pStrings = &g_elfsections[pSymbols->iLink];
}
if(!remove_weak_relocs(pReloc, pSymbols, pStrings))
{
return 0;
}
}
else
{
if(g_verbose)
{
fprintf(stderr, "Ignoring relocation section %d, invalid link number\n", i);
}
}
}
}
return 1;
}
/* Reindex the sections we are keeping */
void reindex_sections(void)
{
int i;
int sect = 1;
for(i = 0; i < g_elfhead.iShnum; i++)
{
if(g_elfsections[i].blOutput)
{
g_elfsections[i].iIndex = sect++;
}
}
}
/* Load an ELF file */
int load_elf(const char *elf)
{
int ret = 0;
do
{
g_elfdata = load_file(elf);
if(g_elfdata == NULL)
{
break;
}
if(!validate_header(g_elfdata))
{
break;
}
if(!load_sections(g_elfdata))
{
break;
}
if(!process_relocs())
{
break;
}
reindex_sections();
ret = 1;
}
while(0);
return ret;
}
int calculate_outsize(void)
{
/* out_sects starts at two for the null section and the section string table */
int out_sects = 2;
int alloc_size = 0;
int reloc_size = 0;
int mem_size = 0;
/* 1 for the NUL for the NULL section */
int str_size = 1;
int i;
/* Calculate how big our output file needs to be */
/* We have elf header + 1 PH + allocated data + section headers + relocation data */
/* Note that the ELF should be based from 0, we use this to calculate the alloc and mem sizes */
/* Skip null section */
for(i = 1; i < g_elfhead.iShnum; i++)
{
if(g_elfsections[i].blOutput)
{
if(g_elfsections[i].iType == SHT_PROGBITS)
{
unsigned int top_addr;
top_addr = g_elfsections[i].iAddr + g_elfsections[i].iSize;
if(top_addr > alloc_size)
{
alloc_size = top_addr;
}
if(top_addr > mem_size)
{
mem_size = top_addr;
}
str_size += strlen(g_elfsections[i].szName) + 1;
}
else if((g_elfsections[i].iType == SHT_REL) || (g_elfsections[i].iType == SHT_PRXRELOC))
{
reloc_size += g_elfsections[i].iSize;
str_size += strlen(g_elfsections[i].szName) + 1;
}
else
{
unsigned int top_addr;
top_addr = g_elfsections[i].iAddr + g_elfsections[i].iSize;
if(top_addr > mem_size)
{
mem_size = top_addr;
}
str_size += strlen(g_elfsections[i].szName) + 1;
}
out_sects++;
}
}
alloc_size = (alloc_size + 3) & ~3;
mem_size = (mem_size + 3) & ~3;
str_size = (str_size + 3) & ~3;
str_size += strlen(ELF_SH_STRTAB) + 1;
if(g_verbose)
{
fprintf(stderr, "Out_sects %d, alloc_size %d, reloc_size %d, str_size %d, mem_size %d\n",
out_sects, alloc_size, reloc_size, str_size, mem_size);
}
/* Save them for future use */
g_out_sects = out_sects;
g_alloc_size = alloc_size;
g_reloc_size = reloc_size;
g_mem_size = mem_size;
g_str_size = str_size;
/* Lets build the offsets */
g_phbase = sizeof(Elf32_Ehdr);
/* The allocated data needs to be 16 byte aligned */
g_allocbase = (g_phbase + sizeof(Elf32_Shdr) + 0xF) & ~0xF;
g_shbase = g_allocbase + g_alloc_size;
g_relocbase = g_shbase + (g_out_sects * sizeof(Elf32_Shdr));
g_shstrbase = g_relocbase + g_reloc_size;
if(g_verbose)
{
fprintf(stderr, "PHBase %08X, AllocBase %08X, SHBase %08X\n", g_phbase, g_allocbase, g_shbase);
fprintf(stderr, "Relocbase %08X, Shstrbase %08X\n", g_relocbase, g_shstrbase);
fprintf(stderr, "Total size %d\n", g_shstrbase + g_str_size);
}
return (g_shstrbase + g_str_size);
}
/* Output the ELF header */
void output_header(unsigned char *data)
{
Elf32_Ehdr *head;
head = (Elf32_Ehdr*) data;
SW(&head->e_magic, g_elfhead.iMagic);
head->e_class = g_elfhead.iClass;
head->e_data = g_elfhead.iData;
head->e_idver = g_elfhead.iIdver;
SH(&head->e_type, ELF_PRX_TYPE);
SH(&head->e_machine, g_elfhead.iMachine);
SW(&head->e_version, g_elfhead.iVersion);
SW(&head->e_entry, g_elfhead.iEntry);
SW(&head->e_phoff, g_phbase);
SW(&head->e_shoff, g_shbase);
SW(&head->e_flags, g_elfhead.iFlags);
SH(&head->e_ehsize, sizeof(Elf32_Ehdr));
SH(&head->e_phentsize, sizeof(Elf32_Phdr));
SH(&head->e_phnum, 1);
SH(&head->e_shentsize, sizeof(Elf32_Shdr));
SH(&head->e_shnum, g_out_sects);
SH(&head->e_shstrndx, g_out_sects-1);
}
/* Output the program header */
void output_ph(unsigned char *data)
{
Elf32_Phdr *phdr;
struct PspModuleInfo *pModinfo;
int mod_flags;
phdr = (Elf32_Phdr*) data;
pModinfo = (struct PspModuleInfo *) (g_modinfo->pData);
mod_flags = LW(pModinfo->flags);
SW(&phdr->p_type, 1);
/* Starts after the program header */
SW(&phdr->p_offset, g_allocbase);
SW(&phdr->p_vaddr, 0);
/* Check if this is a kernel module */
if(mod_flags & 0x1000)
{
SW(&phdr->p_paddr, 0x80000000 | (g_modinfo->iAddr + g_allocbase));
}
else
{
SW(&phdr->p_paddr, (g_modinfo->iAddr + g_allocbase));
}
SW(&phdr->p_filesz, g_alloc_size);
SW(&phdr->p_memsz, g_mem_size);
SW(&phdr->p_flags, 5);
SW(&phdr->p_align, 0x10);
}
/* Output the allocated sections */
void output_alloc(unsigned char *data)
{
int i;
for(i = 0; i < g_elfhead.iShnum; i++)
{
if((g_elfsections[i].blOutput) && (g_elfsections[i].iType == SHT_PROGBITS))
{
memcpy(&data[g_elfsections[i].iAddr], g_elfsections[i].pData, g_elfsections[i].iSize);
}
}
}
/* Output the section headers */
void output_sh(unsigned char *data)
{
unsigned int reloc_ofs;
unsigned int str_ofs;
Elf32_Shdr *shdr;
int i;
shdr = (Elf32_Shdr*) data;
/* For the NULL section */
shdr++;
memset(data, 0, g_out_sects * sizeof(Elf32_Shdr));
reloc_ofs = g_relocbase;
str_ofs = 1;
for(i = 1; i < g_elfhead.iShnum; i++)
{
if(g_elfsections[i].blOutput)
{
SW(&shdr->sh_name, str_ofs);
str_ofs += strlen(g_elfsections[i].szName) + 1;
SW(&shdr->sh_flags, g_elfsections[i].iFlags);
SW(&shdr->sh_addr, g_elfsections[i].iAddr);
SW(&shdr->sh_size, g_elfsections[i].iSize);
SW(&shdr->sh_link, 0);
SW(&shdr->sh_addralign, g_elfsections[i].iAddralign);
SW(&shdr->sh_entsize, g_elfsections[i].iEntsize);
if((g_elfsections[i].iType == SHT_REL) || (g_elfsections[i].iType == SHT_PRXRELOC))
{
SW(&shdr->sh_type, SHT_PRXRELOC);
if (g_elfsections[i].pRef)
SW(&shdr->sh_info, g_elfsections[i].pRef->iIndex);
else
SW(&shdr->sh_info, 0);
SW(&shdr->sh_offset, reloc_ofs);
reloc_ofs += g_elfsections[i].iSize;
}
else if(g_elfsections[i].iType == SHT_PROGBITS)
{
SW(&shdr->sh_type, g_elfsections[i].iType);
SW(&shdr->sh_info, 0);
SW(&shdr->sh_offset, g_allocbase + g_elfsections[i].iAddr);
}
else
{
SW(&shdr->sh_type, g_elfsections[i].iType);
SW(&shdr->sh_info, 0);
/* Point it to the end of the allocated section */
SW(&shdr->sh_offset, g_allocbase + g_alloc_size);
}
shdr++;
}
}
/* Fill in the shstrtab section */
SW(&shdr->sh_name, str_ofs);
SW(&shdr->sh_flags, 0);
SW(&shdr->sh_addr, 0);
SW(&shdr->sh_size, g_str_size);
SW(&shdr->sh_link, 0);
SW(&shdr->sh_addralign, 1);
SW(&shdr->sh_entsize, 0);
SW(&shdr->sh_type, SHT_STRTAB);
SW(&shdr->sh_info, 0);
SW(&shdr->sh_offset, g_shstrbase);
}
/* Output relocations */
void output_relocs(unsigned char *data)
{
int i;
unsigned char *pReloc;
pReloc = data;
for(i = 0; i < g_elfhead.iShnum; i++)
{
if((g_elfsections[i].blOutput) &&
((g_elfsections[i].iType == SHT_REL) || (g_elfsections[i].iType == SHT_PRXRELOC)))
{
Elf32_Rel *rel;
int j, count;
memcpy(pReloc, g_elfsections[i].pData, g_elfsections[i].iSize);
rel = (Elf32_Rel*) pReloc;
count = g_elfsections[i].iSize / sizeof(Elf32_Rel);
for(j = 0; j < count; j++)
{
unsigned int sym;
/* Clear the top 24bits of the info */
/* Kind of a dirty trick but hey :P */
sym = LW(rel->r_info);
sym &= 0xFF;
SW(&rel->r_info, sym);
rel++;
}
pReloc += g_elfsections[i].iSize;
}
}
}
/* Output the section header string table */
void output_shstrtab(unsigned char *data)
{
int i;
char *pData;
/* For the NULL section, memory should be zeroed anyway */
memset(data, 0, g_str_size);
pData = (char *) (data + 1);
for(i = 1; i < g_elfhead.iShnum; i++)
{
if(g_elfsections[i].blOutput)
{
if(g_verbose)
{
fprintf(stderr, "String %d: %s\n", i, g_elfsections[i].szName);
}
strcpy(pData, g_elfsections[i].szName);
pData += strlen(g_elfsections[i].szName) + 1;
}
}
strcpy(pData, ELF_SH_STRTAB);
}
/* Output a stripped prx file */
int output_prx(const char *prxfile)
{
int size;
unsigned char *data;
FILE *fp;
do
{
size = calculate_outsize();
data = (unsigned char *) malloc(size);
if(data == NULL)
{
fprintf(stderr, "Error, couldn't allocate output data\n");
break;
}
memset(data, 0, size);
output_header(data);
output_ph(data + g_phbase);
output_alloc(data + g_allocbase);
output_sh(data + g_shbase);
output_relocs(data + g_relocbase);
output_shstrtab(data + g_shstrbase);
fp = fopen(prxfile, "wb");
if(fp != NULL)
{
fwrite(data, 1, size, fp);
fclose(fp);
}
else
{
fprintf(stderr, "Error, could not open output file %s\n", prxfile);
}
free(data);
}
while(0);
return 0;
}
/* Free allocated memory */
void free_data(void)
{
if(g_elfdata != NULL)
{
free(g_elfdata);
g_elfdata = NULL;
}
if(g_elfsections != NULL)
{
free(g_elfsections);
g_elfsections = NULL;
}
}
int main(int argc, char **argv)
{
if(process_args(argc, argv))
{
if(load_elf(g_infile))
{
(void) output_prx(g_outfile);
free_data();
}
}
else
{
print_help();
}
return 0;
}