00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "bfd.h"
00026 #include "sysdep.h"
00027 #include "libbfd.h"
00028 #include "elf-bfd.h"
00029 #include "elf/ip2k.h"
00030
00031
00032
00033 struct misc
00034 {
00035 Elf_Internal_Shdr * symtab_hdr;
00036 Elf_Internal_Rela * irelbase;
00037 bfd_byte * contents;
00038 Elf_Internal_Sym * isymbuf;
00039 };
00040
00041 struct ip2k_opcode
00042 {
00043 unsigned short opcode;
00044 unsigned short mask;
00045 };
00046
00047
00048 static reloc_howto_type *ip2k_reloc_type_lookup
00049 PARAMS ((bfd *, bfd_reloc_code_real_type));
00050 static int ip2k_is_opcode
00051 PARAMS ((bfd_byte *, const struct ip2k_opcode *));
00052 static bfd_vma symbol_value
00053 PARAMS ((bfd *, Elf_Internal_Shdr *, Elf_Internal_Sym *,
00054 Elf_Internal_Rela *));
00055 static void ip2k_get_mem
00056 PARAMS ((bfd *, bfd_byte *, int, bfd_byte *));
00057 static bfd_vma ip2k_nominal_page_bits
00058 PARAMS ((bfd *, asection *, bfd_vma, bfd_byte *));
00059 static bfd_boolean ip2k_test_page_insn
00060 PARAMS ((bfd *, asection *, Elf_Internal_Rela *, struct misc *));
00061 static bfd_boolean ip2k_delete_page_insn
00062 PARAMS ((bfd *, asection *, Elf_Internal_Rela *, bfd_boolean *, struct misc *));
00063 static int ip2k_is_switch_table_128
00064 PARAMS ((bfd *, asection *, bfd_vma, bfd_byte *));
00065 static bfd_boolean ip2k_relax_switch_table_128
00066 PARAMS ((bfd *, asection *, Elf_Internal_Rela *, bfd_boolean *, struct misc *));
00067 static int ip2k_is_switch_table_256
00068 PARAMS ((bfd *, asection *, bfd_vma, bfd_byte *));
00069 static bfd_boolean ip2k_relax_switch_table_256
00070 PARAMS ((bfd *, asection *, Elf_Internal_Rela *, bfd_boolean *, struct misc *));
00071 static bfd_boolean ip2k_elf_relax_section
00072 PARAMS ((bfd *, asection *, struct bfd_link_info *, bfd_boolean *));
00073 static bfd_boolean ip2k_elf_relax_section_page
00074 PARAMS ((bfd *, asection *, bfd_boolean *, struct misc *, unsigned long, unsigned long));
00075 static void adjust_all_relocations
00076 PARAMS ((bfd *, asection *, bfd_vma, bfd_vma, int, int));
00077 static bfd_boolean ip2k_elf_relax_delete_bytes
00078 PARAMS ((bfd *, asection *, bfd_vma, int));
00079 static void ip2k_info_to_howto_rela
00080 PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
00081 static bfd_reloc_status_type ip2k_final_link_relocate
00082 PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
00083 Elf_Internal_Rela *, bfd_vma));
00084 static bfd_boolean ip2k_elf_relocate_section
00085 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
00086 Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
00087 static asection *ip2k_elf_gc_mark_hook
00088 PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
00089 struct elf_link_hash_entry *, Elf_Internal_Sym *));
00090 static bfd_boolean ip2k_elf_gc_sweep_hook
00091 PARAMS ((bfd *, struct bfd_link_info *, asection *,
00092 const Elf_Internal_Rela *));
00093
00094 static bfd_boolean ip2k_relaxed = FALSE;
00095
00096 static const struct ip2k_opcode ip2k_page_opcode[] =
00097 {
00098 {0x0010, 0xFFF8},
00099 {0x0000, 0x0000},
00100 };
00101
00102 #define IS_PAGE_OPCODE(code) \
00103 ip2k_is_opcode (code, ip2k_page_opcode)
00104
00105 static const struct ip2k_opcode ip2k_jmp_opcode[] =
00106 {
00107 {0xE000, 0xE000},
00108 {0x0000, 0x0000},
00109 };
00110
00111 #define IS_JMP_OPCODE(code) \
00112 ip2k_is_opcode (code, ip2k_jmp_opcode)
00113
00114 static const struct ip2k_opcode ip2k_snc_opcode[] =
00115 {
00116 {0xA00B, 0xFFFF},
00117 {0x0000, 0x0000},
00118 };
00119
00120 #define IS_SNC_OPCODE(code) \
00121 ip2k_is_opcode (code, ip2k_snc_opcode)
00122
00123 static const struct ip2k_opcode ip2k_inc_1sp_opcode[] =
00124 {
00125 {0x2B81, 0xFFFF},
00126 {0x0000, 0x0000},
00127 };
00128
00129 #define IS_INC_1SP_OPCODE(code) \
00130 ip2k_is_opcode (code, ip2k_inc_1sp_opcode)
00131
00132 static const struct ip2k_opcode ip2k_add_2sp_w_opcode[] =
00133 {
00134 {0x1F82, 0xFFFF},
00135 {0x0000, 0x0000},
00136 };
00137
00138 #define IS_ADD_2SP_W_OPCODE(code) \
00139 ip2k_is_opcode (code, ip2k_add_2sp_w_opcode)
00140
00141 static const struct ip2k_opcode ip2k_add_w_wreg_opcode[] =
00142 {
00143 {0x1C0A, 0xFFFF},
00144 {0x1E0A, 0xFFFF},
00145 {0x0000, 0x0000},
00146 };
00147
00148 #define IS_ADD_W_WREG_OPCODE(code) \
00149 ip2k_is_opcode (code, ip2k_add_w_wreg_opcode)
00150
00151 static const struct ip2k_opcode ip2k_add_pcl_w_opcode[] =
00152 {
00153 {0x1E09, 0xFFFF},
00154 {0x0000, 0x0000},
00155 };
00156
00157 #define IS_ADD_PCL_W_OPCODE(code) \
00158 ip2k_is_opcode (code, ip2k_add_pcl_w_opcode)
00159
00160 static const struct ip2k_opcode ip2k_skip_opcodes[] =
00161 {
00162 {0xB000, 0xF000},
00163 {0xA000, 0xF000},
00164 {0x7600, 0xFE00},
00165 {0x5800, 0xFC00},
00166 {0x4C00, 0xFC00},
00167 {0x4000, 0xFC00},
00168 {0x3C00, 0xFC00},
00169 {0x2C00, 0xFC00},
00170 {0x0000, 0x0000},
00171 };
00172
00173 #define IS_SKIP_OPCODE(code) \
00174 ip2k_is_opcode (code, ip2k_skip_opcodes)
00175
00176
00177 static reloc_howto_type ip2k_elf_howto_table [] =
00178 {
00179 #define IP2K_HOWTO(t,rs,s,bs,pr,bp,name,sm,dm) \
00180 HOWTO(t, \
00181 rs, \
00182 s, \
00183 bs, \
00184 pr, \
00185 bp, \
00186 complain_overflow_dont, \
00187 bfd_elf_generic_reloc, \
00188 name, \
00189 FALSE, \
00190 sm, \
00191 dm, \
00192 pr)
00193
00194
00195 IP2K_HOWTO (R_IP2K_NONE, 0,2,32, FALSE, 0, "R_IP2K_NONE", 0, 0),
00196
00197 IP2K_HOWTO (R_IP2K_16, 0,1,16, FALSE, 0, "R_IP2K_16", 0, 0xffff),
00198
00199 IP2K_HOWTO (R_IP2K_32, 0,2,32, FALSE, 0, "R_IP2K_32", 0, 0xffffffff),
00200
00201 IP2K_HOWTO (R_IP2K_FR9, 0,1,9, FALSE, 0, "R_IP2K_FR9", 0, 0x00ff),
00202
00203 IP2K_HOWTO (R_IP2K_BANK, 8,1,4, FALSE, 0, "R_IP2K_BANK", 0, 0x000f),
00204
00205 IP2K_HOWTO (R_IP2K_ADDR16CJP, 1,1,13, FALSE, 0, "R_IP2K_ADDR16CJP", 0, 0x1fff),
00206
00207 IP2K_HOWTO (R_IP2K_PAGE3, 14,1,3, FALSE, 0, "R_IP2K_PAGE3", 0, 0x0007),
00208
00209 IP2K_HOWTO (R_IP2K_LO8DATA, 0,1,8, FALSE, 0, "R_IP2K_LO8DATA", 0, 0x00ff),
00210 IP2K_HOWTO (R_IP2K_HI8DATA, 8,1,8, FALSE, 0, "R_IP2K_HI8DATA", 0, 0x00ff),
00211
00212 IP2K_HOWTO (R_IP2K_LO8INSN, 1,1,8, FALSE, 0, "R_IP2K_LO8INSN", 0, 0x00ff),
00213 IP2K_HOWTO (R_IP2K_HI8INSN, 9,1,8, FALSE, 0, "R_IP2K_HI8INSN", 0, 0x00ff),
00214
00215
00216 IP2K_HOWTO (R_IP2K_PC_SKIP, 1,1,1, FALSE, 12, "R_IP2K_PC_SKIP", 0xfffe, 0x1000),
00217
00218 IP2K_HOWTO (R_IP2K_TEXT, 1,1,16, FALSE, 0, "R_IP2K_TEXT", 0, 0xffff),
00219
00220 IP2K_HOWTO (R_IP2K_FR_OFFSET, 0,1,9, FALSE, 0, "R_IP2K_FR_OFFSET", 0x180, 0x007f),
00221
00222 IP2K_HOWTO (R_IP2K_EX8DATA, 16,1,8, FALSE, 0, "R_IP2K_EX8DATA", 0, 0x00ff),
00223 };
00224
00225
00226
00227 static reloc_howto_type *
00228 ip2k_reloc_type_lookup (abfd, code)
00229 bfd * abfd ATTRIBUTE_UNUSED;
00230 bfd_reloc_code_real_type code;
00231 {
00232
00233
00234
00235
00236
00237 switch (code)
00238 {
00239 case BFD_RELOC_NONE:
00240 return &ip2k_elf_howto_table[ (int) R_IP2K_NONE];
00241 case BFD_RELOC_16:
00242 return &ip2k_elf_howto_table[ (int) R_IP2K_16];
00243 case BFD_RELOC_32:
00244 return &ip2k_elf_howto_table[ (int) R_IP2K_32];
00245 case BFD_RELOC_IP2K_FR9:
00246 return &ip2k_elf_howto_table[ (int) R_IP2K_FR9];
00247 case BFD_RELOC_IP2K_BANK:
00248 return &ip2k_elf_howto_table[ (int) R_IP2K_BANK];
00249 case BFD_RELOC_IP2K_ADDR16CJP:
00250 return &ip2k_elf_howto_table[ (int) R_IP2K_ADDR16CJP];
00251 case BFD_RELOC_IP2K_PAGE3:
00252 return &ip2k_elf_howto_table[ (int) R_IP2K_PAGE3];
00253 case BFD_RELOC_IP2K_LO8DATA:
00254 return &ip2k_elf_howto_table[ (int) R_IP2K_LO8DATA];
00255 case BFD_RELOC_IP2K_HI8DATA:
00256 return &ip2k_elf_howto_table[ (int) R_IP2K_HI8DATA];
00257 case BFD_RELOC_IP2K_LO8INSN:
00258 return &ip2k_elf_howto_table[ (int) R_IP2K_LO8INSN];
00259 case BFD_RELOC_IP2K_HI8INSN:
00260 return &ip2k_elf_howto_table[ (int) R_IP2K_HI8INSN];
00261 case BFD_RELOC_IP2K_PC_SKIP:
00262 return &ip2k_elf_howto_table[ (int) R_IP2K_PC_SKIP];
00263 case BFD_RELOC_IP2K_TEXT:
00264 return &ip2k_elf_howto_table[ (int) R_IP2K_TEXT];
00265 case BFD_RELOC_IP2K_FR_OFFSET:
00266 return &ip2k_elf_howto_table[ (int) R_IP2K_FR_OFFSET];
00267 case BFD_RELOC_IP2K_EX8DATA:
00268 return &ip2k_elf_howto_table[ (int) R_IP2K_EX8DATA];
00269 default:
00270
00271 return NULL;
00272 }
00273 return NULL;
00274 }
00275
00276 static void
00277 ip2k_get_mem (abfd, addr, length, ptr)
00278 bfd *abfd ATTRIBUTE_UNUSED;
00279 bfd_byte *addr;
00280 int length;
00281 bfd_byte *ptr;
00282 {
00283 while (length --)
00284 * ptr ++ = bfd_get_8 (abfd, addr ++);
00285 }
00286
00287 static bfd_boolean
00288 ip2k_is_opcode (code, opcodes)
00289 bfd_byte *code;
00290 const struct ip2k_opcode *opcodes;
00291 {
00292 unsigned short insn = (code[0] << 8) | code[1];
00293
00294 while (opcodes->mask != 0)
00295 {
00296 if ((insn & opcodes->mask) == opcodes->opcode)
00297 return TRUE;
00298
00299 opcodes ++;
00300 }
00301
00302 return FALSE;
00303 }
00304
00305 #define PAGENO(ABSADDR) ((ABSADDR) & 0xFFFFC000)
00306 #define BASEADDR(SEC) ((SEC)->output_section->vma + (SEC)->output_offset)
00307
00308 #define UNDEFINED_SYMBOL (~(bfd_vma)0)
00309
00310
00311
00312 static bfd_vma
00313 symbol_value (abfd, symtab_hdr, isymbuf, irel)
00314 bfd *abfd;
00315 Elf_Internal_Shdr *symtab_hdr;
00316 Elf_Internal_Sym *isymbuf;
00317 Elf_Internal_Rela *irel;
00318 {
00319 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
00320 {
00321 Elf_Internal_Sym *isym;
00322 asection *sym_sec;
00323
00324 isym = isymbuf + ELF32_R_SYM (irel->r_info);
00325 if (isym->st_shndx == SHN_UNDEF)
00326 sym_sec = bfd_und_section_ptr;
00327 else if (isym->st_shndx == SHN_ABS)
00328 sym_sec = bfd_abs_section_ptr;
00329 else if (isym->st_shndx == SHN_COMMON)
00330 sym_sec = bfd_com_section_ptr;
00331 else
00332 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
00333
00334 return isym->st_value + BASEADDR (sym_sec);
00335 }
00336 else
00337 {
00338 unsigned long indx;
00339 struct elf_link_hash_entry *h;
00340
00341 indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
00342 h = elf_sym_hashes (abfd)[indx];
00343 BFD_ASSERT (h != NULL);
00344
00345 if (h->root.type != bfd_link_hash_defined
00346 && h->root.type != bfd_link_hash_defweak)
00347 return UNDEFINED_SYMBOL;
00348
00349 return (h->root.u.def.value + BASEADDR (h->root.u.def.section));
00350 }
00351 }
00352
00353
00354
00355
00356 static bfd_vma
00357 ip2k_nominal_page_bits (abfd, sec, addr, contents)
00358 bfd *abfd ATTRIBUTE_UNUSED;
00359 asection *sec;
00360 bfd_vma addr;
00361 bfd_byte *contents;
00362 {
00363 bfd_vma page = PAGENO (BASEADDR (sec) + addr);
00364
00365
00366
00367
00368
00369 if (PAGENO (BASEADDR (sec)) == page)
00370 return page;
00371
00372
00373
00374
00375
00376 while (PAGENO (BASEADDR (sec) + addr - 2) == page)
00377 {
00378 bfd_byte code[2];
00379
00380 addr -= 2;
00381 ip2k_get_mem (abfd, contents + addr, 2, code);
00382 if (!IS_PAGE_OPCODE (code))
00383 continue;
00384
00385
00386 if (ip2k_is_switch_table_128 (abfd, sec, addr, contents) != -1)
00387
00388 continue;
00389
00390 if (ip2k_is_switch_table_256 (abfd, sec, addr, contents) != -1)
00391
00392 continue;
00393
00394
00395 if (addr >= 2)
00396 {
00397 ip2k_get_mem (abfd, contents + addr - 2, 2, code);
00398 if (IS_SKIP_OPCODE (code))
00399
00400 continue;
00401 }
00402
00403
00404 return page;
00405 }
00406
00407
00408 return 0;
00409 }
00410
00411 static bfd_boolean
00412 ip2k_test_page_insn (abfd, sec, irel, misc)
00413 bfd *abfd ATTRIBUTE_UNUSED;
00414 asection *sec;
00415 Elf_Internal_Rela *irel;
00416 struct misc *misc;
00417 {
00418 bfd_vma symval;
00419
00420
00421 symval = symbol_value (abfd, misc->symtab_hdr, misc->isymbuf, irel);
00422 if (symval == UNDEFINED_SYMBOL)
00423
00424
00425
00426 return FALSE;
00427
00428
00429 if (PAGENO (symval + irel->r_addend) !=
00430 ip2k_nominal_page_bits (abfd, sec, irel->r_offset, misc->contents))
00431 return FALSE;
00432
00433 return TRUE;
00434 }
00435
00436 static bfd_boolean
00437 ip2k_delete_page_insn (abfd, sec, irel, again, misc)
00438 bfd *abfd ATTRIBUTE_UNUSED;
00439 asection *sec;
00440 Elf_Internal_Rela *irel;
00441 bfd_boolean *again;
00442 struct misc *misc;
00443 {
00444
00445 elf_section_data (sec)->relocs = misc->irelbase;
00446 elf_section_data (sec)->this_hdr.contents = misc->contents;
00447 misc->symtab_hdr->contents = (bfd_byte *) misc->isymbuf;
00448
00449
00450 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_IP2K_NONE);
00451
00452
00453 if (!ip2k_elf_relax_delete_bytes (abfd, sec, irel->r_offset, 2))
00454 return FALSE;
00455
00456
00457 *again = TRUE;
00458
00459 return TRUE;
00460 }
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491 static int
00492 ip2k_is_switch_table_128 (abfd, sec, addr, contents)
00493 bfd *abfd ATTRIBUTE_UNUSED;
00494 asection *sec;
00495 bfd_vma addr;
00496 bfd_byte *contents;
00497 {
00498 bfd_byte code[4];
00499 int index = 0;
00500
00501
00502 if (addr + 4 > sec->size)
00503 return -1;
00504
00505 ip2k_get_mem (abfd, contents + addr, 4, code);
00506
00507 if ((! IS_PAGE_OPCODE (code + 0))
00508 || (! IS_JMP_OPCODE (code + 2)))
00509 return -1;
00510
00511
00512 while (1)
00513 {
00514 if (addr < 4)
00515 return -1;
00516
00517
00518 ip2k_get_mem (abfd, contents + addr - 4, 4, code);
00519 if ((IS_ADD_W_WREG_OPCODE (code + 0))
00520 && (IS_ADD_PCL_W_OPCODE (code + 2)))
00521 return index;
00522
00523 if ((! IS_PAGE_OPCODE (code + 0))
00524 || (! IS_JMP_OPCODE (code + 2)))
00525 return -1;
00526
00527 index++;
00528 addr -= 4;
00529 }
00530 }
00531
00532 static bfd_boolean
00533 ip2k_relax_switch_table_128 (abfd, sec, irel, again, misc)
00534 bfd *abfd ATTRIBUTE_UNUSED;
00535 asection *sec;
00536 Elf_Internal_Rela *irel;
00537 bfd_boolean *again;
00538 struct misc *misc;
00539 {
00540 Elf_Internal_Rela *irelend = misc->irelbase + sec->reloc_count;
00541 Elf_Internal_Rela *ireltest = irel;
00542 bfd_byte code[4];
00543 bfd_vma addr;
00544
00545
00546 addr = irel->r_offset;
00547 while (1)
00548 {
00549 if (addr + 4 > sec->size)
00550 break;
00551
00552 ip2k_get_mem (abfd, misc->contents + addr, 4, code);
00553 if ((! IS_PAGE_OPCODE (code + 0))
00554 || (! IS_JMP_OPCODE (code + 2)))
00555 break;
00556
00557
00558
00559 if (ireltest >= irelend)
00560 {
00561 _bfd_error_handler (_("ip2k relaxer: switch table without complete matching relocation information."));
00562 return FALSE;
00563 }
00564
00565 if (ireltest->r_offset != addr)
00566 {
00567 _bfd_error_handler (_("ip2k relaxer: switch table without complete matching relocation information."));
00568 return FALSE;
00569 }
00570
00571 if (! ip2k_test_page_insn (abfd, sec, ireltest, misc))
00572
00573 return TRUE;
00574
00575 addr += 4;
00576 ireltest += 2;
00577 }
00578
00579
00580 ip2k_get_mem (abfd, misc->contents + irel->r_offset - 4, 4, code);
00581 if ((! IS_ADD_W_WREG_OPCODE (code + 0))
00582 || (! IS_ADD_PCL_W_OPCODE (code + 2)))
00583 {
00584 _bfd_error_handler (_("ip2k relaxer: switch table header corrupt."));
00585 return FALSE;
00586 }
00587
00588 if (!ip2k_elf_relax_delete_bytes (abfd, sec, irel->r_offset - 4, 2))
00589 return FALSE;
00590
00591 *again = TRUE;
00592
00593
00594 while (irel < ireltest)
00595 {
00596 if (!ip2k_delete_page_insn (abfd, sec, irel, again, misc))
00597 return FALSE;
00598 irel += 2;
00599 }
00600
00601 return TRUE;
00602 }
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644 static int
00645 ip2k_is_switch_table_256 (abfd, sec, addr, contents)
00646 bfd *abfd ATTRIBUTE_UNUSED;
00647 asection *sec;
00648 bfd_vma addr;
00649 bfd_byte *contents;
00650 {
00651 bfd_byte code[16];
00652 int index = 0;
00653
00654
00655 if (addr + 4 > sec->size)
00656 return -1;
00657
00658 ip2k_get_mem (abfd, contents + addr, 4, code);
00659 if ((! IS_PAGE_OPCODE (code + 0))
00660 || (! IS_JMP_OPCODE (code + 2)))
00661 return -1;
00662
00663
00664 while (1)
00665 {
00666 if (addr < 16)
00667 return -1;
00668
00669
00670 ip2k_get_mem (abfd, contents + addr - 16, 16, code);
00671 if ((IS_ADD_W_WREG_OPCODE (code + 0))
00672 && (IS_SNC_OPCODE (code + 2))
00673 && (IS_INC_1SP_OPCODE (code + 4))
00674 && (IS_ADD_2SP_W_OPCODE (code + 6))
00675 && (IS_SNC_OPCODE (code + 8))
00676 && (IS_INC_1SP_OPCODE (code + 10))
00677 && (IS_PAGE_OPCODE (code + 12))
00678 && (IS_JMP_OPCODE (code + 14)))
00679 return index;
00680
00681 if ((IS_ADD_W_WREG_OPCODE (code + 2))
00682 && (IS_SNC_OPCODE (code + 4))
00683 && (IS_INC_1SP_OPCODE (code + 6))
00684 && (IS_ADD_2SP_W_OPCODE (code + 8))
00685 && (IS_SNC_OPCODE (code + 10))
00686 && (IS_INC_1SP_OPCODE (code + 12))
00687 && (IS_JMP_OPCODE (code + 14)))
00688 return index;
00689
00690 if ((! IS_PAGE_OPCODE (code + 0))
00691 || (! IS_JMP_OPCODE (code + 2)))
00692 return -1;
00693
00694 index++;
00695 addr -= 4;
00696 }
00697 }
00698
00699 static bfd_boolean
00700 ip2k_relax_switch_table_256 (abfd, sec, irel, again, misc)
00701 bfd *abfd ATTRIBUTE_UNUSED;
00702 asection *sec;
00703 Elf_Internal_Rela *irel;
00704 bfd_boolean *again;
00705 struct misc *misc;
00706 {
00707 Elf_Internal_Rela *irelend = misc->irelbase + sec->reloc_count;
00708 Elf_Internal_Rela *ireltest = irel;
00709 bfd_byte code[12];
00710 bfd_vma addr;
00711
00712
00713 addr = irel->r_offset;
00714
00715 while (1)
00716 {
00717 if (addr + 4 > sec->size)
00718 break;
00719
00720 ip2k_get_mem (abfd, misc->contents + addr, 4, code);
00721
00722 if ((! IS_PAGE_OPCODE (code + 0))
00723 || (! IS_JMP_OPCODE (code + 2)))
00724 break;
00725
00726
00727
00728 if (ireltest >= irelend)
00729 {
00730 _bfd_error_handler (_("ip2k relaxer: switch table without complete matching relocation information."));
00731 return FALSE;
00732 }
00733
00734 if (ireltest->r_offset != addr)
00735 {
00736 _bfd_error_handler (_("ip2k relaxer: switch table without complete matching relocation information."));
00737 return FALSE;
00738 }
00739
00740 if (!ip2k_test_page_insn (abfd, sec, ireltest, misc))
00741
00742 return TRUE;
00743
00744 addr += 4;
00745 ireltest += 2;
00746 }
00747
00748
00749 ip2k_get_mem (abfd, misc->contents + irel->r_offset - 4, 2, code);
00750 if (IS_PAGE_OPCODE (code))
00751 addr = irel->r_offset - 16;
00752 else
00753 addr = irel->r_offset - 14;
00754
00755 ip2k_get_mem (abfd, misc->contents + addr, 12, code);
00756 if ((!IS_ADD_W_WREG_OPCODE (code + 0))
00757 || (!IS_SNC_OPCODE (code + 2))
00758 || (!IS_INC_1SP_OPCODE (code + 4))
00759 || (!IS_ADD_2SP_W_OPCODE (code + 6))
00760 || (!IS_SNC_OPCODE (code + 8))
00761 || (!IS_INC_1SP_OPCODE (code + 10)))
00762 {
00763 _bfd_error_handler (_("ip2k relaxer: switch table header corrupt."));
00764 return FALSE;
00765 }
00766
00767
00768 if (!ip2k_elf_relax_delete_bytes (abfd, sec, addr + 0, 6))
00769 return FALSE;
00770
00771 *again = TRUE;
00772
00773
00774 while (irel < ireltest)
00775 {
00776 if (!ip2k_delete_page_insn (abfd, sec, irel, again, misc))
00777 return FALSE;
00778 irel += 2;
00779 }
00780
00781 return TRUE;
00782 }
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794 static bfd_boolean
00795 ip2k_elf_relax_section (abfd, sec, link_info, again)
00796 bfd *abfd;
00797 asection *sec;
00798 struct bfd_link_info *link_info;
00799 bfd_boolean *again;
00800 {
00801 Elf_Internal_Shdr *symtab_hdr;
00802 Elf_Internal_Rela *internal_relocs;
00803 bfd_byte *contents = NULL;
00804 Elf_Internal_Sym *isymbuf = NULL;
00805 static asection * first_section = NULL;
00806 static unsigned long search_addr;
00807 static unsigned long page_start = 0;
00808 static unsigned long page_end = 0;
00809 static unsigned int pass = 0;
00810 static bfd_boolean new_pass = FALSE;
00811 static bfd_boolean changed = FALSE;
00812 struct misc misc;
00813 asection *stab;
00814
00815
00816 *again = FALSE;
00817
00818 if (first_section == NULL)
00819 {
00820 ip2k_relaxed = TRUE;
00821 first_section = sec;
00822 }
00823
00824 if (first_section == sec)
00825 {
00826 pass++;
00827 new_pass = TRUE;
00828 }
00829
00830
00831
00832
00833 if (link_info->relocatable
00834 || (sec->flags & SEC_RELOC) == 0
00835 || sec->reloc_count == 0
00836 || (sec->flags & SEC_CODE) == 0)
00837 return TRUE;
00838
00839 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
00840
00841 internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL,
00842 (Elf_Internal_Rela *)NULL,
00843 link_info->keep_memory);
00844 if (internal_relocs == NULL)
00845 goto error_return;
00846
00847
00848 stab = bfd_get_section_by_name (abfd, ".stab");
00849
00850 if (stab)
00851 {
00852
00853 Elf_Internal_Rela * irelbase;
00854
00855 irelbase = _bfd_elf_link_read_relocs (abfd, stab, NULL,
00856 (Elf_Internal_Rela *)NULL,
00857 link_info->keep_memory);
00858 }
00859
00860
00861 if (contents == NULL)
00862 {
00863
00864 if (elf_section_data (sec)->this_hdr.contents != NULL)
00865 contents = elf_section_data (sec)->this_hdr.contents;
00866 else
00867 {
00868
00869 if (!bfd_malloc_and_get_section (abfd, sec, &contents))
00870 goto error_return;
00871 }
00872 }
00873
00874
00875 if (isymbuf == NULL && symtab_hdr->sh_info != 0)
00876 {
00877 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
00878 if (isymbuf == NULL)
00879 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
00880 symtab_hdr->sh_info, 0,
00881 NULL, NULL, NULL);
00882 if (isymbuf == NULL)
00883 goto error_return;
00884 }
00885
00886 misc.symtab_hdr = symtab_hdr;
00887 misc.isymbuf = isymbuf;
00888 misc.irelbase = internal_relocs;
00889 misc.contents = contents;
00890
00891
00892 if ((pass == 1) || (new_pass && !changed))
00893 {
00894
00895
00896
00897
00898 if (new_pass)
00899 {
00900 pass = 1;
00901 new_pass = FALSE;
00902 changed = TRUE;
00903 search_addr = 0xFFFFFFFF;
00904 }
00905
00906 if ((BASEADDR (sec) + sec->size < search_addr)
00907 && (BASEADDR (sec) + sec->size > page_end))
00908 {
00909 if (BASEADDR (sec) <= page_end)
00910 search_addr = page_end + 1;
00911 else
00912 search_addr = BASEADDR (sec);
00913
00914
00915 *again = TRUE;
00916 }
00917 }
00918 else
00919 {
00920 if (new_pass)
00921 {
00922 new_pass = FALSE;
00923 changed = FALSE;
00924 page_start = PAGENO (search_addr);
00925 page_end = page_start | 0x00003FFF;
00926 }
00927
00928
00929 if ((BASEADDR (sec) + sec->size >= page_start)
00930 && (BASEADDR (sec) <= page_end))
00931 {
00932 if (!ip2k_elf_relax_section_page (abfd, sec, &changed, &misc, page_start, page_end))
00933 return FALSE;
00934 }
00935 *again = TRUE;
00936 }
00937
00938
00939
00940 if (isymbuf != NULL
00941 && symtab_hdr->contents != (unsigned char *) isymbuf)
00942 {
00943 if (! link_info->keep_memory)
00944 free (isymbuf);
00945 else
00946 symtab_hdr->contents = (unsigned char *) isymbuf;
00947 }
00948
00949 if (contents != NULL
00950 && elf_section_data (sec)->this_hdr.contents != contents)
00951 {
00952 if (! link_info->keep_memory)
00953 free (contents);
00954 else
00955 {
00956
00957 elf_section_data (sec)->this_hdr.contents = contents;
00958 }
00959 }
00960
00961 if (internal_relocs != NULL
00962 && elf_section_data (sec)->relocs != internal_relocs)
00963 free (internal_relocs);
00964
00965 return TRUE;
00966
00967 error_return:
00968 if (isymbuf != NULL
00969 && symtab_hdr->contents != (unsigned char *) isymbuf)
00970 free (isymbuf);
00971 if (contents != NULL
00972 && elf_section_data (sec)->this_hdr.contents != contents)
00973 free (contents);
00974 if (internal_relocs != NULL
00975 && elf_section_data (sec)->relocs != internal_relocs)
00976 free (internal_relocs);
00977 return FALSE;
00978 }
00979
00980
00981
00982 static bfd_boolean
00983 ip2k_elf_relax_section_page (abfd, sec, again, misc, page_start, page_end)
00984 bfd *abfd;
00985 asection *sec;
00986 bfd_boolean *again;
00987 struct misc *misc;
00988 unsigned long page_start;
00989 unsigned long page_end;
00990 {
00991 Elf_Internal_Rela *irelend = misc->irelbase + sec->reloc_count;
00992 Elf_Internal_Rela *irel;
00993 int switch_table_128;
00994 int switch_table_256;
00995
00996
00997 for (irel = misc->irelbase; irel < irelend; irel++)
00998 {
00999 if (ELF32_R_TYPE (irel->r_info) != (int) R_IP2K_PAGE3)
01000
01001 continue;
01002
01003 if (BASEADDR (sec) + irel->r_offset < page_start)
01004
01005
01006
01007 continue;
01008
01009 if (BASEADDR (sec) + irel->r_offset > page_end)
01010
01011 return TRUE;
01012
01013
01014 switch_table_128 = ip2k_is_switch_table_128 (abfd, sec, irel->r_offset, misc->contents);
01015 switch_table_256 = ip2k_is_switch_table_256 (abfd, sec, irel->r_offset, misc->contents);
01016
01017 if ((switch_table_128 > 0) || (switch_table_256 > 0))
01018
01019 continue;
01020
01021 if (switch_table_128 == 0)
01022 {
01023 if (!ip2k_relax_switch_table_128 (abfd, sec, irel, again, misc))
01024 return FALSE;
01025
01026 continue;
01027 }
01028
01029 if (switch_table_256 == 0)
01030 {
01031 if (!ip2k_relax_switch_table_256 (abfd, sec, irel, again, misc))
01032 return FALSE;
01033
01034 continue;
01035 }
01036
01037
01038 if (ip2k_test_page_insn (abfd, sec, irel, misc))
01039 {
01040 if (!ip2k_delete_page_insn (abfd, sec, irel, again, misc))
01041 return FALSE;
01042
01043 continue;
01044 }
01045 }
01046
01047 return TRUE;
01048 }
01049
01050
01051
01052 #define STRDXOFF (0)
01053 #define TYPEOFF (4)
01054 #define OTHEROFF (5)
01055 #define DESCOFF (6)
01056 #define VALOFF (8)
01057 #define STABSIZE (12)
01058
01059
01060
01061 static void
01062 adjust_all_relocations (abfd, sec, addr, endaddr, count, noadj)
01063 bfd *abfd;
01064 asection *sec;
01065 bfd_vma addr;
01066 bfd_vma endaddr;
01067 int count;
01068 int noadj;
01069 {
01070 Elf_Internal_Shdr *symtab_hdr;
01071 Elf_Internal_Sym *isymbuf, *isym, *isymend;
01072 unsigned int shndx;
01073 bfd_byte *contents;
01074 Elf_Internal_Rela *irel, *irelend, *irelbase;
01075 struct elf_link_hash_entry **sym_hashes;
01076 struct elf_link_hash_entry **end_hashes;
01077 unsigned int symcount;
01078 asection *stab;
01079
01080 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
01081 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
01082
01083 shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
01084
01085 contents = elf_section_data (sec)->this_hdr.contents;
01086
01087 irelbase = elf_section_data (sec)->relocs;
01088 irelend = irelbase + sec->reloc_count;
01089
01090 for (irel = irelbase; irel < irelend; irel++)
01091 {
01092 if (ELF32_R_TYPE (irel->r_info) != R_IP2K_NONE)
01093 {
01094
01095 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
01096 {
01097 asection *sym_sec;
01098
01099
01100 isym = isymbuf + ELF32_R_SYM (irel->r_info);
01101 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
01102
01103 if (isym->st_shndx == shndx)
01104 {
01105 bfd_vma baseaddr = BASEADDR (sec);
01106 bfd_vma symval = BASEADDR (sym_sec) + isym->st_value
01107 + irel->r_addend;
01108
01109 if ((baseaddr + addr + noadj) <= symval
01110 && symval < (baseaddr + endaddr))
01111 irel->r_addend += count;
01112 }
01113 }
01114 }
01115
01116
01117 if (addr <= irel->r_offset && irel->r_offset < endaddr)
01118 irel->r_offset += count;
01119 }
01120
01121
01122 stab = bfd_get_section_by_name (abfd, ".stab");
01123 if (stab)
01124 {
01125 bfd_byte *stabcontents, *stabend, *stabp;
01126 bfd_size_type stab_size = stab->rawsize ? stab->rawsize : stab->size;
01127
01128 irelbase = elf_section_data (stab)->relocs;
01129 irelend = irelbase + stab->reloc_count;
01130
01131
01132 if (elf_section_data (stab)->this_hdr.contents != NULL)
01133 stabcontents = elf_section_data (stab)->this_hdr.contents;
01134 else
01135 {
01136 if (!bfd_malloc_and_get_section (abfd, stab, &stabcontents))
01137 {
01138 if (stabcontents != NULL)
01139 free (stabcontents);
01140 return;
01141 }
01142
01143
01144 elf_section_data (stab)->this_hdr.contents = stabcontents;
01145 }
01146
01147 stabend = stabcontents + stab_size;
01148
01149 for (irel = irelbase; irel < irelend; irel++)
01150 {
01151 if (ELF32_R_TYPE (irel->r_info) != R_IP2K_NONE)
01152 {
01153
01154 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
01155 {
01156 asection *sym_sec;
01157
01158
01159 isym = isymbuf + ELF32_R_SYM (irel->r_info);
01160 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
01161
01162 if (sym_sec == sec)
01163 {
01164 const char *name;
01165 unsigned long strx;
01166 unsigned char type, other;
01167 unsigned short desc;
01168 bfd_vma value;
01169 bfd_vma baseaddr = BASEADDR (sec);
01170 bfd_vma symval = BASEADDR (sym_sec) + isym->st_value
01171 + irel->r_addend;
01172
01173 if ((baseaddr + addr) <= symval
01174 && symval <= (baseaddr + endaddr))
01175 irel->r_addend += count;
01176
01177
01178 stabp = stabcontents + irel->r_offset - 8;
01179
01180
01181 strx = bfd_h_get_32 (abfd, stabp + STRDXOFF);
01182 type = bfd_h_get_8 (abfd, stabp + TYPEOFF);
01183 other = bfd_h_get_8 (abfd, stabp + OTHEROFF);
01184 desc = bfd_h_get_16 (abfd, stabp + DESCOFF);
01185 value = bfd_h_get_32 (abfd, stabp + VALOFF);
01186
01187 name = bfd_get_stab_name (type);
01188
01189 if (strcmp (name, "FUN") == 0)
01190 {
01191 int function_adjusted = 0;
01192
01193 if (symval > (baseaddr + addr))
01194
01195 continue;
01196
01197
01198 stabp += STABSIZE;
01199 for (;stabp < stabend; stabp += STABSIZE)
01200 {
01201
01202 strx = bfd_h_get_32 (abfd, stabp + STRDXOFF);
01203 type = bfd_h_get_8 (abfd, stabp + TYPEOFF);
01204 other = bfd_h_get_8 (abfd, stabp + OTHEROFF);
01205 desc = bfd_h_get_16 (abfd, stabp + DESCOFF);
01206 value = bfd_h_get_32 (abfd, stabp + VALOFF);
01207
01208 name = bfd_get_stab_name (type);
01209
01210 if (strcmp (name, "FUN") == 0)
01211 {
01212
01213 if (function_adjusted)
01214 {
01215
01216 value += count;
01217
01218
01219 bfd_h_put_32 (abfd, value,stabp + VALOFF);
01220 }
01221
01222
01223 break;
01224 }
01225
01226 if (strcmp (name, "SLINE") == 0)
01227 {
01228
01229 if ((baseaddr + addr) <= (symval + value))
01230 {
01231
01232 value += count;
01233
01234
01235 bfd_h_put_32 (abfd, value,stabp + VALOFF);
01236 function_adjusted = 1;
01237 }
01238 }
01239 }
01240 }
01241 }
01242 }
01243 }
01244 }
01245 }
01246
01247
01248
01249
01250
01251
01252
01253 addr += noadj;
01254
01255
01256 isymend = isymbuf + symtab_hdr->sh_info;
01257 for (isym = isymbuf; isym < isymend; isym++)
01258 {
01259 if (isym->st_shndx == shndx
01260 && addr <= isym->st_value
01261 && isym->st_value < endaddr)
01262 isym->st_value += count;
01263 }
01264
01265
01266 symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
01267 - symtab_hdr->sh_info);
01268 sym_hashes = elf_sym_hashes (abfd);
01269 end_hashes = sym_hashes + symcount;
01270 for (; sym_hashes < end_hashes; sym_hashes++)
01271 {
01272 struct elf_link_hash_entry *sym_hash = *sym_hashes;
01273
01274 if ((sym_hash->root.type == bfd_link_hash_defined
01275 || sym_hash->root.type == bfd_link_hash_defweak)
01276 && sym_hash->root.u.def.section == sec)
01277 {
01278 if (addr <= sym_hash->root.u.def.value
01279 && sym_hash->root.u.def.value < endaddr)
01280 sym_hash->root.u.def.value += count;
01281 }
01282 }
01283
01284 return;
01285 }
01286
01287
01288
01289 static bfd_boolean
01290 ip2k_elf_relax_delete_bytes (abfd, sec, addr, count)
01291 bfd *abfd;
01292 asection *sec;
01293 bfd_vma addr;
01294 int count;
01295 {
01296 bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
01297 bfd_vma endaddr = sec->size;
01298
01299
01300 memmove (contents + addr, contents + addr + count,
01301 endaddr - addr - count);
01302
01303 sec->size -= count;
01304
01305 adjust_all_relocations (abfd, sec, addr + count, endaddr, -count, 0);
01306 return TRUE;
01307 }
01308
01309
01310
01311
01312
01313
01314
01315
01316 static void
01317 ip2k_info_to_howto_rela (abfd, cache_ptr, dst)
01318 bfd * abfd ATTRIBUTE_UNUSED;
01319 arelent * cache_ptr;
01320 Elf_Internal_Rela * dst;
01321 {
01322 unsigned int r_type;
01323
01324 r_type = ELF32_R_TYPE (dst->r_info);
01325 switch (r_type)
01326 {
01327 default:
01328 cache_ptr->howto = & ip2k_elf_howto_table [r_type];
01329 break;
01330 }
01331 }
01332
01333
01334
01335
01336 static bfd_reloc_status_type
01337 ip2k_final_link_relocate (howto, input_bfd, input_section, contents, rel,
01338 relocation)
01339 reloc_howto_type * howto;
01340 bfd * input_bfd;
01341 asection * input_section;
01342 bfd_byte * contents;
01343 Elf_Internal_Rela * rel;
01344 bfd_vma relocation;
01345 {
01346 static bfd_vma page_addr = 0;
01347
01348 bfd_reloc_status_type r = bfd_reloc_ok;
01349 switch (howto->type)
01350 {
01351
01352 case R_IP2K_FR9:
01353 case R_IP2K_BANK:
01354 if ((relocation & IP2K_DATA_MASK) == IP2K_DATA_VALUE)
01355 relocation &= ~IP2K_DATA_MASK;
01356 else
01357 r = bfd_reloc_notsupported;
01358 break;
01359
01360 case R_IP2K_LO8DATA:
01361 case R_IP2K_HI8DATA:
01362 case R_IP2K_EX8DATA:
01363 break;
01364
01365
01366 case R_IP2K_PAGE3:
01367 page_addr = BASEADDR (input_section) + rel->r_offset;
01368 if ((relocation & IP2K_INSN_MASK) == IP2K_INSN_VALUE)
01369 relocation &= ~IP2K_INSN_MASK;
01370 else
01371 r = bfd_reloc_notsupported;
01372 break;
01373
01374 case R_IP2K_ADDR16CJP:
01375 if (BASEADDR (input_section) + rel->r_offset != page_addr + 2)
01376 {
01377
01378 if (PAGENO (relocation + rel->r_addend) !=
01379 ip2k_nominal_page_bits (input_bfd, input_section,
01380 rel->r_offset, contents))
01381 _bfd_error_handler (_("ip2k linker: missing page instruction at 0x%08lx (dest = 0x%08lx)."),
01382 BASEADDR (input_section) + rel->r_offset,
01383 relocation + rel->r_addend);
01384 }
01385 else if (ip2k_relaxed)
01386 {
01387
01388
01389
01390 if (!ip2k_is_switch_table_128 (input_bfd, input_section, rel->r_offset - 2, contents) &&
01391 !ip2k_is_switch_table_256 (input_bfd, input_section, rel->r_offset - 2, contents) &&
01392 (PAGENO (relocation + rel->r_addend) ==
01393 ip2k_nominal_page_bits (input_bfd, input_section,
01394 rel->r_offset - 2, contents)))
01395 _bfd_error_handler (_("ip2k linker: redundant page instruction at 0x%08lx (dest = 0x%08lx)."),
01396 page_addr,
01397 relocation + rel->r_addend);
01398 }
01399 if ((relocation & IP2K_INSN_MASK) == IP2K_INSN_VALUE)
01400 relocation &= ~IP2K_INSN_MASK;
01401 else
01402 r = bfd_reloc_notsupported;
01403 break;
01404
01405 case R_IP2K_LO8INSN:
01406 case R_IP2K_HI8INSN:
01407 case R_IP2K_PC_SKIP:
01408 if ((relocation & IP2K_INSN_MASK) == IP2K_INSN_VALUE)
01409 relocation &= ~IP2K_INSN_MASK;
01410 else
01411 r = bfd_reloc_notsupported;
01412 break;
01413
01414 case R_IP2K_16:
01415
01416
01417 if ((relocation & IP2K_INSN_MASK) == IP2K_INSN_VALUE)
01418 howto = &ip2k_elf_howto_table[ (int) R_IP2K_TEXT];
01419 break;
01420
01421
01422 default:
01423 break;
01424 }
01425
01426
01427 if (r == bfd_reloc_ok)
01428 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
01429 contents, rel->r_offset,
01430 relocation, rel->r_addend);
01431
01432 return r;
01433 }
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465 static bfd_boolean
01466 ip2k_elf_relocate_section (output_bfd, info, input_bfd, input_section,
01467 contents, relocs, local_syms, local_sections)
01468 bfd *output_bfd ATTRIBUTE_UNUSED;
01469 struct bfd_link_info *info;
01470 bfd *input_bfd;
01471 asection *input_section;
01472 bfd_byte *contents;
01473 Elf_Internal_Rela *relocs;
01474 Elf_Internal_Sym *local_syms;
01475 asection **local_sections;
01476 {
01477 Elf_Internal_Shdr *symtab_hdr;
01478 struct elf_link_hash_entry **sym_hashes;
01479 Elf_Internal_Rela *rel;
01480 Elf_Internal_Rela *relend;
01481
01482 if (info->relocatable)
01483 return TRUE;
01484
01485 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
01486 sym_hashes = elf_sym_hashes (input_bfd);
01487 relend = relocs + input_section->reloc_count;
01488
01489 for (rel = relocs; rel < relend; rel ++)
01490 {
01491 reloc_howto_type * howto;
01492 unsigned long r_symndx;
01493 Elf_Internal_Sym * sym;
01494 asection * sec;
01495 struct elf_link_hash_entry * h;
01496 bfd_vma relocation;
01497 bfd_reloc_status_type r;
01498 const char * name = NULL;
01499 int r_type;
01500
01501
01502 r_type = ELF32_R_TYPE (rel->r_info);
01503 r_symndx = ELF32_R_SYM (rel->r_info);
01504 howto = ip2k_elf_howto_table + ELF32_R_TYPE (rel->r_info);
01505 h = NULL;
01506 sym = NULL;
01507 sec = NULL;
01508
01509 if (r_symndx < symtab_hdr->sh_info)
01510 {
01511 sym = local_syms + r_symndx;
01512 sec = local_sections [r_symndx];
01513 relocation = BASEADDR (sec) + sym->st_value;
01514
01515 name = bfd_elf_string_from_elf_section
01516 (input_bfd, symtab_hdr->sh_link, sym->st_name);
01517 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
01518 }
01519 else
01520 {
01521 bfd_boolean warned;
01522 bfd_boolean unresolved_reloc;
01523
01524 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
01525 r_symndx, symtab_hdr, sym_hashes,
01526 h, sec, relocation,
01527 unresolved_reloc, warned);
01528
01529 name = h->root.root.string;
01530 }
01531
01532
01533 r = ip2k_final_link_relocate (howto, input_bfd, input_section,
01534 contents, rel, relocation);
01535
01536 if (r != bfd_reloc_ok)
01537 {
01538 const char * msg = (const char *) NULL;
01539
01540 switch (r)
01541 {
01542 case bfd_reloc_overflow:
01543 r = info->callbacks->reloc_overflow
01544 (info, (h ? &h->root : NULL), name, howto->name,
01545 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
01546 break;
01547
01548 case bfd_reloc_undefined:
01549 r = info->callbacks->undefined_symbol
01550 (info, name, input_bfd, input_section, rel->r_offset, TRUE);
01551 break;
01552
01553 case bfd_reloc_outofrange:
01554 msg = _("internal error: out of range error");
01555 break;
01556
01557
01558
01559 case bfd_reloc_notsupported:
01560 if (sym != NULL)
01561 msg = _("unsupported relocation between data/insn address spaces");
01562 break;
01563
01564 case bfd_reloc_dangerous:
01565 msg = _("internal error: dangerous relocation");
01566 break;
01567
01568 default:
01569 msg = _("internal error: unknown error");
01570 break;
01571 }
01572
01573 if (msg)
01574 r = info->callbacks->warning
01575 (info, msg, name, input_bfd, input_section, rel->r_offset);
01576
01577 if (! r)
01578 return FALSE;
01579 }
01580 }
01581
01582 return TRUE;
01583 }
01584
01585 static asection *
01586 ip2k_elf_gc_mark_hook (sec, info, rel, h, sym)
01587 asection *sec;
01588 struct bfd_link_info *info ATTRIBUTE_UNUSED;
01589 Elf_Internal_Rela *rel;
01590 struct elf_link_hash_entry *h;
01591 Elf_Internal_Sym *sym;
01592 {
01593 if (h != NULL)
01594 {
01595 switch (ELF32_R_TYPE (rel->r_info))
01596 {
01597 default:
01598 switch (h->root.type)
01599 {
01600 case bfd_link_hash_defined:
01601 case bfd_link_hash_defweak:
01602 return h->root.u.def.section;
01603
01604 case bfd_link_hash_common:
01605 return h->root.u.c.p->section;
01606
01607 default:
01608 break;
01609 }
01610 }
01611 }
01612 else
01613 {
01614 if (!(elf_bad_symtab (sec->owner)
01615 && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
01616 && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
01617 && sym->st_shndx != SHN_COMMON))
01618 return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
01619 }
01620 return NULL;
01621 }
01622
01623 static bfd_boolean
01624 ip2k_elf_gc_sweep_hook (abfd, info, sec, relocs)
01625 bfd *abfd ATTRIBUTE_UNUSED;
01626 struct bfd_link_info *info ATTRIBUTE_UNUSED;
01627 asection *sec ATTRIBUTE_UNUSED;
01628 const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
01629 {
01630
01631 return TRUE;
01632 }
01633
01634 #define TARGET_BIG_SYM bfd_elf32_ip2k_vec
01635 #define TARGET_BIG_NAME "elf32-ip2k"
01636
01637 #define ELF_ARCH bfd_arch_ip2k
01638 #define ELF_MACHINE_CODE EM_IP2K
01639 #define ELF_MACHINE_ALT1 EM_IP2K_OLD
01640 #define ELF_MAXPAGESIZE 1
01641
01642 #define elf_info_to_howto_rel NULL
01643 #define elf_info_to_howto ip2k_info_to_howto_rela
01644
01645 #define elf_backend_can_gc_sections 1
01646 #define elf_backend_rela_normal 1
01647 #define elf_backend_gc_mark_hook ip2k_elf_gc_mark_hook
01648 #define elf_backend_gc_sweep_hook ip2k_elf_gc_sweep_hook
01649 #define elf_backend_relocate_section ip2k_elf_relocate_section
01650
01651 #define elf_symbol_leading_char '_'
01652 #define bfd_elf32_bfd_reloc_type_lookup ip2k_reloc_type_lookup
01653 #define bfd_elf32_bfd_relax_section ip2k_elf_relax_section
01654
01655 #include "elf32-target.h"