00001
00002
00003
00004
00005
00006 #include<linux/linkage.h>
00007
00008 #include<linux/mm.h>
00009 #include <asm/uaccess.h>
00010
00011 #include<starlet.h>
00012
00013 #include<descrip.h>
00014 #include<ihadef.h>
00015 #include<ihddef.h>
00016 #include<ihidef.h>
00017 #include<ihpdef.h>
00018 #include<ihsdef.h>
00019 #include<ihvndef.h>
00020 #include<isddef.h>
00021
00022 #include<imcbdef.h>
00023
00024 #include<va_rangedef.h>
00025
00026 #include<system_data_cells.h>
00027
00028 #include <iafdef.h>
00029 #include <ihddef.h>
00030 #include <shldef.h>
00031
00032 #include<ssdef.h>
00033
00034 typedef struct {
00035 unsigned char r_offset[4];
00036 unsigned char r_info[4];
00037 unsigned char r_addend[4];
00038 } Elf32_External_Rela;
00039
00040 typedef struct {
00041 unsigned char st_name[4];
00042 unsigned char st_value[4];
00043 unsigned char st_size[4];
00044 unsigned char st_info[1];
00045 unsigned char st_other[1];
00046 unsigned char st_shndx[2];
00047 } Elf32_External_Sym;
00048
00049 typedef struct bfd_symbol
00050 {
00051 const char *name;
00052 int value;
00053 int flags;
00054 struct bfd_section *section;
00055 }
00056 asymbol;
00057
00058 #define COERCE32(x) (((signed long) (x) ^ 0x80000000) - 0x80000000)
00059
00060 unsigned int
00061 bfd_getl32 (void * dummy, const void *p)
00062 {
00063 const unsigned char *addr = p;
00064 unsigned long v;
00065
00066 v = (unsigned long) addr[0];
00067 v |= (unsigned long) addr[1] << 8;
00068 v |= (unsigned long) addr[2] << 16;
00069 v |= (unsigned long) addr[3] << 24;
00070 return v;
00071 }
00072
00073 signed int
00074 bfd_getl_signed_32 (void * dummy, const void *p)
00075 {
00076 const unsigned char *addr = p;
00077 unsigned long v;
00078
00079 v = (unsigned long) addr[0];
00080 v |= (unsigned long) addr[1] << 8;
00081 v |= (unsigned long) addr[2] << 16;
00082 v |= (unsigned long) addr[3] << 24;
00083 return COERCE32 (v);
00084 }
00085
00086 signed short
00087 bfd_getl16 (void * dummy, const void *p)
00088 {
00089 const unsigned char *addr = p;
00090 return (addr[1] << 8) | addr[0];
00091 }
00092
00093
00094 #define bfd_h_get_16 bfd_getl16
00095 #define bfd_h_get_32 bfd_getl32
00096 #define bfd_h_get_signed_32 bfd_getl_signed_32
00097 #define H_GET_16 bfd_h_get_16
00098 #define H_GET_32 bfd_h_get_32
00099 #define H_GET_S32 bfd_h_get_signed_32
00100 #define H_GET_WORD H_GET_32
00101 #define H_GET_SIGNED_WORD H_GET_S32
00102
00103 void
00104 nisse_swap_symbol_in (void *abfd,
00105 const void *psrc,
00106 const void *pshn,
00107 asymbol *dst)
00108 {
00109 const Elf32_External_Sym *src = psrc;
00110
00111 int signed_vma = 0;
00112 dst->name = H_GET_32 (abfd, src->st_name);
00113 if (signed_vma)
00114 dst->value = H_GET_SIGNED_WORD (abfd, src->st_value);
00115 else
00116 dst->value = H_GET_WORD (abfd, src->st_value);
00117 dst->flags = H_GET_WORD (abfd, src->st_size);
00118 dst->section = H_GET_16 (abfd, src->st_shndx);
00119 }
00120
00121 int
00122 find_symtab_offset(void * symtab, long offset, void **v) {
00123 while (1) {
00124 Elf32_External_Sym * src = symtab;
00125 if (src->st_name[0]==0 && src->st_name[1]==0) break;
00126 asymbol dst;
00127 nisse_swap_symbol_in(0, src, 0, &dst);
00128 symtab += sizeof(Elf32_External_Sym);
00129 if (offset==dst.name)
00130 *v=src;
00131 if (offset==dst.name)
00132 return dst.value;
00133 src++;
00134 }
00135 return -1;
00136 }
00137
00138 int
00139 find_section_offset (struct _ihd * ihd, int secno)
00140 {
00141 struct _isd * isd = (long)ihd+ihd->ihd_w_size;
00142 while (secno && isd<((long)ihd+512*ihd->ihd_b_hdrblkcnt)) {
00143 if (isd->isd_w_size==0)
00144 break;
00145 if (isd->isd_w_size==0xffffffff) {
00146 int no=((unsigned long)isd-(unsigned long)ihd)>>9;
00147 isd=(long)+512*(no+1);
00148 continue;
00149 }
00150 secno--;
00151 isd=(unsigned long)isd+isd->isd_w_size;
00152 }
00153 return isd->isd_v_vpn<<12;
00154 }
00155
00156 int find_symtab(void * abfd, void * symtab, long symstr, char * s) {
00157 while (1) {
00158 Elf32_External_Sym * src = symtab;
00159 if (src->st_name[0]==0 && src->st_name[1]==0) break;
00160 asymbol dst;
00161 nisse_swap_symbol_in(abfd, src, 0, &dst);
00162 symtab += sizeof(Elf32_External_Sym);
00163 if (0==strcmp(symstr+dst.name,s)) {
00164 return src;
00165 }
00166 src++;
00167 }
00168 return 0;
00169 }
00170
00171 void *
00172 find_it(void * sh, char * s, void ** retiaf ) {
00173 struct _shl * shlst=sh;
00174 int i;
00175 for(i=0;shlst[i].shl_t_imgnam[0];i++) {
00176 struct _iaf * iaf = ctl_gl_fixuplnk;
00177 char * imgnam=&shlst[i].shl_t_imgnam[0];
00178 for(;iaf;iaf=iaf->iaf_l_fixuplnk) {
00179 struct _ihd * ihd=iaf->iaf_l_iaflink;
00180 struct _ihi * ihi=(unsigned long)ihd+ihd->ihd_w_imgidoff;
00181 struct _ihs * ihs=(unsigned long)ihd+ihd->ihd_w_symdbgoff;
00182
00183 int symtab = (long)iaf->iaf_l_permctx+0xf000+(ihs->ihs$l_dstvbn<<9);
00184 char * symtabstr = (long)iaf->iaf_l_permctx+0xf000+(ihs->ihs$l_dmtvbn<<9);
00185 void *src;
00186 src=find_symtab(0,symtab,symtabstr,s);
00187 if (src==0)
00188 continue;
00189 asymbol dst;
00190 nisse_swap_symbol_in(0, src, 0, &dst);
00191 if (dst.section==255)
00192 continue;
00193 *retiaf=iaf;
00194 return src;
00195 }
00196 }
00197 return 0;
00198 }
00199
00200 asmlinkage int exe_imgfix(void) {
00201 #ifdef CONFIG_VMS
00202
00203 char buf[512];
00204
00205 struct _ihd * ehdr32 = buf;
00206
00207 struct _iaf * iaf = ctl_gl_fixuplnk;
00208
00209 for(;iaf;iaf=iaf->iaf_l_fixuplnk) {
00210 int fixup_vector = iaf;
00211
00212 long * g_fix = fixup_vector + iaf->iaf_l_g_fixoff;
00213 long * dotad = fixup_vector + iaf->iaf_l_dotadroff;
00214 long * shlp = fixup_vector + iaf->iaf_l_shlstoff;
00215 int shrimgcnt = iaf->iaf_l_shrimgcnt;
00216
00217 struct _shl * shlst = shlp;
00218 int * addr;
00219
00220 int shri;
00221
00222 #if 0
00223 for (shri=0;shri<1;shri++) { }
00224 #endif
00225
00226 int mainbase=shlst[shri].shl_l_baseva;
00227
00228 int * addr_g;
00229 addr_g = fixup_vector+iaf->iaf_l_g_fixoff;
00230 int * addr_d;
00231 addr_d = fixup_vector+iaf->iaf_l_dotadroff;
00232
00233 addr=addr_g;
00234 int again=2;
00235 while (again) {
00236 int refc=*addr++;
00237 int shli=*addr++;
00238 #if 0
00239
00240 long base=shlst[shli].shl_l_baseva;
00241 #endif
00242 #if 0
00243
00244 while (refc--) {}
00245 *addr+=mainbase;
00246 addr++;
00247 #else
00248 Elf32_External_Rela * adr = addr;
00249 if (refc==0)
00250 goto norefc;
00251 while (refc--) {
00252 int * tmp = &adr->r_info;
00253 char type=(*tmp)&0xff;
00254 int symo=(*tmp)>>8;
00255 tmp=&adr->r_offset;
00256 Elf32_External_Sym * p = 0;
00257 struct _ihd * ihd=iaf->iaf_l_iaflink;
00258 struct _ihs * ihs=(unsigned long)ihd+ihd->ihd_w_symdbgoff;
00259 int symtab = (long)iaf->iaf_l_permctx+0xf000+(ihs->ihs$l_dstvbn<<9);
00260 char * symtabstr = (long)iaf->iaf_l_permctx+0xf000+(ihs->ihs$l_dmtvbn<<9);
00261 void *src;
00262 if (symo)
00263 p=find_symtab_offset(symtab, symo, &src);
00264 if (p==-1)
00265 printk("problem finding %x %x\n",symtab, symo);
00266 if (p==-1)
00267 goto skip_me;
00268
00269 asymbol dst;
00270 nisse_swap_symbol_in(0, src, 0, &dst);
00271
00272 struct _iaf * iaf2=iaf;
00273 int base2=0;
00274 int base3=0;
00275 int sec3=dst.section;
00276 if (dst.section==255) {
00277 src=find_it((long)iaf+iaf->iaf_l_shlstoff,symtabstr+symo, &iaf2);
00278 if (src==0)
00279 printk("problem2 finding %x %s\n",(long)iaf->iaf_l_shlstoff,symtabstr+symo);
00280 if (src==0)
00281 goto skip_me;
00282 nisse_swap_symbol_in(0, src, 0, &dst);
00283 sec3=dst.section;
00284 }
00285
00286 base2=find_section_offset(iaf->iaf_l_iaflink,shli);
00287 base3=find_section_offset(iaf2->iaf_l_iaflink,sec3);
00288
00289 int base4=iaf->iaf_l_permctx;
00290 int base5=iaf2->iaf_l_permctx;
00291
00292 int offset = *tmp;
00293 long * myaddr = base4 + base2 + + offset;
00294
00295 #if 0
00296 printk("rel %x %x %x %x %x %x %x %x %s\n",type,shli,base2,base3,base4,base5,p,offset,symtabstr+symo);
00297 #endif
00298
00299 if (type==1)
00300 *myaddr=base5+base3+(int)p;
00301 if (type==2)
00302 *myaddr=base5+base3+(int)p-(int)myaddr-4;
00303 #if 0
00304 printk("rel2 %x %x\n",myaddr,*myaddr);
00305 #endif
00306 skip_me:
00307 adr++;
00308 }
00309 addr=adr;
00310 if (*addr==0)
00311 addr+=2;
00312 norefc:
00313 if (*addr==0) {
00314 addr+=2;
00315 again--;
00316 }
00317 }
00318 #endif
00319
00320 #if 0
00321
00322 if (dotad) {
00323 addr=0x3e000000 + dotad;
00324 while (*addr) {
00325 int refc=*addr++;
00326 int shli=*addr++;
00327 long base=shlst[shli].shl_l_baseva;
00328 #if 0
00329
00330 while (refc--) {
00331 int * dest = mainbase + *addr++;
00332 *dest+=base;
00333 }
00334 #else
00335 Elf32_External_Rela * adr = addr;
00336 while (refc--) {
00337 }
00338 #endif
00339 }
00340 }
00341 #endif
00342 }
00343
00344 ctl_gl_iaflnkptr=0;
00345 ctl_gl_fixuplnk=0;
00346 #endif
00347 return SS__NORMAL;
00348 }
00349
00350
00351
00352