OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-7.1/] [bfd/] [elf32-ip2k.c] - Blame information for rev 285

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 227 jeremybenn
/* Ubicom IP2xxx specific support for 32-bit ELF
2
   Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009
3
   Free Software Foundation, Inc.
4
 
5
   This file is part of BFD, the Binary File Descriptor library.
6
 
7
   This program is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 3 of the License, or
10
   (at your option) any later version.
11
 
12
   This program is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
   GNU General Public License for more details.
16
 
17
   You should have received a copy of the GNU General Public License
18
   along with this program; if not, write to the Free Software
19
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20
   MA 02110-1301, USA.  */
21
 
22
#include "sysdep.h"
23
#include "bfd.h"
24
#include "libbfd.h"
25
#include "elf-bfd.h"
26
#include "elf/ip2k.h"
27
 
28
/* Struct used to pass miscellaneous paramaters which
29
   helps to avoid overly long parameter lists.  */
30
struct misc
31
{
32
  Elf_Internal_Shdr *  symtab_hdr;
33
  Elf_Internal_Rela *  irelbase;
34
  bfd_byte *           contents;
35
  Elf_Internal_Sym *   isymbuf;
36
};
37
 
38
struct ip2k_opcode
39
{
40
  unsigned short opcode;
41
  unsigned short mask;
42
};
43
 
44
static bfd_boolean ip2k_relaxed = FALSE;
45
 
46
static const struct ip2k_opcode ip2k_page_opcode[] =
47
{
48
  {0x0010, 0xFFF8},     /* Page.  */
49
  {0x0000, 0x0000},
50
};
51
 
52
#define IS_PAGE_OPCODE(code) \
53
  ip2k_is_opcode (code, ip2k_page_opcode)
54
 
55
static const struct ip2k_opcode ip2k_jmp_opcode[] =
56
{
57
  {0xE000, 0xE000},     /* Jmp.  */
58
  {0x0000, 0x0000},
59
};
60
 
61
#define IS_JMP_OPCODE(code) \
62
  ip2k_is_opcode (code, ip2k_jmp_opcode)
63
 
64
static const struct ip2k_opcode ip2k_snc_opcode[] =
65
{
66
  {0xA00B, 0xFFFF},     /* Snc.  */
67
  {0x0000, 0x0000},
68
};
69
 
70
#define IS_SNC_OPCODE(code) \
71
  ip2k_is_opcode (code, ip2k_snc_opcode)
72
 
73
static const struct ip2k_opcode ip2k_inc_1sp_opcode[] =
74
{
75
  {0x2B81, 0xFFFF},     /* Inc 1(SP).  */
76
  {0x0000, 0x0000},
77
};
78
 
79
#define IS_INC_1SP_OPCODE(code) \
80
  ip2k_is_opcode (code, ip2k_inc_1sp_opcode)
81
 
82
static const struct ip2k_opcode ip2k_add_2sp_w_opcode[] =
83
{
84
  {0x1F82, 0xFFFF},     /* Add 2(SP),w.  */
85
  {0x0000, 0x0000},
86
};
87
 
88
#define IS_ADD_2SP_W_OPCODE(code) \
89
  ip2k_is_opcode (code, ip2k_add_2sp_w_opcode)
90
 
91
static const struct ip2k_opcode ip2k_add_w_wreg_opcode[] =
92
{
93
  {0x1C0A, 0xFFFF},     /* Add w,wreg.  */
94
  {0x1E0A, 0xFFFF},     /* Add wreg,w.  */
95
  {0x0000, 0x0000},
96
};
97
 
98
#define IS_ADD_W_WREG_OPCODE(code) \
99
  ip2k_is_opcode (code, ip2k_add_w_wreg_opcode)
100
 
101
static const struct ip2k_opcode ip2k_add_pcl_w_opcode[] =
102
{
103
  {0x1E09, 0xFFFF},     /* Add pcl,w.  */
104
  {0x0000, 0x0000},
105
};
106
 
107
#define IS_ADD_PCL_W_OPCODE(code) \
108
  ip2k_is_opcode (code, ip2k_add_pcl_w_opcode)
109
 
110
static const struct ip2k_opcode ip2k_skip_opcodes[] =
111
{
112
  {0xB000, 0xF000},     /* sb */
113
  {0xA000, 0xF000},     /* snb */
114
  {0x7600, 0xFE00},     /* cse/csne #lit */
115
  {0x5800, 0xFC00},     /* incsnz */
116
  {0x4C00, 0xFC00},     /* decsnz */
117
  {0x4000, 0xFC00},     /* cse/csne */
118
  {0x3C00, 0xFC00},     /* incsz */
119
  {0x2C00, 0xFC00},     /* decsz */
120
  {0x0000, 0x0000},
121
};
122
 
123
#define IS_SKIP_OPCODE(code) \
124
  ip2k_is_opcode (code, ip2k_skip_opcodes)
125
 
126
/* Relocation tables.  */
127
static reloc_howto_type ip2k_elf_howto_table [] =
128
{
129
#define IP2K_HOWTO(t,rs,s,bs,pr,bp,name,sm,dm) \
130
    HOWTO(t,                    /* type */ \
131
          rs,                   /* rightshift */ \
132
          s,                    /* size (0 = byte, 1 = short, 2 = long) */ \
133
          bs,                   /* bitsize */ \
134
          pr,                   /* pc_relative */ \
135
          bp,                   /* bitpos */ \
136
          complain_overflow_dont,/* complain_on_overflow */ \
137
          bfd_elf_generic_reloc,/* special_function */ \
138
          name,                 /* name */ \
139
          FALSE,                /* partial_inplace */ \
140
          sm,                   /* src_mask */ \
141
          dm,                   /* dst_mask */ \
142
          pr)                   /* pcrel_offset */
143
 
144
  /* This reloc does nothing.  */
145
  IP2K_HOWTO (R_IP2K_NONE, 0,2,32, FALSE, 0, "R_IP2K_NONE", 0, 0),
146
  /* A 16 bit absolute relocation.  */
147
  IP2K_HOWTO (R_IP2K_16, 0,1,16, FALSE, 0, "R_IP2K_16", 0, 0xffff),
148
  /* A 32 bit absolute relocation.  */
149
  IP2K_HOWTO (R_IP2K_32, 0,2,32, FALSE, 0, "R_IP2K_32", 0, 0xffffffff),
150
  /* A 8-bit data relocation for the FR9 field.  Ninth bit is computed specially.  */
151
  IP2K_HOWTO (R_IP2K_FR9, 0,1,9, FALSE, 0, "R_IP2K_FR9", 0, 0x00ff),
152
  /* A 4-bit data relocation.  */
153
  IP2K_HOWTO (R_IP2K_BANK, 8,1,4, FALSE, 0, "R_IP2K_BANK", 0, 0x000f),
154
  /* A 13-bit insn relocation - word address => right-shift 1 bit extra.  */
155
  IP2K_HOWTO (R_IP2K_ADDR16CJP, 1,1,13, FALSE, 0, "R_IP2K_ADDR16CJP", 0, 0x1fff),
156
  /* A 3-bit insn relocation - word address => right-shift 1 bit extra.  */
157
  IP2K_HOWTO (R_IP2K_PAGE3, 14,1,3, FALSE, 0, "R_IP2K_PAGE3", 0, 0x0007),
158
  /* Two 8-bit data relocations.  */
159
  IP2K_HOWTO (R_IP2K_LO8DATA, 0,1,8, FALSE, 0, "R_IP2K_LO8DATA", 0, 0x00ff),
160
  IP2K_HOWTO (R_IP2K_HI8DATA, 8,1,8, FALSE, 0, "R_IP2K_HI8DATA", 0, 0x00ff),
161
  /* Two 8-bit insn relocations.  word address => right-shift 1 bit extra.  */
162
  IP2K_HOWTO (R_IP2K_LO8INSN, 1,1,8, FALSE, 0, "R_IP2K_LO8INSN", 0, 0x00ff),
163
  IP2K_HOWTO (R_IP2K_HI8INSN, 9,1,8, FALSE, 0, "R_IP2K_HI8INSN", 0, 0x00ff),
164
 
165
  /* Special 1 bit relocation for SKIP instructions.  */
166
  IP2K_HOWTO (R_IP2K_PC_SKIP, 1,1,1, FALSE, 12, "R_IP2K_PC_SKIP", 0xfffe, 0x1000),
167
  /* 16 bit word address.  */
168
  IP2K_HOWTO (R_IP2K_TEXT, 1,1,16, FALSE, 0, "R_IP2K_TEXT", 0, 0xffff),
169
  /* A 7-bit offset relocation for the FR9 field.  Eigth and ninth bit comes from insn.  */
170
  IP2K_HOWTO (R_IP2K_FR_OFFSET, 0,1,9, FALSE, 0, "R_IP2K_FR_OFFSET", 0x180, 0x007f),
171
  /* Bits 23:16 of an address.  */
172
  IP2K_HOWTO (R_IP2K_EX8DATA, 16,1,8, FALSE, 0, "R_IP2K_EX8DATA", 0, 0x00ff),
173
};
174
 
175
 
176
/* Map BFD reloc types to IP2K ELF reloc types.  */
177
 
178
static reloc_howto_type *
179
ip2k_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
180
                        bfd_reloc_code_real_type code)
181
{
182
  /* Note that the ip2k_elf_howto_table is indxed by the R_
183
     constants.  Thus, the order that the howto records appear in the
184
     table *must* match the order of the relocation types defined in
185
     include/elf/ip2k.h.  */
186
 
187
  switch (code)
188
    {
189
    case BFD_RELOC_NONE:
190
      return &ip2k_elf_howto_table[ (int) R_IP2K_NONE];
191
    case BFD_RELOC_16:
192
      return &ip2k_elf_howto_table[ (int) R_IP2K_16];
193
    case BFD_RELOC_32:
194
      return &ip2k_elf_howto_table[ (int) R_IP2K_32];
195
    case BFD_RELOC_IP2K_FR9:
196
      return &ip2k_elf_howto_table[ (int) R_IP2K_FR9];
197
    case BFD_RELOC_IP2K_BANK:
198
      return &ip2k_elf_howto_table[ (int) R_IP2K_BANK];
199
    case BFD_RELOC_IP2K_ADDR16CJP:
200
      return &ip2k_elf_howto_table[ (int) R_IP2K_ADDR16CJP];
201
    case BFD_RELOC_IP2K_PAGE3:
202
      return &ip2k_elf_howto_table[ (int) R_IP2K_PAGE3];
203
    case BFD_RELOC_IP2K_LO8DATA:
204
      return &ip2k_elf_howto_table[ (int) R_IP2K_LO8DATA];
205
    case BFD_RELOC_IP2K_HI8DATA:
206
      return &ip2k_elf_howto_table[ (int) R_IP2K_HI8DATA];
207
    case BFD_RELOC_IP2K_LO8INSN:
208
      return &ip2k_elf_howto_table[ (int) R_IP2K_LO8INSN];
209
    case BFD_RELOC_IP2K_HI8INSN:
210
      return &ip2k_elf_howto_table[ (int) R_IP2K_HI8INSN];
211
    case BFD_RELOC_IP2K_PC_SKIP:
212
      return &ip2k_elf_howto_table[ (int) R_IP2K_PC_SKIP];
213
    case BFD_RELOC_IP2K_TEXT:
214
      return &ip2k_elf_howto_table[ (int) R_IP2K_TEXT];
215
    case BFD_RELOC_IP2K_FR_OFFSET:
216
      return &ip2k_elf_howto_table[ (int) R_IP2K_FR_OFFSET];
217
    case BFD_RELOC_IP2K_EX8DATA:
218
      return &ip2k_elf_howto_table[ (int) R_IP2K_EX8DATA];
219
    default:
220
      /* Pacify gcc -Wall.  */
221
      return NULL;
222
    }
223
  return NULL;
224
}
225
 
226
static reloc_howto_type *
227
ip2k_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
228
{
229
  unsigned int i;
230
 
231
  for (i = 0;
232
       i < sizeof (ip2k_elf_howto_table) / sizeof (ip2k_elf_howto_table[0]);
233
       i++)
234
    if (ip2k_elf_howto_table[i].name != NULL
235
        && strcasecmp (ip2k_elf_howto_table[i].name, r_name) == 0)
236
      return &ip2k_elf_howto_table[i];
237
 
238
  return NULL;
239
}
240
 
241
static void
242
ip2k_get_mem (bfd *abfd ATTRIBUTE_UNUSED,
243
              bfd_byte *addr,
244
              int length,
245
              bfd_byte *ptr)
246
{
247
  while (length --)
248
    * ptr ++ = bfd_get_8 (abfd, addr ++);
249
}
250
 
251
static bfd_boolean
252
ip2k_is_opcode (bfd_byte *code, const struct ip2k_opcode *opcodes)
253
{
254
  unsigned short insn = (code[0] << 8) | code[1];
255
 
256
  while (opcodes->mask != 0)
257
    {
258
      if ((insn & opcodes->mask) == opcodes->opcode)
259
        return TRUE;
260
 
261
      opcodes ++;
262
    }
263
 
264
  return FALSE;
265
}
266
 
267
#define PAGENO(ABSADDR) ((ABSADDR) & 0xFFFFC000)
268
#define BASEADDR(SEC)   ((SEC)->output_section->vma + (SEC)->output_offset)
269
 
270
#define UNDEFINED_SYMBOL (~(bfd_vma)0)
271
 
272
/* Return the value of the symbol associated with the relocation IREL.  */
273
 
274
static bfd_vma
275
symbol_value (bfd *abfd,
276
              Elf_Internal_Shdr *symtab_hdr,
277
              Elf_Internal_Sym *isymbuf,
278
              Elf_Internal_Rela *irel)
279
{
280
  if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
281
    {
282
      Elf_Internal_Sym *isym;
283
      asection *sym_sec;
284
 
285
      isym = isymbuf + ELF32_R_SYM (irel->r_info);
286
      if (isym->st_shndx == SHN_UNDEF)
287
        sym_sec = bfd_und_section_ptr;
288
      else if (isym->st_shndx == SHN_ABS)
289
        sym_sec = bfd_abs_section_ptr;
290
      else if (isym->st_shndx == SHN_COMMON)
291
        sym_sec = bfd_com_section_ptr;
292
      else
293
        sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
294
 
295
      return isym->st_value + BASEADDR (sym_sec);
296
    }
297
  else
298
    {
299
      unsigned long indx;
300
      struct elf_link_hash_entry *h;
301
 
302
      indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
303
      h = elf_sym_hashes (abfd)[indx];
304
      BFD_ASSERT (h != NULL);
305
 
306
      if (h->root.type != bfd_link_hash_defined
307
          && h->root.type != bfd_link_hash_defweak)
308
        return UNDEFINED_SYMBOL;
309
 
310
      return (h->root.u.def.value + BASEADDR (h->root.u.def.section));
311
    }
312
}
313
 
314
/* Determine if the instruction sequence matches that for
315
   the prologue of a switch dispatch table with fewer than
316
   128 entries.
317
 
318
          sc
319
          page    $nnn0
320
          jmp     $nnn0
321
          add     w,wreg
322
          add     pcl,w
323
  addr=>
324
          page    $nnn1
325
          jmp     $nnn1
326
           page    $nnn2
327
           jmp     $nnn2
328
           ...
329
           page    $nnnN
330
           jmp     $nnnN
331
 
332
  After relaxation.
333
           sc
334
           page    $nnn0
335
           jmp     $nnn0
336
           add     pcl,w
337
  addr=>
338
           jmp     $nnn1
339
           jmp     $nnn2
340
           ...
341
          jmp     $nnnN  */
342
 
343
static int
344
ip2k_is_switch_table_128 (bfd *abfd ATTRIBUTE_UNUSED,
345
                          asection *sec,
346
                          bfd_vma addr,
347
                          bfd_byte *contents)
348
{
349
  bfd_byte code[4];
350
  int table_index = 0;
351
 
352
  /* Check current page-jmp.  */
353
  if (addr + 4 > sec->size)
354
    return -1;
355
 
356
  ip2k_get_mem (abfd, contents + addr, 4, code);
357
 
358
  if ((! IS_PAGE_OPCODE (code + 0))
359
      || (! IS_JMP_OPCODE (code + 2)))
360
    return -1;
361
 
362
  /* Search back.  */
363
  while (1)
364
    {
365
      if (addr < 4)
366
        return -1;
367
 
368
      /* Check previous 2 instructions.  */
369
      ip2k_get_mem (abfd, contents + addr - 4, 4, code);
370
      if ((IS_ADD_W_WREG_OPCODE (code + 0))
371
          && (IS_ADD_PCL_W_OPCODE (code + 2)))
372
        return table_index;
373
 
374
      if ((! IS_PAGE_OPCODE (code + 0))
375
          || (! IS_JMP_OPCODE (code + 2)))
376
        return -1;
377
 
378
      table_index++;
379
      addr -= 4;
380
    }
381
}
382
 
383
/* Determine if the instruction sequence matches that for
384
   the prologue switch dispatch table with fewer than
385
   256 entries but more than 127.
386
 
387
   Before relaxation.
388
          push    %lo8insn(label) ; Push address of table
389
          push    %hi8insn(label)
390
          add     w,wreg          ; index*2 => offset
391
          snc                     ; CARRY SET?
392
          inc     1(sp)           ; Propagate MSB into table address
393
          add     2(sp),w         ; Add low bits of offset to table address
394
          snc                     ; and handle any carry-out
395
          inc     1(sp)
396
   addr=>
397
          page    __indjmp        ; Do an indirect jump to that location
398
          jmp     __indjmp
399
   label:                         ; case dispatch table starts here
400
           page    $nnn1
401
           jmp     $nnn1
402
           page    $nnn2
403
           jmp     $nnn2
404
           ...
405
           page    $nnnN
406
           jmp     $nnnN
407
 
408
  After relaxation.
409
          push    %lo8insn(label) ; Push address of table
410
          push    %hi8insn(label)
411
          add     2(sp),w         ; Add low bits of offset to table address
412
          snc                     ; and handle any carry-out
413
          inc     1(sp)
414
  addr=>
415
          page    __indjmp        ; Do an indirect jump to that location
416
          jmp     __indjmp
417
   label:                         ; case dispatch table starts here
418
          jmp     $nnn1
419
          jmp     $nnn2
420
          ...
421
          jmp     $nnnN  */
422
 
423
static int
424
ip2k_is_switch_table_256 (bfd *abfd ATTRIBUTE_UNUSED,
425
                          asection *sec,
426
                          bfd_vma addr,
427
                          bfd_byte *contents)
428
{
429
  bfd_byte code[16];
430
  int table_index = 0;
431
 
432
  /* Check current page-jmp.  */
433
  if (addr + 4 > sec->size)
434
    return -1;
435
 
436
  ip2k_get_mem (abfd, contents + addr, 4, code);
437
  if ((! IS_PAGE_OPCODE (code + 0))
438
      || (! IS_JMP_OPCODE (code + 2)))
439
    return -1;
440
 
441
  /* Search back.  */
442
  while (1)
443
    {
444
      if (addr < 16)
445
        return -1;
446
 
447
      /* Check previous 8 instructions.  */
448
      ip2k_get_mem (abfd, contents + addr - 16, 16, code);
449
      if ((IS_ADD_W_WREG_OPCODE (code + 0))
450
          && (IS_SNC_OPCODE (code + 2))
451
          && (IS_INC_1SP_OPCODE (code + 4))
452
          && (IS_ADD_2SP_W_OPCODE (code + 6))
453
          && (IS_SNC_OPCODE (code + 8))
454
          && (IS_INC_1SP_OPCODE (code + 10))
455
          && (IS_PAGE_OPCODE (code + 12))
456
          && (IS_JMP_OPCODE (code + 14)))
457
        return table_index;
458
 
459
      if ((IS_ADD_W_WREG_OPCODE (code + 2))
460
          && (IS_SNC_OPCODE (code + 4))
461
          && (IS_INC_1SP_OPCODE (code + 6))
462
          && (IS_ADD_2SP_W_OPCODE (code + 8))
463
          && (IS_SNC_OPCODE (code + 10))
464
          && (IS_INC_1SP_OPCODE (code + 12))
465
          && (IS_JMP_OPCODE (code + 14)))
466
        return table_index;
467
 
468
      if ((! IS_PAGE_OPCODE (code + 0))
469
          || (! IS_JMP_OPCODE (code + 2)))
470
        return -1;
471
 
472
      table_index++;
473
      addr -= 4;
474
    }
475
}
476
 
477
/* Returns the expected page state for the given instruction not including
478
   the effect of page instructions.  */
479
 
480
static bfd_vma
481
ip2k_nominal_page_bits (bfd *abfd ATTRIBUTE_UNUSED,
482
                        asection *sec,
483
                        bfd_vma addr,
484
                        bfd_byte *contents)
485
{
486
  bfd_vma page = PAGENO (BASEADDR (sec) + addr);
487
 
488
  /* Check if section flows into this page. If not then the page
489
     bits are assumed to match the PC. This will be true unless
490
     the user has a page instruction without a call/jump, in which
491
     case they are on their own.  */
492
  if (PAGENO (BASEADDR (sec)) == page)
493
    return page;
494
 
495
  /* Section flows across page boundary. The page bits should match
496
     the PC unless there is a possible flow from the previous page,
497
     in which case it is not possible to determine the value of the
498
     page bits.  */
499
  while (PAGENO (BASEADDR (sec) + addr - 2) == page)
500
    {
501
      bfd_byte code[2];
502
 
503
      addr -= 2;
504
      ip2k_get_mem (abfd, contents + addr, 2, code);
505
      if (!IS_PAGE_OPCODE (code))
506
        continue;
507
 
508
      /* Found a page instruction, check if jump table.  */
509
      if (ip2k_is_switch_table_128 (abfd, sec, addr, contents) != -1)
510
        /* Jump table => page is conditional.  */
511
        continue;
512
 
513
      if (ip2k_is_switch_table_256 (abfd, sec, addr, contents) != -1)
514
        /* Jump table => page is conditional.  */
515
        continue;
516
 
517
      /* Found a page instruction, check if conditional.  */
518
      if (addr >= 2)
519
        {
520
          ip2k_get_mem (abfd, contents + addr - 2, 2, code);
521
          if (IS_SKIP_OPCODE (code))
522
            /* Page is conditional.  */
523
            continue;
524
        }
525
 
526
      /* Unconditional page instruction => page bits should be correct.  */
527
      return page;
528
    }
529
 
530
  /* Flow from previous page => page bits are impossible to determine.  */
531
  return 0;
532
}
533
 
534
static bfd_boolean
535
ip2k_test_page_insn (bfd *abfd ATTRIBUTE_UNUSED,
536
                     asection *sec,
537
                     Elf_Internal_Rela *irel,
538
                     struct misc *misc)
539
{
540
  bfd_vma symval;
541
 
542
  /* Get the value of the symbol referred to by the reloc.  */
543
  symval = symbol_value (abfd, misc->symtab_hdr, misc->isymbuf, irel);
544
  if (symval == UNDEFINED_SYMBOL)
545
    /* This appears to be a reference to an undefined
546
       symbol.  Just ignore it--it will be caught by the
547
       regular reloc processing.  */
548
    return FALSE;
549
 
550
  /* Test if we can delete this page instruction.  */
551
  if (PAGENO (symval + irel->r_addend) !=
552
      ip2k_nominal_page_bits (abfd, sec, irel->r_offset, misc->contents))
553
    return FALSE;
554
 
555
  return TRUE;
556
}
557
 
558
/* Parts of a Stabs entry.  */
559
 
560
#define STRDXOFF   0
561
#define TYPEOFF    4
562
#define OTHEROFF   5
563
#define DESCOFF    6
564
#define VALOFF     8
565
#define STABSIZE   12
566
 
567
/* Adjust all the relocations entries after adding or inserting instructions.  */
568
 
569
static void
570
adjust_all_relocations (bfd *abfd,
571
                        asection *sec,
572
                        bfd_vma addr,
573
                        bfd_vma endaddr,
574
                        int count,
575
                        int noadj)
576
{
577
  Elf_Internal_Shdr *symtab_hdr;
578
  Elf_Internal_Sym *isymbuf, *isym, *isymend;
579
  unsigned int shndx;
580
  bfd_byte *contents;
581
  Elf_Internal_Rela *irel, *irelend, *irelbase;
582
  struct elf_link_hash_entry **sym_hashes;
583
  struct elf_link_hash_entry **end_hashes;
584
  unsigned int symcount;
585
  asection *stab;
586
 
587
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
588
  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
589
 
590
  shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
591
 
592
  contents = elf_section_data (sec)->this_hdr.contents;
593
 
594
  irelbase = elf_section_data (sec)->relocs;
595
  irelend = irelbase + sec->reloc_count;
596
 
597
  for (irel = irelbase; irel < irelend; irel++)
598
    {
599
      if (ELF32_R_TYPE (irel->r_info) != R_IP2K_NONE)
600
        {
601
          /* Get the value of the symbol referred to by the reloc.  */
602
          if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
603
            {
604
              asection *sym_sec;
605
 
606
              /* A local symbol.  */
607
              isym = isymbuf + ELF32_R_SYM (irel->r_info);
608
              sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
609
 
610
              if (isym->st_shndx == shndx)
611
                {
612
                  bfd_vma baseaddr = BASEADDR (sec);
613
                  bfd_vma symval = BASEADDR (sym_sec) + isym->st_value
614
                                   + irel->r_addend;
615
 
616
                  if ((baseaddr + addr + noadj) <= symval
617
                      && symval < (baseaddr + endaddr))
618
                    irel->r_addend += count;
619
                }
620
            }
621
        }
622
 
623
      /* Do this only for PC space relocations.  */
624
      if (addr <= irel->r_offset && irel->r_offset < endaddr)
625
        irel->r_offset += count;
626
    }
627
 
628
  /* Now fix the stab relocations.  */
629
  stab = bfd_get_section_by_name (abfd, ".stab");
630
  if (stab)
631
    {
632
      bfd_byte *stabcontents, *stabend, *stabp;
633
      bfd_size_type stab_size = stab->rawsize ? stab->rawsize : stab->size;
634
 
635
      irelbase = elf_section_data (stab)->relocs;
636
      irelend = irelbase + stab->reloc_count;
637
 
638
      /* Pull out the contents of the stab section.  */
639
      if (elf_section_data (stab)->this_hdr.contents != NULL)
640
        stabcontents = elf_section_data (stab)->this_hdr.contents;
641
      else
642
        {
643
          if (!bfd_malloc_and_get_section (abfd, stab, &stabcontents))
644
            {
645
              if (stabcontents != NULL)
646
                free (stabcontents);
647
              return;
648
            }
649
 
650
          /* We need to remember this.  */
651
          elf_section_data (stab)->this_hdr.contents = stabcontents;
652
        }
653
 
654
      stabend = stabcontents + stab_size;
655
 
656
      for (irel = irelbase; irel < irelend; irel++)
657
        {
658
          if (ELF32_R_TYPE (irel->r_info) != R_IP2K_NONE)
659
            {
660
              /* Get the value of the symbol referred to by the reloc.  */
661
              if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
662
                {
663
                  asection *sym_sec;
664
 
665
                  /* A local symbol.  */
666
                  isym = isymbuf + ELF32_R_SYM (irel->r_info);
667
                  sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
668
 
669
                  if (sym_sec == sec)
670
                    {
671
                      const char *name;
672
                      unsigned long strx;
673
                      unsigned char type, other;
674
                      unsigned short desc;
675
                      bfd_vma value;
676
                      bfd_vma baseaddr = BASEADDR (sec);
677
                      bfd_vma symval = BASEADDR (sym_sec) + isym->st_value
678
                        + irel->r_addend;
679
 
680
                      if ((baseaddr + addr) <= symval
681
                          && symval <= (baseaddr + endaddr))
682
                        irel->r_addend += count;
683
 
684
                      /* Go hunt up a function and fix its line info if needed.  */
685
                      stabp = stabcontents + irel->r_offset - 8;
686
 
687
                      /* Go pullout the stab entry.  */
688
                      strx  = bfd_h_get_32 (abfd, stabp + STRDXOFF);
689
                      type  = bfd_h_get_8 (abfd, stabp + TYPEOFF);
690
                      other = bfd_h_get_8 (abfd, stabp + OTHEROFF);
691
                      desc  = bfd_h_get_16 (abfd, stabp + DESCOFF);
692
                      value = bfd_h_get_32 (abfd, stabp + VALOFF);
693
 
694
                      name = bfd_get_stab_name (type);
695
 
696
                      if (strcmp (name, "FUN") == 0)
697
                        {
698
                          int function_adjusted = 0;
699
 
700
                          if (symval > (baseaddr + addr))
701
                            /* Not in this function.  */
702
                            continue;
703
 
704
                          /* Hey we got a function hit.  */
705
                          stabp += STABSIZE;
706
                          for (;stabp < stabend; stabp += STABSIZE)
707
                            {
708
                              /* Go pullout the stab entry.  */
709
                              strx  = bfd_h_get_32 (abfd, stabp + STRDXOFF);
710
                              type  = bfd_h_get_8 (abfd, stabp + TYPEOFF);
711
                              other = bfd_h_get_8 (abfd, stabp + OTHEROFF);
712
                              desc  = bfd_h_get_16 (abfd, stabp + DESCOFF);
713
                              value = bfd_h_get_32 (abfd, stabp + VALOFF);
714
 
715
                              name = bfd_get_stab_name (type);
716
 
717
                              if (strcmp (name, "FUN") == 0)
718
                                {
719
                                  /* Hit another function entry.  */
720
                                  if (function_adjusted)
721
                                    {
722
                                      /* Adjust the value.  */
723
                                      value += count;
724
 
725
                                      /* We need to put it back.  */
726
                                      bfd_h_put_32 (abfd, value,stabp + VALOFF);
727
                                    }
728
 
729
                                  /* And then bale out.  */
730
                                  break;
731
                                }
732
 
733
                              if (strcmp (name, "SLINE") == 0)
734
                                {
735
                                  /* Got a line entry.  */
736
                                  if ((baseaddr + addr) <= (symval + value))
737
                                    {
738
                                      /* Adjust the line entry.  */
739
                                      value += count;
740
 
741
                                      /* We need to put it back.  */
742
                                      bfd_h_put_32 (abfd, value,stabp + VALOFF);
743
                                      function_adjusted = 1;
744
                                    }
745
                                }
746
                            }
747
                        }
748
                    }
749
                }
750
            }
751
        }
752
    }
753
 
754
  /* When adding an instruction back it is sometimes necessary to move any
755
     global or local symbol that was referencing the first instruction of
756
     the moved block to refer to the first instruction of the inserted block.
757
 
758
     For example adding a PAGE instruction before a CALL or JMP requires
759
     that any label on the CALL or JMP is moved to the PAGE insn.  */
760
  addr += noadj;
761
 
762
  /* Adjust the local symbols defined in this section.  */
763
  isymend = isymbuf + symtab_hdr->sh_info;
764
  for (isym = isymbuf; isym < isymend; isym++)
765
    {
766
      if (isym->st_shndx == shndx
767
          && addr <= isym->st_value
768
          && isym->st_value < endaddr)
769
        isym->st_value += count;
770
    }
771
 
772
  /* Now adjust the global symbols defined in this section.  */
773
  symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
774
              - symtab_hdr->sh_info);
775
  sym_hashes = elf_sym_hashes (abfd);
776
  end_hashes = sym_hashes + symcount;
777
  for (; sym_hashes < end_hashes; sym_hashes++)
778
    {
779
      struct elf_link_hash_entry *sym_hash = *sym_hashes;
780
 
781
      if ((sym_hash->root.type == bfd_link_hash_defined
782
           || sym_hash->root.type == bfd_link_hash_defweak)
783
          && sym_hash->root.u.def.section == sec)
784
        {
785
          if (addr <= sym_hash->root.u.def.value
786
              && sym_hash->root.u.def.value < endaddr)
787
            sym_hash->root.u.def.value += count;
788
        }
789
    }
790
 
791
  return;
792
}
793
 
794
/* Delete some bytes from a section while relaxing.  */
795
 
796
static bfd_boolean
797
ip2k_elf_relax_delete_bytes (bfd *abfd,
798
                             asection *sec,
799
                             bfd_vma addr,
800
                             int count)
801
{
802
  bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
803
  bfd_vma endaddr = sec->size;
804
 
805
  /* Actually delete the bytes.  */
806
  memmove (contents + addr, contents + addr + count,
807
           endaddr - addr - count);
808
 
809
  sec->size -= count;
810
 
811
  adjust_all_relocations (abfd, sec, addr + count, endaddr, -count, 0);
812
  return TRUE;
813
}
814
 
815
static bfd_boolean
816
ip2k_delete_page_insn (bfd *abfd ATTRIBUTE_UNUSED,
817
                       asection *sec,
818
                       Elf_Internal_Rela *irel,
819
                       bfd_boolean *again,
820
                       struct misc *misc)
821
{
822
  /* Note that we've changed the relocs, section contents, etc.  */
823
  elf_section_data (sec)->relocs = misc->irelbase;
824
  elf_section_data (sec)->this_hdr.contents = misc->contents;
825
  misc->symtab_hdr->contents = (bfd_byte *) misc->isymbuf;
826
 
827
  /* Fix the relocation's type.  */
828
  irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_IP2K_NONE);
829
 
830
  /* Delete the PAGE insn.  */
831
  if (!ip2k_elf_relax_delete_bytes (abfd, sec, irel->r_offset, 2))
832
    return FALSE;
833
 
834
  /* Modified => will need to iterate relaxation again.  */
835
  *again = TRUE;
836
 
837
  return TRUE;
838
}
839
 
840
static bfd_boolean
841
ip2k_relax_switch_table_128 (bfd *abfd ATTRIBUTE_UNUSED,
842
                             asection *sec,
843
                             Elf_Internal_Rela *irel,
844
                             bfd_boolean *again,
845
                             struct misc *misc)
846
{
847
  Elf_Internal_Rela *irelend = misc->irelbase + sec->reloc_count;
848
  Elf_Internal_Rela *ireltest = irel;
849
  bfd_byte code[4];
850
  bfd_vma addr;
851
 
852
  /* Test all page instructions.  */
853
  addr = irel->r_offset;
854
  while (1)
855
    {
856
      if (addr + 4 > sec->size)
857
        break;
858
 
859
      ip2k_get_mem (abfd, misc->contents + addr, 4, code);
860
      if ((! IS_PAGE_OPCODE (code + 0))
861
          || (! IS_JMP_OPCODE (code + 2)))
862
        break;
863
 
864
      /* Validate relocation entry (every entry should have a matching
865
          relocation entry).  */
866
      if (ireltest >= irelend)
867
        {
868
          _bfd_error_handler (_("ip2k relaxer: switch table without complete matching relocation information."));
869
          return FALSE;
870
        }
871
 
872
      if (ireltest->r_offset != addr)
873
        {
874
          _bfd_error_handler (_("ip2k relaxer: switch table without complete matching relocation information."));
875
          return FALSE;
876
        }
877
 
878
      if (! ip2k_test_page_insn (abfd, sec, ireltest, misc))
879
        /* Un-removable page insn => nothing can be done.  */
880
        return TRUE;
881
 
882
      addr += 4;
883
      ireltest += 2;
884
    }
885
 
886
  /* Relaxable. Adjust table header.  */
887
  ip2k_get_mem (abfd, misc->contents + irel->r_offset - 4, 4, code);
888
  if ((! IS_ADD_W_WREG_OPCODE (code + 0))
889
      || (! IS_ADD_PCL_W_OPCODE (code + 2)))
890
    {
891
      _bfd_error_handler (_("ip2k relaxer: switch table header corrupt."));
892
      return FALSE;
893
    }
894
 
895
  if (!ip2k_elf_relax_delete_bytes (abfd, sec, irel->r_offset - 4, 2))
896
    return FALSE;
897
 
898
  *again = TRUE;
899
 
900
  /* Delete all page instructions in table.  */
901
  while (irel < ireltest)
902
    {
903
      if (!ip2k_delete_page_insn (abfd, sec, irel, again, misc))
904
        return FALSE;
905
      irel += 2;
906
    }
907
 
908
  return TRUE;
909
}
910
 
911
static bfd_boolean
912
ip2k_relax_switch_table_256 (bfd *abfd ATTRIBUTE_UNUSED,
913
                             asection *sec,
914
                             Elf_Internal_Rela *irel,
915
                             bfd_boolean *again,
916
                             struct misc *misc)
917
{
918
  Elf_Internal_Rela *irelend = misc->irelbase + sec->reloc_count;
919
  Elf_Internal_Rela *ireltest = irel;
920
  bfd_byte code[12];
921
  bfd_vma addr;
922
 
923
  /* Test all page instructions.  */
924
  addr = irel->r_offset;
925
 
926
  while (1)
927
    {
928
      if (addr + 4 > sec->size)
929
        break;
930
 
931
      ip2k_get_mem (abfd, misc->contents + addr, 4, code);
932
 
933
      if ((! IS_PAGE_OPCODE (code + 0))
934
          || (! IS_JMP_OPCODE (code + 2)))
935
        break;
936
 
937
      /* Validate relocation entry (every entry should have a matching
938
          relocation entry).  */
939
      if (ireltest >= irelend)
940
        {
941
          _bfd_error_handler (_("ip2k relaxer: switch table without complete matching relocation information."));
942
          return FALSE;
943
        }
944
 
945
      if (ireltest->r_offset != addr)
946
        {
947
          _bfd_error_handler (_("ip2k relaxer: switch table without complete matching relocation information."));
948
          return FALSE;
949
        }
950
 
951
      if (!ip2k_test_page_insn (abfd, sec, ireltest, misc))
952
        /* Un-removable page insn => nothing can be done.  */
953
        return TRUE;
954
 
955
      addr += 4;
956
      ireltest += 2;
957
    }
958
 
959
  /* Relaxable. Adjust table header.  */
960
  ip2k_get_mem (abfd, misc->contents + irel->r_offset - 4, 2, code);
961
  if (IS_PAGE_OPCODE (code))
962
    addr = irel->r_offset - 16;
963
  else
964
    addr = irel->r_offset - 14;
965
 
966
  ip2k_get_mem (abfd, misc->contents + addr, 12, code);
967
  if ((!IS_ADD_W_WREG_OPCODE (code + 0))
968
      || (!IS_SNC_OPCODE (code + 2))
969
      || (!IS_INC_1SP_OPCODE (code + 4))
970
      || (!IS_ADD_2SP_W_OPCODE (code + 6))
971
      || (!IS_SNC_OPCODE (code + 8))
972
      || (!IS_INC_1SP_OPCODE (code + 10)))
973
    {
974
      _bfd_error_handler (_("ip2k relaxer: switch table header corrupt."));
975
      return FALSE;
976
    }
977
 
978
  /* Delete first 3 opcodes.  */
979
  if (!ip2k_elf_relax_delete_bytes (abfd, sec, addr + 0, 6))
980
    return FALSE;
981
 
982
  *again = TRUE;
983
 
984
  /* Delete all page instructions in table.  */
985
  while (irel < ireltest)
986
    {
987
      if (!ip2k_delete_page_insn (abfd, sec, irel, again, misc))
988
        return FALSE;
989
      irel += 2;
990
    }
991
 
992
  return TRUE;
993
}
994
 
995
/* This function handles relaxation of a section in a specific page.  */
996
 
997
static bfd_boolean
998
ip2k_elf_relax_section_page (bfd *abfd,
999
                             asection *sec,
1000
                             bfd_boolean *again,
1001
                             struct misc *misc,
1002
                             unsigned long page_start,
1003
                             unsigned long page_end)
1004
{
1005
  Elf_Internal_Rela *irelend = misc->irelbase + sec->reloc_count;
1006
  Elf_Internal_Rela *irel;
1007
  int switch_table_128;
1008
  int switch_table_256;
1009
 
1010
  /* Walk thru the section looking for relaxation opportunities.  */
1011
  for (irel = misc->irelbase; irel < irelend; irel++)
1012
    {
1013
      if (ELF32_R_TYPE (irel->r_info) != (int) R_IP2K_PAGE3)
1014
        /* Ignore non page instructions.  */
1015
        continue;
1016
 
1017
      if (BASEADDR (sec) + irel->r_offset < page_start)
1018
        /* Ignore page instructions on earlier page - they have
1019
           already been processed. Remember that there is code flow
1020
           that crosses a page boundary.  */
1021
        continue;
1022
 
1023
      if (BASEADDR (sec) + irel->r_offset > page_end)
1024
        /* Flow beyond end of page => nothing more to do for this page.  */
1025
        return TRUE;
1026
 
1027
      /* Detect switch tables.  */
1028
      switch_table_128 = ip2k_is_switch_table_128 (abfd, sec, irel->r_offset, misc->contents);
1029
      switch_table_256 = ip2k_is_switch_table_256 (abfd, sec, irel->r_offset, misc->contents);
1030
 
1031
      if ((switch_table_128 > 0) || (switch_table_256 > 0))
1032
        /* If the index is greater than 0 then it has already been processed.  */
1033
        continue;
1034
 
1035
      if (switch_table_128 == 0)
1036
        {
1037
          if (!ip2k_relax_switch_table_128 (abfd, sec, irel, again, misc))
1038
            return FALSE;
1039
 
1040
          continue;
1041
        }
1042
 
1043
      if (switch_table_256 == 0)
1044
        {
1045
          if (!ip2k_relax_switch_table_256 (abfd, sec, irel, again, misc))
1046
            return FALSE;
1047
 
1048
          continue;
1049
        }
1050
 
1051
      /* Simple relax.  */
1052
      if (ip2k_test_page_insn (abfd, sec, irel, misc))
1053
        {
1054
          if (!ip2k_delete_page_insn (abfd, sec, irel, again, misc))
1055
            return FALSE;
1056
 
1057
          continue;
1058
        }
1059
    }
1060
 
1061
  return TRUE;
1062
}
1063
 
1064
/* This function handles relaxing for the ip2k.
1065
 
1066
   Principle: Start with the first page and remove page instructions that
1067
   are not require on this first page. By removing page instructions more
1068
   code will fit into this page - repeat until nothing more can be achieved
1069
   for this page. Move on to the next page.
1070
 
1071
   Processing the pages one at a time from the lowest page allows a removal
1072
   only policy to be used - pages can be removed but are never reinserted.  */
1073
 
1074
static bfd_boolean
1075
ip2k_elf_relax_section (bfd *abfd,
1076
                        asection *sec,
1077
                        struct bfd_link_info *link_info,
1078
                        bfd_boolean *again)
1079
{
1080
  Elf_Internal_Shdr *symtab_hdr;
1081
  Elf_Internal_Rela *internal_relocs;
1082
  bfd_byte *contents = NULL;
1083
  Elf_Internal_Sym *isymbuf = NULL;
1084
  static asection * first_section = NULL;
1085
  static unsigned long search_addr;
1086
  static unsigned long page_start = 0;
1087
  static unsigned long page_end = 0;
1088
  static unsigned int pass = 0;
1089
  static bfd_boolean new_pass = FALSE;
1090
  static bfd_boolean changed = FALSE;
1091
  struct misc misc;
1092
  asection *stab;
1093
 
1094
  /* Assume nothing changes.  */
1095
  *again = FALSE;
1096
 
1097
  if (first_section == NULL)
1098
    {
1099
      ip2k_relaxed = TRUE;
1100
      first_section = sec;
1101
    }
1102
 
1103
  if (first_section == sec)
1104
    {
1105
      pass++;
1106
      new_pass = TRUE;
1107
    }
1108
 
1109
  /* We don't have to do anything for a relocatable link,
1110
     if this section does not have relocs, or if this is
1111
     not a code section.  */
1112
  if (link_info->relocatable
1113
      || (sec->flags & SEC_RELOC) == 0
1114
      || sec->reloc_count == 0
1115
      || (sec->flags & SEC_CODE) == 0)
1116
    return TRUE;
1117
 
1118
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1119
 
1120
  internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
1121
                                               link_info->keep_memory);
1122
  if (internal_relocs == NULL)
1123
    goto error_return;
1124
 
1125
  /* Make sure the stac.rela stuff gets read in.  */
1126
  stab = bfd_get_section_by_name (abfd, ".stab");
1127
 
1128
  if (stab)
1129
    {
1130
      /* So stab does exits.  */
1131
      Elf_Internal_Rela * irelbase;
1132
 
1133
      irelbase = _bfd_elf_link_read_relocs (abfd, stab, NULL, NULL,
1134
                                            link_info->keep_memory);
1135
    }
1136
 
1137
  /* Get section contents cached copy if it exists.  */
1138
  if (contents == NULL)
1139
    {
1140
      /* Get cached copy if it exists.  */
1141
      if (elf_section_data (sec)->this_hdr.contents != NULL)
1142
        contents = elf_section_data (sec)->this_hdr.contents;
1143
      else
1144
        {
1145
          /* Go get them off disk.  */
1146
          if (!bfd_malloc_and_get_section (abfd, sec, &contents))
1147
            goto error_return;
1148
        }
1149
    }
1150
 
1151
  /* Read this BFD's symbols cached copy if it exists.  */
1152
  if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1153
    {
1154
      isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1155
      if (isymbuf == NULL)
1156
        isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1157
                                        symtab_hdr->sh_info, 0,
1158
                                        NULL, NULL, NULL);
1159
      if (isymbuf == NULL)
1160
        goto error_return;
1161
    }
1162
 
1163
  misc.symtab_hdr = symtab_hdr;
1164
  misc.isymbuf = isymbuf;
1165
  misc.irelbase = internal_relocs;
1166
  misc.contents = contents;
1167
 
1168
  /* This is where all the relaxation actually get done.  */
1169
  if ((pass == 1) || (new_pass && !changed))
1170
    {
1171
      /* On the first pass we simply search for the lowest page that
1172
         we havn't relaxed yet. Note that the pass count is reset
1173
         each time a page is complete in order to move on to the next page.
1174
         If we can't find any more pages then we are finished.  */
1175
      if (new_pass)
1176
        {
1177
          pass = 1;
1178
          new_pass = FALSE;
1179
          changed = TRUE; /* Pre-initialize to break out of pass 1.  */
1180
          search_addr = 0xFFFFFFFF;
1181
        }
1182
 
1183
      if ((BASEADDR (sec) + sec->size < search_addr)
1184
          && (BASEADDR (sec) + sec->size > page_end))
1185
        {
1186
          if (BASEADDR (sec) <= page_end)
1187
            search_addr = page_end + 1;
1188
          else
1189
            search_addr = BASEADDR (sec);
1190
 
1191
          /* Found a page => more work to do.  */
1192
          *again = TRUE;
1193
        }
1194
    }
1195
  else
1196
    {
1197
      if (new_pass)
1198
        {
1199
          new_pass = FALSE;
1200
          changed = FALSE;
1201
          page_start = PAGENO (search_addr);
1202
          page_end = page_start | 0x00003FFF;
1203
        }
1204
 
1205
      /* Only process sections in range.  */
1206
      if ((BASEADDR (sec) + sec->size >= page_start)
1207
          && (BASEADDR (sec) <= page_end))
1208
        {
1209
          if (!ip2k_elf_relax_section_page (abfd, sec, &changed, &misc, page_start, page_end))
1210
            return FALSE;
1211
        }
1212
      *again = TRUE;
1213
    }
1214
 
1215
  /* Perform some house keeping after relaxing the section.  */
1216
 
1217
  if (isymbuf != NULL
1218
      && symtab_hdr->contents != (unsigned char *) isymbuf)
1219
    {
1220
      if (! link_info->keep_memory)
1221
        free (isymbuf);
1222
      else
1223
        symtab_hdr->contents = (unsigned char *) isymbuf;
1224
    }
1225
 
1226
  if (contents != NULL
1227
      && elf_section_data (sec)->this_hdr.contents != contents)
1228
    {
1229
      if (! link_info->keep_memory)
1230
        free (contents);
1231
      else
1232
        {
1233
          /* Cache the section contents for elf_link_input_bfd.  */
1234
          elf_section_data (sec)->this_hdr.contents = contents;
1235
        }
1236
    }
1237
 
1238
  if (internal_relocs != NULL
1239
      && elf_section_data (sec)->relocs != internal_relocs)
1240
    free (internal_relocs);
1241
 
1242
  return TRUE;
1243
 
1244
 error_return:
1245
  if (isymbuf != NULL
1246
      && symtab_hdr->contents != (unsigned char *) isymbuf)
1247
    free (isymbuf);
1248
  if (contents != NULL
1249
      && elf_section_data (sec)->this_hdr.contents != contents)
1250
    free (contents);
1251
  if (internal_relocs != NULL
1252
      && elf_section_data (sec)->relocs != internal_relocs)
1253
    free (internal_relocs);
1254
  return FALSE;
1255
}
1256
 
1257
/* Set the howto pointer for a IP2K ELF reloc.  */
1258
 
1259
static void
1260
ip2k_info_to_howto_rela (bfd * abfd ATTRIBUTE_UNUSED,
1261
                         arelent * cache_ptr,
1262
                         Elf_Internal_Rela * dst)
1263
{
1264
  unsigned int r_type;
1265
 
1266
  r_type = ELF32_R_TYPE (dst->r_info);
1267
  cache_ptr->howto = & ip2k_elf_howto_table [r_type];
1268
}
1269
 
1270
/* Perform a single relocation.
1271
   By default we use the standard BFD routines.  */
1272
 
1273
static bfd_reloc_status_type
1274
ip2k_final_link_relocate (reloc_howto_type *  howto,
1275
                          bfd *               input_bfd,
1276
                          asection *          input_section,
1277
                          bfd_byte *          contents,
1278
                          Elf_Internal_Rela * rel,
1279
                          bfd_vma             relocation)
1280
{
1281
  static bfd_vma page_addr = 0;
1282
 
1283
  bfd_reloc_status_type r = bfd_reloc_ok;
1284
  switch (howto->type)
1285
    {
1286
      /* Handle data space relocations.  */
1287
    case R_IP2K_FR9:
1288
    case R_IP2K_BANK:
1289
      if ((relocation & IP2K_DATA_MASK) == IP2K_DATA_VALUE)
1290
        relocation &= ~IP2K_DATA_MASK;
1291
      else
1292
        r = bfd_reloc_notsupported;
1293
      break;
1294
 
1295
    case R_IP2K_LO8DATA:
1296
    case R_IP2K_HI8DATA:
1297
    case R_IP2K_EX8DATA:
1298
      break;
1299
 
1300
      /* Handle insn space relocations.  */
1301
    case R_IP2K_PAGE3:
1302
      page_addr = BASEADDR (input_section) + rel->r_offset;
1303
      if ((relocation & IP2K_INSN_MASK) == IP2K_INSN_VALUE)
1304
        relocation &= ~IP2K_INSN_MASK;
1305
      else
1306
        r = bfd_reloc_notsupported;
1307
      break;
1308
 
1309
    case R_IP2K_ADDR16CJP:
1310
      if (BASEADDR (input_section) + rel->r_offset != page_addr + 2)
1311
        {
1312
          /* No preceding page instruction, verify that it isn't needed.  */
1313
          if (PAGENO (relocation + rel->r_addend) !=
1314
              ip2k_nominal_page_bits (input_bfd, input_section,
1315
                                      rel->r_offset, contents))
1316
            _bfd_error_handler (_("ip2k linker: missing page instruction at 0x%08lx (dest = 0x%08lx)."),
1317
                                BASEADDR (input_section) + rel->r_offset,
1318
                                relocation + rel->r_addend);
1319
        }
1320
      else if (ip2k_relaxed)
1321
        {
1322
          /* Preceding page instruction. Verify that the page instruction is
1323
             really needed. One reason for the relaxation to miss a page is if
1324
             the section is not marked as executable.  */
1325
          if (!ip2k_is_switch_table_128 (input_bfd, input_section,
1326
                                         rel->r_offset - 2, contents)
1327
              && !ip2k_is_switch_table_256 (input_bfd, input_section,
1328
                                            rel->r_offset - 2, contents)
1329
              && (PAGENO (relocation + rel->r_addend) ==
1330
                  ip2k_nominal_page_bits (input_bfd, input_section,
1331
                                          rel->r_offset - 2, contents)))
1332
            _bfd_error_handler (_("ip2k linker: redundant page instruction at 0x%08lx (dest = 0x%08lx)."),
1333
                                page_addr,
1334
                                relocation + rel->r_addend);
1335
        }
1336
      if ((relocation & IP2K_INSN_MASK) == IP2K_INSN_VALUE)
1337
        relocation &= ~IP2K_INSN_MASK;
1338
      else
1339
        r = bfd_reloc_notsupported;
1340
      break;
1341
 
1342
    case R_IP2K_LO8INSN:
1343
    case R_IP2K_HI8INSN:
1344
    case R_IP2K_PC_SKIP:
1345
      if ((relocation & IP2K_INSN_MASK) == IP2K_INSN_VALUE)
1346
        relocation &= ~IP2K_INSN_MASK;
1347
      else
1348
        r = bfd_reloc_notsupported;
1349
      break;
1350
 
1351
    case R_IP2K_16:
1352
      /* If this is a relocation involving a TEXT
1353
         symbol, reduce it to a word address.  */
1354
      if ((relocation & IP2K_INSN_MASK) == IP2K_INSN_VALUE)
1355
        howto = &ip2k_elf_howto_table[ (int) R_IP2K_TEXT];
1356
      break;
1357
 
1358
      /* Pass others through.  */
1359
    default:
1360
      break;
1361
    }
1362
 
1363
  /* Only install relocation if above tests did not disqualify it.  */
1364
  if (r == bfd_reloc_ok)
1365
    r = _bfd_final_link_relocate (howto, input_bfd, input_section,
1366
                                  contents, rel->r_offset,
1367
                                  relocation, rel->r_addend);
1368
 
1369
  return r;
1370
}
1371
 
1372
/* Relocate a IP2K ELF section.
1373
 
1374
   The RELOCATE_SECTION function is called by the new ELF backend linker
1375
   to handle the relocations for a section.
1376
 
1377
   The relocs are always passed as Rela structures; if the section
1378
   actually uses Rel structures, the r_addend field will always be
1379
   zero.
1380
 
1381
   This function is responsible for adjusting the section contents as
1382
   necessary, and (if using Rela relocs and generating a relocatable
1383
   output file) adjusting the reloc addend as necessary.
1384
 
1385
   This function does not have to worry about setting the reloc
1386
   address or the reloc symbol index.
1387
 
1388
   LOCAL_SYMS is a pointer to the swapped in local symbols.
1389
 
1390
   LOCAL_SECTIONS is an array giving the section in the input file
1391
   corresponding to the st_shndx field of each local symbol.
1392
 
1393
   The global hash table entry for the global symbols can be found
1394
   via elf_sym_hashes (input_bfd).
1395
 
1396
   When generating relocatable output, this function must handle
1397
   STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
1398
   going to be the section symbol corresponding to the output
1399
   section, which means that the addend must be adjusted
1400
   accordingly.  */
1401
 
1402
static bfd_boolean
1403
ip2k_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
1404
                           struct bfd_link_info *info,
1405
                           bfd *input_bfd,
1406
                           asection *input_section,
1407
                           bfd_byte *contents,
1408
                           Elf_Internal_Rela *relocs,
1409
                           Elf_Internal_Sym *local_syms,
1410
                           asection **local_sections)
1411
{
1412
  Elf_Internal_Shdr *symtab_hdr;
1413
  struct elf_link_hash_entry **sym_hashes;
1414
  Elf_Internal_Rela *rel;
1415
  Elf_Internal_Rela *relend;
1416
 
1417
  symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
1418
  sym_hashes = elf_sym_hashes (input_bfd);
1419
  relend     = relocs + input_section->reloc_count;
1420
 
1421
  for (rel = relocs; rel < relend; rel ++)
1422
    {
1423
      reloc_howto_type *           howto;
1424
      unsigned long                r_symndx;
1425
      Elf_Internal_Sym *           sym;
1426
      asection *                   sec;
1427
      struct elf_link_hash_entry * h;
1428
      bfd_vma                      relocation;
1429
      bfd_reloc_status_type        r;
1430
      const char *                 name = NULL;
1431
      int                          r_type;
1432
 
1433
      r_type = ELF32_R_TYPE (rel->r_info);
1434
      r_symndx = ELF32_R_SYM (rel->r_info);
1435
      howto  = ip2k_elf_howto_table + ELF32_R_TYPE (rel->r_info);
1436
      h      = NULL;
1437
      sym    = NULL;
1438
      sec    = NULL;
1439
 
1440
      if (r_symndx < symtab_hdr->sh_info)
1441
        {
1442
          sym = local_syms + r_symndx;
1443
          sec = local_sections [r_symndx];
1444
          relocation = BASEADDR (sec) + sym->st_value;
1445
 
1446
          name = bfd_elf_string_from_elf_section
1447
            (input_bfd, symtab_hdr->sh_link, sym->st_name);
1448
          name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
1449
        }
1450
      else
1451
        {
1452
          bfd_boolean warned;
1453
          bfd_boolean unresolved_reloc;
1454
 
1455
          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
1456
                                   r_symndx, symtab_hdr, sym_hashes,
1457
                                   h, sec, relocation,
1458
                                   unresolved_reloc, warned);
1459
 
1460
          name = h->root.root.string;
1461
        }
1462
 
1463
      if (sec != NULL && elf_discarded_section (sec))
1464
        {
1465
          /* For relocs against symbols from removed linkonce sections,
1466
             or sections discarded by a linker script, we just want the
1467
             section contents zeroed.  Avoid any special processing.  */
1468
          _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
1469
          rel->r_info = 0;
1470
          rel->r_addend = 0;
1471
          continue;
1472
        }
1473
 
1474
      if (info->relocatable)
1475
        continue;
1476
 
1477
      /* Finally, the sole IP2K-specific part.  */
1478
      r = ip2k_final_link_relocate (howto, input_bfd, input_section,
1479
                                     contents, rel, relocation);
1480
 
1481
      if (r != bfd_reloc_ok)
1482
        {
1483
          const char * msg = NULL;
1484
 
1485
          switch (r)
1486
            {
1487
            case bfd_reloc_overflow:
1488
              r = info->callbacks->reloc_overflow
1489
                (info, (h ? &h->root : NULL), name, howto->name,
1490
                 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
1491
              break;
1492
 
1493
            case bfd_reloc_undefined:
1494
              r = info->callbacks->undefined_symbol
1495
                (info, name, input_bfd, input_section, rel->r_offset, TRUE);
1496
              break;
1497
 
1498
            case bfd_reloc_outofrange:
1499
              msg = _("internal error: out of range error");
1500
              break;
1501
 
1502
              /* This is how ip2k_final_link_relocate tells us of a non-kosher
1503
                 reference between insn & data address spaces.  */
1504
            case bfd_reloc_notsupported:
1505
              if (sym != NULL) /* Only if it's not an unresolved symbol.  */
1506
                 msg = _("unsupported relocation between data/insn address spaces");
1507
              break;
1508
 
1509
            case bfd_reloc_dangerous:
1510
              msg = _("internal error: dangerous relocation");
1511
              break;
1512
 
1513
            default:
1514
              msg = _("internal error: unknown error");
1515
              break;
1516
            }
1517
 
1518
          if (msg)
1519
            r = info->callbacks->warning
1520
              (info, msg, name, input_bfd, input_section, rel->r_offset);
1521
 
1522
          if (! r)
1523
            return FALSE;
1524
        }
1525
    }
1526
 
1527
  return TRUE;
1528
}
1529
 
1530
#define TARGET_BIG_SYM   bfd_elf32_ip2k_vec
1531
#define TARGET_BIG_NAME  "elf32-ip2k"
1532
 
1533
#define ELF_ARCH         bfd_arch_ip2k
1534
#define ELF_MACHINE_CODE EM_IP2K
1535
#define ELF_MACHINE_ALT1 EM_IP2K_OLD
1536
#define ELF_MAXPAGESIZE  1 /* No pages on the IP2K.  */
1537
 
1538
#define elf_info_to_howto_rel                   NULL
1539
#define elf_info_to_howto                       ip2k_info_to_howto_rela
1540
 
1541
#define elf_backend_can_gc_sections             1
1542
#define elf_backend_rela_normal                 1
1543
#define elf_backend_relocate_section            ip2k_elf_relocate_section
1544
 
1545
#define elf_symbol_leading_char                 '_'
1546
#define bfd_elf32_bfd_reloc_type_lookup         ip2k_reloc_type_lookup
1547
#define bfd_elf32_bfd_reloc_name_lookup ip2k_reloc_name_lookup
1548
#define bfd_elf32_bfd_relax_section             ip2k_elf_relax_section
1549
 
1550
#include "elf32-target.h"

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.