Back to index

cell-binutils  2.17cvs20070401
elf32-ip2k.c
Go to the documentation of this file.
00001 /* Ubicom IP2xxx specific support for 32-bit ELF
00002    Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
00003    Free Software Foundation, Inc.
00004 
00005    This file is part of BFD, the Binary File Descriptor library.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program; if not, write to the Free Software
00019    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
00020    MA 02110-1301, USA.  */
00021 
00022 #include "bfd.h"
00023 #include "sysdep.h"
00024 #include "libbfd.h"
00025 #include "elf-bfd.h"
00026 #include "elf/ip2k.h"
00027 
00028 /* Struct used to pass miscellaneous paramaters which
00029    helps to avoid overly long parameter lists.  */
00030 struct misc
00031 {
00032   Elf_Internal_Shdr *  symtab_hdr;
00033   Elf_Internal_Rela *  irelbase;
00034   bfd_byte *           contents;
00035   Elf_Internal_Sym *   isymbuf;
00036 };
00037 
00038 struct ip2k_opcode
00039 {
00040   unsigned short opcode;
00041   unsigned short mask;
00042 };
00043 
00044 static bfd_boolean ip2k_relaxed = FALSE;
00045 
00046 static const struct ip2k_opcode ip2k_page_opcode[] =
00047 {
00048   {0x0010, 0xFFF8},  /* Page.  */
00049   {0x0000, 0x0000},
00050 };
00051 
00052 #define IS_PAGE_OPCODE(code) \
00053   ip2k_is_opcode (code, ip2k_page_opcode)
00054 
00055 static const struct ip2k_opcode ip2k_jmp_opcode[] =
00056 {
00057   {0xE000, 0xE000},  /* Jmp.  */
00058   {0x0000, 0x0000},
00059 };
00060 
00061 #define IS_JMP_OPCODE(code) \
00062   ip2k_is_opcode (code, ip2k_jmp_opcode)
00063 
00064 static const struct ip2k_opcode ip2k_snc_opcode[] =
00065 {
00066   {0xA00B, 0xFFFF},  /* Snc.  */
00067   {0x0000, 0x0000},
00068 };
00069 
00070 #define IS_SNC_OPCODE(code) \
00071   ip2k_is_opcode (code, ip2k_snc_opcode)
00072 
00073 static const struct ip2k_opcode ip2k_inc_1sp_opcode[] =
00074 {
00075   {0x2B81, 0xFFFF},  /* Inc 1(SP).  */
00076   {0x0000, 0x0000},
00077 };
00078 
00079 #define IS_INC_1SP_OPCODE(code) \
00080   ip2k_is_opcode (code, ip2k_inc_1sp_opcode)
00081 
00082 static const struct ip2k_opcode ip2k_add_2sp_w_opcode[] =
00083 {
00084   {0x1F82, 0xFFFF},  /* Add 2(SP),w.  */
00085   {0x0000, 0x0000},
00086 };
00087 
00088 #define IS_ADD_2SP_W_OPCODE(code) \
00089   ip2k_is_opcode (code, ip2k_add_2sp_w_opcode)
00090 
00091 static const struct ip2k_opcode ip2k_add_w_wreg_opcode[] =
00092 {
00093   {0x1C0A, 0xFFFF},  /* Add w,wreg.  */
00094   {0x1E0A, 0xFFFF},  /* Add wreg,w.  */
00095   {0x0000, 0x0000},
00096 };
00097 
00098 #define IS_ADD_W_WREG_OPCODE(code) \
00099   ip2k_is_opcode (code, ip2k_add_w_wreg_opcode)
00100 
00101 static const struct ip2k_opcode ip2k_add_pcl_w_opcode[] =
00102 {
00103   {0x1E09, 0xFFFF},  /* Add pcl,w.  */
00104   {0x0000, 0x0000},
00105 };
00106 
00107 #define IS_ADD_PCL_W_OPCODE(code) \
00108   ip2k_is_opcode (code, ip2k_add_pcl_w_opcode)
00109 
00110 static const struct ip2k_opcode ip2k_skip_opcodes[] =
00111 {
00112   {0xB000, 0xF000},  /* sb */
00113   {0xA000, 0xF000},  /* snb */
00114   {0x7600, 0xFE00},  /* cse/csne #lit */
00115   {0x5800, 0xFC00},  /* incsnz */
00116   {0x4C00, 0xFC00},  /* decsnz */
00117   {0x4000, 0xFC00},  /* cse/csne */
00118   {0x3C00, 0xFC00},  /* incsz */
00119   {0x2C00, 0xFC00},  /* decsz */
00120   {0x0000, 0x0000},
00121 };
00122 
00123 #define IS_SKIP_OPCODE(code) \
00124   ip2k_is_opcode (code, ip2k_skip_opcodes)
00125 
00126 /* Relocation tables.  */
00127 static reloc_howto_type ip2k_elf_howto_table [] =
00128 {
00129 #define IP2K_HOWTO(t,rs,s,bs,pr,bp,name,sm,dm) \
00130     HOWTO(t,                    /* type */ \
00131           rs,                   /* rightshift */ \
00132           s,                    /* size (0 = byte, 1 = short, 2 = long) */ \
00133           bs,                   /* bitsize */ \
00134           pr,                   /* pc_relative */ \
00135           bp,                   /* bitpos */ \
00136           complain_overflow_dont,/* complain_on_overflow */ \
00137           bfd_elf_generic_reloc,/* special_function */ \
00138           name,                 /* name */ \
00139           FALSE,                /* partial_inplace */ \
00140           sm,                   /* src_mask */ \
00141           dm,                   /* dst_mask */ \
00142           pr)                   /* pcrel_offset */
00143 
00144   /* This reloc does nothing.  */
00145   IP2K_HOWTO (R_IP2K_NONE, 0,2,32, FALSE, 0, "R_IP2K_NONE", 0, 0),
00146   /* A 16 bit absolute relocation.  */
00147   IP2K_HOWTO (R_IP2K_16, 0,1,16, FALSE, 0, "R_IP2K_16", 0, 0xffff),
00148   /* A 32 bit absolute relocation.  */
00149   IP2K_HOWTO (R_IP2K_32, 0,2,32, FALSE, 0, "R_IP2K_32", 0, 0xffffffff),
00150   /* A 8-bit data relocation for the FR9 field.  Ninth bit is computed specially.  */
00151   IP2K_HOWTO (R_IP2K_FR9, 0,1,9, FALSE, 0, "R_IP2K_FR9", 0, 0x00ff),
00152   /* A 4-bit data relocation.  */
00153   IP2K_HOWTO (R_IP2K_BANK, 8,1,4, FALSE, 0, "R_IP2K_BANK", 0, 0x000f),
00154   /* A 13-bit insn relocation - word address => right-shift 1 bit extra.  */
00155   IP2K_HOWTO (R_IP2K_ADDR16CJP, 1,1,13, FALSE, 0, "R_IP2K_ADDR16CJP", 0, 0x1fff),
00156   /* A 3-bit insn relocation - word address => right-shift 1 bit extra.  */
00157   IP2K_HOWTO (R_IP2K_PAGE3, 14,1,3, FALSE, 0, "R_IP2K_PAGE3", 0, 0x0007),
00158   /* Two 8-bit data relocations.  */
00159   IP2K_HOWTO (R_IP2K_LO8DATA, 0,1,8, FALSE, 0, "R_IP2K_LO8DATA", 0, 0x00ff),
00160   IP2K_HOWTO (R_IP2K_HI8DATA, 8,1,8, FALSE, 0, "R_IP2K_HI8DATA", 0, 0x00ff),
00161   /* Two 8-bit insn relocations.  word address => right-shift 1 bit extra.  */
00162   IP2K_HOWTO (R_IP2K_LO8INSN, 1,1,8, FALSE, 0, "R_IP2K_LO8INSN", 0, 0x00ff),
00163   IP2K_HOWTO (R_IP2K_HI8INSN, 9,1,8, FALSE, 0, "R_IP2K_HI8INSN", 0, 0x00ff),
00164 
00165   /* Special 1 bit relocation for SKIP instructions.  */
00166   IP2K_HOWTO (R_IP2K_PC_SKIP, 1,1,1, FALSE, 12, "R_IP2K_PC_SKIP", 0xfffe, 0x1000),
00167   /* 16 bit word address.  */
00168   IP2K_HOWTO (R_IP2K_TEXT, 1,1,16, FALSE, 0, "R_IP2K_TEXT", 0, 0xffff),
00169   /* A 7-bit offset relocation for the FR9 field.  Eigth and ninth bit comes from insn.  */
00170   IP2K_HOWTO (R_IP2K_FR_OFFSET, 0,1,9, FALSE, 0, "R_IP2K_FR_OFFSET", 0x180, 0x007f),
00171   /* Bits 23:16 of an address.  */
00172   IP2K_HOWTO (R_IP2K_EX8DATA, 16,1,8, FALSE, 0, "R_IP2K_EX8DATA", 0, 0x00ff),
00173 };
00174 
00175 
00176 /* Map BFD reloc types to IP2K ELF reloc types.  */
00177 
00178 static reloc_howto_type *
00179 ip2k_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
00180                      bfd_reloc_code_real_type code)
00181 {
00182   /* Note that the ip2k_elf_howto_table is indxed by the R_
00183      constants.  Thus, the order that the howto records appear in the
00184      table *must* match the order of the relocation types defined in
00185      include/elf/ip2k.h.  */
00186 
00187   switch (code)
00188     {
00189     case BFD_RELOC_NONE:
00190       return &ip2k_elf_howto_table[ (int) R_IP2K_NONE];
00191     case BFD_RELOC_16:
00192       return &ip2k_elf_howto_table[ (int) R_IP2K_16];
00193     case BFD_RELOC_32:
00194       return &ip2k_elf_howto_table[ (int) R_IP2K_32];
00195     case BFD_RELOC_IP2K_FR9:
00196       return &ip2k_elf_howto_table[ (int) R_IP2K_FR9];
00197     case BFD_RELOC_IP2K_BANK:
00198       return &ip2k_elf_howto_table[ (int) R_IP2K_BANK];
00199     case BFD_RELOC_IP2K_ADDR16CJP:
00200       return &ip2k_elf_howto_table[ (int) R_IP2K_ADDR16CJP];
00201     case BFD_RELOC_IP2K_PAGE3:
00202       return &ip2k_elf_howto_table[ (int) R_IP2K_PAGE3];
00203     case BFD_RELOC_IP2K_LO8DATA:
00204       return &ip2k_elf_howto_table[ (int) R_IP2K_LO8DATA];
00205     case BFD_RELOC_IP2K_HI8DATA:
00206       return &ip2k_elf_howto_table[ (int) R_IP2K_HI8DATA];
00207     case BFD_RELOC_IP2K_LO8INSN:
00208       return &ip2k_elf_howto_table[ (int) R_IP2K_LO8INSN];
00209     case BFD_RELOC_IP2K_HI8INSN:
00210       return &ip2k_elf_howto_table[ (int) R_IP2K_HI8INSN];
00211     case BFD_RELOC_IP2K_PC_SKIP:
00212       return &ip2k_elf_howto_table[ (int) R_IP2K_PC_SKIP];
00213     case BFD_RELOC_IP2K_TEXT:
00214       return &ip2k_elf_howto_table[ (int) R_IP2K_TEXT];
00215     case BFD_RELOC_IP2K_FR_OFFSET:
00216       return &ip2k_elf_howto_table[ (int) R_IP2K_FR_OFFSET];
00217     case BFD_RELOC_IP2K_EX8DATA:
00218       return &ip2k_elf_howto_table[ (int) R_IP2K_EX8DATA];
00219     default:
00220       /* Pacify gcc -Wall.  */
00221       return NULL;
00222     }
00223   return NULL;
00224 }
00225 
00226 static reloc_howto_type *
00227 ip2k_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
00228 {
00229   unsigned int i;
00230 
00231   for (i = 0;
00232        i < sizeof (ip2k_elf_howto_table) / sizeof (ip2k_elf_howto_table[0]);
00233        i++)
00234     if (ip2k_elf_howto_table[i].name != NULL
00235        && strcasecmp (ip2k_elf_howto_table[i].name, r_name) == 0)
00236       return &ip2k_elf_howto_table[i];
00237 
00238   return NULL;
00239 }
00240 
00241 static void
00242 ip2k_get_mem (bfd *abfd ATTRIBUTE_UNUSED,
00243              bfd_byte *addr,
00244              int length,
00245              bfd_byte *ptr)
00246 {
00247   while (length --)
00248     * ptr ++ = bfd_get_8 (abfd, addr ++);
00249 }
00250 
00251 static bfd_boolean
00252 ip2k_is_opcode (bfd_byte *code, const struct ip2k_opcode *opcodes)
00253 {
00254   unsigned short insn = (code[0] << 8) | code[1];
00255 
00256   while (opcodes->mask != 0)
00257     {
00258       if ((insn & opcodes->mask) == opcodes->opcode)
00259        return TRUE;
00260 
00261       opcodes ++;
00262     }
00263 
00264   return FALSE;
00265 }
00266 
00267 #define PAGENO(ABSADDR) ((ABSADDR) & 0xFFFFC000)
00268 #define BASEADDR(SEC)       ((SEC)->output_section->vma + (SEC)->output_offset)
00269 
00270 #define UNDEFINED_SYMBOL (~(bfd_vma)0)
00271 
00272 /* Return the value of the symbol associated with the relocation IREL.  */
00273 
00274 static bfd_vma
00275 symbol_value (bfd *abfd,
00276              Elf_Internal_Shdr *symtab_hdr,
00277              Elf_Internal_Sym *isymbuf,
00278              Elf_Internal_Rela *irel)
00279 {
00280   if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
00281     {
00282       Elf_Internal_Sym *isym;
00283       asection *sym_sec;
00284 
00285       isym = isymbuf + ELF32_R_SYM (irel->r_info);
00286       if (isym->st_shndx == SHN_UNDEF)
00287        sym_sec = bfd_und_section_ptr;
00288       else if (isym->st_shndx == SHN_ABS)
00289        sym_sec = bfd_abs_section_ptr;
00290       else if (isym->st_shndx == SHN_COMMON)
00291        sym_sec = bfd_com_section_ptr;
00292       else
00293        sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
00294 
00295       return isym->st_value + BASEADDR (sym_sec);
00296     }
00297   else
00298     {
00299       unsigned long indx;
00300       struct elf_link_hash_entry *h;
00301 
00302       indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
00303       h = elf_sym_hashes (abfd)[indx];
00304       BFD_ASSERT (h != NULL);
00305 
00306       if (h->root.type != bfd_link_hash_defined
00307          && h->root.type != bfd_link_hash_defweak)
00308        return UNDEFINED_SYMBOL;
00309 
00310       return (h->root.u.def.value + BASEADDR (h->root.u.def.section));
00311     }
00312 }
00313 
00314 /* Determine if the instruction sequence matches that for
00315    the prologue of a switch dispatch table with fewer than
00316    128 entries.
00317 
00318           sc
00319           page    $nnn0
00320           jmp     $nnn0
00321           add     w,wreg
00322           add     pcl,w
00323   addr=>
00324           page    $nnn1
00325           jmp     $nnn1
00326           page    $nnn2
00327           jmp     $nnn2
00328           ...
00329           page    $nnnN
00330           jmp     $nnnN
00331 
00332   After relaxation.
00333           sc
00334           page    $nnn0
00335           jmp     $nnn0
00336           add     pcl,w
00337   addr=>
00338           jmp     $nnn1
00339           jmp     $nnn2
00340           ...
00341           jmp     $nnnN  */
00342 
00343 static int
00344 ip2k_is_switch_table_128 (bfd *abfd ATTRIBUTE_UNUSED,
00345                        asection *sec,
00346                        bfd_vma addr,
00347                        bfd_byte *contents)
00348 {
00349   bfd_byte code[4];
00350   int index = 0;
00351   
00352   /* Check current page-jmp.  */
00353   if (addr + 4 > sec->size)
00354     return -1;
00355 
00356   ip2k_get_mem (abfd, contents + addr, 4, code);
00357 
00358   if ((! IS_PAGE_OPCODE (code + 0))
00359       || (! IS_JMP_OPCODE (code + 2)))
00360     return -1;
00361   
00362   /* Search back.  */
00363   while (1)
00364     {
00365       if (addr < 4)
00366        return -1;
00367 
00368       /* Check previous 2 instructions.  */
00369       ip2k_get_mem (abfd, contents + addr - 4, 4, code);
00370       if ((IS_ADD_W_WREG_OPCODE (code + 0))
00371          && (IS_ADD_PCL_W_OPCODE (code + 2)))
00372        return index;
00373 
00374       if ((! IS_PAGE_OPCODE (code + 0))
00375          || (! IS_JMP_OPCODE (code + 2)))
00376        return -1;
00377 
00378       index++;
00379       addr -= 4;
00380     }
00381 }
00382 
00383 /* Determine if the instruction sequence matches that for
00384    the prologue switch dispatch table with fewer than
00385    256 entries but more than 127.
00386 
00387    Before relaxation.
00388           push    %lo8insn(label) ; Push address of table
00389           push    %hi8insn(label)
00390           add     w,wreg          ; index*2 => offset
00391           snc                     ; CARRY SET?
00392           inc     1(sp)           ; Propagate MSB into table address
00393           add     2(sp),w         ; Add low bits of offset to table address
00394           snc                     ; and handle any carry-out
00395           inc     1(sp)
00396    addr=>
00397           page    __indjmp        ; Do an indirect jump to that location
00398           jmp     __indjmp
00399    label:                         ; case dispatch table starts here
00400           page    $nnn1
00401           jmp    $nnn1
00402           page          $nnn2
00403           jmp     $nnn2
00404           ...
00405           page    $nnnN
00406           jmp    $nnnN
00407 
00408   After relaxation.
00409           push    %lo8insn(label) ; Push address of table
00410           push    %hi8insn(label)
00411           add     2(sp),w         ; Add low bits of offset to table address
00412           snc                     ; and handle any carry-out
00413           inc     1(sp)
00414   addr=>
00415           page    __indjmp        ; Do an indirect jump to that location
00416           jmp     __indjmp
00417    label:                         ; case dispatch table starts here
00418           jmp     $nnn1
00419           jmp     $nnn2
00420           ...
00421           jmp     $nnnN  */
00422 
00423 static int
00424 ip2k_is_switch_table_256 (bfd *abfd ATTRIBUTE_UNUSED,
00425                        asection *sec,
00426                        bfd_vma addr,
00427                        bfd_byte *contents)
00428 {
00429   bfd_byte code[16];
00430   int index = 0;
00431   
00432   /* Check current page-jmp.  */
00433   if (addr + 4 > sec->size)
00434     return -1;
00435 
00436   ip2k_get_mem (abfd, contents + addr, 4, code);
00437   if ((! IS_PAGE_OPCODE (code + 0))
00438       || (! IS_JMP_OPCODE (code + 2)))
00439     return -1;
00440   
00441   /* Search back.  */
00442   while (1)
00443     {
00444       if (addr < 16)
00445        return -1;
00446 
00447       /* Check previous 8 instructions.  */
00448       ip2k_get_mem (abfd, contents + addr - 16, 16, code);
00449       if ((IS_ADD_W_WREG_OPCODE (code + 0))
00450          && (IS_SNC_OPCODE (code + 2))
00451          && (IS_INC_1SP_OPCODE (code + 4))
00452          && (IS_ADD_2SP_W_OPCODE (code + 6))
00453          && (IS_SNC_OPCODE (code + 8))
00454          && (IS_INC_1SP_OPCODE (code + 10))
00455          && (IS_PAGE_OPCODE (code + 12))
00456          && (IS_JMP_OPCODE (code + 14)))
00457        return index;
00458 
00459       if ((IS_ADD_W_WREG_OPCODE (code + 2))
00460          && (IS_SNC_OPCODE (code + 4))
00461          && (IS_INC_1SP_OPCODE (code + 6))
00462          && (IS_ADD_2SP_W_OPCODE (code + 8))
00463          && (IS_SNC_OPCODE (code + 10))
00464          && (IS_INC_1SP_OPCODE (code + 12))
00465          && (IS_JMP_OPCODE (code + 14)))
00466        return index;
00467       
00468       if ((! IS_PAGE_OPCODE (code + 0))
00469          || (! IS_JMP_OPCODE (code + 2)))
00470        return -1;
00471 
00472       index++;
00473       addr -= 4;
00474     }
00475 }
00476 
00477 /* Returns the expected page state for the given instruction not including
00478    the effect of page instructions.  */
00479 
00480 static bfd_vma
00481 ip2k_nominal_page_bits (bfd *abfd ATTRIBUTE_UNUSED,
00482                      asection *sec,
00483                      bfd_vma addr,
00484                      bfd_byte *contents)
00485 {
00486   bfd_vma page = PAGENO (BASEADDR (sec) + addr);
00487 
00488   /* Check if section flows into this page. If not then the page
00489      bits are assumed to match the PC. This will be true unless
00490      the user has a page instruction without a call/jump, in which
00491      case they are on their own.  */
00492   if (PAGENO (BASEADDR (sec)) == page)
00493     return page;
00494 
00495   /* Section flows across page boundary. The page bits should match
00496      the PC unless there is a possible flow from the previous page,
00497      in which case it is not possible to determine the value of the
00498      page bits.  */
00499   while (PAGENO (BASEADDR (sec) + addr - 2) == page)
00500     {
00501       bfd_byte code[2];
00502 
00503       addr -= 2;
00504       ip2k_get_mem (abfd, contents + addr, 2, code);
00505       if (!IS_PAGE_OPCODE (code))
00506        continue;
00507 
00508       /* Found a page instruction, check if jump table.  */
00509       if (ip2k_is_switch_table_128 (abfd, sec, addr, contents) != -1)
00510        /* Jump table => page is conditional.  */
00511        continue;
00512 
00513       if (ip2k_is_switch_table_256 (abfd, sec, addr, contents) != -1)
00514        /* Jump table => page is conditional.  */
00515        continue;
00516 
00517       /* Found a page instruction, check if conditional.  */
00518       if (addr >= 2)
00519         {
00520          ip2k_get_mem (abfd, contents + addr - 2, 2, code);
00521           if (IS_SKIP_OPCODE (code))
00522            /* Page is conditional.  */
00523            continue;
00524         }
00525 
00526       /* Unconditional page instruction => page bits should be correct.  */
00527       return page;
00528     }
00529 
00530   /* Flow from previous page => page bits are impossible to determine.  */
00531   return 0;
00532 }
00533 
00534 static bfd_boolean
00535 ip2k_test_page_insn (bfd *abfd ATTRIBUTE_UNUSED,
00536                    asection *sec,
00537                    Elf_Internal_Rela *irel,
00538                    struct misc *misc)
00539 {
00540   bfd_vma symval;
00541 
00542   /* Get the value of the symbol referred to by the reloc.  */
00543   symval = symbol_value (abfd, misc->symtab_hdr, misc->isymbuf, irel);
00544   if (symval == UNDEFINED_SYMBOL)
00545     /* This appears to be a reference to an undefined
00546        symbol.  Just ignore it--it will be caught by the
00547        regular reloc processing.  */
00548     return FALSE;
00549 
00550   /* Test if we can delete this page instruction.  */
00551   if (PAGENO (symval + irel->r_addend) !=
00552       ip2k_nominal_page_bits (abfd, sec, irel->r_offset, misc->contents))
00553     return FALSE;
00554 
00555   return TRUE;
00556 }
00557 
00558 /* Parts of a Stabs entry.  */
00559 
00560 #define STRDXOFF   0
00561 #define TYPEOFF    4
00562 #define OTHEROFF   5
00563 #define DESCOFF    6
00564 #define VALOFF     8
00565 #define STABSIZE   12
00566 
00567 /* Adjust all the relocations entries after adding or inserting instructions.  */
00568 
00569 static void
00570 adjust_all_relocations (bfd *abfd,
00571                      asection *sec,
00572                      bfd_vma addr,
00573                      bfd_vma endaddr,
00574                      int count,
00575                      int noadj)
00576 {
00577   Elf_Internal_Shdr *symtab_hdr;
00578   Elf_Internal_Sym *isymbuf, *isym, *isymend;
00579   unsigned int shndx;
00580   bfd_byte *contents;
00581   Elf_Internal_Rela *irel, *irelend, *irelbase;
00582   struct elf_link_hash_entry **sym_hashes;
00583   struct elf_link_hash_entry **end_hashes;
00584   unsigned int symcount;
00585   asection *stab;
00586 
00587   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
00588   isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
00589 
00590   shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
00591 
00592   contents = elf_section_data (sec)->this_hdr.contents;
00593 
00594   irelbase = elf_section_data (sec)->relocs;
00595   irelend = irelbase + sec->reloc_count;
00596 
00597   for (irel = irelbase; irel < irelend; irel++)
00598     {
00599       if (ELF32_R_TYPE (irel->r_info) != R_IP2K_NONE)
00600         {
00601           /* Get the value of the symbol referred to by the reloc.  */
00602           if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
00603             {
00604               asection *sym_sec;
00605 
00606               /* A local symbol.  */
00607              isym = isymbuf + ELF32_R_SYM (irel->r_info);
00608               sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
00609 
00610               if (isym->st_shndx == shndx)
00611                 {
00612                   bfd_vma baseaddr = BASEADDR (sec);
00613                   bfd_vma symval = BASEADDR (sym_sec) + isym->st_value
00614                                    + irel->r_addend;
00615 
00616                   if ((baseaddr + addr + noadj) <= symval
00617                       && symval < (baseaddr + endaddr))
00618                     irel->r_addend += count;
00619                 }
00620             }
00621         }
00622 
00623       /* Do this only for PC space relocations.  */
00624       if (addr <= irel->r_offset && irel->r_offset < endaddr)
00625         irel->r_offset += count;
00626     }
00627 
00628   /* Now fix the stab relocations.  */
00629   stab = bfd_get_section_by_name (abfd, ".stab");
00630   if (stab)
00631     {
00632       bfd_byte *stabcontents, *stabend, *stabp;
00633       bfd_size_type stab_size = stab->rawsize ? stab->rawsize : stab->size;
00634 
00635       irelbase = elf_section_data (stab)->relocs;
00636       irelend = irelbase + stab->reloc_count;
00637 
00638       /* Pull out the contents of the stab section.  */
00639       if (elf_section_data (stab)->this_hdr.contents != NULL)
00640        stabcontents = elf_section_data (stab)->this_hdr.contents;
00641       else
00642        {
00643          if (!bfd_malloc_and_get_section (abfd, stab, &stabcontents))
00644            {
00645              if (stabcontents != NULL)
00646               free (stabcontents);
00647              return;
00648            }
00649 
00650          /* We need to remember this.  */
00651          elf_section_data (stab)->this_hdr.contents = stabcontents;
00652        }
00653 
00654       stabend = stabcontents + stab_size;
00655 
00656       for (irel = irelbase; irel < irelend; irel++)
00657        {
00658          if (ELF32_R_TYPE (irel->r_info) != R_IP2K_NONE)
00659            {
00660              /* Get the value of the symbol referred to by the reloc.  */
00661              if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
00662               {
00663                 asection *sym_sec;
00664                 
00665                 /* A local symbol.  */
00666                 isym = isymbuf + ELF32_R_SYM (irel->r_info);
00667                 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
00668                 
00669                 if (sym_sec == sec)
00670                   {
00671                     const char *name;
00672                     unsigned long strx;
00673                     unsigned char type, other;
00674                     unsigned short desc;
00675                     bfd_vma value;
00676                     bfd_vma baseaddr = BASEADDR (sec);
00677                     bfd_vma symval = BASEADDR (sym_sec) + isym->st_value
00678                      + irel->r_addend;
00679                     
00680                     if ((baseaddr + addr) <= symval
00681                        && symval <= (baseaddr + endaddr))
00682                      irel->r_addend += count;
00683 
00684                     /* Go hunt up a function and fix its line info if needed.  */
00685                     stabp = stabcontents + irel->r_offset - 8; 
00686 
00687                     /* Go pullout the stab entry.  */
00688                     strx  = bfd_h_get_32 (abfd, stabp + STRDXOFF);
00689                     type  = bfd_h_get_8 (abfd, stabp + TYPEOFF);
00690                     other = bfd_h_get_8 (abfd, stabp + OTHEROFF);
00691                     desc  = bfd_h_get_16 (abfd, stabp + DESCOFF);
00692                     value = bfd_h_get_32 (abfd, stabp + VALOFF);
00693                     
00694                     name = bfd_get_stab_name (type);
00695                     
00696                     if (strcmp (name, "FUN") == 0)
00697                      {
00698                        int function_adjusted = 0;
00699 
00700                        if (symval > (baseaddr + addr))
00701                          /* Not in this function.  */
00702                          continue;
00703 
00704                        /* Hey we got a function hit.  */
00705                        stabp += STABSIZE;
00706                        for (;stabp < stabend; stabp += STABSIZE)
00707                          {
00708                            /* Go pullout the stab entry.  */
00709                            strx  = bfd_h_get_32 (abfd, stabp + STRDXOFF);
00710                            type  = bfd_h_get_8 (abfd, stabp + TYPEOFF);
00711                            other = bfd_h_get_8 (abfd, stabp + OTHEROFF);
00712                            desc  = bfd_h_get_16 (abfd, stabp + DESCOFF);
00713                            value = bfd_h_get_32 (abfd, stabp + VALOFF);
00714 
00715                            name = bfd_get_stab_name (type);
00716 
00717                            if (strcmp (name, "FUN") == 0)
00718                             {
00719                               /* Hit another function entry.  */
00720                               if (function_adjusted)
00721                                 {
00722                                   /* Adjust the value.  */
00723                                   value += count;
00724                               
00725                                   /* We need to put it back.  */
00726                                   bfd_h_put_32 (abfd, value,stabp + VALOFF);
00727                                 }
00728 
00729                               /* And then bale out.  */
00730                               break;
00731                             }
00732 
00733                            if (strcmp (name, "SLINE") == 0)
00734                             {
00735                               /* Got a line entry.  */
00736                               if ((baseaddr + addr) <= (symval + value))
00737                                 {
00738                                   /* Adjust the line entry.  */
00739                                   value += count;
00740 
00741                                   /* We need to put it back.  */
00742                                   bfd_h_put_32 (abfd, value,stabp + VALOFF);
00743                                   function_adjusted = 1;
00744                                 }
00745                             }
00746                          }
00747                      }
00748                   }
00749               }
00750            }
00751        }
00752     }
00753 
00754   /* When adding an instruction back it is sometimes necessary to move any
00755      global or local symbol that was referencing the first instruction of
00756      the moved block to refer to the first instruction of the inserted block.
00757 
00758      For example adding a PAGE instruction before a CALL or JMP requires
00759      that any label on the CALL or JMP is moved to the PAGE insn.  */
00760   addr += noadj;
00761 
00762   /* Adjust the local symbols defined in this section.  */
00763   isymend = isymbuf + symtab_hdr->sh_info;
00764   for (isym = isymbuf; isym < isymend; isym++)
00765     {
00766       if (isym->st_shndx == shndx
00767          && addr <= isym->st_value
00768          && isym->st_value < endaddr)
00769        isym->st_value += count;
00770     }
00771 
00772   /* Now adjust the global symbols defined in this section.  */
00773   symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
00774              - symtab_hdr->sh_info);
00775   sym_hashes = elf_sym_hashes (abfd);
00776   end_hashes = sym_hashes + symcount;
00777   for (; sym_hashes < end_hashes; sym_hashes++)
00778     {
00779       struct elf_link_hash_entry *sym_hash = *sym_hashes;
00780 
00781       if ((sym_hash->root.type == bfd_link_hash_defined
00782           || sym_hash->root.type == bfd_link_hash_defweak)
00783          && sym_hash->root.u.def.section == sec)
00784        {
00785           if (addr <= sym_hash->root.u.def.value
00786               && sym_hash->root.u.def.value < endaddr)
00787            sym_hash->root.u.def.value += count;
00788        }
00789     }
00790 
00791   return;
00792 }
00793 
00794 /* Delete some bytes from a section while relaxing.  */
00795 
00796 static bfd_boolean
00797 ip2k_elf_relax_delete_bytes (bfd *abfd,
00798                           asection *sec,
00799                           bfd_vma addr,
00800                           int count)
00801 {
00802   bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
00803   bfd_vma endaddr = sec->size;
00804 
00805   /* Actually delete the bytes.  */
00806   memmove (contents + addr, contents + addr + count,
00807           endaddr - addr - count);
00808 
00809   sec->size -= count;
00810 
00811   adjust_all_relocations (abfd, sec, addr + count, endaddr, -count, 0);
00812   return TRUE;
00813 }
00814 
00815 static bfd_boolean
00816 ip2k_delete_page_insn (bfd *abfd ATTRIBUTE_UNUSED,
00817                      asection *sec,
00818                      Elf_Internal_Rela *irel,
00819                      bfd_boolean *again,
00820                      struct misc *misc)
00821 {
00822   /* Note that we've changed the relocs, section contents, etc.  */
00823   elf_section_data (sec)->relocs = misc->irelbase;
00824   elf_section_data (sec)->this_hdr.contents = misc->contents;
00825   misc->symtab_hdr->contents = (bfd_byte *) misc->isymbuf;
00826 
00827   /* Fix the relocation's type.  */
00828   irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_IP2K_NONE);
00829 
00830   /* Delete the PAGE insn.  */
00831   if (!ip2k_elf_relax_delete_bytes (abfd, sec, irel->r_offset, 2))
00832     return FALSE;
00833        
00834   /* Modified => will need to iterate relaxation again.  */
00835   *again = TRUE;
00836   
00837   return TRUE;
00838 }
00839 
00840 static bfd_boolean
00841 ip2k_relax_switch_table_128 (bfd *abfd ATTRIBUTE_UNUSED,
00842                           asection *sec,
00843                           Elf_Internal_Rela *irel,
00844                           bfd_boolean *again,
00845                           struct misc *misc)
00846 {
00847   Elf_Internal_Rela *irelend = misc->irelbase + sec->reloc_count;
00848   Elf_Internal_Rela *ireltest = irel;
00849   bfd_byte code[4];
00850   bfd_vma addr;
00851   
00852   /* Test all page instructions.  */
00853   addr = irel->r_offset;
00854   while (1)
00855     {
00856       if (addr + 4 > sec->size)
00857        break;
00858 
00859       ip2k_get_mem (abfd, misc->contents + addr, 4, code);
00860       if ((! IS_PAGE_OPCODE (code + 0))
00861          || (! IS_JMP_OPCODE (code + 2)))
00862        break;
00863 
00864       /* Validate relocation entry (every entry should have a matching
00865           relocation entry).  */
00866       if (ireltest >= irelend)
00867         {
00868          _bfd_error_handler (_("ip2k relaxer: switch table without complete matching relocation information."));
00869           return FALSE;
00870         }
00871 
00872       if (ireltest->r_offset != addr)
00873         {
00874          _bfd_error_handler (_("ip2k relaxer: switch table without complete matching relocation information."));
00875           return FALSE;
00876         }
00877 
00878       if (! ip2k_test_page_insn (abfd, sec, ireltest, misc))
00879        /* Un-removable page insn => nothing can be done.  */
00880        return TRUE;
00881 
00882       addr += 4;
00883       ireltest += 2;
00884     }
00885 
00886   /* Relaxable. Adjust table header.  */
00887   ip2k_get_mem (abfd, misc->contents + irel->r_offset - 4, 4, code);
00888   if ((! IS_ADD_W_WREG_OPCODE (code + 0))
00889       || (! IS_ADD_PCL_W_OPCODE (code + 2)))
00890     {
00891       _bfd_error_handler (_("ip2k relaxer: switch table header corrupt."));
00892       return FALSE;
00893     }
00894 
00895   if (!ip2k_elf_relax_delete_bytes (abfd, sec, irel->r_offset - 4, 2))
00896     return FALSE;
00897 
00898   *again = TRUE;
00899 
00900   /* Delete all page instructions in table.  */
00901   while (irel < ireltest)
00902     {
00903       if (!ip2k_delete_page_insn (abfd, sec, irel, again, misc))
00904        return FALSE;
00905       irel += 2;
00906     }
00907 
00908   return TRUE;
00909 }
00910 
00911 static bfd_boolean
00912 ip2k_relax_switch_table_256 (bfd *abfd ATTRIBUTE_UNUSED,
00913                           asection *sec,
00914                           Elf_Internal_Rela *irel,
00915                           bfd_boolean *again,
00916                           struct misc *misc)
00917 {
00918   Elf_Internal_Rela *irelend = misc->irelbase + sec->reloc_count;
00919   Elf_Internal_Rela *ireltest = irel;
00920   bfd_byte code[12];
00921   bfd_vma addr;
00922   
00923   /* Test all page instructions.  */
00924   addr = irel->r_offset;
00925 
00926   while (1)
00927     {
00928       if (addr + 4 > sec->size)
00929        break;
00930 
00931       ip2k_get_mem (abfd, misc->contents + addr, 4, code);
00932 
00933       if ((! IS_PAGE_OPCODE (code + 0))
00934          || (! IS_JMP_OPCODE (code + 2)))
00935        break;
00936 
00937       /* Validate relocation entry (every entry should have a matching
00938           relocation entry).  */
00939       if (ireltest >= irelend)
00940         {
00941           _bfd_error_handler (_("ip2k relaxer: switch table without complete matching relocation information."));
00942           return FALSE;
00943         }
00944 
00945       if (ireltest->r_offset != addr)
00946         {
00947           _bfd_error_handler (_("ip2k relaxer: switch table without complete matching relocation information."));
00948           return FALSE;
00949         }
00950 
00951       if (!ip2k_test_page_insn (abfd, sec, ireltest, misc))
00952        /* Un-removable page insn => nothing can be done.  */
00953        return TRUE;
00954 
00955       addr += 4;
00956       ireltest += 2;
00957     }
00958 
00959   /* Relaxable. Adjust table header.  */
00960   ip2k_get_mem (abfd, misc->contents + irel->r_offset - 4, 2, code);
00961   if (IS_PAGE_OPCODE (code))
00962     addr = irel->r_offset - 16;
00963   else
00964     addr = irel->r_offset - 14;
00965 
00966   ip2k_get_mem (abfd, misc->contents + addr, 12, code);
00967   if ((!IS_ADD_W_WREG_OPCODE (code + 0))
00968       || (!IS_SNC_OPCODE (code + 2))
00969       || (!IS_INC_1SP_OPCODE (code + 4))
00970       || (!IS_ADD_2SP_W_OPCODE (code + 6))
00971       || (!IS_SNC_OPCODE (code + 8))
00972       || (!IS_INC_1SP_OPCODE (code + 10)))
00973     {
00974       _bfd_error_handler (_("ip2k relaxer: switch table header corrupt."));
00975       return FALSE;
00976     }
00977 
00978   /* Delete first 3 opcodes.  */
00979   if (!ip2k_elf_relax_delete_bytes (abfd, sec, addr + 0, 6))
00980     return FALSE;
00981 
00982   *again = TRUE;
00983 
00984   /* Delete all page instructions in table.  */
00985   while (irel < ireltest)
00986     {
00987       if (!ip2k_delete_page_insn (abfd, sec, irel, again, misc))
00988        return FALSE;
00989       irel += 2;
00990     }
00991 
00992   return TRUE;
00993 }
00994 
00995 /* This function handles relaxation of a section in a specific page.  */
00996 
00997 static bfd_boolean
00998 ip2k_elf_relax_section_page (bfd *abfd,
00999                           asection *sec,
01000                           bfd_boolean *again,
01001                           struct misc *misc,
01002                           unsigned long page_start,
01003                           unsigned long page_end)
01004 {
01005   Elf_Internal_Rela *irelend = misc->irelbase + sec->reloc_count;
01006   Elf_Internal_Rela *irel;
01007   int switch_table_128;
01008   int switch_table_256;
01009   
01010   /* Walk thru the section looking for relaxation opportunities.  */
01011   for (irel = misc->irelbase; irel < irelend; irel++)
01012     {
01013       if (ELF32_R_TYPE (irel->r_info) != (int) R_IP2K_PAGE3)
01014        /* Ignore non page instructions.  */
01015        continue;
01016 
01017       if (BASEADDR (sec) + irel->r_offset < page_start)
01018        /* Ignore page instructions on earlier page - they have
01019           already been processed. Remember that there is code flow
01020           that crosses a page boundary.  */
01021        continue;
01022 
01023       if (BASEADDR (sec) + irel->r_offset > page_end)
01024        /* Flow beyond end of page => nothing more to do for this page.  */
01025        return TRUE;
01026 
01027       /* Detect switch tables.  */
01028       switch_table_128 = ip2k_is_switch_table_128 (abfd, sec, irel->r_offset, misc->contents);
01029       switch_table_256 = ip2k_is_switch_table_256 (abfd, sec, irel->r_offset, misc->contents);
01030 
01031       if ((switch_table_128 > 0) || (switch_table_256 > 0))
01032        /* If the index is greater than 0 then it has already been processed.  */
01033        continue;
01034 
01035       if (switch_table_128 == 0)
01036        {
01037          if (!ip2k_relax_switch_table_128 (abfd, sec, irel, again, misc))
01038            return FALSE;
01039 
01040          continue;
01041        }
01042 
01043       if (switch_table_256 == 0)
01044        {
01045          if (!ip2k_relax_switch_table_256 (abfd, sec, irel, again, misc))
01046            return FALSE;
01047 
01048          continue;
01049        }
01050 
01051       /* Simple relax.  */
01052       if (ip2k_test_page_insn (abfd, sec, irel, misc))
01053        {
01054          if (!ip2k_delete_page_insn (abfd, sec, irel, again, misc))
01055            return FALSE;
01056 
01057          continue;
01058        }
01059     }
01060 
01061   return TRUE;
01062 }
01063 
01064 /* This function handles relaxing for the ip2k.
01065 
01066    Principle: Start with the first page and remove page instructions that
01067    are not require on this first page. By removing page instructions more
01068    code will fit into this page - repeat until nothing more can be achieved
01069    for this page. Move on to the next page.
01070 
01071    Processing the pages one at a time from the lowest page allows a removal
01072    only policy to be used - pages can be removed but are never reinserted.  */
01073 
01074 static bfd_boolean
01075 ip2k_elf_relax_section (bfd *abfd,
01076                      asection *sec,
01077                      struct bfd_link_info *link_info,
01078                      bfd_boolean *again)
01079 {
01080   Elf_Internal_Shdr *symtab_hdr;
01081   Elf_Internal_Rela *internal_relocs;
01082   bfd_byte *contents = NULL;
01083   Elf_Internal_Sym *isymbuf = NULL;
01084   static asection * first_section = NULL;
01085   static unsigned long search_addr;
01086   static unsigned long page_start = 0;
01087   static unsigned long page_end = 0;
01088   static unsigned int pass = 0;
01089   static bfd_boolean new_pass = FALSE;
01090   static bfd_boolean changed = FALSE;
01091   struct misc misc;
01092   asection *stab;
01093 
01094   /* Assume nothing changes.  */
01095   *again = FALSE;
01096 
01097   if (first_section == NULL)
01098     {
01099       ip2k_relaxed = TRUE;
01100       first_section = sec;
01101     }
01102 
01103   if (first_section == sec)
01104     {
01105       pass++;
01106       new_pass = TRUE;
01107     }
01108 
01109   /* We don't have to do anything for a relocatable link,
01110      if this section does not have relocs, or if this is
01111      not a code section.  */
01112   if (link_info->relocatable
01113       || (sec->flags & SEC_RELOC) == 0
01114       || sec->reloc_count == 0
01115       || (sec->flags & SEC_CODE) == 0)
01116     return TRUE;
01117 
01118   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
01119 
01120   internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
01121                                           link_info->keep_memory);
01122   if (internal_relocs == NULL)
01123     goto error_return;
01124 
01125   /* Make sure the stac.rela stuff gets read in.  */
01126   stab = bfd_get_section_by_name (abfd, ".stab");
01127 
01128   if (stab)
01129     {
01130       /* So stab does exits.  */
01131       Elf_Internal_Rela * irelbase;
01132 
01133       irelbase = _bfd_elf_link_read_relocs (abfd, stab, NULL, NULL,
01134                                        link_info->keep_memory);
01135     }
01136 
01137   /* Get section contents cached copy if it exists.  */
01138   if (contents == NULL)
01139     {
01140       /* Get cached copy if it exists.  */
01141       if (elf_section_data (sec)->this_hdr.contents != NULL)
01142        contents = elf_section_data (sec)->this_hdr.contents;
01143       else
01144        {
01145          /* Go get them off disk.  */
01146          if (!bfd_malloc_and_get_section (abfd, sec, &contents))
01147            goto error_return;
01148        }
01149     }
01150 
01151   /* Read this BFD's symbols cached copy if it exists.  */
01152   if (isymbuf == NULL && symtab_hdr->sh_info != 0)
01153     {
01154       isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
01155       if (isymbuf == NULL)
01156        isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
01157                                    symtab_hdr->sh_info, 0,
01158                                    NULL, NULL, NULL);
01159       if (isymbuf == NULL)
01160        goto error_return;
01161     }
01162 
01163   misc.symtab_hdr = symtab_hdr;
01164   misc.isymbuf = isymbuf;
01165   misc.irelbase = internal_relocs;
01166   misc.contents = contents;
01167 
01168   /* This is where all the relaxation actually get done.  */
01169   if ((pass == 1) || (new_pass && !changed))
01170     {
01171       /* On the first pass we simply search for the lowest page that
01172          we havn't relaxed yet. Note that the pass count is reset
01173          each time a page is complete in order to move on to the next page.
01174          If we can't find any more pages then we are finished.  */
01175       if (new_pass)
01176        {
01177          pass = 1;
01178          new_pass = FALSE;
01179          changed = TRUE; /* Pre-initialize to break out of pass 1.  */
01180          search_addr = 0xFFFFFFFF;
01181        }
01182 
01183       if ((BASEADDR (sec) + sec->size < search_addr)
01184          && (BASEADDR (sec) + sec->size > page_end))
01185        {
01186          if (BASEADDR (sec) <= page_end)
01187            search_addr = page_end + 1;
01188          else
01189            search_addr = BASEADDR (sec);
01190 
01191          /* Found a page => more work to do.  */
01192          *again = TRUE;
01193        }
01194     }
01195   else
01196     {
01197       if (new_pass)
01198        {
01199          new_pass = FALSE;
01200          changed = FALSE;
01201          page_start = PAGENO (search_addr);
01202          page_end = page_start | 0x00003FFF;
01203        }
01204 
01205       /* Only process sections in range.  */
01206       if ((BASEADDR (sec) + sec->size >= page_start)
01207          && (BASEADDR (sec) <= page_end))
01208        {
01209           if (!ip2k_elf_relax_section_page (abfd, sec, &changed, &misc, page_start, page_end))
01210            return FALSE;
01211        }
01212       *again = TRUE;
01213     }
01214 
01215   /* Perform some house keeping after relaxing the section.  */
01216 
01217   if (isymbuf != NULL
01218       && symtab_hdr->contents != (unsigned char *) isymbuf)
01219     {
01220       if (! link_info->keep_memory)
01221        free (isymbuf);
01222       else
01223        symtab_hdr->contents = (unsigned char *) isymbuf;
01224     }
01225 
01226   if (contents != NULL
01227       && elf_section_data (sec)->this_hdr.contents != contents)
01228     {
01229       if (! link_info->keep_memory)
01230        free (contents);
01231       else
01232        {
01233          /* Cache the section contents for elf_link_input_bfd.  */
01234          elf_section_data (sec)->this_hdr.contents = contents;
01235        }
01236     }
01237 
01238   if (internal_relocs != NULL
01239       && elf_section_data (sec)->relocs != internal_relocs)
01240     free (internal_relocs);
01241 
01242   return TRUE;
01243 
01244  error_return:
01245   if (isymbuf != NULL
01246       && symtab_hdr->contents != (unsigned char *) isymbuf)
01247     free (isymbuf);
01248   if (contents != NULL
01249       && elf_section_data (sec)->this_hdr.contents != contents)
01250     free (contents);
01251   if (internal_relocs != NULL
01252       && elf_section_data (sec)->relocs != internal_relocs)
01253     free (internal_relocs);
01254   return FALSE;
01255 }
01256 
01257 /* Set the howto pointer for a IP2K ELF reloc.  */
01258 
01259 static void
01260 ip2k_info_to_howto_rela (bfd * abfd ATTRIBUTE_UNUSED,
01261                       arelent * cache_ptr,
01262                       Elf_Internal_Rela * dst)
01263 {
01264   unsigned int r_type;
01265 
01266   r_type = ELF32_R_TYPE (dst->r_info);
01267   cache_ptr->howto = & ip2k_elf_howto_table [r_type];
01268 }
01269 
01270 /* Perform a single relocation.
01271    By default we use the standard BFD routines.  */
01272 
01273 static bfd_reloc_status_type
01274 ip2k_final_link_relocate (reloc_howto_type *  howto,
01275                        bfd *               input_bfd,
01276                        asection *          input_section,
01277                        bfd_byte *          contents,
01278                        Elf_Internal_Rela * rel,
01279                        bfd_vma             relocation)
01280 {
01281   static bfd_vma page_addr = 0;
01282 
01283   bfd_reloc_status_type r = bfd_reloc_ok;
01284   switch (howto->type)
01285     {
01286       /* Handle data space relocations.  */
01287     case R_IP2K_FR9:
01288     case R_IP2K_BANK:
01289       if ((relocation & IP2K_DATA_MASK) == IP2K_DATA_VALUE)
01290        relocation &= ~IP2K_DATA_MASK;
01291       else
01292        r = bfd_reloc_notsupported;
01293       break;
01294 
01295     case R_IP2K_LO8DATA:
01296     case R_IP2K_HI8DATA:
01297     case R_IP2K_EX8DATA:
01298       break;
01299 
01300       /* Handle insn space relocations.  */
01301     case R_IP2K_PAGE3:
01302       page_addr = BASEADDR (input_section) + rel->r_offset;
01303       if ((relocation & IP2K_INSN_MASK) == IP2K_INSN_VALUE)
01304        relocation &= ~IP2K_INSN_MASK;
01305       else
01306        r = bfd_reloc_notsupported;
01307       break;
01308 
01309     case R_IP2K_ADDR16CJP:
01310       if (BASEADDR (input_section) + rel->r_offset != page_addr + 2)
01311        {
01312          /* No preceding page instruction, verify that it isn't needed.  */
01313          if (PAGENO (relocation + rel->r_addend) !=
01314              ip2k_nominal_page_bits (input_bfd, input_section,
01315                                   rel->r_offset, contents))
01316            _bfd_error_handler (_("ip2k linker: missing page instruction at 0x%08lx (dest = 0x%08lx)."),
01317                             BASEADDR (input_section) + rel->r_offset,
01318                             relocation + rel->r_addend);
01319         }
01320       else if (ip2k_relaxed)
01321         {
01322           /* Preceding page instruction. Verify that the page instruction is
01323              really needed. One reason for the relaxation to miss a page is if
01324              the section is not marked as executable.  */
01325          if (!ip2k_is_switch_table_128 (input_bfd, input_section,
01326                                     rel->r_offset - 2, contents)
01327              && !ip2k_is_switch_table_256 (input_bfd, input_section,
01328                                        rel->r_offset - 2, contents)
01329              && (PAGENO (relocation + rel->r_addend) ==
01330                 ip2k_nominal_page_bits (input_bfd, input_section,
01331                                      rel->r_offset - 2, contents)))
01332            _bfd_error_handler (_("ip2k linker: redundant page instruction at 0x%08lx (dest = 0x%08lx)."),
01333                             page_addr,
01334                             relocation + rel->r_addend);
01335         }
01336       if ((relocation & IP2K_INSN_MASK) == IP2K_INSN_VALUE)
01337        relocation &= ~IP2K_INSN_MASK;
01338       else
01339        r = bfd_reloc_notsupported;
01340       break;
01341 
01342     case R_IP2K_LO8INSN:
01343     case R_IP2K_HI8INSN:
01344     case R_IP2K_PC_SKIP:
01345       if ((relocation & IP2K_INSN_MASK) == IP2K_INSN_VALUE)
01346        relocation &= ~IP2K_INSN_MASK;
01347       else
01348        r = bfd_reloc_notsupported;
01349       break;
01350 
01351     case R_IP2K_16:
01352       /* If this is a relocation involving a TEXT
01353         symbol, reduce it to a word address.  */
01354       if ((relocation & IP2K_INSN_MASK) == IP2K_INSN_VALUE)
01355        howto = &ip2k_elf_howto_table[ (int) R_IP2K_TEXT];
01356       break;
01357 
01358       /* Pass others through.  */
01359     default:
01360       break;
01361     }
01362 
01363   /* Only install relocation if above tests did not disqualify it.  */
01364   if (r == bfd_reloc_ok)
01365     r = _bfd_final_link_relocate (howto, input_bfd, input_section,
01366                               contents, rel->r_offset,
01367                               relocation, rel->r_addend);
01368 
01369   return r;
01370 }
01371 
01372 /* Relocate a IP2K ELF section.
01373 
01374    The RELOCATE_SECTION function is called by the new ELF backend linker
01375    to handle the relocations for a section.
01376 
01377    The relocs are always passed as Rela structures; if the section
01378    actually uses Rel structures, the r_addend field will always be
01379    zero.
01380 
01381    This function is responsible for adjusting the section contents as
01382    necessary, and (if using Rela relocs and generating a relocatable
01383    output file) adjusting the reloc addend as necessary.
01384 
01385    This function does not have to worry about setting the reloc
01386    address or the reloc symbol index.
01387 
01388    LOCAL_SYMS is a pointer to the swapped in local symbols.
01389 
01390    LOCAL_SECTIONS is an array giving the section in the input file
01391    corresponding to the st_shndx field of each local symbol.
01392 
01393    The global hash table entry for the global symbols can be found
01394    via elf_sym_hashes (input_bfd).
01395 
01396    When generating relocatable output, this function must handle
01397    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
01398    going to be the section symbol corresponding to the output
01399    section, which means that the addend must be adjusted
01400    accordingly.  */
01401 
01402 static bfd_boolean
01403 ip2k_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
01404                         struct bfd_link_info *info,
01405                         bfd *input_bfd,
01406                         asection *input_section,
01407                         bfd_byte *contents,
01408                         Elf_Internal_Rela *relocs,
01409                         Elf_Internal_Sym *local_syms,
01410                         asection **local_sections)
01411 {
01412   Elf_Internal_Shdr *symtab_hdr;
01413   struct elf_link_hash_entry **sym_hashes;
01414   Elf_Internal_Rela *rel;
01415   Elf_Internal_Rela *relend;
01416 
01417   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
01418   sym_hashes = elf_sym_hashes (input_bfd);
01419   relend     = relocs + input_section->reloc_count;
01420 
01421   for (rel = relocs; rel < relend; rel ++)
01422     {
01423       reloc_howto_type *           howto;
01424       unsigned long                r_symndx;
01425       Elf_Internal_Sym *           sym;
01426       asection *                   sec;
01427       struct elf_link_hash_entry * h;
01428       bfd_vma                      relocation;
01429       bfd_reloc_status_type        r;
01430       const char *                 name = NULL;
01431       int                          r_type;
01432 
01433       r_type = ELF32_R_TYPE (rel->r_info);
01434       r_symndx = ELF32_R_SYM (rel->r_info);
01435       howto  = ip2k_elf_howto_table + ELF32_R_TYPE (rel->r_info);
01436       h      = NULL;
01437       sym    = NULL;
01438       sec    = NULL;
01439 
01440       if (r_symndx < symtab_hdr->sh_info)
01441        {
01442          sym = local_syms + r_symndx;
01443          sec = local_sections [r_symndx];
01444          relocation = BASEADDR (sec) + sym->st_value;
01445 
01446          name = bfd_elf_string_from_elf_section
01447            (input_bfd, symtab_hdr->sh_link, sym->st_name);
01448          name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
01449        }
01450       else
01451        {
01452          bfd_boolean warned;
01453          bfd_boolean unresolved_reloc;
01454 
01455          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
01456                                r_symndx, symtab_hdr, sym_hashes,
01457                                h, sec, relocation,
01458                                unresolved_reloc, warned);
01459 
01460          name = h->root.root.string;
01461        }
01462 
01463       if (sec != NULL && elf_discarded_section (sec))
01464        {
01465          /* For relocs against symbols from removed linkonce sections,
01466             or sections discarded by a linker script, we just want the
01467             section contents zeroed.  Avoid any special processing.  */
01468          _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
01469          rel->r_info = 0;
01470          rel->r_addend = 0;
01471          continue;
01472        }
01473 
01474       if (info->relocatable)
01475        continue;
01476 
01477       /* Finally, the sole IP2K-specific part.  */
01478       r = ip2k_final_link_relocate (howto, input_bfd, input_section,
01479                                  contents, rel, relocation);
01480 
01481       if (r != bfd_reloc_ok)
01482        {
01483          const char * msg = NULL;
01484 
01485          switch (r)
01486            {
01487            case bfd_reloc_overflow:
01488              r = info->callbacks->reloc_overflow
01489               (info, (h ? &h->root : NULL), name, howto->name,
01490                (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
01491              break;
01492 
01493            case bfd_reloc_undefined:
01494              r = info->callbacks->undefined_symbol
01495               (info, name, input_bfd, input_section, rel->r_offset, TRUE);
01496              break;
01497 
01498            case bfd_reloc_outofrange:
01499              msg = _("internal error: out of range error");
01500              break;
01501 
01502              /* This is how ip2k_final_link_relocate tells us of a non-kosher
01503                  reference between insn & data address spaces.  */
01504            case bfd_reloc_notsupported:
01505               if (sym != NULL) /* Only if it's not an unresolved symbol.  */
01506                 msg = _("unsupported relocation between data/insn address spaces");
01507              break;
01508 
01509            case bfd_reloc_dangerous:
01510              msg = _("internal error: dangerous relocation");
01511              break;
01512 
01513            default:
01514              msg = _("internal error: unknown error");
01515              break;
01516            }
01517 
01518          if (msg)
01519            r = info->callbacks->warning
01520              (info, msg, name, input_bfd, input_section, rel->r_offset);
01521 
01522          if (! r)
01523            return FALSE;
01524        }
01525     }
01526 
01527   return TRUE;
01528 }
01529 
01530 #define TARGET_BIG_SYM       bfd_elf32_ip2k_vec
01531 #define TARGET_BIG_NAME  "elf32-ip2k"
01532 
01533 #define ELF_ARCH      bfd_arch_ip2k
01534 #define ELF_MACHINE_CODE EM_IP2K
01535 #define ELF_MACHINE_ALT1 EM_IP2K_OLD
01536 #define ELF_MAXPAGESIZE  1 /* No pages on the IP2K.  */
01537 
01538 #define elf_info_to_howto_rel                    NULL
01539 #define elf_info_to_howto                 ip2k_info_to_howto_rela
01540 
01541 #define elf_backend_can_gc_sections       1
01542 #define elf_backend_rela_normal                  1
01543 #define elf_backend_relocate_section             ip2k_elf_relocate_section
01544 
01545 #define elf_symbol_leading_char                  '_'
01546 #define bfd_elf32_bfd_reloc_type_lookup          ip2k_reloc_type_lookup
01547 #define bfd_elf32_bfd_reloc_name_lookup   ip2k_reloc_name_lookup
01548 #define bfd_elf32_bfd_relax_section              ip2k_elf_relax_section
01549 
01550 #include "elf32-target.h"