~ubuntu-branches/ubuntu/quantal/gclcvs/quantal

« back to all changes in this revision

Viewing changes to o/rel_rios.c

  • Committer: Bazaar Package Importer
  • Author(s): Camm Maguire
  • Date: 2004-06-24 15:13:46 UTC
  • Revision ID: james.westby@ubuntu.com-20040624151346-xh0xaaktyyp7aorc
Tags: 2.7.0-26
C_GC_OFFSET is 2 on m68k-linux

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright William Schelter. All rights reserved.  This file does
 
2
the low level relocation which tends to be very system dependent.
 
3
It is included by the file sfasl.c
 
4
*/
 
5
 
 
6
typedef int (*FUNC)();
 
7
extern int akcltoc;
 
8
extern int toc_start;
 
9
static int current_toc;
 
10
static int ptrgl_offset = 0;
 
11
static int  ptrgl_text;
 
12
 
 
13
static int akcltoc_used=0;
 
14
 
 
15
/* This is an alternating list of addresses x1,y1,x2,y2,... where
 
16
   relocation entries for changing value in address x1 shold be read as changing
 
17
   it in y1 */
 
18
 
 
19
static  int  toc_addresses_to_relocate [10];
 
20
static  int *next_toc_addresses_to_relocate = toc_addresses_to_relocate ;
 
21
static int akcltoc_thisload;
 
22
static int begun_relocate = 0;
 
23
 
 
24
static int set_rel_bits(address,bits,val)
 
25
     char *address;
 
26
     int val;
 
27
     int bits;
 
28
{ bits += 1;
 
29
 if ( bits <= 16)
 
30
   {unsigned short  y = *(unsigned short *)address ;
 
31
    y = y &  (~0 << bits) ;
 
32
    y |= (val & ~(~0 << bits));
 
33
    *(unsigned short *)address = val;
 
34
  }
 
35
  else
 
36
   {unsigned int  y = *(unsigned int *)address ;
 
37
    y = y &  (~0 << bits) ;
 
38
    y |= (val & ~(~0 << bits));
 
39
    *(unsigned int *)address = y;
 
40
  }
 
41
}
 
42
 
 
43
#ifdef AIX3
 
44
struct syment *
 
45
get_symbol(name,scnum,sym_table,length)
 
46
     char *name;
 
47
     int scnum,length;
 
48
     struct syment *sym_table;
 
49
{ struct syment *end,*sym;
 
50
 char tem[SYMNMLEN +1];
 
51
  char *na;
 
52
  end =sym_table + length;
 
53
  for(sym=sym_table; sym < end; sym += (NUM_AUX(sym) +1))
 
54
    {if ((sym)->n_scnum  == scnum)
 
55
      { na=SYM_NAME(sym);
 
56
        if (strcmp(name,na) == 0)
 
57
          {return sym;}}}
 
58
  return 0;}
 
59
#endif /* aix3 */
 
60
 
 
61
/*
 
62
 800b0000          l   r0,0x0(r11)  
 
63
 90410014         st   r2,0x14(r1)  
 
64
 7c0903a6      mtctr   r0           
 
65
 804b0004          l   r2,0x4(r11)         
 
66
 816b0008          l   r11,0x8(r11) 
 
67
 4e800420       bctr                
 
68
*/
 
69
int myptrgl[6] = {
 
70
  0x800b0000, 0x90410014, 0x7c0903a6, 0x804b0004,
 
71
  0x816b0008, 0x4e800420};
 
72
 
 
73
/* 7d8903a6      mtctr   r12 
 
74
 4e800420       bctr
 
75
 */
 
76
static int jmp_r12[2] = { 0x7d8903a6, 0x4e800420};
 
77
 
 
78
  
 
79
#define SYM_SMC(sym)  (((union auxent *)(sym+1))->x_csect.x_smclas)
 
80
#define SYM_TOC_ADDR(sym)  (((union auxent *)(sym+1))->x_csect.x_parmhash)
 
81
/* #define SYM_USED(sym)   (((union auxent *)(&sym[1]))->x_csect.x_snhash) */
 
82
#define  TC_SYMBOL_P(sym) ((sym)->n_scnum == DATA_NSCN && NUM_AUX((sym)) && \
 
83
                           (SYM_SMC(sym) == XMC_TC0 ||  SYM_SMC(sym) == XMC_TC))
 
84
                            
 
85
 
 
86
 
 
87
int FIXtemp ;
 
88
static int intcmp2(x,y)
 
89
     int *x,*y;
 
90
{ return (*x - *y);
 
91
}
 
92
 
 
93
#define  TOP6 (~0 << 26)
 
94
#define  BR_IN_DATA_P(x) (((x) & TOP6) == (DBEGIN & TOP6))
 
95
 
 
96
 
 
97
relocate()
 
98
{ struct syment *sym = &symbol_table[relocation_info.r_symndx];
 
99
  char *where;
 
100
  describe_sym(relocation_info.r_symndx);
 
101
  where = the_start + relocation_info.r_vaddr;
 
102
  dprintf (where has %x , *(int *)where);
 
103
  dprintf(   at %x -->, where );
 
104
 
 
105
  if(begun_relocate == 0)
 
106
    {int n =   next_toc_addresses_to_relocate - toc_addresses_to_relocate;
 
107
       begun_relocate = 1;
 
108
     FIXtemp = 0; /* dummy reference for export problem */
 
109
     qsort((char *)toc_addresses_to_relocate, n/2 , 2*sizeof(int),  intcmp2);
 
110
     next_toc_addresses_to_relocate
 
111
       = toc_addresses_to_relocate;}
 
112
 
 
113
  switch(RELOC_RTYPE(relocation_info))
 
114
    { int *q;
 
115
 
 
116
    case R_TOC:     /* TOC_ILodx */
 
117
      set_rel_bits(where,RELOC_RLEN(relocation_info), sym->n_value -  toc_start) ;
 
118
      break;
 
119
    case R_POS:   /* Pos_Rel */
 
120
 
 
121
       if (where == *next_toc_addresses_to_relocate)
 
122
         {where = next_toc_addresses_to_relocate [1];
 
123
          next_toc_addresses_to_relocate +=  2;}
 
124
 
 
125
     if ( sym->n_scnum == N_UNDEF || TC_SYMBOL_P(sym))
 
126
        set_rel_bits(where,RELOC_RLEN(relocation_info),  sym->n_value);
 
127
     else
 
128
       set_rel_bits(where,RELOC_RLEN(relocation_info), (*(int *)where)+ sym->n_value);
 
129
 
 
130
      break;
 
131
    case R_BR:   /* Brn_Sel */
 
132
    case R_RBR:  /* Brn_Selx */
 
133
 
 
134
      {int link_bit = ((((int *)where)[0]) & 1);
 
135
       if (((((int *)where)[0]) & TOP6 ) == 0x48000000) /* bl or b relative */
 
136
         {
 
137
           if (((int *)where)[1] == 0x80410014) /* l   r2,0x14(r1) */
 
138
             {int x = SYM_TOC_ADDR(sym);
 
139
              if (x)
 
140
                { ((int *)where)[0]  = 0x81820000 ; /*  l   r12,0x0(r2) */
 
141
                  set_rel_bits(where+2,15,x - toc_start);
 
142
                  (((int *)where)[1] = 0x48000000); /* b relative */
 
143
                  set_rel_bits(where+4, 0x19, ((int) jmp_r12) - ((int) where + 4 ));
 
144
                  ((int *)where)[1] |=  link_bit; /* link bit */
 
145
                  break;
 
146
                }
 
147
              else              /* must be ptrgl */
 
148
                if  (BR_IN_DATA_P(sym->n_value))
 
149
                  {set_rel_bits(where, 0x19, sym->n_value - (int) where);
 
150
                   ((int *)where)[0] |=  link_bit; /* link bit */
 
151
                   break;}
 
152
            }
 
153
           else
 
154
             if (BR_IN_DATA_P(sym->n_value))
 
155
               {set_rel_bits(where, 0x19,  sym->n_value - (int) where);
 
156
                ((int *)where)[0] |=  link_bit; /* link bit */
 
157
                break;}}
 
158
       else
 
159
         FEerror("The type of Br_sel was new ",0,0);
 
160
     }
 
161
    default:
 
162
      fprintf(stdout, "%d: unsupported relocation type.",
 
163
              RELOC_RTYPE(relocation_info) );
 
164
      FEerror("The relocation type was unknown",0,0);
 
165
    }
 
166
  dprintf( %x,*(int *)where);
 
167
 
 
168
}
 
169
 
 
170
fix_undef_toc_address(answ,sym,str)
 
171
     char *str;
 
172
     struct syment *sym;
 
173
     struct node *answ;
 
174
     /* undefined sym */
 
175
{ if (BR_IN_DATA_P(answ->address)) return;
 
176
  if (answ->tc_offset == 0)
 
177
    { answ->tc_offset = ( akcltoc + akcltoc_used - toc_start);
 
178
      * ((int *)( akcltoc + akcltoc_used)) = answ->address;
 
179
      akcltoc_used += sizeof(char *);
 
180
    }
 
181
 
 
182
      if (NUM_AUX(sym))
 
183
        SYM_TOC_ADDR(sym) =  (toc_start + answ->tc_offset);
 
184
      else printf("symbol should have aux entry");
 
185
  
 
186
  return;
 
187
}
 
188
 
 
189
      
 
190
    
 
191
    
 
192
 
 
193
 
 
194
#ifdef DEBUG
 
195
#undef describe_sym
 
196
#define describe_sym(x) do{if(sfasldebug) describe_sym1(x);} while (0)
 
197
describe_sym1(n)
 
198
int n;
 
199
{char *str;
 
200
 char tem[9];
 
201
 struct syment *sym;
 
202
 sym= &symbol_table[n];
 
203
 str= sym->n_zeroes == 0 ?
 
204
   &my_string_table[sym->n_offset] :
 
205
 (sym->n_name[SYMNMLEN -1] ?
 
206
  /* MAKE IT NULL TERMINATED */
 
207
  (strncpy(tem,sym->n_name,
 
208
           SYMNMLEN),tem):
 
209
  sym->n_name );
 
210
 printf ("sym-index = %d table entry at %x",n,&symbol_table[n]);
 
211
 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,
 
212
        symbol_table[n]._n._n_name,
 
213
        symbol_table[n]._n._n_n._n_zeroes ,
 
214
        symbol_table[n]._n._n_n._n_offset ,
 
215
        symbol_table[n]._n._n_nptr[0] ,
 
216
        symbol_table[n]._n._n_nptr[1] ,
 
217
        symbol_table[n].n_value ,
 
218
        symbol_table[n].n_scnum ,
 
219
        symbol_table[n].n_type ,
 
220
        symbol_table[n].n_sclass ,
 
221
        symbol_table[n].n_numaux );
 
222
}
 
223
 
 
224
#endif 
 
225
 
 
226
 
 
227
 
 
228
 
 
229
/* allocate toc space in the preallocated region starting at akcltoc.
 
230
   If a symbol already has a toc entry, use that instead
 
231
   */
 
232
 
 
233
setup_for_aix_load()
 
234
{ bzero(toc_addresses_to_relocate,sizeof(toc_addresses_to_relocate));
 
235
  next_toc_addresses_to_relocate= toc_addresses_to_relocate;
 
236
  akcltoc_thisload = akcltoc + akcltoc_used;
 
237
  begun_relocate=0;
 
238
 
 
239
}
 
240
 
 
241
char *
 
242
sym_name(sym)
 
243
     struct syment *sym;
 
244
{static char tem[SYMNMLEN +1];
 
245
 char *name;
 
246
 tem[SYMNMLEN] = '0';
 
247
 name =  SYM_NAME(sym);
 
248
 return name;}
 
249
 
 
250
                 
 
251
 
 
252
allocate_toc(sym)
 
253
 struct syment *sym;
 
254
     /* sym is a symbol in the data section with an aux entry */ 
 
255
{ if (SYM_SMC(sym) == XMC_TC0)
 
256
    { sym->n_value =  toc_start; return 1;}
 
257
  if (SYM_SMC(sym) == XMC_TC)
 
258
    {struct node *answ = find_sym(sym,0);
 
259
     if (answ  && answ->tc_offset)
 
260
       { sym->n_value = toc_start + answ->tc_offset;
 
261
         return 1;}
 
262
     {char *na = sym_name(sym);
 
263
#ifdef SYM_USED      
 
264
      if (TC_SYMBOL_P(sym) && SYM_USED(sym) == 0)
 
265
        return 0;
 
266
#endif
 
267
      if (answ == 0 && *na  &&  *na != '_')
 
268
        printf("(strange TC synbol %s[%d])",na,sym - symbol_table);}
 
269
     {int old_value;
 
270
      (*next_toc_addresses_to_relocate++) =  sym->n_value + start_address;
 
271
      sym->n_value = akcltoc + akcltoc_used;
 
272
      if (answ) answ->tc_offset = sym->n_value - toc_start;
 
273
      (*next_toc_addresses_to_relocate++) = sym->n_value;
 
274
      *((int *)(next_toc_addresses_to_relocate[-1])) =
 
275
        *((int *)(next_toc_addresses_to_relocate[-2]));
 
276
      akcltoc_used += sizeof(long int);
 
277
      if (next_toc_addresses_to_relocate - toc_addresses_to_relocate
 
278
          >= (sizeof(toc_addresses_to_relocate)/sizeof(int)))
 
279
        FEerror("ran out",0,0);
 
280
      if (akcltoc_used > 24000) FEerror("toc exhausted",0,0);
 
281
      return 1;
 
282
    }}
 
283
  return 0;
 
284
}