/[gcl]/gcl/o/sfaslbfd_mips.c
ViewVC logotype

Diff of /gcl/o/sfaslbfd_mips.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1 by camm, Sat Apr 9 13:59:23 2005 UTC revision 1.2 by camm, Thu Apr 14 21:31:04 2005 UTC
# Line 12  extern void *bfd_alloc(bfd *,bfd_size_ty Line 12  extern void *bfd_alloc(bfd *,bfd_size_ty
12  #define vmaptr(x) ((void*)(unsigned long)(x))  #define vmaptr(x) ((void*)(unsigned long)(x))
13  #define ptrvma(x) ((bfd_vma)(unsigned long)(x))  #define ptrvma(x) ((bfd_vma)(unsigned long)(x))
14    
15  /* These subroutines alter the relocation code  static void *
16   * and generate the GOT table that BFD  xballoc(bfd *abfd, size_t n) {
  * does not handle properly.  
  */  
17    
18  /* mipself_old_{lo16,hi16}_reloc --    void *ans = (void*)bfd_alloc(abfd, n);
19     pointer to old reloc functions */  
20      if (!ans)
21        FEerror("bfd error: ~S", 1 , bfd_errmsg(bfd_error_no_memory));
22      return ans;
23    
 static void *  
 xballoc(bfd *abfd, size_t n)  
 {  
     void *ans = (void*)bfd_alloc(abfd, n);  
     if (!ans)  
         FEerror("bfd error: ~S", 1 , bfd_errmsg(bfd_error_no_memory));  
     return ans;  
24  }  }
25    
26    
# Line 52  static bfd_reloc_status_type Line 46  static bfd_reloc_status_type
46    
47  /* mipself_gpdisp_hiaddr, mipself_gpdisp_value --  /* mipself_gpdisp_hiaddr, mipself_gpdisp_value --
48     static variables for setting gp_disp */     static variables for setting gp_disp */
   
49  static bfd_vma mipself_gpdisp_value = 0;  static bfd_vma mipself_gpdisp_value = 0;
50  static bfd_vma mipself_gpdisp_hiaddr = 0;  static bfd_vma mipself_gpdisp_hiaddr = 0;
51    
52    
53  /* mipself_new_{lo16,hi16,gprel32}_reloc --  /* mipself_new_{lo16,hi16,gprel32}_reloc --
54     new reloc functions patching the bogus BFD functions */     new reloc functions patching the bogus BFD functions */
   
55  static bfd_reloc_status_type  static bfd_reloc_status_type
56  mipself_new_hi16_reloc (bfd *abfd,  mipself_new_hi16_reloc (bfd *abfd,
57                          arelent *reloc_entry,                          arelent *reloc_entry,
# Line 67  mipself_new_hi16_reloc (bfd *abfd, Line 59  mipself_new_hi16_reloc (bfd *abfd,
59                          PTR data,                          PTR data,
60                          asection *input_section,                          asection *input_section,
61                          bfd *output_bfd,                          bfd *output_bfd,
62                          char **error_message)                          char **error_message) {
63  {  
64    if (output_bfd)    if (output_bfd)
65      return bfd_reloc_notsupported;          return bfd_reloc_notsupported;    
66    
67    /* Test if symbol is '_gp_disp' because it changes everything */    /* Test if symbol is '_gp_disp' because it changes everything */
68    if (!strcmp(symbol->name, "_gp_disp"))    if (!strcmp(symbol->name, "_gp_disp"))  {
69      {  
70        mipself_gpdisp_hiaddr = ptrvma(data) + reloc_entry->address;      mipself_gpdisp_hiaddr = ptrvma(data) + reloc_entry->address;
71        mipself_gpdisp_value = symbol->section->vma + symbol->value;      mipself_gpdisp_value = symbol->section->vma + symbol->value;
72        /* Assume no addend for simplicity*/      
73        if (reloc_entry->addend)      /* Assume no addend for simplicity*/
74          return bfd_reloc_notsupported;      if (reloc_entry->addend)
75        return bfd_reloc_ok;        return bfd_reloc_notsupported;
76      }      
77        return bfd_reloc_ok;
78        
79      }
80    /* Regular procedure */    /* Regular procedure */
81    return (*mipself_old_hi16_reloc)(abfd, reloc_entry, symbol,    return (*mipself_old_hi16_reloc)(abfd, reloc_entry, symbol,
82                                     data, input_section,                                     data, input_section,
# Line 94  mipself_new_lo16_reloc (bfd *abfd, Line 90  mipself_new_lo16_reloc (bfd *abfd,
90                          PTR data,                          PTR data,
91                          asection *input_section,                          asection *input_section,
92                          bfd *output_bfd,                          bfd *output_bfd,
93                          char **error_message)                          char **error_message) {
94  {  
95    if (output_bfd)    if (output_bfd)
96      return bfd_reloc_notsupported;          return bfd_reloc_notsupported;    
97    
98    /* Test if symbol is '_gp_disp' because it changes everything */    /* Test if symbol is '_gp_disp' because it changes everything */
99    if(!strcmp(symbol->name, "_gp_disp"))  
100      {    if(!strcmp(symbol->name, "_gp_disp")) {
101        int loinsn, hiinsn;      
102        bfd_vma loaddr = ptrvma(data) + reloc_entry->address;      int loinsn, hiinsn;
103        bfd_vma value = symbol->section->vma + symbol->value;      
104        assert(value == mipself_gpdisp_value);      bfd_vma loaddr = ptrvma(data) + reloc_entry->address;
105        /* Assume no addend for simplicity*/      bfd_vma value = symbol->section->vma + symbol->value;
106        if (reloc_entry->addend)      
107          return bfd_reloc_notsupported;      assert(value == mipself_gpdisp_value);
108        /* Get instructions */      
109        loinsn = bfd_get_32(abfd, (bfd_byte*)vmaptr(loaddr));      /* Assume no addend for simplicity*/
110        hiinsn = bfd_get_32(abfd, (bfd_byte*)vmaptr(mipself_gpdisp_hiaddr));      if (reloc_entry->addend)
111        if ((loinsn & 0xffff) || (hiinsn & 0xffff))        return bfd_reloc_notsupported;
112          return bfd_reloc_notsupported;      
113        /* Patch instructions (taking care of sign extension on the low 16 bits) */      /* Get instructions */
114        value = value - mipself_gpdisp_hiaddr;      loinsn = bfd_get_32(abfd, (bfd_byte*)vmaptr(loaddr));
115        loinsn |= (value & 0xffff);      hiinsn = bfd_get_32(abfd, (bfd_byte*)vmaptr(mipself_gpdisp_hiaddr));
116        value = (value>>16) + (loinsn&0x8000 ? 1 : 0);      
117        hiinsn |= (value & 0xffff);      if ((loinsn & 0xffff) || (hiinsn & 0xffff))
118        bfd_put_32 (abfd, hiinsn, (bfd_byte*)vmaptr(mipself_gpdisp_hiaddr));        return bfd_reloc_notsupported;
119        bfd_put_32 (abfd, loinsn, (bfd_byte*)vmaptr(loaddr));      /* Patch instructions (taking care of sign extension on the low 16 bits) */
120        return bfd_reloc_ok;      
121      }      value = value - mipself_gpdisp_hiaddr;
122        loinsn |= (value & 0xffff);
123        
124        value = (value>>16) + (loinsn&0x8000 ? 1 : 0);
125        hiinsn |= (value & 0xffff);
126        
127        bfd_put_32 (abfd, hiinsn, (bfd_byte*)vmaptr(mipself_gpdisp_hiaddr));
128        bfd_put_32 (abfd, loinsn, (bfd_byte*)vmaptr(loaddr));
129        
130        return bfd_reloc_ok;
131        
132      }
133    /* Regular procedure */    /* Regular procedure */
134    return (*mipself_old_lo16_reloc)(abfd, reloc_entry, symbol,    return (*mipself_old_lo16_reloc)(abfd, reloc_entry, symbol,
135                                     data, input_section,                                     data, input_section,
# Line 135  mipself_new_call16_reloc (bfd *abfd, Line 143  mipself_new_call16_reloc (bfd *abfd,
143                           PTR data,                           PTR data,
144                           asection *input_section,                           asection *input_section,
145                           bfd *output_bfd,                           bfd *output_bfd,
146                           char **error_message)                           char **error_message) {
147  {  
148    /* This should only happen with GPDISP symbol */    /* This should only happen with GPDISP symbol */
149    int insn;    int insn;
150    bfd_byte *addr;    bfd_byte *addr;
151    
152    /* Plug GOT offset into low 16 bits of instruction */    /* Plug GOT offset into low 16 bits of instruction */
153    addr = (bfd_byte*)(data) + reloc_entry->address;    addr = (bfd_byte*)(data) + reloc_entry->address;
154    insn = bfd_get_32(abfd, addr);    insn = bfd_get_32(abfd, addr);
155    
156    if (insn & 0x0000ffff)    if (insn & 0x0000ffff)
157      return bfd_reloc_notsupported;          return bfd_reloc_notsupported;    
158    
159    if (reloc_entry->addend != (reloc_entry->addend & 0x7fff))    if (reloc_entry->addend != (reloc_entry->addend & 0x7fff))
160      return bfd_reloc_notsupported;              return bfd_reloc_notsupported;        
161    
162    insn |= reloc_entry->addend;    insn |= reloc_entry->addend;
163    
164    bfd_put_32(abfd, insn, addr);    bfd_put_32(abfd, insn, addr);
165    
166    return bfd_reloc_ok;    return bfd_reloc_ok;
167    
168  }  }
169    
170  static bfd_reloc_status_type  static bfd_reloc_status_type
# Line 159  mipself_new_got16_reloc (bfd *abfd, Line 174  mipself_new_got16_reloc (bfd *abfd,
174                           PTR data,                           PTR data,
175                           asection *input_section,                           asection *input_section,
176                           bfd *output_bfd,                           bfd *output_bfd,
177                           char **error_message)                           char **error_message) {
178  {  
179    int insn;    int insn;
180    bfd_byte *addr;    bfd_byte *addr;
181    
182    /* If symbol is '_gp_disp' same as CALL16 */    /* If symbol is '_gp_disp' same as CALL16 */
183    if (!strcmp(symbol->name,"_gp_disp"))    if (!strcmp(symbol->name,"_gp_disp"))
184      return mipself_new_call16_reloc(abfd, reloc_entry, symbol,      return mipself_new_call16_reloc(abfd, reloc_entry, symbol,
# Line 176  mipself_new_got16_reloc (bfd *abfd, Line 192  mipself_new_got16_reloc (bfd *abfd,
192       into a non PIC sequence similar to HI16/LO16 sequences. */       into a non PIC sequence similar to HI16/LO16 sequences. */
193    addr = (bfd_byte*)(data) + reloc_entry->address;    addr = (bfd_byte*)(data) + reloc_entry->address;
194    insn = bfd_get_32(abfd, addr);    insn = bfd_get_32(abfd, addr);
195    
196    /* Transform 'LW Rn, off(GP)' into 'LUI Rn, off' */    /* Transform 'LW Rn, off(GP)' into 'LUI Rn, off' */
197    if ((insn & 0xffe00000) != 0x8f800000)    if ((insn & 0xffe00000) != 0x8f800000)
198      return bfd_reloc_notsupported;          return bfd_reloc_notsupported;    
199    
200    insn &= ~0xffe00000;    insn &= ~0xffe00000;
201    insn |=  0x3c000000;    insn |=  0x3c000000;
202    
203    bfd_put_32(abfd, insn, addr);    bfd_put_32(abfd, insn, addr);
204    
205    /* We can then process it as HI16 */    /* We can then process it as HI16 */
206    return (*mipself_old_hi16_reloc)(abfd, reloc_entry, symbol,    return (*mipself_old_hi16_reloc)(abfd, reloc_entry, symbol,
207                                     data, input_section,                                     data, input_section,
208                                     output_bfd, error_message);                                     output_bfd, error_message);
209    
210  }  }
211    
212    
213  /* mipself_install_patches -- install patches into BFD */  /* mipself_install_patches -- install patches into BFD */
214    
215  static void  static void
216  mipself_install_patches(bfd *abfd)  mipself_install_patches(bfd *abfd) {
217  {  
218    reloc_howto_type *howto;    reloc_howto_type *howto;
219    
220    howto = bfd_reloc_type_lookup(abfd,BFD_RELOC_HI16_S);    howto = bfd_reloc_type_lookup(abfd,BFD_RELOC_HI16_S);
221    assert(howto);    assert(howto);
222    if (howto->special_function != mipself_new_hi16_reloc)    if (howto->special_function != mipself_new_hi16_reloc) {
223      {  
224        mipself_old_hi16_reloc = howto->special_function;      mipself_old_hi16_reloc = howto->special_function;
225        *(void**)&(howto->special_function) = mipself_new_hi16_reloc;      howto->special_function = mipself_new_hi16_reloc;
226        assert(mipself_old_hi16_reloc);      assert(mipself_old_hi16_reloc);
227      }  
228      }
229    
230    /* LO16 */    /* LO16 */
231    howto = bfd_reloc_type_lookup(abfd,BFD_RELOC_LO16);    howto = bfd_reloc_type_lookup(abfd,BFD_RELOC_LO16);
232    assert(howto);    assert(howto);
233    if (howto->special_function != mipself_new_lo16_reloc)    if (howto->special_function != mipself_new_lo16_reloc)  {
234      {  
235        mipself_old_lo16_reloc = howto->special_function;      mipself_old_lo16_reloc = howto->special_function;
236        *(void**)&(howto->special_function) = mipself_new_lo16_reloc;      howto->special_function = mipself_new_lo16_reloc;
237        assert(mipself_old_lo16_reloc);      assert(mipself_old_lo16_reloc);
238      }  
239      }
240    
241    /* GOT16 */    /* GOT16 */
242    howto = bfd_reloc_type_lookup(abfd,BFD_RELOC_MIPS_GOT16);    howto = bfd_reloc_type_lookup(abfd,BFD_RELOC_MIPS_GOT16);
243    assert(howto);    assert(howto);
244    *(void**)&(howto->special_function) = mipself_new_got16_reloc;      howto->special_function = mipself_new_got16_reloc;  
245    
246    /* CALL16 */    /* CALL16 */
247    howto = bfd_reloc_type_lookup(abfd,BFD_RELOC_MIPS_CALL16);    howto = bfd_reloc_type_lookup(abfd,BFD_RELOC_MIPS_CALL16);
248    assert(howto);    assert(howto);
249    *(void**)&(howto->special_function) = mipself_new_call16_reloc;      howto->special_function = mipself_new_call16_reloc;  
250    
251  }  }
252    
253    
254  /* mipself_got_info -- structure containing GOT information */  /* mipself_got_info -- structure containing GOT information */
   
255  typedef struct mipself_got_info {  typedef struct mipself_got_info {
256    int gotsize;    int gotsize;
257    asection *sgot;    asection *sgot;
# Line 236  typedef struct mipself_got_info { Line 263  typedef struct mipself_got_info {
263    
264    
265  /* mipself_got_entry -- structure for GOT entries */  /* mipself_got_entry -- structure for GOT entries */
   
266  typedef struct mipself_got_entry {  typedef struct mipself_got_entry {
267    struct bfd_hash_entry root;    struct bfd_hash_entry root;
268    arelent *reloc;    arelent *reloc;
# Line 246  typedef struct mipself_got_entry { Line 272  typedef struct mipself_got_entry {
272    
273    
274  /* mipself_init_got_entry -- initialize got hash table component */  /* mipself_init_got_entry -- initialize got hash table component */
   
275  static struct bfd_hash_entry *  static struct bfd_hash_entry *
276  mipself_init_got_entry(struct bfd_hash_entry *entry,  mipself_init_got_entry(struct bfd_hash_entry *entry,
277                         struct bfd_hash_table *table,                         struct bfd_hash_table *table,
278                         const char *string)                         const char *string) {
279  {  
280    mipself_got_entry *ret = (mipself_got_entry*)entry;    mipself_got_entry *ret = (mipself_got_entry*)entry;
281    if (!ret)  
282      {    if (!ret) {
283        ret = (mipself_got_entry*)  
284          bfd_hash_allocate(table, sizeof(mipself_got_entry));      ret = (mipself_got_entry*)
285        if (!ret)        bfd_hash_allocate(table, sizeof(mipself_got_entry));
286          FEerror("bfd error:~S",1,bfd_errmsg(bfd_error_no_memory));      if (!ret)
287      }        FEerror("bfd error:~S",1,bfd_errmsg(bfd_error_no_memory));
288    
289      }
290    
291    memset(ret, 0, sizeof(mipself_got_entry));    memset(ret, 0, sizeof(mipself_got_entry));
292    
293    return bfd_hash_newfunc((struct bfd_hash_entry*)ret, table, string);    return bfd_hash_newfunc((struct bfd_hash_entry*)ret, table, string);
294    
295  }  }
296    
297    
298  /* mipself_init_got_info -- initialize info about got */  /* mipself_init_got_info -- initialize info about got */
   
299  static void  static void
300  mipself_init_got_info(bfd *b,  mipself_init_got_info(bfd *b,
301                        mipself_got_info *info)                        mipself_got_info *info) {
302  {  
303    /* Create GOT hash table */    /* Create GOT hash table */
304    info->sgot = NULL;    info->sgot = NULL;
305    info->gotsize = 0;    info->gotsize = 0;
306    
307    bfd_hash_table_init(&info->got_table, mipself_init_got_entry);    bfd_hash_table_init(&info->got_table, mipself_init_got_entry);
308    
309    /* Identify pertinent howto information */    /* Identify pertinent howto information */
310    info->reloc_got16 = bfd_reloc_type_lookup(b,BFD_RELOC_MIPS_GOT16);    info->reloc_got16 = bfd_reloc_type_lookup(b,BFD_RELOC_MIPS_GOT16);
311    info->reloc_call16 = bfd_reloc_type_lookup(b,BFD_RELOC_MIPS_CALL16);    info->reloc_call16 = bfd_reloc_type_lookup(b,BFD_RELOC_MIPS_CALL16);
312    info->reloc_32 = bfd_reloc_type_lookup(b,BFD_RELOC_32);    info->reloc_32 = bfd_reloc_type_lookup(b,BFD_RELOC_32);
313    
314  }  }
315    
316    
317  /* mipself_free_got_info -- free got information */  /* mipself_free_got_info -- free got information */
   
318  static void  static void
319  mipself_free_got_info(mipself_got_info *info)  mipself_free_got_info(mipself_got_info *info) {
320  {  
321    bfd_hash_table_free(&info->got_table);    bfd_hash_table_free(&info->got_table);
322    
323  }  }
324    
325    
326  /* mipself_got_traverse -- got table traversal function */  /* mipself_got_traverse -- got table traversal function */
   
327  static int  static int
328  mipself_got_traverse(struct bfd_hash_entry *ent, void *gcookie)  mipself_got_traverse(struct bfd_hash_entry *ent, void *gcookie) {
329  {  
330    mipself_got_entry *gotent = (mipself_got_entry*)ent;    mipself_got_entry *gotent = (mipself_got_entry*)ent;
331    asection *sgot = (asection*)gcookie;    asection *sgot = (asection*)gcookie;
332  /*   sgot->orelocation[gotent->index] = gotent->reloc; */  
333    sgot->relocation[gotent->index] = *gotent->reloc;    sgot->relocation[gotent->index] = *gotent->reloc;
334    
335    return TRUE;    return TRUE;
336    
337  }  }
338    
339    
340  /* mipself_create_got -- create a section for GOT */  /* mipself_create_got -- create a section for GOT */
   
341  static asection *  static asection *
342  mipself_create_got(bfd *b,asymbol **syms,  mipself_create_got(bfd *b,asymbol **syms,
343                     mipself_got_info *info)                     mipself_got_info *info) {
344  {  
345    asection *sgot;    asection *sgot;
346    bfd_vma offset;    bfd_vma offset;
347    asection *p;    asection *p;
   bfd *abfd;  
348    int i;    int i;
349    
350    /* Check that there are no GOT section */    /* Check that there are no GOT section */
351    sgot = bfd_get_section_by_name(b, ".got");    sgot = bfd_get_section_by_name(b, ".got");
352    assert(!sgot);    assert(!sgot);
353    
354    /* Compute GOT hash table */    /* Compute GOT hash table */
355    offset = 0;    offset = 0;
356    abfd = b;    for (p=b->sections; p; p=p->next)
357    for (p=abfd->sections; p; p=p->next)  
358      if ((p->flags & SEC_ALLOC) && (p->flags & SEC_RELOC))      if ((p->flags & SEC_ALLOC) && (p->flags & SEC_RELOC)) {
359        {  
360          int storage_needed,reloc_count;        int storage_needed,reloc_count;
361          arelent **reloc;        arelent **reloc;
362    
363          /*  MIPS native relocs: This section and analogs below have        /*  MIPS native relocs: This section and analogs below have
364              been modified to avoid orelocation in favor of relocation            been modified to avoid orelocation in favor of relocation
365              itself.  bfd_canonicalize_reloc reads in the relocation            itself.  bfd_canonicalize_reloc reads in the relocation
366              table to the latter as an array and makes a pointer list            table to the latter as an array and makes a pointer list
367              to it in the supplied argument.  We will call            to it in the supplied argument.  We will call
368              bfd_get_relocated_section_contents, which will call            bfd_get_relocated_section_contents, which will call
369              bfd_canonicalize_reloc internally, on all sections,            bfd_canonicalize_reloc internally, on all sections,
370              including the new .got section.  If no relocation array            including the new .got section.  If no relocation array
371              exists, this will fail when bfd_cannicalize_reloc attempts            exists, this will fail when bfd_cannicalize_reloc attempts
372              to read in the non-existent table.  20050409 CM*/            to read in the non-existent table.  20050409 CM*/
373          
374          
375          storage_needed = bfd_get_reloc_upper_bound(b, p);        storage_needed = bfd_get_reloc_upper_bound(b, p);
376          assert(storage_needed>0);        assert(storage_needed>0);
377  /*      reloc = xballoc(b,storage_needed); */        reloc=alloca(storage_needed);
378          reloc=alloca(storage_needed);  
379          reloc_count = bfd_canonicalize_reloc(b, p, reloc, syms);        reloc_count = bfd_canonicalize_reloc(b, p, reloc, syms);
380          assert(reloc_count>0);        assert(reloc_count>0);
381          assert(p->reloc_count==0 || p->reloc_count==reloc_count);        assert(p->reloc_count==0 || p->reloc_count==reloc_count);
382          /* Keep relocation table in field orelocation (unused in input bfd) */  
383  /*      p->reloc_count = reloc_count; */        assert(p->relocation);
384  /*      p->orelocation = reloc; */  
385          /* Mark symbols used by relocations with flag BSF_KEEP */        for (i=0; i<p->reloc_count; i++) {
386    
387  /*         assert(p->orelocation); */          arelent *reloc = p->relocation+i;
388          assert(p->relocation);          asymbol *symbol = *(reloc->sym_ptr_ptr);
389          for (i=0; i<p->reloc_count; i++)          if ((reloc->howto==info->reloc_call16)
390            {              || ((reloc->howto==info->reloc_got16)
391  /*             arelent *reloc = p->orelocation[i]; */                  && !(symbol->flags & BSF_SECTION_SYM))) {
392              arelent *reloc = p->relocation+i;  
393              asymbol *symbol = *(reloc->sym_ptr_ptr);            /* Search entry in GOT table */
394              if ((reloc->howto==info->reloc_call16)            const char *name = (*reloc->sym_ptr_ptr)->name;
395                  || ((reloc->howto==info->reloc_got16)            mipself_got_entry *gotent =
396                      && !(symbol->flags & BSF_SECTION_SYM) ) )              (mipself_got_entry*) bfd_hash_lookup(&info->got_table, name, TRUE, TRUE );
397                {  
398                  /* Search entry in GOT table */            if (!gotent->reloc) {
399                  const char *name = (*reloc->sym_ptr_ptr)->name;  
400                  mipself_got_entry *gotent = (mipself_got_entry*)              /* Compute offset */
401                    bfd_hash_lookup(&info->got_table, name, TRUE, TRUE );              gotent->index = info->gotsize;
402                  /* Fill entry */              gotent->offset = offset;
403                  if (!gotent->reloc)  
404                    {              gotent->reloc = xballoc(b, sizeof(arelent));
405                      /* Compute offset */              gotent->reloc->sym_ptr_ptr = reloc->sym_ptr_ptr;
406                      gotent->index = info->gotsize;              gotent->reloc->address = offset;
407                      gotent->offset = offset;              gotent->reloc->addend = 0;
408                      /* Prepare relocation entry */              gotent->reloc->howto = info->reloc_32;
409                      gotent->reloc = xballoc(b, sizeof(arelent));  
410                      gotent->reloc->sym_ptr_ptr = reloc->sym_ptr_ptr;              /* Increment GOT offset */
411                      gotent->reloc->address = offset;              offset += sizeof(void*);
412                      gotent->reloc->addend = 0;              info->gotsize += 1;
413                      gotent->reloc->howto = info->reloc_32;  
414                      /* Increment GOT offset */            }
415                      offset += sizeof(void*);  
416                      info->gotsize += 1;          }
417                    }  
               }  
           }  
418        }        }
419    
420        }
421    
422    /* Check GOT size */    /* Check GOT size */
423    if (offset >= 0x8000)    if (offset >= 0x8000)
424      FEerror("Too many entries in GOT (GOT full, merci MIPS)",0);      FEerror("Too many entries in GOT (GOT full, merci MIPS)",0);
425    
426    /* Create GOT if necessary */    /* Create GOT if necessary */
427    if (info->gotsize > 0)    if (info->gotsize > 0) {
428      {  
429        sgot = bfd_make_section(b, ".got");      sgot = bfd_make_section(b, ".got");
430        assert(sgot);      assert(sgot);
431        sgot->flags = SEC_ALLOC|SEC_RELOC|SEC_LOAD;      sgot->flags = SEC_ALLOC|SEC_RELOC|SEC_LOAD;
432  /*       sgot->_raw_size = 0; */      
433  /*       sgot->_cooked_size = offset; */      /* MIPS native relocs: we need _raw_size set here too -- this is
434           the generic way to do it, avoiding structure element name changes,
435     /* MIPS native relocs: we need _raw_size set here too -- this is         etc.*/
436     the generic way to do it, avoiding structure element name changes,      
437     etc.*/      if (!bfd_set_section_size(b,sgot,offset))
438          FEerror("Cannot set got section size",0);
439        if (!bfd_set_section_size(b,sgot,offset))  
440          FEerror("Cannot set got section size",0);      if (sgot->alignment_power < 4)
441        if (sgot->alignment_power < 4)        sgot->alignment_power = 4;      /* Set GOT relocations */
442          sgot->alignment_power = 4;      /* Set GOT relocations */  
443  /*       sgot->orelocation = xballoc(b, info->gotsize*sizeof(void*)); */      sgot->relocation = xballoc(b, info->gotsize*sizeof(*sgot->relocation));
444        sgot->relocation = xballoc(b, info->gotsize*sizeof(*sgot->relocation));      bfd_hash_traverse(&info->got_table, (void*)mipself_got_traverse, sgot);
445        bfd_hash_traverse(&info->got_table, (void*)mipself_got_traverse, sgot);      sgot->reloc_count = info->gotsize;
446        sgot->reloc_count = info->gotsize;  
447      }    }
448    
449    /* return GOT section if any */    /* return GOT section if any */
450    info->sgot = sgot;    info->sgot = sgot;
451    return sgot;    return sgot;
452    
453  }  }
454    
455    
456  /* mipself_fix_relocs -- patches the relocation for GOT */  /* mipself_fix_relocs -- patches the relocation for GOT */
   
457  static void  static void
458  mipself_fix_relocs(bfd *b,asymbol ** symbols,int symbol_count,  mipself_fix_relocs(bfd *b,asymbol ** symbols,int symbol_count,
459                     mipself_got_info *info)                     mipself_got_info *info) {
460  {  
461    int i;    int i;
462    asymbol *gpdisp = NULL;    asymbol *gpdisp = NULL;
463    asymbol **gpdisp_ptr = NULL;    asymbol **gpdisp_ptr = NULL;
# Line 429  mipself_fix_relocs(bfd *b,asymbol ** sym Line 465  mipself_fix_relocs(bfd *b,asymbol ** sym
465    
466    /* Locate and patch gpdisp symbol */    /* Locate and patch gpdisp symbol */
467    for (i=0; i<symbol_count; i++)    for (i=0; i<symbol_count; i++)
468      if (!strcmp(symbols[i]->name, "_gp_disp"))  
469        {      if (!strcmp(symbols[i]->name, "_gp_disp")) {
470          gpdisp = symbols[i];  
471  /*         if (bfd_is_und_section(gpdisp->section)) */        gpdisp = symbols[i];
472  /*           ent->undefined_symbol_count -= 1; */        gpdisp->value = 0;
473          gpdisp->value = 0;        gpdisp->flags = BSF_LOCAL|BSF_SECTION_SYM;
474          gpdisp->flags = BSF_LOCAL|BSF_SECTION_SYM;        gpdisp->section = info->sgot ? info->sgot : info->sgot : bfd_abs_section_ptr;
475          if (info->sgot)        gpdisp->udata.p = NULL;
476            gpdisp->section = info->sgot;        break;
477          else      }
478            gpdisp->section =  bfd_abs_section_ptr;  
         gpdisp->udata.p = NULL;  
         break;  
       }  
479    if (!info->sgot)    if (!info->sgot)
480      return;      return;
481    
482    if (!gpdisp)    if (!gpdisp)
483      FEerror("Found GOT relocations but no symbol '_gp_disp'",0);      FEerror("Found GOT relocations but no symbol '_gp_disp'",0);
484        
# Line 453  mipself_fix_relocs(bfd *b,asymbol ** sym Line 487  mipself_fix_relocs(bfd *b,asymbol ** sym
487    *gpdisp_ptr = gpdisp;    *gpdisp_ptr = gpdisp;
488        
489    /* Iterate on sections and relocations */    /* Iterate on sections and relocations */
490    for (p=b->sections; p; p=p->next)    for (p=b->sections; p; p=p->next)
491      {  
492        if ((p->flags & SEC_ALLOC) && (p->flags & SEC_RELOC))      if ((p->flags & SEC_ALLOC) && (p->flags & SEC_RELOC)) {
493          {        
494  /*           assert(p->orelocation); */        assert(p->relocation);
495            assert(p->relocation);  
496            for (i=0; i<p->reloc_count; i++)        for (i=0; i<p->reloc_count; i++) {
497              {          
498  /*               arelent *reloc = p->orelocation[i]; */          arelent *reloc = p->relocation+i;
499                arelent *reloc = p->relocation+i;          asymbol *symbol = *reloc->sym_ptr_ptr;
500                asymbol *symbol = *reloc->sym_ptr_ptr;  
501                if ((reloc->howto==info->reloc_call16)          if ((reloc->howto==info->reloc_call16)
502                    || ((reloc->howto==info->reloc_got16)              || ((reloc->howto==info->reloc_got16)
503                        && !(symbol->flags & BSF_SECTION_SYM) ) )                  && !(symbol->flags & BSF_SECTION_SYM))) {
504                  {  
505                    /* Find GOT entry */            /* Find GOT entry */
506                    mipself_got_entry *gotent = (mipself_got_entry*)            mipself_got_entry *gotent = (mipself_got_entry*)
507                      bfd_hash_lookup(&info->got_table, symbol->name, FALSE, FALSE );              bfd_hash_lookup(&info->got_table, symbol->name, FALSE, FALSE );
508                    assert(gotent);            assert(gotent);
509                    /* Addend should be null */  
510                    if (reloc->addend)            /* Addend should be null */
511                      FEerror("Non zero addend in GOT16/CALL16 relocation",0);            if (reloc->addend)
512                    /* GOT16 and CALL16 relocations will refer              FEerror("Non zero addend in GOT16/CALL16 relocation",0);
513                     * to the GPDISP symbol and have the GOT index  
514                     * in the addend */            /* GOT16 and CALL16 relocations will refer
515                    reloc->addend = gotent->offset;             * to the GPDISP symbol and have the GOT index
516                    reloc->sym_ptr_ptr = gpdisp_ptr;             * in the addend */
517                  }            reloc->addend = gotent->offset;
518              }            reloc->sym_ptr_ptr = gpdisp_ptr;
519          }  
520            }
521            
522          }
523    
524      }      }
525    
526  }  }
527    
528  /* mipself_special -- special processing for mips elf */  /* mipself_special -- special processing for mips elf */
529    #define SPECIAL_BFD mipself_special
530  static void  static void
531  mipself_special(bfd *b,asymbol **syms,int nsyms)  SPECIAL_BFD(bfd *b,asymbol **syms,int nsyms) {
532  {  
533    /* MIPSELF case */    mipself_got_info got_info;
534    if (bfd_get_flavour(b) == bfd_target_elf_flavour &&    mipself_install_patches(b);
535        bfd_get_arch(b) == bfd_arch_mips )    mipself_init_got_info(b, &got_info);
536      {    mipself_create_got(b, syms, &got_info);
537        mipself_got_info got_info;    mipself_fix_relocs(b,syms,nsyms, &got_info);
538        /* Install BFD patches */    mipself_free_got_info(&got_info);
539        mipself_install_patches(b);  
       /* Create GOT section */  
       mipself_init_got_info(b, &got_info);  
       mipself_create_got(b, syms, &got_info);  
       mipself_fix_relocs(b,syms,nsyms, &got_info);  
       mipself_free_got_info(&got_info);  
     }  
540  }  }

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.2

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26