Make the build system work EXACTLY the same way as for official kernel modules.

Fixed alignment.
Added our/my own version of psp-build-exports from the PSPSDK, so the library name is placed right before the library exports in .rodata.
Added our/my own version of psp-prxgen from the PSPSDK (named psp-kprxgen for us), so the module uses only program headers and absolutely no sections.
This commit is contained in:
artart78 2011-12-30 18:48:23 +00:00
parent 0202f8712a
commit 484569d7fb
12 changed files with 2838 additions and 8 deletions

View File

@ -23,10 +23,10 @@ $(TARGET).elf: $(OBJS) $(EXPORT_OBJ)
-$(FIXUP) $@
%.prx: %.elf
psp-prxgen $< $@
../../utils/kprxgen/psp-kprxgen $< $@
%.c: %.exp
psp-build-exports -b $< > $@
../../utils/build-exports/psp-build-exports -b $< > $@
clean:
-rm -f $(TARGET).prx $(TARGET).elf $(EXPORT_OBJ) $(OBJS)

View File

@ -2,6 +2,7 @@
OUTPUT_FORMAT("elf32-littlemips", "elf32-bigmips",
"elf32-littlemips")
OUTPUT_ARCH(mips:allegrex)
ENTRY(module_start)
/* SEARCH_DIR("/usr/local/pspdev/psp/lib"); */
/* Do we need any of these for elf?
__DYNAMIC = 0; */
@ -72,6 +73,7 @@ SECTIONS
*(.gnu.warning)
*(.mips16.fn.*) *(.mips16.call.*)
} =0
. = ALIGN(16);
.init :
{
KEEP (*(.init))
@ -108,9 +110,6 @@ SECTIONS
.eh_frame_hdr : { *(.eh_frame_hdr) }
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }
.gcc_except_table : ONLY_IF_RO { KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) }
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
. = ALIGN(256) + (. & (256 - 1));
/* Exception handling */
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) }
.gcc_except_table : ONLY_IF_RW { KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) }

View File

@ -77,15 +77,16 @@ enum PspModuleInfoAttr
extern char __lib_stub_top[], __lib_stub_bottom[]; \
SceModuleInfo module_info \
__attribute__((section(".rodata.sceModuleInfo"), \
aligned(16), unused)) = { \
, unused)) = { \
attributes, { minor_version, major_version }, name, 0, _gp, \
__lib_ent_top, __lib_ent_bottom, \
__lib_stub_top, __lib_stub_bottom \
}
#define PSP_SDK_VERSION(ver) int syslib_11B97506 = ver
#define PSP_SDK_VERSION(ver) const int syslib_11B97506 = ver
#define PSP_MODULE_BOOTSTART(name) int module_bootstart(int arglen, void *argp) __attribute__((alias(name)))
#define PSP_MODULE_BOOTSTART(name) int module_start(int arglen, void *argp) __attribute__((alias(name))); \
int module_bootstart(int arglen, void *argp) __attribute__((alias(name)))
/********** TEMPORARY: it'll be in their corresponding module's header *********/
typedef int (*SceKernelCallbackFunction)(int arg1, int arg2, void *arg);

View File

@ -0,0 +1,27 @@
# Copyright (C) 2011 The uOFW team
# See the file COPYING for copying permission.
CPP=gcc
CFLAGS=-Wall -Wextra -Werror
LDFLAGS=
TARGET=psp-build-exports
OBJECTS=sha1.o psp-build-exports.o
all: $(TARGET)
$(TARGET): $(OBJECTS)
@echo "Creating binary $(TARGET)"
@$(CPP) $(OBJECTS) -o $@ $(LDFLAGS)
%.o: %.cpp
@echo "Compiling $^"
$(CPP) $(CFLAGS) -c $^ -o $@
clean:
@echo "Removing all the .o files"
@$(RM) $(OBJECTS)
mrproper: clean
@echo "Removing binary"
@$(RM) $(TARGET)

File diff suppressed because it is too large Load Diff

282
utils/build-exports/sha1.c Normal file
View File

@ -0,0 +1,282 @@
/*
---------------------------------------------------------------------------
Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved.
LICENSE TERMS
The free distribution and use of this software in both source and binary
form is allowed (with or without changes) provided that:
1. distributions of this source code include the above copyright
notice, this list of conditions and the following disclaimer;
2. distributions in binary form include the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other associated materials;
3. the copyright holder's name is not used to endorse products
built using this software without specific written permission.
ALTERNATIVELY, provided that this notice is retained in full, this product
may be distributed under the terms of the GNU General Public License (GPL),
in which case the provisions of the GPL apply INSTEAD OF those given above.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 18/06/2004
This is a byte oriented version of SHA1 that operates on arrays of bytes
stored in memory.
*/
#include <string.h> /* for memcpy() etc. */
#include <stdlib.h> /* for _lrotl with VC++ */
#include "sha1.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#if defined(__cplusplus)
extern "C"
{
#endif
/*
To obtain the highest speed on processors with 32-bit words, this code
needs to determine the order in which bytes are packed into such words.
The following block of code is an attempt to capture the most obvious
ways in which various environemnts specify their endian definitions.
It may well fail, in which case the definitions will need to be set by
editing at the points marked **** EDIT HERE IF NECESSARY **** below.
*/
/* PLATFORM SPECIFIC INCLUDES */
#define BRG_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */
#define BRG_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */
#ifdef WORDS_BIGENDIAN
#define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN
#else
#define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN
#endif
#ifdef _MSC_VER
#pragma intrinsic(memcpy)
#endif
#if 0 && defined(_MSC_VER)
#define rotl32 _lrotl
#define rotr32 _lrotr
#else
#define rotl32(x,n) (((x) << n) | ((x) >> (32 - n)))
#define rotr32(x,n) (((x) >> n) | ((x) << (32 - n)))
#endif
#if !defined(bswap_32)
#define bswap_32(x) ((rotr32((x), 24) & 0x00ff00ff) | (rotr32((x), 8) & 0xff00ff00))
#endif
#if (PLATFORM_BYTE_ORDER == BRG_LITTLE_ENDIAN)
#define SWAP_BYTES
#else
#undef SWAP_BYTES
#endif
#if defined(SWAP_BYTES)
#define bsw_32(p,n) \
{ int _i = (n); while(_i--) ((sha1_32t*)p)[_i] = bswap_32(((sha1_32t*)p)[_i]); }
#else
#define bsw_32(p,n)
#endif
#define SHA1_MASK (SHA1_BLOCK_SIZE - 1)
#if 0
#define ch(x,y,z) (((x) & (y)) ^ (~(x) & (z)))
#define parity(x,y,z) ((x) ^ (y) ^ (z))
#define maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
#else /* Discovered by Rich Schroeppel and Colin Plumb */
#define ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
#define parity(x,y,z) ((x) ^ (y) ^ (z))
#define maj(x,y,z) (((x) & (y)) | ((z) & ((x) ^ (y))))
#endif
/* Compile 64 bytes of hash data into SHA1 context. Note */
/* that this routine assumes that the byte order in the */
/* ctx->wbuf[] at this point is in such an order that low */
/* address bytes in the ORIGINAL byte stream will go in */
/* this buffer to the high end of 32-bit words on BOTH big */
/* and little endian systems */
#ifdef ARRAY
#define q(v,n) v[n]
#else
#define q(v,n) v##n
#endif
#define one_cycle(v,a,b,c,d,e,f,k,h) \
q(v,e) += rotr32(q(v,a),27) + \
f(q(v,b),q(v,c),q(v,d)) + k + h; \
q(v,b) = rotr32(q(v,b), 2)
#define five_cycle(v,f,k,i) \
one_cycle(v, 0,1,2,3,4, f,k,hf(i )); \
one_cycle(v, 4,0,1,2,3, f,k,hf(i+1)); \
one_cycle(v, 3,4,0,1,2, f,k,hf(i+2)); \
one_cycle(v, 2,3,4,0,1, f,k,hf(i+3)); \
one_cycle(v, 1,2,3,4,0, f,k,hf(i+4))
void sha1_compile(sha1_ctx ctx[1])
{ sha1_32t *w = ctx->wbuf;
#ifdef ARRAY
sha1_32t v[5];
memcpy(v, ctx->hash, 5 * sizeof(sha1_32t));
#else
sha1_32t v0, v1, v2, v3, v4;
v0 = ctx->hash[0]; v1 = ctx->hash[1];
v2 = ctx->hash[2]; v3 = ctx->hash[3];
v4 = ctx->hash[4];
#endif
#define hf(i) w[i]
five_cycle(v, ch, 0x5a827999, 0);
five_cycle(v, ch, 0x5a827999, 5);
five_cycle(v, ch, 0x5a827999, 10);
one_cycle(v,0,1,2,3,4, ch, 0x5a827999, hf(15)); \
#undef hf
#define hf(i) (w[(i) & 15] = rotl32( \
w[((i) + 13) & 15] ^ w[((i) + 8) & 15] \
^ w[((i) + 2) & 15] ^ w[(i) & 15], 1))
one_cycle(v,4,0,1,2,3, ch, 0x5a827999, hf(16));
one_cycle(v,3,4,0,1,2, ch, 0x5a827999, hf(17));
one_cycle(v,2,3,4,0,1, ch, 0x5a827999, hf(18));
one_cycle(v,1,2,3,4,0, ch, 0x5a827999, hf(19));
five_cycle(v, parity, 0x6ed9eba1, 20);
five_cycle(v, parity, 0x6ed9eba1, 25);
five_cycle(v, parity, 0x6ed9eba1, 30);
five_cycle(v, parity, 0x6ed9eba1, 35);
five_cycle(v, maj, 0x8f1bbcdc, 40);
five_cycle(v, maj, 0x8f1bbcdc, 45);
five_cycle(v, maj, 0x8f1bbcdc, 50);
five_cycle(v, maj, 0x8f1bbcdc, 55);
five_cycle(v, parity, 0xca62c1d6, 60);
five_cycle(v, parity, 0xca62c1d6, 65);
five_cycle(v, parity, 0xca62c1d6, 70);
five_cycle(v, parity, 0xca62c1d6, 75);
#ifdef ARRAY
ctx->hash[0] += v[0]; ctx->hash[1] += v[1];
ctx->hash[2] += v[2]; ctx->hash[3] += v[3];
ctx->hash[4] += v[4];
#else
ctx->hash[0] += v0; ctx->hash[1] += v1;
ctx->hash[2] += v2; ctx->hash[3] += v3;
ctx->hash[4] += v4;
#endif
}
void sha1_begin(sha1_ctx ctx[1])
{
ctx->count[0] = ctx->count[1] = 0;
ctx->hash[0] = 0x67452301;
ctx->hash[1] = 0xefcdab89;
ctx->hash[2] = 0x98badcfe;
ctx->hash[3] = 0x10325476;
ctx->hash[4] = 0xc3d2e1f0;
}
/* SHA1 hash data in an array of bytes into hash buffer and */
/* call the hash_compile function as required. */
void sha1_hash(const unsigned char data[], unsigned long len, sha1_ctx ctx[1])
{ sha1_32t pos = (sha1_32t)(ctx->count[0] & SHA1_MASK),
space = SHA1_BLOCK_SIZE - pos;
const unsigned char *sp = data;
if((ctx->count[0] += len) < len)
++(ctx->count[1]);
while(len >= space) /* tranfer whole blocks if possible */
{
memcpy(((unsigned char*)ctx->wbuf) + pos, sp, space);
sp += space; len -= space; space = SHA1_BLOCK_SIZE; pos = 0;
bsw_32(ctx->wbuf, SHA1_BLOCK_SIZE >> 2);
sha1_compile(ctx);
}
memcpy(((unsigned char*)ctx->wbuf) + pos, sp, len);
}
/* SHA1 final padding and digest calculation */
void sha1_end(unsigned char hval[], sha1_ctx ctx[1])
{ sha1_32t i = (sha1_32t)(ctx->count[0] & SHA1_MASK);
/* put bytes in the buffer in an order in which references to */
/* 32-bit words will put bytes with lower addresses into the */
/* top of 32 bit words on BOTH big and little endian machines */
bsw_32(ctx->wbuf, (i + 3) >> 2);
/* we now need to mask valid bytes and add the padding which is */
/* a single 1 bit and as many zero bits as necessary. Note that */
/* we can always add the first padding byte here because the */
/* buffer always has at least one empty slot */
ctx->wbuf[i >> 2] &= 0xffffff80 << 8 * (~i & 3);
ctx->wbuf[i >> 2] |= 0x00000080 << 8 * (~i & 3);
/* we need 9 or more empty positions, one for the padding byte */
/* (above) and eight for the length count. If there is not */
/* enough space, pad and empty the buffer */
if(i > SHA1_BLOCK_SIZE - 9)
{
if(i < 60) ctx->wbuf[15] = 0;
sha1_compile(ctx);
i = 0;
}
else /* compute a word index for the empty buffer positions */
i = (i >> 2) + 1;
while(i < 14) /* and zero pad all but last two positions */
ctx->wbuf[i++] = 0;
/* the following 32-bit length fields are assembled in the */
/* wrong byte order on little endian machines but this is */
/* corrected later since they are only ever used as 32-bit */
/* word values. */
ctx->wbuf[14] = (ctx->count[1] << 3) | (ctx->count[0] >> 29);
ctx->wbuf[15] = ctx->count[0] << 3;
sha1_compile(ctx);
/* extract the hash value as bytes in case the hash buffer is */
/* misaligned for 32-bit words */
for(i = 0; i < SHA1_DIGEST_SIZE; ++i)
hval[i] = (unsigned char)(ctx->hash[i >> 2] >> (8 * (~i & 3)));
}
void sha1(unsigned char hval[], const unsigned char data[], unsigned long len)
{ sha1_ctx cx[1];
sha1_begin(cx); sha1_hash(data, len, cx); sha1_end(hval, cx);
}
#if defined(__cplusplus)
}
#endif

View File

@ -0,0 +1,84 @@
/*
---------------------------------------------------------------------------
Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved.
LICENSE TERMS
The free distribution and use of this software in both source and binary
form is allowed (with or without changes) provided that:
1. distributions of this source code include the above copyright
notice, this list of conditions and the following disclaimer;
2. distributions in binary form include the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other associated materials;
3. the copyright holder's name is not used to endorse products
built using this software without specific written permission.
ALTERNATIVELY, provided that this notice is retained in full, this product
may be distributed under the terms of the GNU General Public License (GPL),
in which case the provisions of the GPL apply INSTEAD OF those given above.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 26/08/2003
*/
#ifndef _SHA1_H
#define _SHA1_H
#include <limits.h>
#define SHA1_BLOCK_SIZE 64
#define SHA1_DIGEST_SIZE 20
#if defined(__cplusplus)
extern "C"
{
#endif
/* define an unsigned 32-bit type */
#if defined(_MSC_VER)
typedef unsigned long sha1_32t;
#elif defined(ULONG_MAX) && ULONG_MAX == 0xfffffffful
typedef unsigned long sha1_32t;
#elif defined(UINT_MAX) && UINT_MAX == 0xffffffff
typedef unsigned int sha1_32t;
#else
# error Please define sha1_32t as an unsigned 32 bit type in sha1.h
#endif
/* type to hold the SHA256 context */
typedef struct
{ sha1_32t count[2];
sha1_32t hash[5];
sha1_32t wbuf[16];
} sha1_ctx;
/* Note that these prototypes are the same for both bit and */
/* byte oriented implementations. However the length fields */
/* are in bytes or bits as appropriate for the version used */
/* and bit sequences are input as arrays of bytes in which */
/* bit sequences run from the most to the least significant */
/* end of each byte */
void sha1_compile(sha1_ctx ctx[1]);
void sha1_begin(sha1_ctx ctx[1]);
void sha1_hash(const unsigned char data[], unsigned long len, sha1_ctx ctx[1]);
void sha1_end(unsigned char hval[], sha1_ctx ctx[1]);
void sha1(unsigned char hval[], const unsigned char data[], unsigned long len);
#if defined(__cplusplus)
}
#endif
#endif

27
utils/kprxgen/Makefile Normal file
View File

@ -0,0 +1,27 @@
# Copyright (C) 2011 The uOFW team
# See the file COPYING for copying permission.
CPP=gcc
CFLAGS=-Wall -Wextra -Werror
LDFLAGS=
TARGET=psp-kprxgen
OBJECTS=psp-kprxgen.o
all: $(TARGET)
$(TARGET): $(OBJECTS)
@echo "Creating binary $(TARGET)"
@$(CPP) $(OBJECTS) -o $@ $(LDFLAGS)
%.o: %.cpp
@echo "Compiling $^"
$(CPP) $(CFLAGS) -c $^ -o $@
clean:
@echo "Removing all the .o files"
@$(RM) $(OBJECTS)
mrproper: clean
@echo "Removing binary"
@$(RM) $(TARGET)

246
utils/kprxgen/elftypes.h Normal file
View File

@ -0,0 +1,246 @@
/*
* PSP Software Development Kit - http://www.pspdev.org
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* elftypes.h - Definitions for the different ELF types.
*
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
*
* $Id: elftypes.h 1520 2005-12-04 20:09:36Z tyranid $
*/
#ifndef __ELF_TYPES_H__
#define __ELF_TYPES_H__
#include "types.h"
#define ELF_MACHINE_MIPS 0x0008
#define ELF_SH_STRTAB ".shstrtab"
#define ELF_SECT_MAX_NAME 128
/* Structure defining a single elf section */
struct ElfSection
{
/* Name index */
u32 iName;
/* Type of section */
u32 iType;
/* Section flags */
u32 iFlags;
/* Addr of section when loaded */
u32 iAddr;
/* Offset of the section in the elf */
u32 iOffset;
/* Size of the sections data */
u32 iSize;
/* Link info */
u32 iLink;
/* Info */
u32 iInfo;
/* Address alignment */
u32 iAddralign;
/* Entry size */
u32 iEntsize;
/* Aliased pointer to the data (in the original Elf) */
u8 *pData;
/* Name of the section */
char szName[ELF_SECT_MAX_NAME];
/* Index */
int iIndex;
/* Section Ref. Used for relocations */
struct ElfSection *pRef;
/* Indicates if this section is to be outputted */
int blOutput;
};
struct ElfProgram
{
u32 iType;
u32 iOffset;
u32 iVaddr;
u32 iPaddr;
u32 iFilesz;
u32 iMemsz;
u32 iFlags;
u32 iAlign;
/* Aliased pointer to the data (in the original Elf)*/
u8 *pData;
};
/* Structure to hold elf header data, in native format */
struct ElfHeader
{
u32 iMagic;
u32 iClass;
u32 iData;
u32 iIdver;
u32 iType;
u32 iMachine;
u32 iVersion;
u32 iEntry;
u32 iPhoff;
u32 iShoff;
u32 iFlags;
u32 iEhsize;
u32 iPhentsize;
u32 iPhnum;
u32 iShentsize;
u32 iShnum;
u32 iShstrndx;
};
struct ElfReloc
{
/* Pointer to the section name */
const char* secname;
/* Base address */
u32 base;
/* Type */
u32 type;
/* Symbol (if known) */
u32 symbol;
/* Offset into the file */
u32 offset;
/* New Address for the relocation (to do with what you will) */
u32 addr;
};
/* Define ELF types */
typedef u32 Elf32_Addr;
typedef u16 Elf32_Half;
typedef u32 Elf32_Off;
typedef s32 Elf32_Sword;
typedef u32 Elf32_Word;
#define ELF_MAGIC 0x464C457F
#define ELF_EXEC_TYPE 0x0002
#define ELF_PRX_TYPE 0xFFA0
#define SHT_NULL 0
#define SHT_PROGBITS 1
#define SHT_SYMTAB 2
#define SHT_STRTAB 3
#define SHT_RELA 4
#define SHT_HASH 5
#define SHT_DYNAMIC 6
#define SHT_NOTE 7
#define SHT_NOBITS 8
#define SHT_REL 9
#define SHT_SHLIB 10
#define SHT_DYNSYM 11
#define SHT_LOPROC 0x70000000
#define SHT_HIPROC 0x7fffffff
#define SHT_LOUSER 0x80000000
#define SHT_HIUSER 0xffffffff
#define SHT_PRXRELOC (SHT_LOPROC | 0xA0)
// MIPS Reloc Entry Types
#define R_MIPS_NONE 0
#define R_MIPS_16 1
#define R_MIPS_32 2
#define R_MIPS_REL32 3
#define R_MIPS_26 4
#define R_MIPS_HI16 5
#define R_MIPS_LO16 6
#define R_MIPS_GPREL16 7
#define R_MIPS_LITERAL 8
#define R_MIPS_GOT16 9
#define R_MIPS_PC16 10
#define R_MIPS_CALL16 11
#define R_MIPS_GPREL32 12
#define SHF_WRITE 1
#define SHF_ALLOC 2
#define SHF_EXECINSTR 4
#define PT_NULL 0
#define PT_LOAD 1
#define PT_DYNAMIC 2
#define PT_INTERP 3
#define PT_NOTE 4
#define PT_SHLIB 5
#define PT_PHDR 6
#define PT_LOPROC 0x70000000
#define PT_HIPROC 0x7fffffff
/* ELF file header */
typedef struct {
Elf32_Word e_magic;
u8 e_class;
u8 e_data;
u8 e_idver;
u8 e_pad[9];
Elf32_Half e_type;
Elf32_Half e_machine;
Elf32_Word e_version;
Elf32_Addr e_entry;
Elf32_Off e_phoff;
Elf32_Off e_shoff;
Elf32_Word e_flags;
Elf32_Half e_ehsize;
Elf32_Half e_phentsize;
Elf32_Half e_phnum;
Elf32_Half e_shentsize;
Elf32_Half e_shnum;
Elf32_Half e_shstrndx;
} __attribute__((packed)) Elf32_Ehdr;
/* ELF section header */
typedef struct {
Elf32_Word sh_name;
Elf32_Word sh_type;
Elf32_Word sh_flags;
Elf32_Addr sh_addr;
Elf32_Off sh_offset;
Elf32_Word sh_size;
Elf32_Word sh_link;
Elf32_Word sh_info;
Elf32_Word sh_addralign;
Elf32_Word sh_entsize;
} __attribute__((packed)) Elf32_Shdr;
typedef struct {
Elf32_Word p_type;
Elf32_Off p_offset;
Elf32_Addr p_vaddr;
Elf32_Addr p_paddr;
Elf32_Word p_filesz;
Elf32_Word p_memsz;
Elf32_Word p_flags;
Elf32_Word p_align;
} Elf32_Phdr;
#define ELF32_R_SYM(i) ((i)>>8)
#define ELF32_R_TYPE(i) ((u8)(i&0xFF))
typedef struct {
Elf32_Addr r_offset;
Elf32_Word r_info;
} Elf32_Rel;
typedef struct {
Elf32_Word st_name;
Elf32_Addr st_value;
Elf32_Word st_size;
unsigned char st_info;
unsigned char st_other;
Elf32_Half st_shndx;
} __attribute__((packed)) Elf32_Sym;
#define STB_LOCAL 0
#define STB_GLOBAL 1
#define STB_WEAK 2
#define STB_LOPROC 13
#define STB_HIPROC 15
#define ELF32_ST_BIND(i) ((i)>>4)
#define ELF32_ST_TYPE(i) ((i)&0xf)
#define ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf))
#endif

150
utils/kprxgen/prxtypes.h Normal file
View File

@ -0,0 +1,150 @@
/*
* PSP Software Development Kit - http://www.pspdev.org
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* prxtypes.h - Definition of PRX specific types.
*
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
*
* $Id: prxtypes.h 1095 2005-09-27 21:02:16Z jim $
*/
#ifndef __PRXTYPES_H__
#define __PRXTYPES_H__
#include "types.h"
#define PSP_MODULE_MAX_NAME 28
#define PSP_LIB_MAX_NAME 128
#define PSP_ENTRY_MAX_NAME 128
/* Define the maximum number of permitted entries per lib */
#define PSP_MAX_V_ENTRIES 255
#define PSP_MAX_F_ENTRIES 65535
#define PSP_MODULE_INFO_NAME ".rodata.sceModuleInfo"
/* Remove the .rel.sceStub.text section as it shouldn't have been there */
#define PSP_MODULE_REMOVE_REL ".rel.sceStub.text"
/* Define a name for the unnamed first export */
#define PSP_SYSTEM_EXPORT "syslib"
enum PspEntryType
{
PSP_ENTRY_FUNC = 0,
PSP_ENTRY_VAR = 1
};
/* Define the in-prx structure types */
/* Structure to hold the module export information */
struct PspModuleExport
{
u32 name;
u32 flags;
u32 counts;
u32 exports;
} __attribute__((packed));
/* Structure to hold the module import information */
struct PspModuleImport
{
u32 name;
u32 flags;
u8 entry_size;
u8 var_count;
u16 func_count;
u32 nids;
u32 funcs;
};
/* Structure to hold the module info */
struct PspModuleInfo
{
u32 flags;
char name[PSP_MODULE_MAX_NAME];
u32 gp;
u32 exports;
u32 exp_end;
u32 imports;
u32 imp_end;
};
/* Define the loaded prx types */
struct PspEntry
{
/* Name of the entry */
char name[PSP_ENTRY_MAX_NAME];
/* Nid of the entry */
u32 nid;
/* Type of the entry */
enum PspEntryType type;
/* Virtual address of the entry in the loaded elf */
u32 addr;
/* Virtual address of the nid dword */
u32 nid_addr;
};
/* Holds a linking entry for an import library */
struct PspLibImport
{
/** Previous import */
struct PspLibImport *prev;
/** Next import */
struct PspLibImport *next;
/** Name of the library */
char name[PSP_LIB_MAX_NAME];
/* Virtual address of the lib import stub */
u32 addr;
/* Copy of the import stub (in native byte order) */
struct PspModuleImport stub;
/* List of function entries */
struct PspEntry funcs[PSP_MAX_F_ENTRIES];
/* Number of function entries */
int f_count;
/* List of variable entried */
struct PspEntry vars[PSP_MAX_V_ENTRIES];
/* Number of variable entires */
int v_count;
};
/* Holds a linking entry for an export library */
struct PspLibExport
{
/** Previous export in the chain */
struct PspLibExport *prev;
/** Next export in the chain */
struct PspLibExport *next;
/** Name of the library */
char name[PSP_LIB_MAX_NAME];
/** Virtual address of the lib import stub */
u32 addr;
/** Copy of the import stub (in native byte order) */
struct PspModuleExport stub;
/** List of function entries */
struct PspEntry funcs[PSP_MAX_F_ENTRIES];
/** Number of function entries */
int f_count;
/** List of variable entried */
struct PspEntry vars[PSP_MAX_V_ENTRIES];
/** Number of variable entires */
int v_count;
};
/** Structure to hold the loaded module information */
struct PspModule
{
/** Name of the module */
char name[PSP_MODULE_MAX_NAME+1];
/** Info structure, in native byte order */
struct PspModuleInfo info;
/** Virtual address of the module info section */
u32 addr;
/** Head of the export list */
struct PspLibExport *exp_head;
/** Head of the import list */
struct PspLibImport *imp_head;
};
#endif

815
utils/kprxgen/psp-kprxgen.c Normal file
View File

@ -0,0 +1,815 @@
/* Copyright (C) 2011 The uOFW team
See the file COPYING for copying permission.
Based on the original file from PSPSDK, written by tyranid; many thanks to him!
*/
#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;
static struct ElfSection *g_elfsections = NULL;
static struct ElfSection *g_modinfo = NULL;
static int g_alloc_size = 0;
static int g_reloc_size = 0;
/* 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;
/* 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");
break;
}
data = (unsigned char *) malloc(size);
if(data == NULL)
{
fprintf(stderr, "Error, could not allocate memory for ELF\n");
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()
{
int ret = 0;
int found_rel = 0;
unsigned int load_addr = 0xFFFFFFFF;
if(g_elfhead.iShnum > 0)
{
do
{
Elf32_Shdr *sect;
u32 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;
}
}
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;
}
}
/* Okay so we have loaded all the sections, lets fix up the names */
for(i = 0; i < g_elfhead.iShnum; i++)
{
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);
}
}
if(LH(pSymData[iSymbol].st_shndx) == 0)
{
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)
{
u32 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)
{
u32 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())
{
break;
}
if(!process_relocs())
{
break;
}
reindex_sections();
ret = 1;
}
while(0);
return ret;
}
int calculate_outsize(void)
{
u32 alloc_size = 0;
int reloc_size = 0;
u32 i;
/* Calculate how big our output file needs to be */
/* We have elf header + 3 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 = g_elfsections[i].iAddr + g_elfsections[i].iSize;
if(top_addr > alloc_size)
{
alloc_size = top_addr;
}
}
else if((g_elfsections[i].iType == SHT_REL) || (g_elfsections[i].iType == SHT_PRXRELOC))
{
/* Check this is a reloc for an allocated section */
if(g_elfsections[g_elfsections[i].iInfo].iFlags & SHF_ALLOC)
{
reloc_size += g_elfsections[i].iSize;
}
}
}
}
alloc_size = (alloc_size + 3) & ~3;
/* Save them for future use */
g_alloc_size = alloc_size;
g_reloc_size = reloc_size;
/* Lets build the offsets */
g_phbase = sizeof(Elf32_Ehdr);
/* The allocated data needs to be 64 byte aligned (probably; seen in kernel .prx files) */
g_allocbase = (g_phbase + 3 * sizeof(Elf32_Phdr) + 0x3F) & ~0x3F;
g_relocbase = g_allocbase + g_alloc_size;
return g_relocbase + g_reloc_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, 3);
SH(&head->e_shentsize, 0);
SH(&head->e_shnum, 0);
SH(&head->e_shstrndx, 0);
}
struct ElfSection *get_sh(const char *name)
{
u32 i;
for(i = 0; i < g_elfhead.iShnum; i++)
if (strcmp(name, g_elfsections[i].szName) == 0)
return &g_elfsections[i];
return NULL;
}
/* 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_alloc_size);
SW(&phdr->p_flags, 5);
SW(&phdr->p_align, 0x40);
/* Second program header */
phdr++;
SW(&phdr->p_type, 1);
SW(&phdr->p_offset, get_sh(".data")->iAddr + g_allocbase);
SW(&phdr->p_vaddr, get_sh(".data")->iAddr);
SW(&phdr->p_paddr, 0);
SW(&phdr->p_filesz, get_sh(".data")->iSize);
SW(&phdr->p_memsz, get_sh(".data")->iSize + get_sh(".bss")->iSize);
SW(&phdr->p_flags, 6);
SW(&phdr->p_align, 0x40);
/* Third program header */
phdr++;
SW(&phdr->p_type, 0x700000A1);
SW(&phdr->p_offset, g_relocbase);
SW(&phdr->p_vaddr, 0);
SW(&phdr->p_paddr, 0);
SW(&phdr->p_filesz, g_reloc_size);
SW(&phdr->p_memsz, 0);
SW(&phdr->p_flags, 0);
SW(&phdr->p_align, 0x10);
}
/* Output the allocated sections */
void output_alloc(unsigned char *data)
{
u32 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 relocations */
void output_relocs(unsigned char *data)
{
u32 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 a stripped prx file */
int output_prx(const char *prxfile)
{
int size;
unsigned char *data;
FILE *fp;
do
{
size = calculate_outsize();
data = 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_relocs(data + g_relocbase);
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;
}

149
utils/kprxgen/types.h Normal file
View File

@ -0,0 +1,149 @@
/*
* PSP Software Development Kit - http://www.pspdev.org
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* types.h - Definition of basic cross platform types.
*
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
*
* $Id: types.h 2333 2007-10-31 19:37:40Z tyranid $
*/
#ifndef __TYPES_H__
#define __TYPES_H__
#include <stdint.h>
/* Re-define some system types */
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef int8_t s8;
typedef int16_t s16;
typedef int32_t s32;
typedef int64_t s64;
#ifdef WORDS_BIGENDIAN
inline u32 lw_le(u32 data)
{
u8 *ptr;
u32 val;
ptr = (u8*) &data;
val = ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
return val;
}
inline u16 lh_le(u16 data)
{
u8 *ptr;
u16 val;
ptr = (u8*) &data;
val = ptr[0] | (ptr[1] << 8);
return val;
}
#define LW_LE(x) (lw_le((x)))
#define LW_BE(x) (x)
#define LH_LE(x) (lh_le((x)))
#define LH_BE(x) (x)
#else
inline u32 lw_be(u32 data)
{
u8 *ptr;
u32 val;
ptr = (u8*) &data;
val = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3];
return val;
}
inline u16 lh_be(u16 data)
{
u8 *ptr;
u16 val;
ptr = (u8*) &data;
val = (ptr[0] << 16) | ptr[1];
return val;
}
#define LW_LE(x) (x)
#define LW_BE(x) (lw_be((x)))
#define LH_LE(x) (x)
#define LH_BE(x) (lh_be((x)))
#endif
#define LW(x) (LW_LE(x))
#define LH(x) (LH_LE(x))
#ifdef WORDS_BIGENDIAN
inline void sw_le(u32 *data, u32 val)
{
u8* ptr = (u8*) data;
ptr[0] = (u8) (val & 0xFF);
ptr[1] = (u8) ((val >> 8) & 0xFF);
ptr[2] = (u8) ((val >> 16) & 0xFF);
ptr[3] = (u8) ((val >> 24) & 0xFF);
}
inline void sh_le(u16 *data, u16 val)
{
u8 *ptr = (u8*) data;
ptr[0] = (u8) (val & 0xFF);
ptr[1] = (u8) ((val >> 8) & 0xFF);
}
#define SW_LE(x, v) (sw_le((x), (v)))
#define SW_BE(x, v) (*(x) = (v))
#define SH_LE(x, v) (sh_le((x), (v)))
#define SH_BE(x, v) (*(x) = (v))
#else
inline void sw_be(u32 *data, u32 val)
{
u8 *ptr = (u8*) data;
ptr[0] = (u8) ((val >> 24) & 0xFF);
ptr[1] = (u8) ((val >> 16) & 0xFF);
ptr[2] = (u8) ((val >> 8) & 0xFF);
ptr[3] = (u8) (val & 0xFF);
}
inline void sh_be(u16 *data, u16 val)
{
u8* ptr = (u8*) data;
ptr[0] = (u8) ((val >> 8) & 0xFF);
ptr[1] = (u8) (val & 0xFF);
}
#define SW_LE(x, v) (*(x) = (v))
#define SW_BE(x, v) (sw_be((x), (v)))
#define SH_LE(x, v) (*(x) = (v))
#define SH_BE(x, v) (sh_be((x), (v)))
#endif
#define SW(x, v) (SW_LE(x, v))
#define SH(x, v) (SH_LE(x, v))
#endif