/[gcl]/gcl/binutils/bfd/elf32-ip2k.c
ViewVC logotype

Diff of /gcl/binutils/bfd/elf32-ip2k.c

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

revision 1.1.1.1 by camm, Fri Aug 9 05:36:07 2002 UTC revision 1.1.1.1.20.1 by camm, Fri Sep 30 02:08:58 2005 UTC
# Line 1  Line 1 
1  /* Scenix IP2xxx specific support for 32-bit ELF  /* Ubicom IP2xxx specific support for 32-bit ELF
2     Copyright 2000, 2001, 2002 Free Software Foundation, Inc.     Copyright 2000, 2001, 2002, 2003, 2004, 2005
3       Free Software Foundation, Inc.
4    
5     This file is part of BFD, the Binary File Descriptor library.     This file is part of BFD, the Binary File Descriptor library.
6    
# Line 30  struct misc Line 31  struct misc
31    Elf_Internal_Shdr *  symtab_hdr;    Elf_Internal_Shdr *  symtab_hdr;
32    Elf_Internal_Rela *  irelbase;    Elf_Internal_Rela *  irelbase;
33    bfd_byte *           contents;    bfd_byte *           contents;
34    bfd_byte *           free_contents;    Elf_Internal_Sym *   isymbuf;
   Elf32_External_Sym * extsyms;  
   Elf32_External_Sym * free_extsyms;  
   Elf_Internal_Rela *  free_relocs;  
35  };  };
36    
37    struct ip2k_opcode
38    {
39      unsigned short opcode;
40      unsigned short mask;
41    };
42      
43  /* Prototypes.  */  /* Prototypes.  */
44  static reloc_howto_type *    ip2k_reloc_type_lookup               PARAMS ((bfd *, bfd_reloc_code_real_type));  static reloc_howto_type *ip2k_reloc_type_lookup
45  static void                  ip2k_info_to_howto_rela              PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));    PARAMS ((bfd *, bfd_reloc_code_real_type));
46  static asection *            ip2k_elf_gc_mark_hook                PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *, struct elf_link_hash_entry *, Elf_Internal_Sym *));  static int ip2k_is_opcode
47  static boolean               ip2k_elf_gc_sweep_hook               PARAMS ((bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *));    PARAMS ((bfd_byte *, const struct ip2k_opcode *));
48  static bfd_vma               symbol_value                         PARAMS ((bfd *, Elf_Internal_Shdr *, Elf32_External_Sym *, Elf_Internal_Rela *));  static bfd_vma symbol_value
49  static void                  adjust_all_relocations               PARAMS ((bfd *, asection *, bfd_vma, bfd_vma, int, int));    PARAMS ((bfd *, Elf_Internal_Shdr *, Elf_Internal_Sym *,
50  static boolean               ip2k_elf_relax_delete_bytes          PARAMS ((bfd *, asection *, bfd_vma, int));             Elf_Internal_Rela *));
51  static boolean               ip2k_elf_relax_add_bytes             PARAMS ((bfd *, asection *, bfd_vma, const bfd_byte *, int, int));  static void ip2k_get_mem
52  static boolean               add_page_insn                        PARAMS ((bfd *, asection *, Elf_Internal_Rela *, struct misc *));    PARAMS ((bfd *, bfd_byte *, int, bfd_byte *));
53  static boolean               ip2k_elf_relax_section               PARAMS ((bfd *, asection *, struct bfd_link_info *, boolean *));  static bfd_vma ip2k_nominal_page_bits
54  static boolean               relax_switch_dispatch_tables_pass1   PARAMS ((bfd *, asection *, bfd_vma, struct misc *));    PARAMS ((bfd *, asection *, bfd_vma, bfd_byte *));
55  static boolean               unrelax_dispatch_table_entries       PARAMS ((bfd *, asection *, bfd_vma, bfd_vma, boolean *, struct misc *));  static bfd_boolean ip2k_test_page_insn
56  static boolean               unrelax_switch_dispatch_tables_passN PARAMS ((bfd *, asection *, bfd_vma, boolean *, struct misc *));    PARAMS ((bfd *, asection *, Elf_Internal_Rela *, struct misc *));
57  static boolean               is_switch_128_dispatch_table_p       PARAMS ((bfd *, bfd_vma, boolean, struct misc *));  static bfd_boolean ip2k_delete_page_insn
58  static boolean               is_switch_256_dispatch_table_p       PARAMS ((bfd *, bfd_vma, boolean, struct misc *));    PARAMS ((bfd *, asection *, Elf_Internal_Rela *, bfd_boolean *, struct misc *));
59  static void                  tidyup_after_error                   PARAMS ((struct misc *));  static int ip2k_is_switch_table_128
60  static boolean               ip2k_elf_relax_section_pass1         PARAMS ((bfd *, asection *, boolean *, struct misc *));    PARAMS ((bfd *, asection *, bfd_vma, bfd_byte *));
61  static boolean               ip2k_elf_relax_section_passN         PARAMS ((bfd *, asection *, boolean *, boolean *, struct misc *));  static bfd_boolean ip2k_relax_switch_table_128
62  static bfd_reloc_status_type ip2k_final_link_relocate             PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, bfd_vma));    PARAMS ((bfd *, asection *, Elf_Internal_Rela *, bfd_boolean *, struct misc *));
63  static boolean               ip2k_elf_relocate_section            PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));  static int ip2k_is_switch_table_256
64      PARAMS ((bfd *, asection *, bfd_vma, bfd_byte *));
65  #define IS_OPCODE(CODE0,CODE1,OPCODE) \  static bfd_boolean ip2k_relax_switch_table_256
66    ((CODE0) == (OPCODE)[0] && (CODE1) == (OPCODE)[1])    PARAMS ((bfd *, asection *, Elf_Internal_Rela *, bfd_boolean *, struct misc *));
67    static bfd_boolean ip2k_elf_relax_section
68      PARAMS ((bfd *, asection *, struct bfd_link_info *, bfd_boolean *));
69    static bfd_boolean ip2k_elf_relax_section_page
70      PARAMS ((bfd *, asection *, bfd_boolean *, struct misc *, unsigned long, unsigned long));
71    static void adjust_all_relocations
72      PARAMS ((bfd *, asection *, bfd_vma, bfd_vma, int, int));
73    static bfd_boolean ip2k_elf_relax_delete_bytes
74      PARAMS ((bfd *, asection *, bfd_vma, int));
75    static void ip2k_info_to_howto_rela
76      PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
77    static bfd_reloc_status_type ip2k_final_link_relocate
78      PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
79               Elf_Internal_Rela *, bfd_vma));
80    static bfd_boolean ip2k_elf_relocate_section
81      PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
82               Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
83    static asection *ip2k_elf_gc_mark_hook
84      PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
85               struct elf_link_hash_entry *, Elf_Internal_Sym *));
86    static bfd_boolean ip2k_elf_gc_sweep_hook
87      PARAMS ((bfd *, struct bfd_link_info *, asection *,
88               const Elf_Internal_Rela *));
89    
90  #define PAGE_INSN_0             0x00  static bfd_boolean ip2k_relaxed = FALSE;
 #define PAGE_INSN_1             0x10  
91    
92  static const bfd_byte page_opcode[] =  static const struct ip2k_opcode ip2k_page_opcode[] =
93  {  {
94     PAGE_INSN_0, PAGE_INSN_1    {0x0010, 0xFFF8},     /* page */
95      {0x0000, 0x0000},
96  };  };
97    
98  #define IS_PAGE_OPCODE(CODE0,CODE1) \  #define IS_PAGE_OPCODE(code) \
99    IS_OPCODE (CODE0, CODE1, page_opcode)    ip2k_is_opcode (code, ip2k_page_opcode)
100    
101  #define JMP_INSN_0              0xE0  static const struct ip2k_opcode ip2k_jmp_opcode[] =
 #define JMP_INSN_1              0x00  
   
 static const bfd_byte jmp_opcode[] =  
102  {  {
103     JMP_INSN_0, JMP_INSN_1    {0xE000, 0xE000},     /* jmp */
104      {0x0000, 0x0000},
105  };  };
106    
107  #define IS_JMP_OPCODE(CODE0,CODE1) \  #define IS_JMP_OPCODE(code) \
108    IS_OPCODE (CODE0, CODE1, jmp_opcode)    ip2k_is_opcode (code, ip2k_jmp_opcode)
   
 #define CALL_INSN_0             0xC0  
 #define CALL_INSN_1             0x00  
109    
110  static const bfd_byte call_opcode[] =  static const struct ip2k_opcode ip2k_snc_opcode[] =
111  {  {
112    CALL_INSN_0, CALL_INSN_1    {0xA00B, 0xFFFF},     /* snc */
113      {0x0000, 0x0000},
114  };  };
115    
116  #define IS_CALL_OPCODE(CODE0,CODE1) \  #define IS_SNC_OPCODE(code) \
117    IS_OPCODE (CODE0, CODE1, call_opcode)    ip2k_is_opcode (code, ip2k_snc_opcode)
   
 #define ADD_PCL_W_INSN_0        0x1E  
 #define ADD_PCL_W_INSN_1        0x09  
118    
119  static const bfd_byte add_pcl_w_opcode[] =  static const struct ip2k_opcode ip2k_inc_1sp_opcode[] =
120  {  {
121    ADD_PCL_W_INSN_0, ADD_PCL_W_INSN_1    {0x2B81, 0xFFFF},     /* inc 1(SP) */
122      {0x0000, 0x0000},
123  };  };
124    
125  #define IS_ADD_PCL_W_OPCODE(CODE0,CODE1) \  #define IS_INC_1SP_OPCODE(code) \
126    IS_OPCODE (CODE0, CODE1, add_pcl_w_opcode)    ip2k_is_opcode (code, ip2k_inc_1sp_opcode)
127    
128  #define ADD_W_WREG_INSN_0       0x1C  static const struct ip2k_opcode ip2k_add_2sp_w_opcode[] =
 #define ADD_W_WREG_INSN_1       0x0A  
   
 static const bfd_byte add_w_wreg_opcode[] =  
129  {  {
130    ADD_W_WREG_INSN_0, ADD_W_WREG_INSN_1    {0x1F82, 0xFFFF},     /* add 2(SP),w */
131      {0x0000, 0x0000},
132  };  };
133    
134  #define IS_ADD_W_WREG_OPCODE(CODE0,CODE1) \  #define IS_ADD_2SP_W_OPCODE(code) \
135    IS_OPCODE (CODE0, CODE1, add_w_wreg_opcode)    ip2k_is_opcode (code, ip2k_add_2sp_w_opcode)
   
 #define SNC_INSN_0              0xA0  
 #define SNC_INSN_1              0x0B  
136    
137  static const bfd_byte snc_opcode[] =  static const struct ip2k_opcode ip2k_add_w_wreg_opcode[] =
138  {  {
139     SNC_INSN_0, SNC_INSN_1    {0x1C0A, 0xFFFF},     /* add w,wreg */
140      {0x1E0A, 0xFFFF},     /* add wreg,w */
141      {0x0000, 0x0000},
142  };  };
143    
144  #define IS_SNC_OPCODE(CODE0,CODE1) \  #define IS_ADD_W_WREG_OPCODE(code) \
145    IS_OPCODE (CODE0, CODE1, snc_opcode)    ip2k_is_opcode (code, ip2k_add_w_wreg_opcode)
   
 #define INC_1_SP_INSN_0         0x2B  
 #define INC_1_SP_INSN_1         0x81  
146    
147  static const bfd_byte inc_1_sp_opcode[] =  static const struct ip2k_opcode ip2k_add_pcl_w_opcode[] =
148  {  {
149     INC_1_SP_INSN_0, INC_1_SP_INSN_1    {0x1E09, 0xFFFF},     /* add pcl,w */
150      {0x0000, 0x0000},
151  };  };
152    
153  #define IS_INC_1_SP_OPCODE(CODE0,CODE1) \  #define IS_ADD_PCL_W_OPCODE(code) \
154    IS_OPCODE (CODE0, CODE1, inc_1_sp_opcode)    ip2k_is_opcode (code, ip2k_add_pcl_w_opcode)
155    
156  #define ADD_2_SP_W_INSN_0       0x1F  static const struct ip2k_opcode ip2k_skip_opcodes[] =
 #define ADD_2_SP_W_INSN_1       0x82  
   
 static const bfd_byte add_2_sp_w_opcode[] =  
157  {  {
158     ADD_2_SP_W_INSN_0, ADD_2_SP_W_INSN_1    {0xB000, 0xF000},     /* sb */
159      {0xA000, 0xF000},     /* snb */
160      {0x7600, 0xFE00},     /* cse/csne #lit */
161      {0x5800, 0xFC00},     /* incsnz */
162      {0x4C00, 0xFC00},     /* decsnz */
163      {0x4000, 0xFC00},     /* cse/csne */
164      {0x3C00, 0xFC00},     /* incsz */
165      {0x2C00, 0xFC00},     /* decsz */
166      {0x0000, 0x0000},
167  };  };
168    
169  #define IS_ADD_2_SP_W_OPCODE(CODE0,CODE1) \  #define IS_SKIP_OPCODE(code) \
170    IS_OPCODE (CODE0, CODE1, add_2_sp_w_opcode)    ip2k_is_opcode (code, ip2k_skip_opcodes)
171    
172  /* Relocation tables. */  /* Relocation tables.  */
173  static reloc_howto_type ip2k_elf_howto_table [] =  static reloc_howto_type ip2k_elf_howto_table [] =
174  {  {
175  #define IP2K_HOWTO(t,rs,s,bs,pr,bp,name,sm,dm) \  #define IP2K_HOWTO(t,rs,s,bs,pr,bp,name,sm,dm) \
# Line 162  static reloc_howto_type ip2k_elf_howto_t Line 182  static reloc_howto_type ip2k_elf_howto_t
182            complain_overflow_dont,/* complain_on_overflow */ \            complain_overflow_dont,/* complain_on_overflow */ \
183            bfd_elf_generic_reloc,/* special_function */ \            bfd_elf_generic_reloc,/* special_function */ \
184            name,                 /* name */ \            name,                 /* name */ \
185            false,                /* partial_inplace */ \            FALSE,                /* partial_inplace */ \
186            sm,                   /* src_mask */ \            sm,                   /* src_mask */ \
187            dm,                   /* dst_mask */ \            dm,                   /* dst_mask */ \
188            pr)                   /* pcrel_offset */            pr)                   /* pcrel_offset */
189    
190    /* This reloc does nothing. */    /* This reloc does nothing.  */
191    IP2K_HOWTO (R_IP2K_NONE, 0,2,32, false, 0, "R_IP2K_NONE", 0, 0),    IP2K_HOWTO (R_IP2K_NONE, 0,2,32, FALSE, 0, "R_IP2K_NONE", 0, 0),
192    /* A 16 bit absolute relocation.  */    /* A 16 bit absolute relocation.  */
193    IP2K_HOWTO (R_IP2K_16, 0,1,16, false, 0, "R_IP2K_16", 0, 0xffff),    IP2K_HOWTO (R_IP2K_16, 0,1,16, FALSE, 0, "R_IP2K_16", 0, 0xffff),
194    /* A 32 bit absolute relocation.  */    /* A 32 bit absolute relocation.  */
195    IP2K_HOWTO (R_IP2K_32, 0,2,32, false, 0, "R_IP2K_32", 0, 0xffffffff),    IP2K_HOWTO (R_IP2K_32, 0,2,32, FALSE, 0, "R_IP2K_32", 0, 0xffffffff),
196    /* A 8-bit data relocation for the FR9 field.  Ninth bit is computed specially.  */    /* A 8-bit data relocation for the FR9 field.  Ninth bit is computed specially.  */
197    IP2K_HOWTO (R_IP2K_FR9, 0,1,9, false, 0, "R_IP2K_FR9", 0, 0x00ff),    IP2K_HOWTO (R_IP2K_FR9, 0,1,9, FALSE, 0, "R_IP2K_FR9", 0, 0x00ff),
198    /* A 4-bit data relocation.  */    /* A 4-bit data relocation.  */
199    IP2K_HOWTO (R_IP2K_BANK, 8,1,4, false, 0, "R_IP2K_BANK", 0, 0x000f),    IP2K_HOWTO (R_IP2K_BANK, 8,1,4, FALSE, 0, "R_IP2K_BANK", 0, 0x000f),
200    /* A 13-bit insn relocation - word address => right-shift 1 bit extra.  */    /* A 13-bit insn relocation - word address => right-shift 1 bit extra.  */
201    IP2K_HOWTO (R_IP2K_ADDR16CJP, 1,1,13, false, 0, "R_IP2K_ADDR16CJP", 0, 0x1fff),    IP2K_HOWTO (R_IP2K_ADDR16CJP, 1,1,13, FALSE, 0, "R_IP2K_ADDR16CJP", 0, 0x1fff),
202    /* A 3-bit insn relocation - word address => right-shift 1 bit extra.  */    /* A 3-bit insn relocation - word address => right-shift 1 bit extra.  */
203    IP2K_HOWTO (R_IP2K_PAGE3, 14,1,3, false, 0, "R_IP2K_PAGE3", 0, 0x0007),    IP2K_HOWTO (R_IP2K_PAGE3, 14,1,3, FALSE, 0, "R_IP2K_PAGE3", 0, 0x0007),
204    /* Two 8-bit data relocations.  */    /* Two 8-bit data relocations.  */
205    IP2K_HOWTO (R_IP2K_LO8DATA, 0,1,8, false, 0, "R_IP2K_LO8DATA", 0, 0x00ff),    IP2K_HOWTO (R_IP2K_LO8DATA, 0,1,8, FALSE, 0, "R_IP2K_LO8DATA", 0, 0x00ff),
206    IP2K_HOWTO (R_IP2K_HI8DATA, 8,1,8, false, 0, "R_IP2K_HI8DATA", 0, 0x00ff),    IP2K_HOWTO (R_IP2K_HI8DATA, 8,1,8, FALSE, 0, "R_IP2K_HI8DATA", 0, 0x00ff),
207    /* Two 8-bit insn relocations.  word address => right-shift 1 bit extra.  */    /* Two 8-bit insn relocations.  word address => right-shift 1 bit extra.  */
208    IP2K_HOWTO (R_IP2K_LO8INSN, 1,1,8, false, 0, "R_IP2K_LO8INSN", 0, 0x00ff),    IP2K_HOWTO (R_IP2K_LO8INSN, 1,1,8, FALSE, 0, "R_IP2K_LO8INSN", 0, 0x00ff),
209    IP2K_HOWTO (R_IP2K_HI8INSN, 9,1,8, false, 0, "R_IP2K_HI8INSN", 0, 0x00ff),    IP2K_HOWTO (R_IP2K_HI8INSN, 9,1,8, FALSE, 0, "R_IP2K_HI8INSN", 0, 0x00ff),
210    
211    /* Special 1 bit relocation for SKIP instructions.  */    /* Special 1 bit relocation for SKIP instructions.  */
212    IP2K_HOWTO (R_IP2K_PC_SKIP, 1,1,1, false, 12, "R_IP2K_PC_SKIP", 0xfffe, 0x1000),    IP2K_HOWTO (R_IP2K_PC_SKIP, 1,1,1, FALSE, 12, "R_IP2K_PC_SKIP", 0xfffe, 0x1000),
213    /* 16 bit word address.  */    /* 16 bit word address.  */
214    IP2K_HOWTO (R_IP2K_TEXT, 1,1,16, false, 0, "R_IP2K_TEXT", 0, 0xffff),    IP2K_HOWTO (R_IP2K_TEXT, 1,1,16, FALSE, 0, "R_IP2K_TEXT", 0, 0xffff),
215    /* A 7-bit offset relocation for the FR9 field.  Eigth and ninth bit comes from insn.  */    /* A 7-bit offset relocation for the FR9 field.  Eigth and ninth bit comes from insn.  */
216    IP2K_HOWTO (R_IP2K_FR_OFFSET, 0,1,9, false, 0, "R_IP2K_FR_OFFSET", 0x180, 0x007f),    IP2K_HOWTO (R_IP2K_FR_OFFSET, 0,1,9, FALSE, 0, "R_IP2K_FR_OFFSET", 0x180, 0x007f),
217    /* Bits 23:16 of an address.  */    /* Bits 23:16 of an address.  */
218    IP2K_HOWTO (R_IP2K_EX8DATA, 16,1,8, false, 0, "R_IP2K_EX8DATA", 0, 0x00ff),    IP2K_HOWTO (R_IP2K_EX8DATA, 16,1,8, FALSE, 0, "R_IP2K_EX8DATA", 0, 0x00ff),
219  };  };
220    
221    
222  /* Map BFD reloc types to IP2K ELF reloc types. */  /* Map BFD reloc types to IP2K ELF reloc types.  */
223  static reloc_howto_type *  static reloc_howto_type *
224  ip2k_reloc_type_lookup (abfd, code)  ip2k_reloc_type_lookup (abfd, code)
225       bfd * abfd ATTRIBUTE_UNUSED;       bfd * abfd ATTRIBUTE_UNUSED;
# Line 208  ip2k_reloc_type_lookup (abfd, code) Line 228  ip2k_reloc_type_lookup (abfd, code)
228    /* Note that the ip2k_elf_howto_table is indxed by the R_    /* Note that the ip2k_elf_howto_table is indxed by the R_
229       constants.  Thus, the order that the howto records appear in the       constants.  Thus, the order that the howto records appear in the
230       table *must* match the order of the relocation types defined in       table *must* match the order of the relocation types defined in
231       include/elf/ip2k.h. */       include/elf/ip2k.h.  */
232    
233    switch (code)    switch (code)
234      {      {
# Line 243  ip2k_reloc_type_lookup (abfd, code) Line 263  ip2k_reloc_type_lookup (abfd, code)
263      case BFD_RELOC_IP2K_EX8DATA:      case BFD_RELOC_IP2K_EX8DATA:
264        return &ip2k_elf_howto_table[ (int) R_IP2K_EX8DATA];        return &ip2k_elf_howto_table[ (int) R_IP2K_EX8DATA];
265      default:      default:
266        /* Pacify gcc -Wall. */        /* Pacify gcc -Wall.  */
267        return NULL;        return NULL;
268      }      }
269    return NULL;    return NULL;
270  }  }
271    
272  #define PAGENO(ABSADDR) ((ABSADDR) & 0x1C000)  static void
273    ip2k_get_mem (abfd, addr, length, ptr)
274         bfd *abfd ATTRIBUTE_UNUSED;
275         bfd_byte *addr;
276         int length;
277         bfd_byte *ptr;
278    {
279      while (length --)
280        * ptr ++ = bfd_get_8 (abfd, addr ++);
281    }
282    
283    static bfd_boolean
284    ip2k_is_opcode (code, opcodes)
285         bfd_byte *code;
286         const struct ip2k_opcode *opcodes;
287    {
288      unsigned short insn = (code[0] << 8) | code[1];
289    
290      while (opcodes->mask != 0)
291        {
292          if ((insn & opcodes->mask) == opcodes->opcode)
293            return TRUE;
294    
295          opcodes ++;
296        }
297    
298      return FALSE;
299    }
300    
301    #define PAGENO(ABSADDR) ((ABSADDR) & 0xFFFFC000)
302  #define BASEADDR(SEC)   ((SEC)->output_section->vma + (SEC)->output_offset)  #define BASEADDR(SEC)   ((SEC)->output_section->vma + (SEC)->output_offset)
303    
304  #define UNDEFINED_SYMBOL (~(bfd_vma)0)  #define UNDEFINED_SYMBOL (~(bfd_vma)0)
# Line 257  ip2k_reloc_type_lookup (abfd, code) Line 306  ip2k_reloc_type_lookup (abfd, code)
306  /* Return the value of the symbol associated with the relocation IREL.  */  /* Return the value of the symbol associated with the relocation IREL.  */
307    
308  static bfd_vma  static bfd_vma
309  symbol_value (abfd, symtab_hdr, extsyms, irel)  symbol_value (abfd, symtab_hdr, isymbuf, irel)
310       bfd *abfd;       bfd *abfd;
311       Elf_Internal_Shdr *symtab_hdr;       Elf_Internal_Shdr *symtab_hdr;
312       Elf32_External_Sym *extsyms;       Elf_Internal_Sym *isymbuf;
313       Elf_Internal_Rela *irel;         Elf_Internal_Rela *irel;
314  {  {
315    if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)    if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
316      {      {
317        Elf_External_Sym_Shndx *sym_shndx;        Elf_Internal_Sym *isym;
       Elf_Internal_Shdr *shndx_hdr;  
       Elf_Internal_Sym isym;  
318        asection *sym_sec;        asection *sym_sec;
319    
320        shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;        isym = isymbuf + ELF32_R_SYM (irel->r_info);
321        sym_shndx = (Elf_External_Sym_Shndx *) shndx_hdr->contents;        if (isym->st_shndx == SHN_UNDEF)
       sym_shndx = sym_shndx ? sym_shndx + ELF32_R_SYM (irel->r_info) : NULL;  
       bfd_elf32_swap_symbol_in (abfd, extsyms + ELF32_R_SYM (irel->r_info),  
                                 sym_shndx, &isym);  
       if (isym.st_shndx == SHN_UNDEF)  
322          sym_sec = bfd_und_section_ptr;          sym_sec = bfd_und_section_ptr;
323        else if (isym.st_shndx == SHN_ABS)        else if (isym->st_shndx == SHN_ABS)
324          sym_sec = bfd_abs_section_ptr;          sym_sec = bfd_abs_section_ptr;
325        else if (isym.st_shndx == SHN_COMMON)        else if (isym->st_shndx == SHN_COMMON)
326          sym_sec = bfd_com_section_ptr;          sym_sec = bfd_com_section_ptr;
327        else        else
328          sym_sec = bfd_section_from_elf_index (abfd, isym.st_shndx);          sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
329    
330        return isym.st_value + BASEADDR (sym_sec);        return isym->st_value + BASEADDR (sym_sec);
331      }      }
332    else    else
333      {      {
# Line 303  symbol_value (abfd, symtab_hdr, extsyms, Line 346  symbol_value (abfd, symtab_hdr, extsyms,
346      }      }
347  }  }
348    
349    /* Returns the expected page state for the given instruction not including
350       the effect of page instructions.  */
351    
352    static bfd_vma
353    ip2k_nominal_page_bits (abfd, sec, addr, contents)
354         bfd *abfd ATTRIBUTE_UNUSED;
355         asection *sec;
356         bfd_vma addr;
357         bfd_byte *contents;
358    {
359      bfd_vma page = PAGENO (BASEADDR (sec) + addr);
360    
361      /* Check if section flows into this page. If not then the page
362         bits are assumed to match the PC. This will be true unless
363         the user has a page instruction without a call/jump, in which
364         case they are on their own.  */
365      if (PAGENO (BASEADDR (sec)) == page)
366        return page;
367    
368      /* Section flows across page boundary. The page bits should match
369         the PC unless there is a possible flow from the previous page,
370         in which case it is not possible to determine the value of the
371         page bits.  */
372      while (PAGENO (BASEADDR (sec) + addr - 2) == page)
373        {
374          bfd_byte code[2];
375    
376          addr -= 2;
377          ip2k_get_mem (abfd, contents + addr, 2, code);
378          if (!IS_PAGE_OPCODE (code))
379            continue;
380    
381          /* Found a page instruction, check if jump table.  */
382          if (ip2k_is_switch_table_128 (abfd, sec, addr, contents) != -1)
383            /* Jump table => page is conditional.  */
384            continue;
385    
386          if (ip2k_is_switch_table_256 (abfd, sec, addr, contents) != -1)
387            /* Jump table => page is conditional.  */
388            continue;
389    
390          /* Found a page instruction, check if conditional.  */
391          if (addr >= 2)
392            {
393              ip2k_get_mem (abfd, contents + addr - 2, 2, code);
394              if (IS_SKIP_OPCODE (code))
395                /* Page is conditional.  */
396                continue;
397            }
398    
399          /* Unconditional page instruction => page bits should be correct.  */
400          return page;
401        }
402    
403      /* Flow from previous page => page bits are impossible to determine.  */
404      return 0;
405    }
406    
407    static bfd_boolean
408    ip2k_test_page_insn (abfd, sec, irel, misc)
409         bfd *abfd ATTRIBUTE_UNUSED;
410         asection *sec;
411         Elf_Internal_Rela *irel;
412         struct misc *misc;
413    {
414      bfd_vma symval;
415    
416      /* Get the value of the symbol referred to by the reloc.  */
417      symval = symbol_value (abfd, misc->symtab_hdr, misc->isymbuf, irel);
418      if (symval == UNDEFINED_SYMBOL)
419        /* This appears to be a reference to an undefined
420           symbol.  Just ignore it--it will be caught by the
421           regular reloc processing.  */
422        return FALSE;
423    
424      /* Test if we can delete this page instruction.  */
425      if (PAGENO (symval + irel->r_addend) !=
426          ip2k_nominal_page_bits (abfd, sec, irel->r_offset, misc->contents))
427        return FALSE;
428    
429      return TRUE;
430    }
431    
432    static bfd_boolean
433    ip2k_delete_page_insn (abfd, sec, irel, again, misc)
434         bfd *abfd ATTRIBUTE_UNUSED;
435         asection *sec;
436         Elf_Internal_Rela *irel;
437         bfd_boolean *again;
438         struct misc *misc;
439    {
440      /* Note that we've changed the relocs, section contents, etc.  */
441      elf_section_data (sec)->relocs = misc->irelbase;
442      elf_section_data (sec)->this_hdr.contents = misc->contents;
443      misc->symtab_hdr->contents = (bfd_byte *) misc->isymbuf;
444    
445      /* Fix the relocation's type.  */
446      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_IP2K_NONE);
447    
448      /* Delete the PAGE insn.  */
449      if (!ip2k_elf_relax_delete_bytes (abfd, sec, irel->r_offset, 2))
450        return FALSE;
451            
452      /* Modified => will need to iterate relaxation again.  */
453      *again = TRUE;
454      
455      return TRUE;
456    }
457    
458  /* Determine if the instruction sequence matches that for  /* Determine if the instruction sequence matches that for
459     the prologue of a switch dispatch table with fewer than     the prologue of a switch dispatch table with fewer than
460     128 entries.     128 entries.
461    
462            sc            sc
463            page    $nnn0            page    $nnn0
464            jmp     $nnn0            jmp     $nnn0
# Line 320  symbol_value (abfd, symtab_hdr, extsyms, Line 472  symbol_value (abfd, symtab_hdr, extsyms,
472             ...             ...
473             page    $nnnN             page    $nnnN
474             jmp     $nnnN             jmp     $nnnN
475    
476    After relaxation.    After relaxation.
477             sc             sc
478             page    $nnn0             page    $nnn0
# Line 332  symbol_value (abfd, symtab_hdr, extsyms, Line 484  symbol_value (abfd, symtab_hdr, extsyms,
484             ...             ...
485            jmp     $nnnN  */            jmp     $nnnN  */
486    
487  static boolean  static int
488  is_switch_128_dispatch_table_p (abfd, addr, relaxed, misc)  ip2k_is_switch_table_128 (abfd, sec, addr, contents)
489       bfd *abfd ATTRIBUTE_UNUSED;                       bfd *abfd ATTRIBUTE_UNUSED;
490         asection *sec;
491       bfd_vma addr;       bfd_vma addr;
492       boolean relaxed;       bfd_byte *contents;
      struct misc *misc;  
493  {  {
494    bfd_byte code0, code1;    bfd_byte code[4];
495      int index = 0;
496      
497      /* Check current page-jmp.  */
498      if (addr + 4 > sec->size)
499        return -1;
500    
501      ip2k_get_mem (abfd, contents + addr, 4, code);
502    
503      if ((! IS_PAGE_OPCODE (code + 0))
504          || (! IS_JMP_OPCODE (code + 2)))
505        return -1;
506      
507      /* Search back.  */
508      while (1)
509        {
510          if (addr < 4)
511            return -1;
512    
513    if (addr < (3 * 2))        /* Check previous 2 instructions.  */
514      return false;        ip2k_get_mem (abfd, contents + addr - 4, 4, code);
515          if ((IS_ADD_W_WREG_OPCODE (code + 0))
516              && (IS_ADD_PCL_W_OPCODE (code + 2)))
517            return index;
518    
519          if ((! IS_PAGE_OPCODE (code + 0))
520              || (! IS_JMP_OPCODE (code + 2)))
521            return -1;
522    
523    code0 = bfd_get_8 (abfd, misc->contents + addr - 2);        index++;
524    code1 = bfd_get_8 (abfd, misc->contents + addr - 1);        addr -= 4;
525        }
526    }
527    
528    /* Is it ADD PCL,W */  static bfd_boolean
529    if (! IS_ADD_PCL_W_OPCODE (code0, code1))  ip2k_relax_switch_table_128 (abfd, sec, irel, again, misc)
530      return false;       bfd *abfd ATTRIBUTE_UNUSED;
531         asection *sec;
532         Elf_Internal_Rela *irel;
533         bfd_boolean *again;
534         struct misc *misc;
535    {
536      Elf_Internal_Rela *irelend = misc->irelbase + sec->reloc_count;
537      Elf_Internal_Rela *ireltest = irel;
538      bfd_byte code[4];
539      bfd_vma addr;
540      
541      /* Test all page instructions.  */
542      addr = irel->r_offset;
543      while (1)
544        {
545          if (addr + 4 > sec->size)
546            break;
547    
548          ip2k_get_mem (abfd, misc->contents + addr, 4, code);
549          if ((! IS_PAGE_OPCODE (code + 0))
550              || (! IS_JMP_OPCODE (code + 2)))
551            break;
552    
553          /* Validate relocation entry (every entry should have a matching
554              relocation entry).  */
555          if (ireltest >= irelend)
556            {
557              _bfd_error_handler (_("ip2k relaxer: switch table without complete matching relocation information."));
558              return FALSE;
559            }
560    
561          if (ireltest->r_offset != addr)
562            {
563              _bfd_error_handler (_("ip2k relaxer: switch table without complete matching relocation information."));
564              return FALSE;
565            }
566    
567    code0 = bfd_get_8 (abfd, misc->contents + addr - 4);        if (! ip2k_test_page_insn (abfd, sec, ireltest, misc))
568    code1 = bfd_get_8 (abfd, misc->contents + addr - 3);          /* Un-removable page insn => nothing can be done.  */
569            return TRUE;
570    
571    if (relaxed)        addr += 4;
572      /* Is it ADD W,WREG  */        ireltest += 2;
573      return ! IS_ADD_W_WREG_OPCODE (code0, code1);      }
574    
575    else    /* Relaxable. Adjust table header.  */
576      ip2k_get_mem (abfd, misc->contents + irel->r_offset - 4, 4, code);
577      if ((! IS_ADD_W_WREG_OPCODE (code + 0))
578          || (! IS_ADD_PCL_W_OPCODE (code + 2)))
579      {      {
580        /* Is it ADD W,WREG  */        _bfd_error_handler (_("ip2k relaxer: switch table header corrupt."));
581        if (! IS_ADD_W_WREG_OPCODE (code0, code1))        return FALSE;
582          return false;      }
583    
584      if (!ip2k_elf_relax_delete_bytes (abfd, sec, irel->r_offset - 4, 2))
585        return FALSE;
586    
587        code0 = bfd_get_8 (abfd, misc->contents + addr - 6);    *again = TRUE;
       code1 = bfd_get_8 (abfd, misc->contents + addr - 5);  
588    
589        /* Is it JMP $nnnn  */    /* Delete all page instructions in table.  */
590        if (! IS_JMP_OPCODE (code0, code1))    while (irel < ireltest)
591          return false;      {
592          if (!ip2k_delete_page_insn (abfd, sec, irel, again, misc))
593            return FALSE;
594          irel += 2;
595      }      }
596    
597    /* It looks like we've found the prologue for    return TRUE;
      a 1-127 entry switch dispatch table.  */  
   return true;  
598  }  }
599    
600  /* Determine if the instruction sequence matches that for  /* Determine if the instruction sequence matches that for
601     the prologue switch dispatch table with fewer than     the prologue switch dispatch table with fewer than
602     256 entries but more than 127.     256 entries but more than 127.
603    
604     Before relaxation.     Before relaxation.
605            push    %lo8insn(label) ; Push address of table            push    %lo8insn(label) ; Push address of table
606            push    %hi8insn(label)            push    %hi8insn(label)
# Line 401  is_switch_128_dispatch_table_p (abfd, ad Line 621  is_switch_128_dispatch_table_p (abfd, ad
621             ...             ...
622             page    $nnnN             page    $nnnN
623             jmp     $nnnN             jmp     $nnnN
624    
625    After relaxation.    After relaxation.
626            push    %lo8insn(label) ; Push address of table            push    %lo8insn(label) ; Push address of table
627            push    %hi8insn(label)            push    %hi8insn(label)
# Line 417  is_switch_128_dispatch_table_p (abfd, ad Line 637  is_switch_128_dispatch_table_p (abfd, ad
637            ...            ...
638            jmp     $nnnN  */            jmp     $nnnN  */
639    
640  static boolean  static int
641  is_switch_256_dispatch_table_p (abfd, addr, relaxed,  misc)  ip2k_is_switch_table_256 (abfd, sec, addr, contents)
642       bfd *abfd ATTRIBUTE_UNUSED;       bfd *abfd ATTRIBUTE_UNUSED;
      bfd_vma addr;  
      boolean relaxed;  
      struct misc *misc;  
 {  
   bfd_byte code0, code1;  
   
   if (addr < (8 * 2))  
     return false;  
   
   code0 = bfd_get_8 (abfd, misc->contents + addr - 2);  
   code1 = bfd_get_8 (abfd, misc->contents + addr - 1);  
   
   /* Is it INC 1(SP).  */  
   if (! IS_INC_1_SP_OPCODE (code0, code1))  
     return false;  
   
   code0 = bfd_get_8 (abfd, misc->contents + addr - 4);  
   code1 = bfd_get_8 (abfd, misc->contents + addr - 3);  
   
   /* Is it SNC.  */  
   if (! IS_SNC_OPCODE (code0, code1))  
     return false;  
   
   code0 = bfd_get_8 (abfd, misc->contents + addr - 6);  
   code1 = bfd_get_8 (abfd, misc->contents + addr - 5);  
   
   /* Is it ADD 2(SP),W.  */  
   if (! IS_ADD_2_SP_W_OPCODE (code0, code1))  
     return false;  
   
   code0 = bfd_get_8 (abfd, misc->contents + addr - 8);  
   code1 = bfd_get_8 (abfd, misc->contents + addr - 7);  
   
   if (relaxed)  
     /* Is it INC 1(SP).  */  
     return ! IS_INC_1_SP_OPCODE (code0, code1);  
   
   else  
     {  
       /* Is it INC 1(SP).  */  
       if (! IS_INC_1_SP_OPCODE (code0, code1))  
         return false;  
   
       code0 = bfd_get_8 (abfd, misc->contents + addr - 10);  
       code1 = bfd_get_8 (abfd, misc->contents + addr - 9);  
   
       /* Is it SNC.  */  
       if (! IS_SNC_OPCODE (code0, code1))  
         return false;  
   
       code0 = bfd_get_8 (abfd, misc->contents + addr - 12);  
       code1 = bfd_get_8 (abfd, misc->contents + addr - 11);  
   
       /* Is it ADD W,WREG.  */  
       if (! IS_ADD_W_WREG_OPCODE (code0, code1))  
         return false;  
     }  
   
   /* It looks like we've found the prologue for  
      a 128-255 entry switch dispatch table.  */  
   return true;  
 }  
   
 static boolean  
 relax_switch_dispatch_tables_pass1 (abfd, sec, addr, misc)  
      bfd *abfd;  
643       asection *sec;       asection *sec;
644       bfd_vma addr;       bfd_vma addr;
645       struct misc *misc;       bfd_byte *contents;
646  {  {
647    if (addr + 3 < sec->_cooked_size)    bfd_byte code[16];
648      int index = 0;
649      
650      /* Check current page-jmp.  */
651      if (addr + 4 > sec->size)
652        return -1;
653    
654      ip2k_get_mem (abfd, contents + addr, 4, code);
655      if ((! IS_PAGE_OPCODE (code + 0))
656          || (! IS_JMP_OPCODE (code + 2)))
657        return -1;
658      
659      /* Search back.  */
660      while (1)
661      {      {
662        bfd_byte code0 = bfd_get_8 (abfd, misc->contents + addr + 2);        if (addr < 16)
663        bfd_byte code1 = bfd_get_8 (abfd, misc->contents + addr + 3);          return -1;
664    
665        if (IS_JMP_OPCODE (code0, code1)        /* Check previous 8 instructions.  */
666            && is_switch_128_dispatch_table_p (abfd, addr, false, misc))        ip2k_get_mem (abfd, contents + addr - 16, 16, code);
667          {        if ((IS_ADD_W_WREG_OPCODE (code + 0))
668            /* Delete ADD W,WREG from prologue.  */            && (IS_SNC_OPCODE (code + 2))
669            ip2k_elf_relax_delete_bytes (abfd, sec, addr - (2 * 2), (1 * 2));            && (IS_INC_1SP_OPCODE (code + 4))
670            return true;            && (IS_ADD_2SP_W_OPCODE (code + 6))
671          }            && (IS_SNC_OPCODE (code + 8))
672              && (IS_INC_1SP_OPCODE (code + 10))
673              && (IS_PAGE_OPCODE (code + 12))
674              && (IS_JMP_OPCODE (code + 14)))
675            return index;
676    
677          if ((IS_ADD_W_WREG_OPCODE (code + 2))
678              && (IS_SNC_OPCODE (code + 4))
679              && (IS_INC_1SP_OPCODE (code + 6))
680              && (IS_ADD_2SP_W_OPCODE (code + 8))
681              && (IS_SNC_OPCODE (code + 10))
682              && (IS_INC_1SP_OPCODE (code + 12))
683              && (IS_JMP_OPCODE (code + 14)))
684            return index;
685          
686          if ((! IS_PAGE_OPCODE (code + 0))
687              || (! IS_JMP_OPCODE (code + 2)))
688            return -1;
689    
690        if (IS_JMP_OPCODE (code0, code1)        index++;
691            && is_switch_256_dispatch_table_p (abfd, addr, false, misc))        addr -= 4;
         {  
           /* Delete ADD W,WREG; SNC ; INC 1(SP) from prologue.  */  
           ip2k_elf_relax_delete_bytes (abfd, sec, addr - 6 * 2, 3 * 2);  
           return true;  
         }  
692      }      }
   
   return true;  
693  }  }
694    
695  static boolean  static bfd_boolean
696  unrelax_dispatch_table_entries (abfd, sec, first, last, changed, misc)  ip2k_relax_switch_table_256 (abfd, sec, irel, again, misc)
697       bfd *abfd;       bfd *abfd ATTRIBUTE_UNUSED;
698       asection *sec;       asection *sec;
699       bfd_vma first;       Elf_Internal_Rela *irel;
700       bfd_vma last;       bfd_boolean *again;
      boolean *changed;  
701       struct misc *misc;       struct misc *misc;
702  {  {
703    bfd_vma addr = first;    Elf_Internal_Rela *irelend = misc->irelbase + sec->reloc_count;
704      Elf_Internal_Rela *ireltest = irel;
705      bfd_byte code[12];
706      bfd_vma addr;
707      
708      /* Test all page instructions.  */
709      addr = irel->r_offset;
710    
711    while (addr < last)    while (1)
712      {      {
713        bfd_byte code0 = bfd_get_8 (abfd, misc->contents + addr);        if (addr + 4 > sec->size)
714        bfd_byte code1 = bfd_get_8 (abfd, misc->contents + addr + 1);          break;
715    
716        /* We are only expecting to find PAGE or JMP insns        ip2k_get_mem (abfd, misc->contents + addr, 4, code);
          in the dispatch table. If we find anything else  
          something has gone wrong failed the relaxation  
          which will cause the link to be aborted.  */  
   
       if (IS_PAGE_OPCODE (code0, code1))  
         /* Skip the PAGE and JMP insns.  */  
         addr += 4;  
       else if (IS_JMP_OPCODE (code0, code1))  
          {  
             Elf_Internal_Rela * irelend = misc->irelbase  
                                           + sec->reloc_count;  
             Elf_Internal_Rela * irel;  
   
             /* Find the relocation entry.  */  
             for (irel = misc->irelbase; irel < irelend; irel++)  
                {  
                   if (irel->r_offset == addr  
                       && ELF32_R_TYPE (irel->r_info) == R_IP2K_ADDR16CJP)  
                     {  
                       if (! add_page_insn (abfd, sec, irel, misc))  
                         /* Something has gone wrong.  */  
                         return false;  
   
                       *changed = true;  
                       break;  
                     }  
                }  
   
             /* If we fell off the end something has gone wrong.  */  
             if (irel >= irelend)  
               /* Something has gone wrong.  */  
               return false;  
   
             /* Skip the PAGE and JMP isns.  */  
             addr += 4;  
             /* Acount for the new PAGE insn.  */  
             last += 2;  
           }  
        else  
          /* Something has gone wrong.  */  
          return false;  
     }  
   
   return true;  
 }  
   
 static boolean  
 unrelax_switch_dispatch_tables_passN (abfd, sec, addr, changed, misc)  
      bfd *abfd;  
      asection *sec;  
      bfd_vma addr;  
      boolean *changed;  
      struct misc *misc;  
 {  
   if (2 <= addr && (addr + 3) < sec->_cooked_size)  
     {  
       bfd_byte code0 = bfd_get_8 (abfd, misc->contents + addr - 2);  
       bfd_byte code1 = bfd_get_8 (abfd, misc->contents + addr - 1);  
717    
718        if (IS_PAGE_OPCODE (code0, code1))        if ((! IS_PAGE_OPCODE (code + 0))
719          {            || (! IS_JMP_OPCODE (code + 2)))
720            addr -= 2;          break;
           code0 = bfd_get_8 (abfd, misc->contents + addr + 2);  
           code1 = bfd_get_8 (abfd, misc->contents + addr + 3);  
         }  
       else  
         {  
           code0 = bfd_get_8 (abfd, misc->contents + addr);  
           code1 = bfd_get_8 (abfd, misc->contents + addr + 1);  
         }  
721    
722        if (IS_JMP_OPCODE (code0, code1)        /* Validate relocation entry (every entry should have a matching
723            && is_switch_128_dispatch_table_p (abfd, addr, true, misc))            relocation entry).  */
724          if (ireltest >= irelend)
725          {          {
726            bfd_vma first = addr;            _bfd_error_handler (_("ip2k relaxer: switch table without complete matching relocation information."));
727            bfd_vma last  = first;            return FALSE;
           boolean relaxed = true;  
   
           /* On the final pass we must check if *all* entries in the  
              dispatch table are relaxed. If *any* are not relaxed  
              then we must unrelax *all* the entries in the dispach  
              table and also unrelax the dispatch table prologue.  */  
   
           /* Find the last entry in the dispach table.  */  
           while (last < sec->_cooked_size)  
              {  
                 code0 = bfd_get_8 (abfd, misc->contents + last);  
                 code1 = bfd_get_8 (abfd, misc->contents + last + 1);  
   
                 if (IS_PAGE_OPCODE (code0, code1))  
                   relaxed = false;  
                 else if (! IS_JMP_OPCODE (code0, code1))  
                     break;  
   
                 last += 2;  
              }  
   
           /* We should have found the end of the dispatch table  
              before reaching the end of the section. If we've have  
              reached the end then fail the relaxation which will  
              cause the link to be aborted.  */  
           if (last >= sec->_cooked_size)  
             /* Something has gone wrong.  */  
             return false;  
   
           /* If we found an unrelaxed entry then  
              unlrelax all the switch table entries.  */  
           if (! relaxed )  
             {  
               if (! unrelax_dispatch_table_entries (abfd, sec, first,  
                                                     last, changed, misc))  
                 /* Something has gone wrong.  */  
                 return false;  
   
               if (! is_switch_128_dispatch_table_p (abfd, addr, true, misc))  
                 /* Something has gone wrong.  */  
                 return false;  
                   
               /* Unrelax the prologue.  */  
   
               /* Insert an ADD W,WREG insnstruction.  */  
               if (! ip2k_elf_relax_add_bytes (abfd, sec,  
                                               addr - 2,  
                                               add_w_wreg_opcode,  
                                               sizeof (add_w_wreg_opcode),  
                                               0))  
                 /* Something has gone wrong.  */  
                 return false;  
             }  
   
           return true;  
728          }          }
729    
730        if (IS_JMP_OPCODE (code0, code1)        if (ireltest->r_offset != addr)
           && is_switch_256_dispatch_table_p (abfd, addr, true, misc))  
731          {          {
732            bfd_vma first = addr;            _bfd_error_handler (_("ip2k relaxer: switch table without complete matching relocation information."));
733            bfd_vma last;            return FALSE;
734            boolean relaxed = true;          }
   
           /* On the final pass we must check if *all* entries in the  
              dispatch table are relaxed. If *any* are not relaxed  
              then we must unrelax *all* the entries in the dispach  
              table and also unrelax the dispatch table prologue.  */  
735    
736            /* Note the 1st PAGE/JMP instructions are part of the        if (!ip2k_test_page_insn (abfd, sec, ireltest, misc))
737               prologue and can safely be relaxed.  */          /* Un-removable page insn => nothing can be done.  */
738            return TRUE;
739    
740          addr += 4;
741          ireltest += 2;
742        }
743    
744            code0 = bfd_get_8 (abfd, misc->contents + first);    /* Relaxable. Adjust table header.  */
745            code1 = bfd_get_8 (abfd, misc->contents + first + 1);    ip2k_get_mem (abfd, misc->contents + irel->r_offset - 4, 2, code);
746      if (IS_PAGE_OPCODE (code))
747        addr = irel->r_offset - 16;
748      else
749        addr = irel->r_offset - 14;
750    
751            if (IS_PAGE_OPCODE (code0, code1))    ip2k_get_mem (abfd, misc->contents + addr, 12, code);
752              {    if ((!IS_ADD_W_WREG_OPCODE (code + 0))
753                first += 2;        || (!IS_SNC_OPCODE (code + 2))
754                code0 = bfd_get_8 (abfd, misc->contents + first);        || (!IS_INC_1SP_OPCODE (code + 4))
755                code1 = bfd_get_8 (abfd, misc->contents + first + 1);        || (!IS_ADD_2SP_W_OPCODE (code + 6))
756              }        || (!IS_SNC_OPCODE (code + 8))
757          || (!IS_INC_1SP_OPCODE (code + 10)))
758        {
759          _bfd_error_handler (_("ip2k relaxer: switch table header corrupt."));
760          return FALSE;
761        }
762    
763            if (! IS_JMP_OPCODE (code0, code1))    /* Delete first 3 opcodes.  */
764              /* Something has gone wrong.  */    if (!ip2k_elf_relax_delete_bytes (abfd, sec, addr + 0, 6))
765              return false;      return FALSE;
   
           first += 2;  
           last = first;  
   
           /* Find the last entry in the dispach table.  */  
           while (last < sec->_cooked_size)  
              {  
                 code0 = bfd_get_8 (abfd, misc->contents + last);  
                 code1 = bfd_get_8 (abfd, misc->contents + last + 1);  
   
                 if (IS_PAGE_OPCODE (code0, code1))  
                   relaxed = false;  
                 else if (! IS_JMP_OPCODE (code0, code1))  
                     break;  
   
                 last += 2;  
              }  
   
           /* We should have found the end of the dispatch table  
              before reaching the end of the section. If we have  
              reached the end of the section then fail the  
              relaxation.  */  
           if (last >= sec->_cooked_size)  
             return false;  
   
           /* If we found an unrelaxed entry then  
               unrelax all the switch table entries.  */  
           if (! relaxed)  
             {  
               if (! unrelax_dispatch_table_entries (abfd, sec, first,  
                                                     last, changed, misc))  
                 return false;  
   
               if (! is_switch_256_dispatch_table_p (abfd, addr, true, misc))  
                 return false;  
   
               /* Unrelax the prologue.  */  
   
               /* Insert an INC 1(SP) insnstruction.  */  
               if (! ip2k_elf_relax_add_bytes (abfd, sec,  
                                               addr - 6,  
                                               inc_1_sp_opcode,  
                                               sizeof (inc_1_sp_opcode),  
                                               0))  
                 return false;  
   
               /* Insert an SNC insnstruction.  */  
               if (! ip2k_elf_relax_add_bytes (abfd, sec,  
                                               addr - 6,  
                                               snc_opcode,  
                                               sizeof (snc_opcode),  
                                               0))  
                 return false;  
   
               /* Insert an ADD W,WREG insnstruction.  */  
               if (! ip2k_elf_relax_add_bytes (abfd, sec,  
                                              addr - 6,  
                                              add_w_wreg_opcode,  
                                              sizeof (add_w_wreg_opcode),  
                                              0))  
                 return false;  
             }  
766    
767            return true;    *again = TRUE;
768          }  
769      /* Delete all page instructions in table.  */
770      while (irel < ireltest)
771        {
772          if (!ip2k_delete_page_insn (abfd, sec, irel, again, misc))
773            return FALSE;
774          irel += 2;
775      }      }
776    
777    return true;    return TRUE;
778  }  }
779    
780  /* This function handles relaxing for the ip2k.  */  /* This function handles relaxing for the ip2k.
781    
782       Principle: Start with the first page and remove page instructions that
783       are not require on this first page. By removing page instructions more
784       code will fit into this page - repeat until nothing more can be achieved
785       for this page. Move on to the next page.
786    
787  static boolean     Processing the pages one at a time from the lowest page allows a removal
788       only policy to be used - pages can be removed but are never reinserted.  */
789    
790    static bfd_boolean
791  ip2k_elf_relax_section (abfd, sec, link_info, again)  ip2k_elf_relax_section (abfd, sec, link_info, again)
792       bfd *abfd;       bfd *abfd;
793       asection *sec;       asection *sec;
794       struct bfd_link_info *link_info;       struct bfd_link_info *link_info;
795       boolean *again;       bfd_boolean *again;
796  {  {
797    Elf_External_Sym_Shndx *shndx_buf;    Elf_Internal_Shdr *symtab_hdr;
798    Elf_Internal_Shdr *shndx_hdr;    Elf_Internal_Rela *internal_relocs;
799      bfd_byte *contents = NULL;
800      Elf_Internal_Sym *isymbuf = NULL;
801    static asection * first_section = NULL;    static asection * first_section = NULL;
802    static asection * last_section = NULL;    static unsigned long search_addr;
803    static boolean changed = false;    static unsigned long page_start = 0;
804    static boolean final_pass = false;    static unsigned long page_end = 0;
805    static unsigned int pass = 0;    static unsigned int pass = 0;
806      static bfd_boolean new_pass = FALSE;
807      static bfd_boolean changed = FALSE;
808    struct misc misc;    struct misc misc;
809    asection *stab;    asection *stab;
810    
811    /* Assume nothing changes.  */    /* Assume nothing changes.  */
812    *again = false;    *again = FALSE;
813    
814    if (first_section == NULL)    if (first_section == NULL)
815      first_section = sec;      {
816          ip2k_relaxed = TRUE;
817          first_section = sec;
818        }
819    
820    if (first_section == sec)    if (first_section == sec)
821      {      {
       changed = false;  
822        pass++;        pass++;
823          new_pass = TRUE;
824      }      }
825    
   /* If we make too many passes then it's a sign that  
      something is wrong and we fail the relaxation.  
      Note if everything is working correctly then the  
      relaxation should converge reasonably quickly.  */  
   if (pass == 4096)  
     return false;  
   
826    /* We don't have to do anything for a relocatable link,    /* We don't have to do anything for a relocatable link,
827       if this section does not have relocs, or if this is       if this section does not have relocs, or if this is
828       not a code section.  */       not a code section.  */
829    if (link_info->relocateable    if (link_info->relocatable
830        || (sec->flags & SEC_RELOC) == 0        || (sec->flags & SEC_RELOC) == 0
831        || sec->reloc_count == 0        || sec->reloc_count == 0
832        || (sec->flags & SEC_CODE) == 0)        || (sec->flags & SEC_CODE) == 0)
833      return true;      return TRUE;
   
   if (pass == 1)  
     last_section = sec;  
834    
835    misc.symtab_hdr = NULL;    symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   misc.irelbase = NULL;  
   misc.contents = NULL;  
   misc.free_contents = NULL;  
   misc.extsyms = NULL;  
   misc.free_extsyms = NULL;  
   misc.free_relocs = NULL;  
   
   /* If this is the first time we have been called  
       for this section, initialise the cooked size.  */  
   if (sec->_cooked_size == 0)  
     sec->_cooked_size = sec->_raw_size;  
   
   misc.symtab_hdr = &elf_tdata (abfd)->symtab_hdr;  
   shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;  
   
   misc.irelbase = _bfd_elf32_link_read_relocs (abfd, sec, NULL,  
                                              (Elf_Internal_Rela *)NULL,  
                                              link_info->keep_memory);  
   if (misc.irelbase == NULL)  
     {  
       tidyup_after_error (&misc);  
       return false;  
     }  
836    
837    if (! link_info->keep_memory)    internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL,
838      misc.free_relocs = misc.irelbase;                                                 (Elf_Internal_Rela *)NULL,
839                                                   link_info->keep_memory);
840      if (internal_relocs == NULL)
841        goto error_return;
842    
843    /* Make sure the stac.rela stuff gets read in.  */    /* Make sure the stac.rela stuff gets read in.  */
844    stab = bfd_get_section_by_name (abfd, ".stab");    stab = bfd_get_section_by_name (abfd, ".stab");
# Line 849  ip2k_elf_relax_section (abfd, sec, link_ Line 848  ip2k_elf_relax_section (abfd, sec, link_
848        /* So stab does exits.  */        /* So stab does exits.  */
849        Elf_Internal_Rela * irelbase;        Elf_Internal_Rela * irelbase;
850    
851        irelbase = _bfd_elf32_link_read_relocs (abfd, stab, NULL,        irelbase = _bfd_elf_link_read_relocs (abfd, stab, NULL,
852                                                (Elf_Internal_Rela *)NULL,                                              (Elf_Internal_Rela *)NULL,
853                                                link_info->keep_memory);                                              link_info->keep_memory);
854      }      }
855    
856    /* Get section contents cached copy if it exists.  */    /* Get section contents cached copy if it exists.  */
857    if (elf_section_data (sec)->this_hdr.contents != NULL)    if (contents == NULL)
     misc.contents = elf_section_data (sec)->this_hdr.contents;  
   else  
858      {      {
859        /* Go get them of disk.  */        /* Get cached copy if it exists.  */
860        misc.contents = (bfd_byte *) bfd_malloc (sec->_raw_size);        if (elf_section_data (sec)->this_hdr.contents != NULL)
861        if (misc.contents == NULL)          contents = elf_section_data (sec)->this_hdr.contents;
862          {        else
           tidyup_after_error (&misc);  
           return false;  
         }  
   
       misc.free_contents = misc.contents;  
       if (! bfd_get_section_contents (abfd, sec, misc.contents,  
                                       (file_ptr)0,  
                                       sec->_raw_size))  
863          {          {
864            tidyup_after_error (&misc);            /* Go get them off disk.  */
865            return false;            if (!bfd_malloc_and_get_section (abfd, sec, &contents))
866                goto error_return;
867          }          }
868      }      }
869      
870    /* Read this BFD's symbols cached copy if it exists.  */    /* Read this BFD's symbols cached copy if it exists.  */
871    if (misc.symtab_hdr->contents != NULL)    if (isymbuf == NULL && symtab_hdr->sh_info != 0)
     misc.extsyms = (Elf32_External_Sym *) misc.symtab_hdr->contents;  
   else  
872      {      {
873        /* Go get them off disk.  */        isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
874        misc.extsyms = ((Elf32_External_Sym *)bfd_malloc (misc.symtab_hdr->sh_size));        if (isymbuf == NULL)
875        if (misc.extsyms == NULL)          isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
876          {                                          symtab_hdr->sh_info, 0,
877            tidyup_after_error (&misc);                                          NULL, NULL, NULL);
878            return false;        if (isymbuf == NULL)
879          }          goto error_return;
   
       misc.free_extsyms = misc.extsyms;  
       if (bfd_seek (abfd, misc.symtab_hdr->sh_offset, SEEK_SET) != 0  
           || (bfd_read (misc.extsyms, 1, misc.symtab_hdr->sh_size, abfd)  
           != misc.symtab_hdr->sh_size))  
         {  
           tidyup_after_error (&misc);  
           return false;  
         }  
880      }      }
881    
882    if (shndx_hdr->sh_size != 0)    misc.symtab_hdr = symtab_hdr;
883      {    misc.isymbuf = isymbuf;
884        bfd_size_type amt;    misc.irelbase = internal_relocs;
885      misc.contents = contents;
       amt = misc.symtab_hdr->sh_info * sizeof (Elf_External_Sym_Shndx);  
       shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);  
       if (shndx_buf == NULL)  
         {  
           tidyup_after_error (&misc);  
           return false;  
         }  
       if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0  
           || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt)  
         {  
           tidyup_after_error (&misc);  
           return false;  
         }  
       shndx_hdr->contents = (PTR) shndx_buf;  
     }  
886    
887    /* This is where all the relaxation actually get done.  */    /* This is where all the relaxation actually get done.  */
888      if ((pass == 1) || (new_pass && !changed))
   if (pass == 1)  
889      {      {
890        /* On the first pass we remove *all* page instructions and        /* On the first pass we simply search for the lowest page that
891           relax the prolog for switch dispatch tables. This gets           we havn't relaxed yet. Note that the pass count is reset
892           us to the starting point for subsequent passes where           each time a page is complete in order to move on to the next page.
893           we add page instructions back in as needed.  */           If we can't find any more pages then we are finished.  */
894          if (new_pass)
895            {
896              pass = 1;
897              new_pass = FALSE;
898              changed = TRUE; /* Pre-initialize to break out of pass 1.  */
899              search_addr = 0xFFFFFFFF;
900            }
901    
902        if (! ip2k_elf_relax_section_pass1 (abfd, sec, again, &misc))        if ((BASEADDR (sec) + sec->size < search_addr)
903          {            && (BASEADDR (sec) + sec->size > page_end))
904            tidyup_after_error (&misc);          {
905            return false;            if (BASEADDR (sec) <= page_end)
906          }              search_addr = page_end + 1;
907              else
908                search_addr = BASEADDR (sec);
909    
910        changed |= *again;            /* Found a page => more work to do.  */
911              *again = TRUE;
912            }
913      }      }
914    else    else
915      {      {
916        /* Add page instructions back in as needed but we ignore        if (new_pass)
          the issue with sections (functions) crossing a page  
          boundary until we have converged to an approximate  
          solution (i.e. nothing has changed on this relaxation  
          pass) and we then know roughly where the page boundaries  
          will end up.  
   
          After we have have converged to an approximate solution  
          we set the final pass flag and continue relaxing. On these  
          final passes if a section (function) cross page boundary  
          we will add *all* the page instructions back into such  
          sections.  
   
          After adding *all* page instructions back into a section  
          which crosses a page bounbdary we reset the final pass flag  
          so the we will again interate until we find a new approximate  
          solution which is closer to the final solution.  */  
   
       if (! ip2k_elf_relax_section_passN (abfd, sec, again,  
                                          &final_pass,  &misc))  
917          {          {
918            tidyup_after_error (&misc);            new_pass = FALSE;
919            return false;            changed = FALSE;
920              page_start = PAGENO (search_addr);
921              page_end = page_start | 0x00003FFF;
922          }          }
923    
924        changed |= *again;        /* Only process sections in range.  */
925          if ((BASEADDR (sec) + sec->size >= page_start)
926        /* If nothing has changed on this relaxation            && (BASEADDR (sec) <= page_end))
           pass restart the final relaxaton pass.  */  
       if (! changed && last_section == sec)  
927          {          {
928            /* If this was the final pass and we didn't reset            if (!ip2k_elf_relax_section_page (abfd, sec, &changed, &misc, page_start, page_end))
929               the final pass flag then we are done, otherwise              return FALSE;
              do another final pass.  */  
           if (! final_pass)  
             {  
               final_pass = true;  
               *again = true;  
             }  
930          }          }
931          *again = TRUE;
932      }      }
933    
934    /* Perform some house keeping after relaxing the section.  */      /* Perform some house keeping after relaxing the section.  */
935    
936    if (misc.free_relocs != NULL)    if (isymbuf != NULL
937      {        && symtab_hdr->contents != (unsigned char *) isymbuf)
       free (misc.free_relocs);  
       misc.free_relocs = NULL;  
     }  
   
   if (misc.free_contents != NULL)  
938      {      {
939        if (! link_info->keep_memory)        if (! link_info->keep_memory)
940          free (misc.free_contents);          free (isymbuf);
941        else        else
942          {          symtab_hdr->contents = (unsigned char *) isymbuf;
           /* Cache the section contents for elf_link_input_bfd.  */  
           elf_section_data (sec)->this_hdr.contents = misc.contents;  
         }  
   
       misc.free_contents = NULL;  
943      }      }
944    
945    if (misc.free_extsyms != NULL)    if (contents != NULL
946          && elf_section_data (sec)->this_hdr.contents != contents)
947      {      {
948        if (! link_info->keep_memory)        if (! link_info->keep_memory)
949          free (misc.free_extsyms);          free (contents);
950        else        else
951          {          {
952            /* Cache the symbols for elf_link_input_bfd.  */            /* Cache the section contents for elf_link_input_bfd.  */
953            misc.symtab_hdr->contents = misc.extsyms;            elf_section_data (sec)->this_hdr.contents = contents;
954          }          }
   
       misc.free_extsyms = NULL;  
955      }      }
956    
957    return true;    if (internal_relocs != NULL
958          && elf_section_data (sec)->relocs != internal_relocs)
959        free (internal_relocs);
960    
961      return TRUE;
962    
963     error_return:
964      if (isymbuf != NULL
965          && symtab_hdr->contents != (unsigned char *) isymbuf)
966        free (isymbuf);
967      if (contents != NULL
968          && elf_section_data (sec)->this_hdr.contents != contents)
969        free (contents);
970      if (internal_relocs != NULL
971          && elf_section_data (sec)->relocs != internal_relocs)
972        free (internal_relocs);
973      return FALSE;
974  }  }
975    
976  static void  /* This function handles relaxation of a section in a specific page.  */
 tidyup_after_error (misc)  
      struct misc *misc;  
 {  
   if (misc->free_relocs != NULL)  
     {  
       free (misc->free_relocs);  
       misc->free_relocs = NULL;  
     }  
   
   if (misc->free_contents != NULL)  
     {  
       free (misc->free_contents);  
       misc->free_contents = NULL;  
     }  
   
   if (misc->free_extsyms != NULL)  
     {  
       free (misc->free_extsyms);  
       misc->free_extsyms = NULL;  
     }  
   
   return;  
 }  
977    
978  /* This function handles relaxation during the first pass.  */  static bfd_boolean
979    ip2k_elf_relax_section_page (abfd, sec, again, misc, page_start, page_end)
 static boolean  
 ip2k_elf_relax_section_pass1 (abfd, sec, again, misc)  
980       bfd *abfd;       bfd *abfd;
981       asection *sec;       asection *sec;
982       boolean *again;       bfd_boolean *again;
983       struct misc * misc;       struct misc *misc;
984         unsigned long page_start;
985         unsigned long page_end;
986  {  {
987    Elf_Internal_Rela *irelend = misc->irelbase + sec->reloc_count;    Elf_Internal_Rela *irelend = misc->irelbase + sec->reloc_count;
988    Elf_Internal_Rela *irel;    Elf_Internal_Rela *irel;
989      int switch_table_128;
990    /* Walk thru the section looking for relaxation opertunities.  */    int switch_table_256;
991      
992      /* Walk thru the section looking for relaxation opportunities.  */
993    for (irel = misc->irelbase; irel < irelend; irel++)    for (irel = misc->irelbase; irel < irelend; irel++)
994      {      {
995        if (ELF32_R_TYPE (irel->r_info) == (int) R_IP2K_PAGE3)        if (ELF32_R_TYPE (irel->r_info) != (int) R_IP2K_PAGE3)
996        {          /* Ignore non page instructions.  */
997          bfd_byte code0 = bfd_get_8 (abfd,          continue;
998                                      misc->contents + irel->r_offset);  
999          bfd_byte code1 = bfd_get_8 (abfd,        if (BASEADDR (sec) + irel->r_offset < page_start)
1000                                      misc->contents + irel->r_offset + 1);          /* Ignore page instructions on earlier page - they have
1001               already been processed. Remember that there is code flow
1002          /* Verify that this is the PAGE opcode.  */             that crosses a page boundary.  */
1003          if (IS_PAGE_OPCODE (code0, code1))          continue;
1004            {  
1005              /* Note that we've changed the relocs, section contents, etc.  */        if (BASEADDR (sec) + irel->r_offset > page_end)
1006              elf_section_data (sec)->relocs = misc->irelbase;          /* Flow beyond end of page => nothing more to do for this page.  */
1007              misc->free_relocs = NULL;          return TRUE;
1008    
1009              elf_section_data (sec)->this_hdr.contents = misc->contents;        /* Detect switch tables.  */
1010              misc->free_contents = NULL;        switch_table_128 = ip2k_is_switch_table_128 (abfd, sec, irel->r_offset, misc->contents);
1011          switch_table_256 = ip2k_is_switch_table_256 (abfd, sec, irel->r_offset, misc->contents);
1012              misc->symtab_hdr->contents = (bfd_byte *) misc->extsyms;  
1013              misc->free_extsyms = NULL;        if ((switch_table_128 > 0) || (switch_table_256 > 0))
1014            /* If the index is greater than 0 then it has already been processed.  */
1015              /* Handle switch dispatch tables/prologues.  */          continue;
             if (!  relax_switch_dispatch_tables_pass1 (abfd, sec,  
                                                        irel->r_offset, misc))  
               return false;  
               
             /* Fix the relocation's type.  */  
             irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),  
                                          R_IP2K_NONE);  
   
             /* Delete the PAGE insn.  */  
             if (! ip2k_elf_relax_delete_bytes (abfd, sec,  
                                                irel->r_offset,  
                                                sizeof (page_opcode)))  
               return false;  
   
             /* That will change things, so, we should relax again.  
                Note that this is not required, and it may be slow.  */  
             *again = true;  
           }  
       }  
     }  
   
   return true;  
 }  
1016    
1017  /* This function handles relaxation for 2nd and subsequent passes.  */        if (switch_table_128 == 0)
1018            {
1019              if (!ip2k_relax_switch_table_128 (abfd, sec, irel, again, misc))
1020                return FALSE;
1021    
1022  static boolean            continue;
1023  ip2k_elf_relax_section_passN (abfd, sec, again, final_pass, misc)          }
      bfd *abfd;  
      asection *sec;  
      boolean *again;  
      boolean *final_pass;  
      struct misc * misc;  
 {  
   Elf_Internal_Rela *irelend = misc->irelbase + sec->reloc_count;  
   Elf_Internal_Rela *irel;  
   boolean add_all;  
1024    
1025    /* If we are on the final relaxation pass and the section crosses        if (switch_table_256 == 0)
      then set a flag to indicate that *all* page instructions need  
      to be added back into this section.  */  
   if (*final_pass)  
     {  
       add_all = (PAGENO (BASEADDR (sec))  
                  != PAGENO (BASEADDR (sec) + sec->_cooked_size));  
   
       /* If this section crosses a page boundary set the crossed  
          page boundary flag.  */  
       if (add_all)  
         sec->userdata = sec;  
       else  
1026          {          {
1027            /* If the section had previously crossed a page boundary            if (!ip2k_relax_switch_table_256 (abfd, sec, irel, again, misc))
1028               but on this pass does not then reset crossed page              return FALSE;
1029               boundary flag and rerun the 1st relaxation pass on  
1030               this section.  */            continue;
           if (sec->userdata)  
             {  
               sec->userdata = NULL;  
               if (! ip2k_elf_relax_section_pass1 (abfd, sec, again, misc))  
                 return false;  
             }  
1031          }          }
     }  
   else  
     add_all = false;  
1032    
1033    /* Walk thru the section looking for call/jmp        /* Simple relax.  */
1034        instructions which need a page instruction.  */        if (ip2k_test_page_insn (abfd, sec, irel, misc))
1035    for (irel = misc->irelbase; irel < irelend; irel++)          {
1036      {            if (!ip2k_delete_page_insn (abfd, sec, irel, again, misc))
1037        if (ELF32_R_TYPE (irel->r_info) == (int) R_IP2K_ADDR16CJP)              return FALSE;
       {  
         /* Get the value of the symbol referred to by the reloc.  */  
         bfd_vma symval = symbol_value (abfd, misc->symtab_hdr, misc->extsyms,  
                                        irel);  
         bfd_byte code0, code1;  
   
         if (symval == UNDEFINED_SYMBOL)  
           {  
             /* This appears to be a reference to an undefined  
                symbol.  Just ignore it--it will be caught by the  
                regular reloc processing.  */  
             continue;  
           }  
1038    
1039          /* For simplicity of coding, we are going to modify the section            continue;
1040             contents, the section relocs, and the BFD symbol table.  We          }
            must tell the rest of the code not to free up this  
            information.  It would be possible to instead create a table  
            of changes which have to be made, as is done in coff-mips.c;  
            that would be more work, but would require less memory when  
            the linker is run.  */  
   
         /* Get the opcode.  */  
         code0 = bfd_get_8 (abfd, misc->contents + irel->r_offset);  
         code1 = bfd_get_8 (abfd, misc->contents + irel->r_offset + 1);  
   
         if (IS_JMP_OPCODE (code0, code1) || IS_CALL_OPCODE (code0, code1))  
           {  
             if (*final_pass)  
               {  
                 if (! unrelax_switch_dispatch_tables_passN (abfd, sec,  
                                                             irel->r_offset,  
                                                             again, misc))  
                   return false;  
   
                 if (*again)  
                   add_all = false;  
               }  
   
             code0 = bfd_get_8 (abfd, misc->contents + irel->r_offset - 2);  
             code1 = bfd_get_8 (abfd, misc->contents + irel->r_offset - 1);  
   
             if (! IS_PAGE_OPCODE (code0, code1))  
               {  
                 bfd_vma value = symval + irel->r_addend;  
                 bfd_vma addr  = BASEADDR (sec) + irel->r_offset;  
   
                 if (add_all || PAGENO (addr) != PAGENO (value))  
                   {  
                     if (! add_page_insn (abfd, sec, irel, misc))  
                       return false;  
   
                     /* That will have changed things, so,  we must relax again.  */  
                     *again = true;  
                   }  
                }  
            }  
         }  
1041      }      }
         
   /* If anything changed reset the final pass flag.  */  
   if (*again)  
     *final_pass = false;  
1042    
1043    return true;    return TRUE;
1044  }  }
1045    
1046  /* Parts of a Stabs entry.  */  /* Parts of a Stabs entry.  */
# Line 1239  adjust_all_relocations (abfd, sec, addr, Line 1064  adjust_all_relocations (abfd, sec, addr,
1064       int noadj;       int noadj;
1065  {  {
1066    Elf_Internal_Shdr *symtab_hdr;    Elf_Internal_Shdr *symtab_hdr;
1067    Elf32_External_Sym *extsyms;    Elf_Internal_Sym *isymbuf, *isym, *isymend;
1068    int shndx, index;    unsigned int shndx;
1069    bfd_byte *contents;    bfd_byte *contents;
1070    Elf_Internal_Rela *irel, *irelend, *irelbase;    Elf_Internal_Rela *irel, *irelend, *irelbase;
1071    Elf32_External_Sym *esym, *esymend;    struct elf_link_hash_entry **sym_hashes;
1072      struct elf_link_hash_entry **end_hashes;
1073      unsigned int symcount;
1074    asection *stab;    asection *stab;
1075    bfd_byte *stabp, *stabend, *stabcontents;  
   Elf_Internal_Shdr *shndx_hdr;  
   Elf_External_Sym_Shndx *sym_shndx;  
       
1076    symtab_hdr = &elf_tdata (abfd)->symtab_hdr;    symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1077    extsyms = (Elf32_External_Sym *) symtab_hdr->contents;    isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1078    
1079    shndx = _bfd_elf_section_from_bfd_section (abfd, sec);    shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
1080    
# Line 1266  adjust_all_relocations (abfd, sec, addr, Line 1090  adjust_all_relocations (abfd, sec, addr,
1090            /* Get the value of the symbol referred to by the reloc.  */            /* Get the value of the symbol referred to by the reloc.  */
1091            if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)            if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1092              {              {
               Elf_Internal_Sym isym;  
1093                asection *sym_sec;                asection *sym_sec;
               Elf_External_Sym_Shndx *sym_shndx;  
               Elf_Internal_Shdr *shndx_hdr;  
1094    
1095                /* A local symbol.  */                /* A local symbol.  */
1096                                isym = isymbuf + ELF32_R_SYM (irel->r_info);
1097                shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;                sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
               sym_shndx = (Elf_External_Sym_Shndx *) shndx_hdr->contents;  
               sym_shndx = (sym_shndx  
                            ? sym_shndx + ELF32_R_SYM (irel->r_info) : NULL);  
               bfd_elf32_swap_symbol_in (abfd,  
                                         extsyms + ELF32_R_SYM (irel->r_info),  
                                         sym_shndx, &isym);  
   
               if (isym.st_shndx == SHN_UNDEF)  
                 sym_sec = bfd_und_section_ptr;  
               else if (isym.st_shndx == SHN_ABS)  
                 sym_sec = bfd_abs_section_ptr;  
               else if (isym.st_shndx == SHN_COMMON)  
                 sym_sec = bfd_com_section_ptr;  
               else  
                 sym_sec = bfd_section_from_elf_index (abfd, isym.st_shndx);  
1098    
1099                if (sym_sec == sec)                if (isym->st_shndx == shndx)
1100                  {                  {
1101                    bfd_vma baseaddr = BASEADDR (sec);                    bfd_vma baseaddr = BASEADDR (sec);
1102                    bfd_vma symval = BASEADDR (sym_sec) + isym.st_value                    bfd_vma symval = BASEADDR (sym_sec) + isym->st_value
1103                                     + irel->r_addend;                                     + irel->r_addend;
1104    
1105                    if ((baseaddr + addr + noadj) <= symval                    if ((baseaddr + addr + noadj) <= symval
# Line 1312  adjust_all_relocations (abfd, sec, addr, Line 1118  adjust_all_relocations (abfd, sec, addr,
1118    stab = bfd_get_section_by_name (abfd, ".stab");    stab = bfd_get_section_by_name (abfd, ".stab");
1119    if (stab)    if (stab)
1120      {      {
1121          bfd_byte *stabcontents, *stabend, *stabp;
1122          bfd_size_type stab_size = stab->rawsize ? stab->rawsize : stab->size;
1123    
1124        irelbase = elf_section_data (stab)->relocs;        irelbase = elf_section_data (stab)->relocs;
1125        irelend = irelbase + stab->reloc_count;        irelend = irelbase + stab->reloc_count;
1126    
# Line 1320  adjust_all_relocations (abfd, sec, addr, Line 1129  adjust_all_relocations (abfd, sec, addr,
1129          stabcontents = elf_section_data (stab)->this_hdr.contents;          stabcontents = elf_section_data (stab)->this_hdr.contents;
1130        else        else
1131          {          {
1132            stabcontents = (bfd_byte *) bfd_alloc (abfd, stab->_raw_size);            if (!bfd_malloc_and_get_section (abfd, stab, &stabcontents))
1133            if (stabcontents == NULL)              {
1134              return;                if (stabcontents != NULL)
1135            if (! bfd_get_section_contents (abfd, stab, stabcontents,                  free (stabcontents);
1136                                            (file_ptr) 0, stab->_raw_size))                return;
1137              return;              }
1138    
1139            /* We need to remember this.  */            /* We need to remember this.  */
1140            elf_section_data (stab)->this_hdr.contents = stabcontents;            elf_section_data (stab)->this_hdr.contents = stabcontents;
1141          }          }
1142    
1143        stabend = stabcontents + stab->_raw_size;        stabend = stabcontents + stab_size;
1144    
1145        for (irel = irelbase; irel < irelend; irel++)        for (irel = irelbase; irel < irelend; irel++)
1146          {          {
# Line 1340  adjust_all_relocations (abfd, sec, addr, Line 1149  adjust_all_relocations (abfd, sec, addr,
1149                /* Get the value of the symbol referred to by the reloc.  */                /* Get the value of the symbol referred to by the reloc.  */
1150                if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)                if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1151                  {                  {
                   Elf_Internal_Sym isym;  
1152                    asection *sym_sec;                    asection *sym_sec;
                   Elf_External_Sym_Shndx *sym_shndx;  
                   Elf_Internal_Shdr *shndx_hdr;  
1153                                        
1154                    /* A local symbol.  */                    /* A local symbol.  */
1155                    shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;                    isym = isymbuf + ELF32_R_SYM (irel->r_info);
1156                    sym_shndx = (Elf_External_Sym_Shndx *) shndx_hdr->contents;                    sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
                   sym_shndx = (sym_shndx  
                                ? sym_shndx + ELF32_R_SYM (irel->r_info)  
                                : NULL);  
                     
                   bfd_elf32_swap_symbol_in (abfd,  
                                             (extsyms  
                                              + ELF32_R_SYM (irel->r_info)),  
                                             sym_shndx, &isym);  
                     
                   if (isym.st_shndx == SHN_UNDEF)  
                     sym_sec = bfd_und_section_ptr;  
                   else if (isym.st_shndx == SHN_ABS)  
                     sym_sec = bfd_abs_section_ptr;  
                   else if (isym.st_shndx == SHN_COMMON)  
                     sym_sec = bfd_com_section_ptr;  
                   else  
                     sym_sec = bfd_section_from_elf_index (abfd, isym.st_shndx);  
1157                                        
1158                    if (sym_sec == sec)                    if (sym_sec == sec)
1159                      {                      {
# Line 1374  adjust_all_relocations (abfd, sec, addr, Line 1163  adjust_all_relocations (abfd, sec, addr,
1163                        unsigned short desc;                        unsigned short desc;
1164                        bfd_vma value;                        bfd_vma value;
1165                        bfd_vma baseaddr = BASEADDR (sec);                        bfd_vma baseaddr = BASEADDR (sec);
1166                        bfd_vma symval = BASEADDR (sym_sec) + isym.st_value                        bfd_vma symval = BASEADDR (sym_sec) + isym->st_value
1167                          + irel->r_addend;                          + irel->r_addend;
1168                                                
1169                        if ((baseaddr + addr) <= symval                        if ((baseaddr + addr) <= symval
# Line 1385  adjust_all_relocations (abfd, sec, addr, Line 1174  adjust_all_relocations (abfd, sec, addr,
1174                        stabp = stabcontents + irel->r_offset - 8;                        stabp = stabcontents + irel->r_offset - 8;
1175    
1176                        /* Go pullout the stab entry.  */                        /* Go pullout the stab entry.  */
1177                        strx = bfd_h_get_32 (abfd, stabp + STRDXOFF);                        strx  = bfd_h_get_32 (abfd, stabp + STRDXOFF);
1178                        type = bfd_h_get_8 (abfd, stabp + TYPEOFF);                        type  = bfd_h_get_8 (abfd, stabp + TYPEOFF);
1179                        other = bfd_h_get_8 (abfd, stabp + OTHEROFF);                        other = bfd_h_get_8 (abfd, stabp + OTHEROFF);
1180                        desc = bfd_h_get_16 (abfd, stabp + DESCOFF);                        desc  = bfd_h_get_16 (abfd, stabp + DESCOFF);
1181                        value = bfd_h_get_32 (abfd, stabp + VALOFF);                        value = bfd_h_get_32 (abfd, stabp + VALOFF);
1182                                                
1183                        name = bfd_get_stab_name (type);                        name = bfd_get_stab_name (type);
# Line 1406  adjust_all_relocations (abfd, sec, addr, Line 1195  adjust_all_relocations (abfd, sec, addr,
1195                            for (;stabp < stabend; stabp += STABSIZE)                            for (;stabp < stabend; stabp += STABSIZE)
1196                              {                              {
1197                                /* Go pullout the stab entry.  */                                /* Go pullout the stab entry.  */
1198                                strx = bfd_h_get_32 (abfd, stabp + STRDXOFF);                                strx  = bfd_h_get_32 (abfd, stabp + STRDXOFF);
1199                                type = bfd_h_get_8 (abfd, stabp + TYPEOFF);                                type  = bfd_h_get_8 (abfd, stabp + TYPEOFF);
1200                                other = bfd_h_get_8 (abfd, stabp + OTHEROFF);                                other = bfd_h_get_8 (abfd, stabp + OTHEROFF);
1201                                desc = bfd_h_get_16 (abfd, stabp + DESCOFF);                                desc  = bfd_h_get_16 (abfd, stabp + DESCOFF);
1202                                value = bfd_h_get_32 (abfd, stabp + VALOFF);                                value = bfd_h_get_32 (abfd, stabp + VALOFF);
1203    
1204                                name = bfd_get_stab_name (type);                                name = bfd_get_stab_name (type);
1205    
1206                                if (strcmp (name, "FUN") == 0)                                if (strcmp (name, "FUN") == 0)
# Line 1459  adjust_all_relocations (abfd, sec, addr, Line 1249  adjust_all_relocations (abfd, sec, addr,
1249    addr += noadj;    addr += noadj;
1250    
1251    /* Adjust the local symbols defined in this section.  */    /* Adjust the local symbols defined in this section.  */
1252    shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;    isymend = isymbuf + symtab_hdr->sh_info;
1253    sym_shndx = (Elf_External_Sym_Shndx *) shndx_hdr->contents;    for (isym = isymbuf; isym < isymend; isym++)
   esym = extsyms;  
   esymend = esym + symtab_hdr->sh_info;  
   for (; esym < esymend; esym++, sym_shndx = (sym_shndx ? sym_shndx + 1: NULL))  
1254      {      {
1255        Elf_Internal_Sym isym;        if (isym->st_shndx == shndx
1256        Elf_External_Sym_Shndx dummy;            && addr <= isym->st_value
1257              && isym->st_value < endaddr)
1258        bfd_elf32_swap_symbol_in (abfd, esym, sym_shndx, &isym);          isym->st_value += count;
1259        }
1260        if (isym.st_shndx == shndx)  
1261          {      /* Now adjust the global symbols defined in this section.  */
1262            if (addr <= isym.st_value && isym.st_value < endaddr)    symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
1263              {                - symtab_hdr->sh_info);
1264                isym.st_value += count;    sym_hashes = elf_sym_hashes (abfd);
1265                bfd_elf32_swap_symbol_out (abfd, &isym, esym, &dummy);    end_hashes = sym_hashes + symcount;
1266              }    for (; sym_hashes < end_hashes; sym_hashes++)
1267          }      {
1268      }        struct elf_link_hash_entry *sym_hash = *sym_hashes;
1269    
1270    /* Now adjust the global symbols defined in this section.  */        if ((sym_hash->root.type == bfd_link_hash_defined
1271    shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;             || sym_hash->root.type == bfd_link_hash_defweak)
1272    sym_shndx = (Elf_External_Sym_Shndx *) shndx_hdr->contents;            && sym_hash->root.u.def.section == sec)
1273    esym = extsyms + symtab_hdr->sh_info;          {
   esymend = extsyms + (symtab_hdr->sh_size / sizeof (Elf32_External_Sym));  
   for (index = 0; esym < esymend;  
        esym++, index++, sym_shndx = (sym_shndx ? sym_shndx + 1: NULL))  
     {  
       Elf_Internal_Sym isym;  
       struct elf_link_hash_entry *sym_hash;  
   
       bfd_elf32_swap_symbol_in (abfd, esym, sym_shndx, &isym);  
       sym_hash = elf_sym_hashes (abfd)[index];  
   
       if (isym.st_shndx == shndx  
           && (sym_hash->root.type == bfd_link_hash_defined  
               || sym_hash->root.type == bfd_link_hash_defweak)  
           && sym_hash->root.u.def.section == sec)  
         {  
1274            if (addr <= sym_hash->root.u.def.value            if (addr <= sym_hash->root.u.def.value
1275                && sym_hash->root.u.def.value < endaddr)                && sym_hash->root.u.def.value < endaddr)
1276              {              sym_hash->root.u.def.value += count;
1277                Elf_External_Sym_Shndx dummy;          }
   
               sym_hash->root.u.def.value += count;  
               bfd_elf32_swap_symbol_out (abfd, &isym, esym, &dummy);  
             }  
         }  
1278      }      }
1279    
1280    return;    return;
1281  }  }
1282    
 static boolean  
 add_page_insn (abfd, sec, irel, misc)  
       bfd *abfd;  
       asection *sec;  
       Elf_Internal_Rela *irel;  
       struct misc *misc;  
 {  
   /* Note that we've changed the relocs, section contents, etc.  */  
   elf_section_data (sec)->relocs = misc->irelbase;  
   misc->free_relocs = NULL;  
   
   elf_section_data (sec)->this_hdr.contents = misc->contents;  
   misc->free_contents = NULL;  
   
   misc->symtab_hdr->contents = (bfd_byte *) misc->extsyms;  
   misc->free_extsyms = NULL;  
   
   /* Add the PAGE insn.  */  
   if (! ip2k_elf_relax_add_bytes (abfd, sec, irel->r_offset,  
                                   page_opcode,  
                                   sizeof (page_opcode),  
                                   sizeof (page_opcode)))  
     return false;  
   else  
     {  
        Elf32_Internal_Rela * jrel = irel - 1;  
   
        /* Add relocation for PAGE insn added.  */  
        if (ELF32_R_TYPE (jrel->r_info) != R_IP2K_NONE)  
          {  
            bfd_byte code0, code1;  
            char *msg = NULL;  
             
            /* Get the opcode.  */  
            code0 = bfd_get_8 (abfd, misc->contents + irel->r_offset);  
            code1 = bfd_get_8 (abfd, misc->contents + irel->r_offset + 1);  
   
            if (IS_JMP_OPCODE (code0, code1))  
              msg = "\tJMP instruction missing a preceeding PAGE instruction in %s\n\n";  
   
            else if (IS_CALL_OPCODE (code0, code1))  
              msg = "\tCALL instruction missing a preceeding PAGE instruction in %s\n\n";  
   
            if (msg)  
              {  
                fprintf (stderr, "\n\t *** LINKER RELAXATION failure ***\n");  
                fprintf (stderr, msg, sec->owner->filename);  
              }  
   
            return false;  
          }  
   
        jrel->r_addend = irel->r_addend;  
        jrel->r_offset = irel->r_offset - sizeof (page_opcode);  
        jrel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),  
                                     R_IP2K_PAGE3);  
      }  
   
    return true;  
 }  
   
 /* Insert bytes into a section while relaxing.  */  
   
 static boolean  
 ip2k_elf_relax_add_bytes (abfd, sec, addr, bytes, count, noadj)  
      bfd *abfd;  
      asection *sec;  
      bfd_vma addr;  
      const bfd_byte *bytes;  
      int count;  
      int noadj;  
 {  
   bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;  
   bfd_vma endaddr = sec->_cooked_size;  
   
   /* Make room to insert the bytes.  */  
   memmove (contents + addr + count, contents + addr, endaddr - addr);  
   
   /* Insert the bytes into the section.  */  
   memcpy  (contents + addr, bytes, count);  
     
   sec->_cooked_size += count;  
   
   adjust_all_relocations (abfd, sec, addr, endaddr, count, noadj);  
   return true;  
 }  
   
1283  /* Delete some bytes from a section while relaxing.  */  /* Delete some bytes from a section while relaxing.  */
1284    
1285  static boolean  static bfd_boolean
1286  ip2k_elf_relax_delete_bytes (abfd, sec, addr, count)  ip2k_elf_relax_delete_bytes (abfd, sec, addr, count)
1287       bfd *abfd;       bfd *abfd;
1288       asection *sec;       asection *sec;
# Line 1610  ip2k_elf_relax_delete_bytes (abfd, sec, Line 1290  ip2k_elf_relax_delete_bytes (abfd, sec,
1290       int count;       int count;
1291  {  {
1292    bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;    bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
1293    bfd_vma endaddr = sec->_cooked_size;    bfd_vma endaddr = sec->size;
1294    
1295    /* Actually delete the bytes.  */    /* Actually delete the bytes.  */
1296    memmove (contents + addr, contents + addr + count,    memmove (contents + addr, contents + addr + count,
1297             endaddr - addr - count);             endaddr - addr - count);
1298    
1299    sec->_cooked_size -= count;    sec->size -= count;
1300    
1301    adjust_all_relocations (abfd, sec, addr + count, endaddr, -count, 0);    adjust_all_relocations (abfd, sec, addr + count, endaddr, -count, 0);
1302    return true;    return TRUE;
1303  }  }
1304    
1305  /* -------------------------------------------------------------------- */  /* -------------------------------------------------------------------- */
# Line 1633  static void Line 1313  static void
1313  ip2k_info_to_howto_rela (abfd, cache_ptr, dst)  ip2k_info_to_howto_rela (abfd, cache_ptr, dst)
1314       bfd * abfd ATTRIBUTE_UNUSED;       bfd * abfd ATTRIBUTE_UNUSED;
1315       arelent * cache_ptr;       arelent * cache_ptr;
1316       Elf32_Internal_Rela * dst;       Elf_Internal_Rela * dst;
1317  {  {
1318    unsigned int r_type;    unsigned int r_type;
1319    
# Line 1659  ip2k_final_link_relocate (howto, input_b Line 1339  ip2k_final_link_relocate (howto, input_b
1339       Elf_Internal_Rela * rel;       Elf_Internal_Rela * rel;
1340       bfd_vma             relocation;       bfd_vma             relocation;
1341  {  {
1342    bfd_reloc_status_type r = bfd_reloc_ok;    static bfd_vma page_addr = 0;
1343    
1344      bfd_reloc_status_type r = bfd_reloc_ok;
1345    switch (howto->type)    switch (howto->type)
1346      {      {
1347        /* Handle data space relocations.  */        /* Handle data space relocations.  */
# Line 1678  ip2k_final_link_relocate (howto, input_b Line 1359  ip2k_final_link_relocate (howto, input_b
1359        break;        break;
1360    
1361        /* Handle insn space relocations.  */        /* Handle insn space relocations.  */
     case R_IP2K_ADDR16CJP:  
1362      case R_IP2K_PAGE3:      case R_IP2K_PAGE3:
1363          page_addr = BASEADDR (input_section) + rel->r_offset;
1364          if ((relocation & IP2K_INSN_MASK) == IP2K_INSN_VALUE)
1365            relocation &= ~IP2K_INSN_MASK;
1366          else
1367            r = bfd_reloc_notsupported;
1368          break;
1369    
1370        case R_IP2K_ADDR16CJP:
1371          if (BASEADDR (input_section) + rel->r_offset != page_addr + 2)
1372            {
1373              /* No preceding page instruction, verify that it isn't needed.  */
1374              if (PAGENO (relocation + rel->r_addend) !=
1375                  ip2k_nominal_page_bits (input_bfd, input_section,
1376                                          rel->r_offset, contents))
1377                _bfd_error_handler (_("ip2k linker: missing page instruction at 0x%08lx (dest = 0x%08lx)."),
1378                                    BASEADDR (input_section) + rel->r_offset,
1379                                    relocation + rel->r_addend);
1380            }
1381          else if (ip2k_relaxed)
1382            {
1383              /* Preceding page instruction. Verify that the page instruction is
1384                 really needed. One reason for the relaxation to miss a page is if
1385                 the section is not marked as executable.  */
1386              if (!ip2k_is_switch_table_128 (input_bfd, input_section, rel->r_offset - 2, contents) &&
1387                  !ip2k_is_switch_table_256 (input_bfd, input_section, rel->r_offset - 2, contents) &&
1388                  (PAGENO (relocation + rel->r_addend) ==
1389                   ip2k_nominal_page_bits (input_bfd, input_section,
1390                                          rel->r_offset - 2, contents)))
1391                _bfd_error_handler (_("ip2k linker: redundant page instruction at 0x%08lx (dest = 0x%08lx)."),
1392                                    page_addr,
1393                                    relocation + rel->r_addend);
1394            }
1395          if ((relocation & IP2K_INSN_MASK) == IP2K_INSN_VALUE)
1396            relocation &= ~IP2K_INSN_MASK;
1397          else
1398            r = bfd_reloc_notsupported;
1399          break;
1400    
1401      case R_IP2K_LO8INSN:      case R_IP2K_LO8INSN:
1402      case R_IP2K_HI8INSN:      case R_IP2K_HI8INSN:
1403      case R_IP2K_PC_SKIP:      case R_IP2K_PC_SKIP:
# Line 1711  ip2k_final_link_relocate (howto, input_b Line 1429  ip2k_final_link_relocate (howto, input_b
1429  }  }
1430    
1431  /* Relocate a IP2K ELF section.  /* Relocate a IP2K ELF section.
    There is some attempt to make this function usable for many architectures,  
    both USE_REL and USE_RELA ['twould be nice if such a critter existed],  
    if only to serve as a learning tool.  
1432    
1433     The RELOCATE_SECTION function is called by the new ELF backend linker     The RELOCATE_SECTION function is called by the new ELF backend linker
1434     to handle the relocations for a section.     to handle the relocations for a section.
# Line 1723  ip2k_final_link_relocate (howto, input_b Line 1438  ip2k_final_link_relocate (howto, input_b
1438     zero.     zero.
1439    
1440     This function is responsible for adjusting the section contents as     This function is responsible for adjusting the section contents as
1441     necessary, and (if using Rela relocs and generating a relocateable     necessary, and (if using Rela relocs and generating a relocatable
1442     output file) adjusting the reloc addend as necessary.     output file) adjusting the reloc addend as necessary.
1443    
1444     This function does not have to worry about setting the reloc     This function does not have to worry about setting the reloc
# Line 1737  ip2k_final_link_relocate (howto, input_b Line 1452  ip2k_final_link_relocate (howto, input_b
1452     The global hash table entry for the global symbols can be found     The global hash table entry for the global symbols can be found
1453     via elf_sym_hashes (input_bfd).     via elf_sym_hashes (input_bfd).
1454    
1455     When generating relocateable output, this function must handle     When generating relocatable output, this function must handle
1456     STB_LOCAL/STT_SECTION symbols specially.  The output symbol is     STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
1457     going to be the section symbol corresponding to the output     going to be the section symbol corresponding to the output
1458     section, which means that the addend must be adjusted     section, which means that the addend must be adjusted
1459     accordingly.  */     accordingly.  */
1460    
1461  static boolean  static bfd_boolean
1462  ip2k_elf_relocate_section (output_bfd, info, input_bfd, input_section,  ip2k_elf_relocate_section (output_bfd, info, input_bfd, input_section,
1463                             contents, relocs, local_syms, local_sections)                             contents, relocs, local_syms, local_sections)
1464       bfd *                   output_bfd ATTRIBUTE_UNUSED;       bfd *output_bfd ATTRIBUTE_UNUSED;
1465       struct bfd_link_info *  info;       struct bfd_link_info *info;
1466       bfd *                   input_bfd;       bfd *input_bfd;
1467       asection *              input_section;       asection *input_section;
1468       bfd_byte *              contents;       bfd_byte *contents;
1469       Elf_Internal_Rela *     relocs;       Elf_Internal_Rela *relocs;
1470       Elf_Internal_Sym *      local_syms;       Elf_Internal_Sym *local_syms;
1471       asection **             local_sections;       asection **local_sections;
1472  {  {
1473    Elf_Internal_Shdr *           symtab_hdr;    Elf_Internal_Shdr *symtab_hdr;
1474    struct elf_link_hash_entry ** sym_hashes;    struct elf_link_hash_entry **sym_hashes;
1475    Elf_Internal_Rela *           rel;    Elf_Internal_Rela *rel;
1476    Elf_Internal_Rela *           relend;    Elf_Internal_Rela *relend;
1477    
1478      if (info->relocatable)
1479        return TRUE;
1480    
1481    symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;    symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
1482    sym_hashes = elf_sym_hashes (input_bfd);    sym_hashes = elf_sym_hashes (input_bfd);
# Line 1775  ip2k_elf_relocate_section (output_bfd, i Line 1493  ip2k_elf_relocate_section (output_bfd, i
1493        bfd_reloc_status_type        r;        bfd_reloc_status_type        r;
1494        const char *                 name = NULL;        const char *                 name = NULL;
1495        int                          r_type;        int                          r_type;
         
       r_type = ELF32_R_TYPE (rel->r_info);  
   
       r_symndx = ELF32_R_SYM (rel->r_info);  
   
       if (info->relocateable)  
         {  
           /* This is a relocateable link.  We don't have to change  
              anything, unless the reloc is against a section symbol,  
              in which case we have to adjust according to where the  
              section symbol winds up in the output section.  */  
           if (r_symndx < symtab_hdr->sh_info)  
             {  
               sym = local_syms + r_symndx;  
                 
               if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)  
                 {  
                   sec = local_sections [r_symndx];  
                   rel->r_addend += sec->output_offset + sym->st_value;  
                 }  
             }  
   
           continue;  
         }  
1496    
1497        /* This is a final link.  */        /* This is a final link.  */
1498          r_type = ELF32_R_TYPE (rel->r_info);
1499          r_symndx = ELF32_R_SYM (rel->r_info);
1500        howto  = ip2k_elf_howto_table + ELF32_R_TYPE (rel->r_info);        howto  = ip2k_elf_howto_table + ELF32_R_TYPE (rel->r_info);
1501        h      = NULL;        h      = NULL;
1502        sym    = NULL;        sym    = NULL;
1503        sec    = NULL;        sec    = NULL;
1504          
1505        if (r_symndx < symtab_hdr->sh_info)        if (r_symndx < symtab_hdr->sh_info)
1506          {          {
1507            sym = local_syms + r_symndx;            sym = local_syms + r_symndx;
1508            sec = local_sections [r_symndx];            sec = local_sections [r_symndx];
1509            relocation = BASEADDR (sec) + sym->st_value;            relocation = BASEADDR (sec) + sym->st_value;
1510              
1511            name = bfd_elf_string_from_elf_section            name = bfd_elf_string_from_elf_section
1512              (input_bfd, symtab_hdr->sh_link, sym->st_name);              (input_bfd, symtab_hdr->sh_link, sym->st_name);
1513            name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;            name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
1514          }          }
1515        else        else
1516          {          {
1517            h = sym_hashes [r_symndx - symtab_hdr->sh_info];            bfd_boolean warned;
1518                        bfd_boolean unresolved_reloc;
1519            while (h->root.type == bfd_link_hash_indirect  
1520                   || h->root.type == bfd_link_hash_warning)            RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
1521              h = (struct elf_link_hash_entry *) h->root.u.i.link;                                     r_symndx, symtab_hdr, sym_hashes,
1522                                       h, sec, relocation,
1523                                       unresolved_reloc, warned);
1524    
1525            name = h->root.root.string;            name = h->root.root.string;
             
           if (h->root.type == bfd_link_hash_defined  
               || h->root.type == bfd_link_hash_defweak)  
             {  
               sec = h->root.u.def.section;  
               relocation = h->root.u.def.value + BASEADDR (sec);  
             }  
           else if (h->root.type == bfd_link_hash_undefweak)  
             {  
               relocation = 0;  
             }  
           else  
             {  
               if (! ((*info->callbacks->undefined_symbol)  
                      (info, h->root.root.string, input_bfd,  
                       input_section, rel->r_offset,  
                      (! info->shared || info->no_undefined))))  
                 return false;  
               relocation = 0;  
             }  
1526          }          }
1527    
1528        /* Finally, the sole IP2K-specific part.  */        /* Finally, the sole IP2K-specific part.  */
# Line 1859  ip2k_elf_relocate_section (output_bfd, i Line 1537  ip2k_elf_relocate_section (output_bfd, i
1537              {              {
1538              case bfd_reloc_overflow:              case bfd_reloc_overflow:
1539                r = info->callbacks->reloc_overflow                r = info->callbacks->reloc_overflow
1540                  (info, name, howto->name, (bfd_vma) 0,                  (info, (h ? &h->root : NULL), name, howto->name,
1541                   input_bfd, input_section, rel->r_offset);                   (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
1542                break;                break;
1543                  
1544              case bfd_reloc_undefined:              case bfd_reloc_undefined:
1545                r = info->callbacks->undefined_symbol                r = info->callbacks->undefined_symbol
1546                  (info, name, input_bfd, input_section, rel->r_offset, true);                  (info, name, input_bfd, input_section, rel->r_offset, TRUE);
1547                break;                break;
1548                  
1549              case bfd_reloc_outofrange:              case bfd_reloc_outofrange:
1550                msg = _("internal error: out of range error");                msg = _("internal error: out of range error");
1551                break;                break;
# Line 1893  ip2k_elf_relocate_section (output_bfd, i Line 1571  ip2k_elf_relocate_section (output_bfd, i
1571                (info, msg, name, input_bfd, input_section, rel->r_offset);                (info, msg, name, input_bfd, input_section, rel->r_offset);
1572    
1573            if (! r)            if (! r)
1574              return false;              return FALSE;
1575          }          }
1576      }      }
1577    
1578    return true;    return TRUE;
1579  }  }
1580    
1581  static asection *  static asection *
# Line 1912  ip2k_elf_gc_mark_hook (sec, info, rel, h Line 1590  ip2k_elf_gc_mark_hook (sec, info, rel, h
1590      {      {
1591        switch (ELF32_R_TYPE (rel->r_info))        switch (ELF32_R_TYPE (rel->r_info))
1592        {        {
 #if 0  
       case R_IP2K_GNU_VTINHERIT:  
       case R_IP2K_GNU_VTENTRY:  
         break;  
 #endif  
   
1593        default:        default:
1594          switch (h->root.type)          switch (h->root.type)
1595            {            {
# Line 1939  ip2k_elf_gc_mark_hook (sec, info, rel, h Line 1611  ip2k_elf_gc_mark_hook (sec, info, rel, h
1611               && ELF_ST_BIND (sym->st_info) != STB_LOCAL)               && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
1612             && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)             && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
1613                   && sym->st_shndx != SHN_COMMON))                   && sym->st_shndx != SHN_COMMON))
1614            {           return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
             return bfd_section_from_elf_index (sec->owner, sym->st_shndx);  
           }  
1615        }        }
1616    return NULL;    return NULL;
1617  }  }
1618    
1619  static boolean  static bfd_boolean
1620  ip2k_elf_gc_sweep_hook (abfd, info, sec, relocs)  ip2k_elf_gc_sweep_hook (abfd, info, sec, relocs)
1621       bfd *abfd ATTRIBUTE_UNUSED;       bfd *abfd ATTRIBUTE_UNUSED;
1622       struct bfd_link_info *info ATTRIBUTE_UNUSED;       struct bfd_link_info *info ATTRIBUTE_UNUSED;
1623       asection *sec ATTRIBUTE_UNUSED;       asection *sec ATTRIBUTE_UNUSED;
1624       const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;       const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
1625  {  {
1626    /* we don't use got and plt entries for ip2k */    /* We don't use got and plt entries for ip2k.  */
1627    return true;    return TRUE;
1628  }  }
1629    
   
 /* -------------------------------------------------------------------- */  
   
   
1630  #define TARGET_BIG_SYM   bfd_elf32_ip2k_vec  #define TARGET_BIG_SYM   bfd_elf32_ip2k_vec
1631  #define TARGET_BIG_NAME  "elf32-ip2k"  #define TARGET_BIG_NAME  "elf32-ip2k"
1632    
1633  #define ELF_ARCH         bfd_arch_ip2k  #define ELF_ARCH         bfd_arch_ip2k
1634  #define ELF_MACHINE_CODE EM_IP2K  #define ELF_MACHINE_CODE EM_IP2K
1635  #define ELF_MAXPAGESIZE  1 /* No pages on the IP2K */  #define ELF_MACHINE_ALT1 EM_IP2K_OLD
1636    #define ELF_MAXPAGESIZE  1 /* No pages on the IP2K.  */
 #undef USE_REL  
 #define USE_RELA  
1637    
1638  #define elf_info_to_howto_rel                   NULL  #define elf_info_to_howto_rel                   NULL
1639  #define elf_info_to_howto                       ip2k_info_to_howto_rela  #define elf_info_to_howto                       ip2k_info_to_howto_rela
1640    
1641  #define elf_backend_can_gc_sections             1  #define elf_backend_can_gc_sections             1
1642    #define elf_backend_rela_normal                 1
1643  #define elf_backend_gc_mark_hook                ip2k_elf_gc_mark_hook  #define elf_backend_gc_mark_hook                ip2k_elf_gc_mark_hook
1644  #define elf_backend_gc_sweep_hook               ip2k_elf_gc_sweep_hook  #define elf_backend_gc_sweep_hook               ip2k_elf_gc_sweep_hook
   
1645  #define elf_backend_relocate_section            ip2k_elf_relocate_section  #define elf_backend_relocate_section            ip2k_elf_relocate_section
1646    
1647  #define elf_symbol_leading_char                 '_'  #define elf_symbol_leading_char                 '_'
1648  #define bfd_elf32_bfd_reloc_type_lookup         ip2k_reloc_type_lookup  #define bfd_elf32_bfd_reloc_type_lookup         ip2k_reloc_type_lookup
1649  #define bfd_elf32_bfd_relax_section             ip2k_elf_relax_section  #define bfd_elf32_bfd_relax_section             ip2k_elf_relax_section
1650    
   
1651  #include "elf32-target.h"  #include "elf32-target.h"
   

Legend:
Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.1.20.1

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