diff -auEbB -r -u5 -N -x CVS -x '*~' -x '.#*' clean/ecos/packages/services/objloader/current/include/relocate_i386.h devo/ecos/packages/services/objloader/current/include/relocate_i386.h --- clean/ecos/packages/services/objloader/current/include/relocate_i386.h 2005-07-08 21:14:13.000000000 +0100 +++ devo/ecos/packages/services/objloader/current/include/relocate_i386.h 2005-08-26 15:52:23.879324800 +0100 @@ -64,8 +64,8 @@ #define R_386_32 1 #define R_386_PC32 2 void cyg_ldr_flush_cache( void ); -cyg_int32 cyg_ldr_relocate( cyg_int32, cyg_uint32, cyg_int32 ); +cyg_int32 cyg_ldr_relocate( cyg_int32, cyg_uint32, cyg_int32, cyg_uint8 * ); #endif //__RELOCATE_I386_H__ diff -auEbB -r -u5 -N -x CVS -x '*~' -x '.#*' clean/ecos/packages/services/objloader/current/include/relocate_ppc.h devo/ecos/packages/services/objloader/current/include/relocate_ppc.h --- clean/ecos/packages/services/objloader/current/include/relocate_ppc.h 2005-07-07 11:55:13.000000000 +0100 +++ devo/ecos/packages/services/objloader/current/include/relocate_ppc.h 2005-08-26 15:52:22.867870400 +0100 @@ -125,8 +125,8 @@ #define _lo_(x) (x & 0xFFFF) #define _hi_(x) ((x >> 16) & 0xFFFF) #define _ha_(x) (((x >> 16)+((x & 0x8000) ? 1 : 0)) & 0xFFFF) void cyg_ldr_flush_cache( void ); -cyg_int32 cyg_ldr_relocate( cyg_int32, cyg_uint32, cyg_int32 ); +cyg_int32 cyg_ldr_relocate( cyg_int32, cyg_uint32, cyg_int32, cyg_uint8 * ); #endif //__RELOCATE_PPC_H__ diff -auEbB -r -u5 -N -x CVS -x '*~' -x '.#*' clean/ecos/packages/services/objloader/current/src/objelf.c devo/ecos/packages/services/objloader/current/src/objelf.c --- clean/ecos/packages/services/objloader/current/src/objelf.c 2005-07-08 21:14:13.000000000 +0100 +++ devo/ecos/packages/services/objloader/current/src/objelf.c 2005-08-26 16:40:30.049433600 +0100 @@ -319,15 +319,15 @@ Elf32_Rela* p_rela = (Elf32_Rela*)cyg_ldr_load_elf_section( p, r_shndx ); #else Elf32_Rel* p_rel = (Elf32_Rel*)cyg_ldr_load_elf_section( p, r_shndx ); #endif -#if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0 Elf32_Sym *p_symtab = (Elf32_Sym*)cyg_ldr_section_address( p, p->hdrndx_symtab ); cyg_uint8 *p_strtab = (cyg_uint8*)cyg_ldr_section_address( p, p->hdrndx_strtab ); +#if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0 cyg_uint8 *p_shstrtab = (cyg_uint8*)cyg_ldr_section_address( p, p->p_elfhdr->e_shstrndx ); #endif // Now we can get the address of the contents of the section to modify. @@ -387,11 +387,12 @@ } diag_printf( "\n" ); #endif rc = cyg_ldr_relocate( r_type, r_target_addr + r_offset, - sym_value + r_addend ); + sym_value + r_addend, + p_strtab + p_symtab[sym_index].st_name); if ( rc != 0 ) { #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0 diag_printf( "Relocation error: Cannot find symbol: %s\n", p_strtab + p_symtab[sym_index].st_name ); diff -auEbB -r -u5 -N -x CVS -x '*~' -x '.#*' clean/ecos/packages/services/objloader/current/src/relocate_i386.c devo/ecos/packages/services/objloader/current/src/relocate_i386.c --- clean/ecos/packages/services/objloader/current/src/relocate_i386.c 2005-07-08 21:14:14.000000000 +0100 +++ devo/ecos/packages/services/objloader/current/src/relocate_i386.c 2005-08-26 15:52:40.583344000 +0100 @@ -73,11 +73,11 @@ // // sym_type Type of relocation to apply, // mem Address in memory to modify (relocate). // sym_value cyg_int32 -cyg_ldr_relocate( cyg_int32 sym_type, cyg_uint32 mem, cyg_int32 sym_value ) +cyg_ldr_relocate( cyg_int32 sym_type, cyg_uint32 mem, cyg_int32 sym_value, cyg_uint8 *strname ) { cyg_int32 i; // PPC uses rela, so we have to add the addend. switch( sym_type ) diff -auEbB -r -u5 -N -x CVS -x '*~' -x '.#*' clean/ecos/packages/services/objloader/current/src/relocate_ppc.c devo/ecos/packages/services/objloader/current/src/relocate_ppc.c --- clean/ecos/packages/services/objloader/current/src/relocate_ppc.c 2005-07-07 11:55:13.000000000 +0100 +++ devo/ecos/packages/services/objloader/current/src/relocate_ppc.c 2005-08-26 15:54:05.725772800 +0100 @@ -63,11 +63,62 @@ #include #include #include + +#include + #ifdef CYGPKG_HAL_POWERPC + +// The code block is make up of +// the following instructions +// NOTE: the bctrl opcode generates 0x4e, 0x80, 0x04, 0x21, +// and we need 0x4e, 0x80, 0x04, 0x20, this will +// leave the LR intact +// +// asm volatile( +// "subi 1,1,8\n" +// "stw 3,0(1)\n" +// "lis 3,16386\n" +// "ori 3,3,8192\n" +// "mtctr 3\n" +// "lwz 3,0(1)\n" +// "addi 1,1,8\n" +// "bctrl\n" +// ); +// + +static const char cyg_ldr_rel24_code[] = +{ + 0x38, 0x21, 0xff, 0xf8, + 0x90, 0x61, 0x00, 0x00, + 0x3c, 0x60, 0x40, 0x02, + 0x60, 0x63, 0x20, 0x00, + 0x7c, 0x69, 0x03, 0xa6, + 0x80, 0x61, 0x00, 0x00, + 0x38, 0x21, 0x00, 0x08, + 0x4e, 0x80, 0x04, 0x20 +}; + + +typedef struct +{ + char cayTrampoline[sizeof(cyg_ldr_rel24_code)]; + char *pcaName; + void *pNextTrampoline; +} cyg_ldr_rel24_trampoline_type; + + +// this assumes that the trampoline will be placed +// in the same memory space as the loaded function +// NOTE: this is a very simple linked list +// we dont free it because we may need the entrys later +// but we could free it!! +static cyg_ldr_rel24_trampoline_type *cyg_ldr_rel24_trampoline_head = NULL; +static cyg_ldr_rel24_trampoline_type *cyg_ldr_rel24_trampoline_tail = NULL; + void cyg_ldr_flush_cache( void ) { HAL_DCACHE_SYNC(); HAL_ICACHE_SYNC(); @@ -77,11 +128,11 @@ // // sym_type Type of relocation to apply, // mem Address in memory to modify (relocate). // sym_value cyg_int32 -cyg_ldr_relocate( cyg_int32 sym_type, cyg_uint32 mem, cyg_int32 sym_value ) +cyg_ldr_relocate( cyg_int32 sym_type, cyg_uint32 mem, cyg_int32 sym_value, cyg_uint8 *strname) { cyg_int32 rel_offset, i; // PPC uses rela, so we have to add the addend. switch( sym_type ) @@ -94,10 +145,101 @@ return 0; case R_PPC_ADDR16_LO: HAL_WRITE_UINT16( mem, _lo_( sym_value ) ); return 0; case R_PPC_REL24: + + // only do this if the name is valid + if (strlen(strname) > 0) + { + if (cyg_ldr_rel24_trampoline_head == NULL ) + { + // need to setup the list + cyg_ldr_rel24_trampoline_head = malloc(sizeof(cyg_ldr_rel24_trampoline_type)); + // TODO: there may be an error here + cyg_ldr_rel24_trampoline_tail = cyg_ldr_rel24_trampoline_head; + + if (cyg_ldr_rel24_trampoline_tail != NULL) + memset(cyg_ldr_rel24_trampoline_tail, 0x0, sizeof(cyg_ldr_rel24_trampoline_type)); + + } + + if (cyg_ldr_rel24_trampoline_head != NULL ) + { + + bool blnFound = false; + + cyg_ldr_rel24_trampoline_type *pCurrentTrampoline; + + pCurrentTrampoline = cyg_ldr_rel24_trampoline_head; + + // ok, name is valid + // now scan the list for a matching entry + while((pCurrentTrampoline != NULL)&&(blnFound == false)) + { + if ((cyg_ldr_rel24_trampoline_tail->pcaName != NULL)&& + (strcmp(pCurrentTrampoline->pcaName, strname) == 0)) + { + // we have a match, so use it + blnFound = true; + } + else + { + // select the next entry + pCurrentTrampoline = pCurrentTrampoline->pNextTrampoline; + } + } + + // ok, did we find it? + if (blnFound == false) + { + // no, so we need to alloc a new entry + + // Ok we need to construct the trampoline + // this will be called instead of the function + // directly and will inturn jump to the function. + memcpy(&cyg_ldr_rel24_trampoline_tail->cayTrampoline[0], cyg_ldr_rel24_code, sizeof(cyg_ldr_rel24_code)); + + // need to mod the address, + // first to the top 16 bits + cyg_ldr_rel24_trampoline_tail->cayTrampoline[10] = (char)((sym_value>>24)&0xff); + cyg_ldr_rel24_trampoline_tail->cayTrampoline[11] = (char)((sym_value>>16)&0xff); + // now the bottom 16 bits + cyg_ldr_rel24_trampoline_tail->cayTrampoline[14] = (char)((sym_value>>8)&0xff); + cyg_ldr_rel24_trampoline_tail->cayTrampoline[15] = (char)((sym_value>>0)&0xff); + + cyg_ldr_rel24_trampoline_tail->pcaName = malloc(strlen(strname)+1); + + if (cyg_ldr_rel24_trampoline_tail->pcaName != NULL) + { + // set this new entry to the correct name + strcpy(cyg_ldr_rel24_trampoline_tail->pcaName, strname); + } + + // ok, use this entry for the Trampoline + pCurrentTrampoline = cyg_ldr_rel24_trampoline_tail; + + + // now create the next entry + cyg_ldr_rel24_trampoline_tail->pNextTrampoline = malloc(sizeof(cyg_ldr_rel24_trampoline_type)); + // set us to the next trampiline + cyg_ldr_rel24_trampoline_tail = (cyg_ldr_rel24_trampoline_type*)cyg_ldr_rel24_trampoline_tail->pNextTrampoline; + + if (cyg_ldr_rel24_trampoline_tail != NULL) + memset(cyg_ldr_rel24_trampoline_tail, 0x0, sizeof(cyg_ldr_rel24_trampoline_type)); + } + else + { + // we found an entry so use it + } + + // set the location of the + // function to the trampoline instead + sym_value = (cyg_int32)&pCurrentTrampoline->cayTrampoline[0]; + } + } + // Now it is time to seek the destination address of the call. // We need to do something in case the user jumps more than 16MB. rel_offset = ( sym_value - mem ) & 0x03FFFFFC; HAL_READ_UINT32( mem, i ); i &= 0xFC000003;