This is rel_rios.c in view mode; [Download] [Up]
/* Copyright William Schelter. All rights reserved. This file does the low level relocation which tends to be very system dependent. It is included by the file sfasl.c */ typedef int (*FUNC)(); extern int akcltoc; extern int toc_start; static int current_toc; static int ptrgl_offset = 0; static int ptrgl_text; static int akcltoc_used=0; /* This is an alternating list of addresses x1,y1,x2,y2,... where relocation entries for changing value in address x1 shold be read as changing it in y1 */ static int toc_addresses_to_relocate [10]; static int *next_toc_addresses_to_relocate = toc_addresses_to_relocate ; static int akcltoc_thisload; static int begun_relocate = 0; static int set_rel_bits(address,bits,val) char *address; int val; int bits; { bits += 1; if ( bits <= 16) {unsigned short y = *(unsigned short *)address ; y = y & (~0 << bits) ; y |= (val & ~(~0 << bits)); *(unsigned short *)address = val; } else {unsigned int y = *(unsigned int *)address ; y = y & (~0 << bits) ; y |= (val & ~(~0 << bits)); *(unsigned int *)address = y; } } /* 800b0000 l r0,0x0(r11) 90410014 st r2,0x14(r1) 7c0903a6 mtctr r0 804b0004 l r2,0x4(r11) 816b0008 l r11,0x8(r11) 4e800420 bctr */ int myptrgl[6] = { 0x800b0000, 0x90410014, 0x7c0903a6, 0x804b0004, 0x816b0008, 0x4e800420}; /* 7d8903a6 mtctr r12 4e800420 bctr */ static int jmp_r12[2] = { 0x7d8903a6, 0x4e800420}; #define SYM_SMC(sym) (((union auxent *)(sym+1))->x_csect.x_smclas) #define SYM_TOC_ADDR(sym) (((union auxent *)(sym+1))->x_csect.x_parmhash) /* #define SYM_USED(sym) (((union auxent *)(&sym[1]))->x_csect.x_snhash) */ #define TC_SYMBOL_P(sym) ((sym)->n_scnum == DATA_NSCN && NUM_AUX((sym)) && \ (SYM_SMC(sym) == XMC_TC0 || SYM_SMC(sym) == XMC_TC)) int FIXtemp ; static int intcmp2(x,y) int *x,*y; { return (*x - *y); } #define TOP6 (~0 << 26) #define BR_IN_DATA_P(x) (((x) & TOP6) == (DBEGIN & TOP6)) relocate() { struct syment *sym = &symbol_table[relocation_info.r_symndx]; char *where; describe_sym(relocation_info.r_symndx); where = the_start + relocation_info.r_vaddr; dprintf (where has %x , *(int *)where); dprintf( at %x -->, where ); if(begun_relocate == 0) {int n = next_toc_addresses_to_relocate - toc_addresses_to_relocate; begun_relocate = 1; FIXtemp = 0; /* dummy reference for export problem */ qsort((char *)toc_addresses_to_relocate, n/2 , 2*sizeof(int), intcmp2); next_toc_addresses_to_relocate = toc_addresses_to_relocate;} switch(RELOC_RTYPE(relocation_info)) { int *q; case R_TOC: /* TOC_ILodx */ set_rel_bits(where,RELOC_RLEN(relocation_info), sym->n_value - toc_start) ; break; case R_POS: /* Pos_Rel */ if (where == *next_toc_addresses_to_relocate) {where = next_toc_addresses_to_relocate [1]; next_toc_addresses_to_relocate += 2;} if ( sym->n_scnum == N_UNDEF || TC_SYMBOL_P(sym)) set_rel_bits(where,RELOC_RLEN(relocation_info), sym->n_value); else set_rel_bits(where,RELOC_RLEN(relocation_info), (*(int *)where)+ sym->n_value); break; case R_BR: /* Brn_Sel */ {int link_bit = ((((int *)where)[0]) & 1); if (((((int *)where)[0]) & TOP6 ) == 0x48000000) /* bl or b relative */ { if (((int *)where)[1] == 0x80410014) /* l r2,0x14(r1) */ {int x = SYM_TOC_ADDR(sym); if (x) { ((int *)where)[0] = 0x81820000 ; /* l r12,0x0(r2) */ set_rel_bits(where+2,15,x - toc_start); (((int *)where)[1] = 0x48000000); /* b relative */ set_rel_bits(where+4, 0x19, ((int) jmp_r12) - ((int) where + 4 )); ((int *)where)[1] |= link_bit; /* link bit */ break; } else /* must be ptrgl */ if (BR_IN_DATA_P(sym->n_value)) {set_rel_bits(where, 0x19, sym->n_value - (int) where); ((int *)where)[0] |= link_bit; /* link bit */ break;} } else if (BR_IN_DATA_P(sym->n_value)) {set_rel_bits(where, 0x19, sym->n_value - (int) where); ((int *)where)[0] |= link_bit; /* link bit */ break;}} else FEerror("The type of Br_sel was new ",0,0); } default: fprintf(stdout, "%d: unsupported relocation type.", RELOC_RTYPE(relocation_info) ); FEerror("The relocation type was unknown",0,0); } dprintf( %x,*(int *)where); } fix_undef_toc_address(answ,sym,str) char *str; struct syment *sym; struct node *answ; /* undefined sym */ { if (BR_IN_DATA_P(answ->address)) return; if (answ->tc_offset == 0) { answ->tc_offset = ( akcltoc + akcltoc_used - toc_start); * ((int *)( akcltoc + akcltoc_used)) = answ->address; akcltoc_used += sizeof(char *); } if (NUM_AUX(sym)) SYM_TOC_ADDR(sym) = (toc_start + answ->tc_offset); else printf("symbol should have aux entry"); return; } #ifdef DEBUG #undef describe_sym #define describe_sym(x) do{if(sfasldebug) describe_sym1(x);} while (0) describe_sym1(n) int n; {char *str; char tem[9]; struct syment *sym; sym= &symbol_table[n]; str= sym->n_zeroes == 0 ? &my_string_table[sym->n_offset] : (sym->n_name[SYMNMLEN -1] ? /* MAKE IT NULL TERMINATED */ (strncpy(tem,sym->n_name, SYMNMLEN),tem): sym->n_name ); printf ("sym-index = %d table entry at %x",n,&symbol_table[n]); printf("symbol is (%s):\nsymbol_table[n]._n._n_name %s\nsymbol_table[n]._n._n_n._n_zeroes %d\nsymbol_table[n]._n._n_n._n_offset %d\nsymbol_table[n]._n._n_nptr[0] %d\nsymbol_table[n]._n._n_nptr[n] %d\nsymbol_table[n].n_value %d\nsymbol_table[n].n_scnum %d nsymbol_table[n].n_type %d\nsymbol_table[n].n_sclass %d\nsymbol_table[n].n_numaux %d", str, symbol_table[n]._n._n_name, symbol_table[n]._n._n_n._n_zeroes , symbol_table[n]._n._n_n._n_offset , symbol_table[n]._n._n_nptr[0] , symbol_table[n]._n._n_nptr[1] , symbol_table[n].n_value , symbol_table[n].n_scnum , symbol_table[n].n_type , symbol_table[n].n_sclass , symbol_table[n].n_numaux ); } #endif /* allocate toc space in the preallocated region starting at akcltoc. If a symbol already has a toc entry, use that instead */ setup_for_aix_load() { bzero(toc_addresses_to_relocate,sizeof(toc_addresses_to_relocate)); next_toc_addresses_to_relocate= toc_addresses_to_relocate; akcltoc_thisload = akcltoc + akcltoc_used; begun_relocate=0; } char * sym_name(sym) struct syment *sym; {static char tem[SYMNMLEN +1]; char *name; tem[SYMNMLEN] = '0'; name = SYM_NAME(sym); return name;} allocate_toc(sym) struct syment *sym; /* sym is a symbol in the data section with an aux entry */ { if (SYM_SMC(sym) == XMC_TC0) { sym->n_value = toc_start; return 1;} if (SYM_SMC(sym) == XMC_TC) {struct node *answ = find_sym(sym,0); if (answ && answ->tc_offset) { sym->n_value = toc_start + answ->tc_offset; return 1;} {char *na = sym_name(sym); #ifdef SYM_USED if (TC_SYMBOL_P(sym) && SYM_USED(sym) == 0) return 0; #endif if (answ == 0 && *na && *na != '_') printf("(strange TC synbol %s[%d])",na,sym - symbol_table);} {int old_value; (*next_toc_addresses_to_relocate++) = sym->n_value + start_address; sym->n_value = akcltoc + akcltoc_used; if (answ) answ->tc_offset = sym->n_value - toc_start; (*next_toc_addresses_to_relocate++) = sym->n_value; *((int *)(next_toc_addresses_to_relocate[-1])) = *((int *)(next_toc_addresses_to_relocate[-2])); akcltoc_used += sizeof(long int); if (next_toc_addresses_to_relocate - toc_addresses_to_relocate >= (sizeof(toc_addresses_to_relocate)/sizeof(int))) FEerror("ran out"); if (akcltoc_used > 24000) FEerror("toc exhausted"); return 1; }} return 0; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.