Commit | Line | Data |
---|---|---|
fd13ed0c | 1 | /* Ubicom IP2xxx specific support for 32-bit ELF |
cf88bb9f NC |
2 | Copyright 2000, 2001, 2002 Free Software Foundation, Inc. |
3 | ||
4 | This file is part of BFD, the Binary File Descriptor library. | |
5 | ||
6 | This program is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 2 of the License, or | |
9 | (at your option) any later version. | |
10 | ||
11 | This program is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with this program; if not, write to the Free Software | |
18 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |
19 | ||
20 | #include "bfd.h" | |
21 | #include "sysdep.h" | |
22 | #include "libbfd.h" | |
23 | #include "elf-bfd.h" | |
24 | #include "elf/ip2k.h" | |
25 | ||
26 | /* Struct used to pass miscellaneous paramaters which | |
27 | helps to avoid overly long parameter lists. */ | |
28 | struct misc | |
29 | { | |
30 | Elf_Internal_Shdr * symtab_hdr; | |
31 | Elf_Internal_Rela * irelbase; | |
32 | bfd_byte * contents; | |
fd13ed0c | 33 | Elf_Internal_Sym * isymbuf; |
cf88bb9f NC |
34 | }; |
35 | ||
36 | /* Prototypes. */ | |
37 | static reloc_howto_type * ip2k_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type)); | |
38 | static void ip2k_info_to_howto_rela PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *)); | |
39 | static asection * ip2k_elf_gc_mark_hook PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *, struct elf_link_hash_entry *, Elf_Internal_Sym *)); | |
40 | static boolean ip2k_elf_gc_sweep_hook PARAMS ((bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *)); | |
fd13ed0c | 41 | static bfd_vma symbol_value PARAMS ((bfd *, Elf_Internal_Shdr *, Elf32_Internal_Sym *, Elf_Internal_Rela *)); |
cf88bb9f NC |
42 | static void adjust_all_relocations PARAMS ((bfd *, asection *, bfd_vma, bfd_vma, int, int)); |
43 | static boolean ip2k_elf_relax_delete_bytes PARAMS ((bfd *, asection *, bfd_vma, int)); | |
44 | static boolean ip2k_elf_relax_add_bytes PARAMS ((bfd *, asection *, bfd_vma, const bfd_byte *, int, int)); | |
45 | static boolean add_page_insn PARAMS ((bfd *, asection *, Elf_Internal_Rela *, struct misc *)); | |
46 | static boolean ip2k_elf_relax_section PARAMS ((bfd *, asection *, struct bfd_link_info *, boolean *)); | |
47 | static boolean relax_switch_dispatch_tables_pass1 PARAMS ((bfd *, asection *, bfd_vma, struct misc *)); | |
48 | static boolean unrelax_dispatch_table_entries PARAMS ((bfd *, asection *, bfd_vma, bfd_vma, boolean *, struct misc *)); | |
49 | static boolean unrelax_switch_dispatch_tables_passN PARAMS ((bfd *, asection *, bfd_vma, boolean *, struct misc *)); | |
50 | static boolean is_switch_128_dispatch_table_p PARAMS ((bfd *, bfd_vma, boolean, struct misc *)); | |
51 | static boolean is_switch_256_dispatch_table_p PARAMS ((bfd *, bfd_vma, boolean, struct misc *)); | |
cf88bb9f NC |
52 | static boolean ip2k_elf_relax_section_pass1 PARAMS ((bfd *, asection *, boolean *, struct misc *)); |
53 | static boolean ip2k_elf_relax_section_passN PARAMS ((bfd *, asection *, boolean *, boolean *, struct misc *)); | |
54 | static bfd_reloc_status_type ip2k_final_link_relocate PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, bfd_vma)); | |
55 | static boolean ip2k_elf_relocate_section PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); | |
56 | ||
57 | #define IS_OPCODE(CODE0,CODE1,OPCODE) \ | |
58 | ((CODE0) == (OPCODE)[0] && (CODE1) == (OPCODE)[1]) | |
59 | ||
60 | #define PAGE_INSN_0 0x00 | |
61 | #define PAGE_INSN_1 0x10 | |
62 | ||
63 | static const bfd_byte page_opcode[] = | |
64 | { | |
65 | PAGE_INSN_0, PAGE_INSN_1 | |
66 | }; | |
67 | ||
68 | #define IS_PAGE_OPCODE(CODE0,CODE1) \ | |
69 | IS_OPCODE (CODE0, CODE1, page_opcode) | |
70 | ||
71 | #define JMP_INSN_0 0xE0 | |
72 | #define JMP_INSN_1 0x00 | |
73 | ||
74 | static const bfd_byte jmp_opcode[] = | |
75 | { | |
76 | JMP_INSN_0, JMP_INSN_1 | |
77 | }; | |
78 | ||
79 | #define IS_JMP_OPCODE(CODE0,CODE1) \ | |
80 | IS_OPCODE (CODE0, CODE1, jmp_opcode) | |
81 | ||
82 | #define CALL_INSN_0 0xC0 | |
83 | #define CALL_INSN_1 0x00 | |
84 | ||
85 | static const bfd_byte call_opcode[] = | |
86 | { | |
87 | CALL_INSN_0, CALL_INSN_1 | |
88 | }; | |
89 | ||
90 | #define IS_CALL_OPCODE(CODE0,CODE1) \ | |
91 | IS_OPCODE (CODE0, CODE1, call_opcode) | |
92 | ||
93 | #define ADD_PCL_W_INSN_0 0x1E | |
94 | #define ADD_PCL_W_INSN_1 0x09 | |
95 | ||
96 | static const bfd_byte add_pcl_w_opcode[] = | |
97 | { | |
98 | ADD_PCL_W_INSN_0, ADD_PCL_W_INSN_1 | |
99 | }; | |
100 | ||
101 | #define IS_ADD_PCL_W_OPCODE(CODE0,CODE1) \ | |
102 | IS_OPCODE (CODE0, CODE1, add_pcl_w_opcode) | |
103 | ||
104 | #define ADD_W_WREG_INSN_0 0x1C | |
105 | #define ADD_W_WREG_INSN_1 0x0A | |
106 | ||
107 | static const bfd_byte add_w_wreg_opcode[] = | |
108 | { | |
109 | ADD_W_WREG_INSN_0, ADD_W_WREG_INSN_1 | |
110 | }; | |
111 | ||
112 | #define IS_ADD_W_WREG_OPCODE(CODE0,CODE1) \ | |
113 | IS_OPCODE (CODE0, CODE1, add_w_wreg_opcode) | |
114 | ||
115 | #define SNC_INSN_0 0xA0 | |
116 | #define SNC_INSN_1 0x0B | |
117 | ||
118 | static const bfd_byte snc_opcode[] = | |
119 | { | |
120 | SNC_INSN_0, SNC_INSN_1 | |
121 | }; | |
122 | ||
123 | #define IS_SNC_OPCODE(CODE0,CODE1) \ | |
124 | IS_OPCODE (CODE0, CODE1, snc_opcode) | |
125 | ||
126 | #define INC_1_SP_INSN_0 0x2B | |
127 | #define INC_1_SP_INSN_1 0x81 | |
128 | ||
129 | static const bfd_byte inc_1_sp_opcode[] = | |
130 | { | |
131 | INC_1_SP_INSN_0, INC_1_SP_INSN_1 | |
132 | }; | |
133 | ||
134 | #define IS_INC_1_SP_OPCODE(CODE0,CODE1) \ | |
135 | IS_OPCODE (CODE0, CODE1, inc_1_sp_opcode) | |
136 | ||
137 | #define ADD_2_SP_W_INSN_0 0x1F | |
138 | #define ADD_2_SP_W_INSN_1 0x82 | |
139 | ||
140 | static const bfd_byte add_2_sp_w_opcode[] = | |
141 | { | |
142 | ADD_2_SP_W_INSN_0, ADD_2_SP_W_INSN_1 | |
143 | }; | |
144 | ||
145 | #define IS_ADD_2_SP_W_OPCODE(CODE0,CODE1) \ | |
146 | IS_OPCODE (CODE0, CODE1, add_2_sp_w_opcode) | |
147 | ||
148 | /* Relocation tables. */ | |
149 | static reloc_howto_type ip2k_elf_howto_table [] = | |
150 | { | |
151 | #define IP2K_HOWTO(t,rs,s,bs,pr,bp,name,sm,dm) \ | |
152 | HOWTO(t, /* type */ \ | |
153 | rs, /* rightshift */ \ | |
154 | s, /* size (0 = byte, 1 = short, 2 = long) */ \ | |
155 | bs, /* bitsize */ \ | |
156 | pr, /* pc_relative */ \ | |
157 | bp, /* bitpos */ \ | |
158 | complain_overflow_dont,/* complain_on_overflow */ \ | |
159 | bfd_elf_generic_reloc,/* special_function */ \ | |
160 | name, /* name */ \ | |
161 | false, /* partial_inplace */ \ | |
162 | sm, /* src_mask */ \ | |
163 | dm, /* dst_mask */ \ | |
164 | pr) /* pcrel_offset */ | |
165 | ||
166 | /* This reloc does nothing. */ | |
167 | IP2K_HOWTO (R_IP2K_NONE, 0,2,32, false, 0, "R_IP2K_NONE", 0, 0), | |
168 | /* A 16 bit absolute relocation. */ | |
169 | IP2K_HOWTO (R_IP2K_16, 0,1,16, false, 0, "R_IP2K_16", 0, 0xffff), | |
170 | /* A 32 bit absolute relocation. */ | |
171 | IP2K_HOWTO (R_IP2K_32, 0,2,32, false, 0, "R_IP2K_32", 0, 0xffffffff), | |
172 | /* A 8-bit data relocation for the FR9 field. Ninth bit is computed specially. */ | |
173 | IP2K_HOWTO (R_IP2K_FR9, 0,1,9, false, 0, "R_IP2K_FR9", 0, 0x00ff), | |
174 | /* A 4-bit data relocation. */ | |
175 | IP2K_HOWTO (R_IP2K_BANK, 8,1,4, false, 0, "R_IP2K_BANK", 0, 0x000f), | |
176 | /* A 13-bit insn relocation - word address => right-shift 1 bit extra. */ | |
177 | IP2K_HOWTO (R_IP2K_ADDR16CJP, 1,1,13, false, 0, "R_IP2K_ADDR16CJP", 0, 0x1fff), | |
178 | /* A 3-bit insn relocation - word address => right-shift 1 bit extra. */ | |
179 | IP2K_HOWTO (R_IP2K_PAGE3, 14,1,3, false, 0, "R_IP2K_PAGE3", 0, 0x0007), | |
180 | /* Two 8-bit data relocations. */ | |
181 | IP2K_HOWTO (R_IP2K_LO8DATA, 0,1,8, false, 0, "R_IP2K_LO8DATA", 0, 0x00ff), | |
182 | IP2K_HOWTO (R_IP2K_HI8DATA, 8,1,8, false, 0, "R_IP2K_HI8DATA", 0, 0x00ff), | |
183 | /* Two 8-bit insn relocations. word address => right-shift 1 bit extra. */ | |
184 | IP2K_HOWTO (R_IP2K_LO8INSN, 1,1,8, false, 0, "R_IP2K_LO8INSN", 0, 0x00ff), | |
185 | IP2K_HOWTO (R_IP2K_HI8INSN, 9,1,8, false, 0, "R_IP2K_HI8INSN", 0, 0x00ff), | |
186 | ||
187 | /* Special 1 bit relocation for SKIP instructions. */ | |
188 | IP2K_HOWTO (R_IP2K_PC_SKIP, 1,1,1, false, 12, "R_IP2K_PC_SKIP", 0xfffe, 0x1000), | |
189 | /* 16 bit word address. */ | |
190 | IP2K_HOWTO (R_IP2K_TEXT, 1,1,16, false, 0, "R_IP2K_TEXT", 0, 0xffff), | |
191 | /* A 7-bit offset relocation for the FR9 field. Eigth and ninth bit comes from insn. */ | |
192 | IP2K_HOWTO (R_IP2K_FR_OFFSET, 0,1,9, false, 0, "R_IP2K_FR_OFFSET", 0x180, 0x007f), | |
193 | /* Bits 23:16 of an address. */ | |
194 | IP2K_HOWTO (R_IP2K_EX8DATA, 16,1,8, false, 0, "R_IP2K_EX8DATA", 0, 0x00ff), | |
195 | }; | |
196 | ||
197 | ||
198 | /* Map BFD reloc types to IP2K ELF reloc types. */ | |
199 | static reloc_howto_type * | |
200 | ip2k_reloc_type_lookup (abfd, code) | |
201 | bfd * abfd ATTRIBUTE_UNUSED; | |
202 | bfd_reloc_code_real_type code; | |
203 | { | |
204 | /* Note that the ip2k_elf_howto_table is indxed by the R_ | |
205 | constants. Thus, the order that the howto records appear in the | |
206 | table *must* match the order of the relocation types defined in | |
207 | include/elf/ip2k.h. */ | |
208 | ||
209 | switch (code) | |
210 | { | |
211 | case BFD_RELOC_NONE: | |
212 | return &ip2k_elf_howto_table[ (int) R_IP2K_NONE]; | |
213 | case BFD_RELOC_16: | |
214 | return &ip2k_elf_howto_table[ (int) R_IP2K_16]; | |
215 | case BFD_RELOC_32: | |
216 | return &ip2k_elf_howto_table[ (int) R_IP2K_32]; | |
217 | case BFD_RELOC_IP2K_FR9: | |
218 | return &ip2k_elf_howto_table[ (int) R_IP2K_FR9]; | |
219 | case BFD_RELOC_IP2K_BANK: | |
220 | return &ip2k_elf_howto_table[ (int) R_IP2K_BANK]; | |
221 | case BFD_RELOC_IP2K_ADDR16CJP: | |
222 | return &ip2k_elf_howto_table[ (int) R_IP2K_ADDR16CJP]; | |
223 | case BFD_RELOC_IP2K_PAGE3: | |
224 | return &ip2k_elf_howto_table[ (int) R_IP2K_PAGE3]; | |
225 | case BFD_RELOC_IP2K_LO8DATA: | |
226 | return &ip2k_elf_howto_table[ (int) R_IP2K_LO8DATA]; | |
227 | case BFD_RELOC_IP2K_HI8DATA: | |
228 | return &ip2k_elf_howto_table[ (int) R_IP2K_HI8DATA]; | |
229 | case BFD_RELOC_IP2K_LO8INSN: | |
230 | return &ip2k_elf_howto_table[ (int) R_IP2K_LO8INSN]; | |
231 | case BFD_RELOC_IP2K_HI8INSN: | |
232 | return &ip2k_elf_howto_table[ (int) R_IP2K_HI8INSN]; | |
233 | case BFD_RELOC_IP2K_PC_SKIP: | |
234 | return &ip2k_elf_howto_table[ (int) R_IP2K_PC_SKIP]; | |
235 | case BFD_RELOC_IP2K_TEXT: | |
236 | return &ip2k_elf_howto_table[ (int) R_IP2K_TEXT]; | |
237 | case BFD_RELOC_IP2K_FR_OFFSET: | |
238 | return &ip2k_elf_howto_table[ (int) R_IP2K_FR_OFFSET]; | |
239 | case BFD_RELOC_IP2K_EX8DATA: | |
240 | return &ip2k_elf_howto_table[ (int) R_IP2K_EX8DATA]; | |
241 | default: | |
242 | /* Pacify gcc -Wall. */ | |
243 | return NULL; | |
244 | } | |
245 | return NULL; | |
246 | } | |
247 | ||
248 | #define PAGENO(ABSADDR) ((ABSADDR) & 0x1C000) | |
249 | #define BASEADDR(SEC) ((SEC)->output_section->vma + (SEC)->output_offset) | |
250 | ||
251 | #define UNDEFINED_SYMBOL (~(bfd_vma)0) | |
252 | ||
253 | /* Return the value of the symbol associated with the relocation IREL. */ | |
254 | ||
255 | static bfd_vma | |
fd13ed0c | 256 | symbol_value (abfd, symtab_hdr, isymbuf, irel) |
cf88bb9f NC |
257 | bfd *abfd; |
258 | Elf_Internal_Shdr *symtab_hdr; | |
fd13ed0c | 259 | Elf32_Internal_Sym *isymbuf; |
cf88bb9f NC |
260 | Elf_Internal_Rela *irel; |
261 | { | |
262 | if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) | |
263 | { | |
fd13ed0c | 264 | Elf_Internal_Sym *isym; |
cf88bb9f NC |
265 | asection *sym_sec; |
266 | ||
fd13ed0c DC |
267 | isym = isymbuf + ELF32_R_SYM (irel->r_info); |
268 | if (isym->st_shndx == SHN_UNDEF) | |
cf88bb9f | 269 | sym_sec = bfd_und_section_ptr; |
fd13ed0c | 270 | else if (isym->st_shndx == SHN_ABS) |
cf88bb9f | 271 | sym_sec = bfd_abs_section_ptr; |
fd13ed0c | 272 | else if (isym->st_shndx == SHN_COMMON) |
cf88bb9f NC |
273 | sym_sec = bfd_com_section_ptr; |
274 | else | |
fd13ed0c | 275 | sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); |
cf88bb9f | 276 | |
fd13ed0c | 277 | return isym->st_value + BASEADDR (sym_sec); |
cf88bb9f NC |
278 | } |
279 | else | |
280 | { | |
281 | unsigned long indx; | |
282 | struct elf_link_hash_entry *h; | |
283 | ||
284 | indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info; | |
285 | h = elf_sym_hashes (abfd)[indx]; | |
286 | BFD_ASSERT (h != NULL); | |
287 | ||
288 | if (h->root.type != bfd_link_hash_defined | |
289 | && h->root.type != bfd_link_hash_defweak) | |
290 | return UNDEFINED_SYMBOL; | |
291 | ||
292 | return (h->root.u.def.value + BASEADDR (h->root.u.def.section)); | |
293 | } | |
294 | } | |
295 | ||
296 | /* Determine if the instruction sequence matches that for | |
297 | the prologue of a switch dispatch table with fewer than | |
298 | 128 entries. | |
299 | ||
300 | sc | |
301 | page $nnn0 | |
302 | jmp $nnn0 | |
303 | add w,wreg | |
304 | add pcl,w | |
305 | addr=> | |
306 | page $nnn1 | |
307 | jmp $nnn1 | |
308 | page $nnn2 | |
309 | jmp $nnn2 | |
310 | ... | |
311 | page $nnnN | |
312 | jmp $nnnN | |
313 | ||
314 | After relaxation. | |
315 | sc | |
316 | page $nnn0 | |
317 | jmp $nnn0 | |
318 | add pcl,w | |
319 | addr=> | |
320 | jmp $nnn1 | |
321 | jmp $nnn2 | |
322 | ... | |
323 | jmp $nnnN */ | |
324 | ||
325 | static boolean | |
326 | is_switch_128_dispatch_table_p (abfd, addr, relaxed, misc) | |
327 | bfd *abfd ATTRIBUTE_UNUSED; | |
328 | bfd_vma addr; | |
329 | boolean relaxed; | |
330 | struct misc *misc; | |
331 | { | |
332 | bfd_byte code0, code1; | |
333 | ||
334 | if (addr < (3 * 2)) | |
335 | return false; | |
336 | ||
337 | code0 = bfd_get_8 (abfd, misc->contents + addr - 2); | |
338 | code1 = bfd_get_8 (abfd, misc->contents + addr - 1); | |
339 | ||
340 | /* Is it ADD PCL,W */ | |
341 | if (! IS_ADD_PCL_W_OPCODE (code0, code1)) | |
342 | return false; | |
343 | ||
344 | code0 = bfd_get_8 (abfd, misc->contents + addr - 4); | |
345 | code1 = bfd_get_8 (abfd, misc->contents + addr - 3); | |
346 | ||
347 | if (relaxed) | |
348 | /* Is it ADD W,WREG */ | |
349 | return ! IS_ADD_W_WREG_OPCODE (code0, code1); | |
350 | ||
351 | else | |
352 | { | |
353 | /* Is it ADD W,WREG */ | |
354 | if (! IS_ADD_W_WREG_OPCODE (code0, code1)) | |
355 | return false; | |
356 | ||
357 | code0 = bfd_get_8 (abfd, misc->contents + addr - 6); | |
358 | code1 = bfd_get_8 (abfd, misc->contents + addr - 5); | |
359 | ||
360 | /* Is it JMP $nnnn */ | |
361 | if (! IS_JMP_OPCODE (code0, code1)) | |
362 | return false; | |
363 | } | |
364 | ||
365 | /* It looks like we've found the prologue for | |
366 | a 1-127 entry switch dispatch table. */ | |
367 | return true; | |
368 | } | |
369 | ||
370 | /* Determine if the instruction sequence matches that for | |
371 | the prologue switch dispatch table with fewer than | |
372 | 256 entries but more than 127. | |
373 | ||
374 | Before relaxation. | |
375 | push %lo8insn(label) ; Push address of table | |
376 | push %hi8insn(label) | |
377 | add w,wreg ; index*2 => offset | |
378 | snc ; CARRY SET? | |
379 | inc 1(sp) ; Propagate MSB into table address | |
380 | add 2(sp),w ; Add low bits of offset to table address | |
381 | snc ; and handle any carry-out | |
382 | inc 1(sp) | |
383 | addr=> | |
384 | page __indjmp ; Do an indirect jump to that location | |
385 | jmp __indjmp | |
386 | label: ; case dispatch table starts here | |
387 | page $nnn1 | |
388 | jmp $nnn1 | |
389 | page $nnn2 | |
390 | jmp $nnn2 | |
391 | ... | |
392 | page $nnnN | |
393 | jmp $nnnN | |
394 | ||
395 | After relaxation. | |
396 | push %lo8insn(label) ; Push address of table | |
397 | push %hi8insn(label) | |
398 | add 2(sp),w ; Add low bits of offset to table address | |
399 | snc ; and handle any carry-out | |
400 | inc 1(sp) | |
401 | addr=> | |
402 | page __indjmp ; Do an indirect jump to that location | |
403 | jmp __indjmp | |
404 | label: ; case dispatch table starts here | |
405 | jmp $nnn1 | |
406 | jmp $nnn2 | |
407 | ... | |
408 | jmp $nnnN */ | |
409 | ||
410 | static boolean | |
411 | is_switch_256_dispatch_table_p (abfd, addr, relaxed, misc) | |
412 | bfd *abfd ATTRIBUTE_UNUSED; | |
413 | bfd_vma addr; | |
414 | boolean relaxed; | |
415 | struct misc *misc; | |
416 | { | |
417 | bfd_byte code0, code1; | |
418 | ||
419 | if (addr < (8 * 2)) | |
420 | return false; | |
421 | ||
422 | code0 = bfd_get_8 (abfd, misc->contents + addr - 2); | |
423 | code1 = bfd_get_8 (abfd, misc->contents + addr - 1); | |
424 | ||
425 | /* Is it INC 1(SP). */ | |
426 | if (! IS_INC_1_SP_OPCODE (code0, code1)) | |
427 | return false; | |
428 | ||
429 | code0 = bfd_get_8 (abfd, misc->contents + addr - 4); | |
430 | code1 = bfd_get_8 (abfd, misc->contents + addr - 3); | |
431 | ||
432 | /* Is it SNC. */ | |
433 | if (! IS_SNC_OPCODE (code0, code1)) | |
434 | return false; | |
435 | ||
436 | code0 = bfd_get_8 (abfd, misc->contents + addr - 6); | |
437 | code1 = bfd_get_8 (abfd, misc->contents + addr - 5); | |
438 | ||
439 | /* Is it ADD 2(SP),W. */ | |
440 | if (! IS_ADD_2_SP_W_OPCODE (code0, code1)) | |
441 | return false; | |
442 | ||
443 | code0 = bfd_get_8 (abfd, misc->contents + addr - 8); | |
444 | code1 = bfd_get_8 (abfd, misc->contents + addr - 7); | |
445 | ||
446 | if (relaxed) | |
447 | /* Is it INC 1(SP). */ | |
448 | return ! IS_INC_1_SP_OPCODE (code0, code1); | |
449 | ||
450 | else | |
451 | { | |
452 | /* Is it INC 1(SP). */ | |
453 | if (! IS_INC_1_SP_OPCODE (code0, code1)) | |
454 | return false; | |
455 | ||
456 | code0 = bfd_get_8 (abfd, misc->contents + addr - 10); | |
457 | code1 = bfd_get_8 (abfd, misc->contents + addr - 9); | |
458 | ||
459 | /* Is it SNC. */ | |
460 | if (! IS_SNC_OPCODE (code0, code1)) | |
461 | return false; | |
462 | ||
463 | code0 = bfd_get_8 (abfd, misc->contents + addr - 12); | |
464 | code1 = bfd_get_8 (abfd, misc->contents + addr - 11); | |
465 | ||
466 | /* Is it ADD W,WREG. */ | |
467 | if (! IS_ADD_W_WREG_OPCODE (code0, code1)) | |
468 | return false; | |
469 | } | |
470 | ||
471 | /* It looks like we've found the prologue for | |
472 | a 128-255 entry switch dispatch table. */ | |
473 | return true; | |
474 | } | |
475 | ||
476 | static boolean | |
477 | relax_switch_dispatch_tables_pass1 (abfd, sec, addr, misc) | |
478 | bfd *abfd; | |
479 | asection *sec; | |
480 | bfd_vma addr; | |
481 | struct misc *misc; | |
482 | { | |
483 | if (addr + 3 < sec->_cooked_size) | |
484 | { | |
485 | bfd_byte code0 = bfd_get_8 (abfd, misc->contents + addr + 2); | |
486 | bfd_byte code1 = bfd_get_8 (abfd, misc->contents + addr + 3); | |
487 | ||
488 | if (IS_JMP_OPCODE (code0, code1) | |
489 | && is_switch_128_dispatch_table_p (abfd, addr, false, misc)) | |
490 | { | |
491 | /* Delete ADD W,WREG from prologue. */ | |
492 | ip2k_elf_relax_delete_bytes (abfd, sec, addr - (2 * 2), (1 * 2)); | |
493 | return true; | |
494 | } | |
495 | ||
496 | if (IS_JMP_OPCODE (code0, code1) | |
497 | && is_switch_256_dispatch_table_p (abfd, addr, false, misc)) | |
498 | { | |
499 | /* Delete ADD W,WREG; SNC ; INC 1(SP) from prologue. */ | |
500 | ip2k_elf_relax_delete_bytes (abfd, sec, addr - 6 * 2, 3 * 2); | |
501 | return true; | |
502 | } | |
503 | } | |
504 | ||
505 | return true; | |
506 | } | |
507 | ||
508 | static boolean | |
509 | unrelax_dispatch_table_entries (abfd, sec, first, last, changed, misc) | |
510 | bfd *abfd; | |
511 | asection *sec; | |
512 | bfd_vma first; | |
513 | bfd_vma last; | |
514 | boolean *changed; | |
515 | struct misc *misc; | |
516 | { | |
517 | bfd_vma addr = first; | |
518 | ||
519 | while (addr < last) | |
520 | { | |
521 | bfd_byte code0 = bfd_get_8 (abfd, misc->contents + addr); | |
522 | bfd_byte code1 = bfd_get_8 (abfd, misc->contents + addr + 1); | |
523 | ||
524 | /* We are only expecting to find PAGE or JMP insns | |
525 | in the dispatch table. If we find anything else | |
526 | something has gone wrong failed the relaxation | |
527 | which will cause the link to be aborted. */ | |
528 | ||
529 | if (IS_PAGE_OPCODE (code0, code1)) | |
530 | /* Skip the PAGE and JMP insns. */ | |
531 | addr += 4; | |
532 | else if (IS_JMP_OPCODE (code0, code1)) | |
533 | { | |
534 | Elf_Internal_Rela * irelend = misc->irelbase | |
535 | + sec->reloc_count; | |
536 | Elf_Internal_Rela * irel; | |
537 | ||
538 | /* Find the relocation entry. */ | |
539 | for (irel = misc->irelbase; irel < irelend; irel++) | |
540 | { | |
541 | if (irel->r_offset == addr | |
542 | && ELF32_R_TYPE (irel->r_info) == R_IP2K_ADDR16CJP) | |
543 | { | |
544 | if (! add_page_insn (abfd, sec, irel, misc)) | |
545 | /* Something has gone wrong. */ | |
546 | return false; | |
547 | ||
548 | *changed = true; | |
549 | break; | |
550 | } | |
551 | } | |
552 | ||
553 | /* If we fell off the end something has gone wrong. */ | |
554 | if (irel >= irelend) | |
555 | /* Something has gone wrong. */ | |
556 | return false; | |
557 | ||
558 | /* Skip the PAGE and JMP isns. */ | |
559 | addr += 4; | |
560 | /* Acount for the new PAGE insn. */ | |
561 | last += 2; | |
562 | } | |
563 | else | |
564 | /* Something has gone wrong. */ | |
565 | return false; | |
566 | } | |
567 | ||
568 | return true; | |
569 | } | |
570 | ||
571 | static boolean | |
572 | unrelax_switch_dispatch_tables_passN (abfd, sec, addr, changed, misc) | |
573 | bfd *abfd; | |
574 | asection *sec; | |
575 | bfd_vma addr; | |
576 | boolean *changed; | |
577 | struct misc *misc; | |
578 | { | |
579 | if (2 <= addr && (addr + 3) < sec->_cooked_size) | |
580 | { | |
581 | bfd_byte code0 = bfd_get_8 (abfd, misc->contents + addr - 2); | |
582 | bfd_byte code1 = bfd_get_8 (abfd, misc->contents + addr - 1); | |
583 | ||
584 | if (IS_PAGE_OPCODE (code0, code1)) | |
585 | { | |
586 | addr -= 2; | |
587 | code0 = bfd_get_8 (abfd, misc->contents + addr + 2); | |
588 | code1 = bfd_get_8 (abfd, misc->contents + addr + 3); | |
589 | } | |
590 | else | |
591 | { | |
592 | code0 = bfd_get_8 (abfd, misc->contents + addr); | |
593 | code1 = bfd_get_8 (abfd, misc->contents + addr + 1); | |
594 | } | |
595 | ||
596 | if (IS_JMP_OPCODE (code0, code1) | |
597 | && is_switch_128_dispatch_table_p (abfd, addr, true, misc)) | |
598 | { | |
599 | bfd_vma first = addr; | |
600 | bfd_vma last = first; | |
601 | boolean relaxed = true; | |
602 | ||
603 | /* On the final pass we must check if *all* entries in the | |
604 | dispatch table are relaxed. If *any* are not relaxed | |
605 | then we must unrelax *all* the entries in the dispach | |
606 | table and also unrelax the dispatch table prologue. */ | |
607 | ||
608 | /* Find the last entry in the dispach table. */ | |
609 | while (last < sec->_cooked_size) | |
610 | { | |
611 | code0 = bfd_get_8 (abfd, misc->contents + last); | |
612 | code1 = bfd_get_8 (abfd, misc->contents + last + 1); | |
613 | ||
614 | if (IS_PAGE_OPCODE (code0, code1)) | |
615 | relaxed = false; | |
616 | else if (! IS_JMP_OPCODE (code0, code1)) | |
617 | break; | |
618 | ||
619 | last += 2; | |
620 | } | |
621 | ||
622 | /* We should have found the end of the dispatch table | |
623 | before reaching the end of the section. If we've have | |
624 | reached the end then fail the relaxation which will | |
625 | cause the link to be aborted. */ | |
626 | if (last >= sec->_cooked_size) | |
627 | /* Something has gone wrong. */ | |
628 | return false; | |
629 | ||
630 | /* If we found an unrelaxed entry then | |
631 | unlrelax all the switch table entries. */ | |
632 | if (! relaxed ) | |
633 | { | |
634 | if (! unrelax_dispatch_table_entries (abfd, sec, first, | |
635 | last, changed, misc)) | |
636 | /* Something has gone wrong. */ | |
637 | return false; | |
638 | ||
639 | if (! is_switch_128_dispatch_table_p (abfd, addr, true, misc)) | |
640 | /* Something has gone wrong. */ | |
641 | return false; | |
642 | ||
643 | /* Unrelax the prologue. */ | |
644 | ||
645 | /* Insert an ADD W,WREG insnstruction. */ | |
646 | if (! ip2k_elf_relax_add_bytes (abfd, sec, | |
647 | addr - 2, | |
648 | add_w_wreg_opcode, | |
649 | sizeof (add_w_wreg_opcode), | |
650 | 0)) | |
651 | /* Something has gone wrong. */ | |
652 | return false; | |
653 | } | |
654 | ||
655 | return true; | |
656 | } | |
657 | ||
658 | if (IS_JMP_OPCODE (code0, code1) | |
659 | && is_switch_256_dispatch_table_p (abfd, addr, true, misc)) | |
660 | { | |
661 | bfd_vma first = addr; | |
662 | bfd_vma last; | |
663 | boolean relaxed = true; | |
664 | ||
665 | /* On the final pass we must check if *all* entries in the | |
666 | dispatch table are relaxed. If *any* are not relaxed | |
667 | then we must unrelax *all* the entries in the dispach | |
668 | table and also unrelax the dispatch table prologue. */ | |
669 | ||
670 | /* Note the 1st PAGE/JMP instructions are part of the | |
671 | prologue and can safely be relaxed. */ | |
672 | ||
673 | code0 = bfd_get_8 (abfd, misc->contents + first); | |
674 | code1 = bfd_get_8 (abfd, misc->contents + first + 1); | |
675 | ||
676 | if (IS_PAGE_OPCODE (code0, code1)) | |
677 | { | |
678 | first += 2; | |
679 | code0 = bfd_get_8 (abfd, misc->contents + first); | |
680 | code1 = bfd_get_8 (abfd, misc->contents + first + 1); | |
681 | } | |
682 | ||
683 | if (! IS_JMP_OPCODE (code0, code1)) | |
684 | /* Something has gone wrong. */ | |
685 | return false; | |
686 | ||
687 | first += 2; | |
688 | last = first; | |
689 | ||
690 | /* Find the last entry in the dispach table. */ | |
691 | while (last < sec->_cooked_size) | |
692 | { | |
693 | code0 = bfd_get_8 (abfd, misc->contents + last); | |
694 | code1 = bfd_get_8 (abfd, misc->contents + last + 1); | |
695 | ||
696 | if (IS_PAGE_OPCODE (code0, code1)) | |
697 | relaxed = false; | |
698 | else if (! IS_JMP_OPCODE (code0, code1)) | |
699 | break; | |
700 | ||
701 | last += 2; | |
702 | } | |
703 | ||
704 | /* We should have found the end of the dispatch table | |
705 | before reaching the end of the section. If we have | |
706 | reached the end of the section then fail the | |
707 | relaxation. */ | |
708 | if (last >= sec->_cooked_size) | |
709 | return false; | |
710 | ||
711 | /* If we found an unrelaxed entry then | |
712 | unrelax all the switch table entries. */ | |
713 | if (! relaxed) | |
714 | { | |
715 | if (! unrelax_dispatch_table_entries (abfd, sec, first, | |
716 | last, changed, misc)) | |
717 | return false; | |
718 | ||
719 | if (! is_switch_256_dispatch_table_p (abfd, addr, true, misc)) | |
720 | return false; | |
721 | ||
722 | /* Unrelax the prologue. */ | |
723 | ||
724 | /* Insert an INC 1(SP) insnstruction. */ | |
725 | if (! ip2k_elf_relax_add_bytes (abfd, sec, | |
726 | addr - 6, | |
727 | inc_1_sp_opcode, | |
728 | sizeof (inc_1_sp_opcode), | |
729 | 0)) | |
730 | return false; | |
731 | ||
732 | /* Insert an SNC insnstruction. */ | |
733 | if (! ip2k_elf_relax_add_bytes (abfd, sec, | |
734 | addr - 6, | |
735 | snc_opcode, | |
736 | sizeof (snc_opcode), | |
737 | 0)) | |
738 | return false; | |
739 | ||
740 | /* Insert an ADD W,WREG insnstruction. */ | |
741 | if (! ip2k_elf_relax_add_bytes (abfd, sec, | |
742 | addr - 6, | |
743 | add_w_wreg_opcode, | |
744 | sizeof (add_w_wreg_opcode), | |
745 | 0)) | |
746 | return false; | |
747 | } | |
748 | ||
749 | return true; | |
750 | } | |
751 | } | |
752 | ||
753 | return true; | |
754 | } | |
755 | ||
756 | /* This function handles relaxing for the ip2k. */ | |
757 | ||
758 | static boolean | |
759 | ip2k_elf_relax_section (abfd, sec, link_info, again) | |
760 | bfd *abfd; | |
761 | asection *sec; | |
762 | struct bfd_link_info *link_info; | |
763 | boolean *again; | |
764 | { | |
fd13ed0c DC |
765 | Elf_Internal_Shdr *symtab_hdr; |
766 | Elf_Internal_Rela *internal_relocs; | |
767 | bfd_byte *contents = NULL; | |
768 | Elf_Internal_Sym *isymbuf = NULL; | |
cf88bb9f NC |
769 | static asection * first_section = NULL; |
770 | static asection * last_section = NULL; | |
771 | static boolean changed = false; | |
772 | static boolean final_pass = false; | |
773 | static unsigned int pass = 0; | |
774 | struct misc misc; | |
775 | asection *stab; | |
776 | ||
777 | /* Assume nothing changes. */ | |
778 | *again = false; | |
779 | ||
780 | if (first_section == NULL) | |
781 | first_section = sec; | |
782 | ||
783 | if (first_section == sec) | |
784 | { | |
785 | changed = false; | |
786 | pass++; | |
787 | } | |
788 | ||
789 | /* If we make too many passes then it's a sign that | |
790 | something is wrong and we fail the relaxation. | |
791 | Note if everything is working correctly then the | |
792 | relaxation should converge reasonably quickly. */ | |
793 | if (pass == 4096) | |
794 | return false; | |
795 | ||
796 | /* We don't have to do anything for a relocatable link, | |
797 | if this section does not have relocs, or if this is | |
798 | not a code section. */ | |
799 | if (link_info->relocateable | |
800 | || (sec->flags & SEC_RELOC) == 0 | |
801 | || sec->reloc_count == 0 | |
802 | || (sec->flags & SEC_CODE) == 0) | |
803 | return true; | |
804 | ||
805 | if (pass == 1) | |
806 | last_section = sec; | |
807 | ||
cf88bb9f NC |
808 | /* If this is the first time we have been called |
809 | for this section, initialise the cooked size. */ | |
810 | if (sec->_cooked_size == 0) | |
811 | sec->_cooked_size = sec->_raw_size; | |
812 | ||
fd13ed0c | 813 | symtab_hdr = &elf_tdata (abfd)->symtab_hdr; |
cf88bb9f | 814 | |
fd13ed0c DC |
815 | internal_relocs = _bfd_elf32_link_read_relocs (abfd, sec, NULL, |
816 | (Elf_Internal_Rela *)NULL, | |
817 | link_info->keep_memory); | |
818 | if (internal_relocs == NULL) | |
819 | goto error_return; | |
cf88bb9f NC |
820 | |
821 | /* Make sure the stac.rela stuff gets read in. */ | |
822 | stab = bfd_get_section_by_name (abfd, ".stab"); | |
823 | ||
824 | if (stab) | |
825 | { | |
826 | /* So stab does exits. */ | |
827 | Elf_Internal_Rela * irelbase; | |
828 | ||
829 | irelbase = _bfd_elf32_link_read_relocs (abfd, stab, NULL, | |
830 | (Elf_Internal_Rela *)NULL, | |
831 | link_info->keep_memory); | |
832 | } | |
833 | ||
834 | /* Get section contents cached copy if it exists. */ | |
fd13ed0c | 835 | if (contents == NULL) |
cf88bb9f | 836 | { |
fd13ed0c DC |
837 | /* Get cached copy if it exists. */ |
838 | if (elf_section_data (sec)->this_hdr.contents != NULL) | |
839 | contents = elf_section_data (sec)->this_hdr.contents; | |
840 | else | |
cf88bb9f | 841 | { |
fd13ed0c DC |
842 | /* Go get them off disk. */ |
843 | contents = (bfd_byte *) bfd_malloc (sec->_raw_size); | |
844 | if (contents == NULL) | |
845 | goto error_return; | |
846 | ||
847 | if (! bfd_get_section_contents (abfd, sec, contents, | |
848 | (file_ptr) 0, sec->_raw_size)) | |
849 | goto error_return; | |
cf88bb9f NC |
850 | } |
851 | } | |
fd13ed0c | 852 | |
cf88bb9f | 853 | /* Read this BFD's symbols cached copy if it exists. */ |
fd13ed0c | 854 | if (isymbuf == NULL && symtab_hdr->sh_info != 0) |
cf88bb9f | 855 | { |
fd13ed0c DC |
856 | isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; |
857 | if (isymbuf == NULL) | |
858 | isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, | |
859 | symtab_hdr->sh_info, 0, | |
860 | NULL, NULL, NULL); | |
861 | if (isymbuf == NULL) | |
862 | goto error_return; | |
cf88bb9f NC |
863 | } |
864 | ||
fd13ed0c DC |
865 | misc.symtab_hdr = symtab_hdr; |
866 | misc.isymbuf = isymbuf; | |
867 | misc.irelbase = internal_relocs; | |
868 | misc.contents = contents; | |
869 | ||
cf88bb9f NC |
870 | /* This is where all the relaxation actually get done. */ |
871 | ||
872 | if (pass == 1) | |
873 | { | |
874 | /* On the first pass we remove *all* page instructions and | |
875 | relax the prolog for switch dispatch tables. This gets | |
876 | us to the starting point for subsequent passes where | |
877 | we add page instructions back in as needed. */ | |
878 | ||
879 | if (! ip2k_elf_relax_section_pass1 (abfd, sec, again, &misc)) | |
fd13ed0c | 880 | goto error_return; |
cf88bb9f NC |
881 | |
882 | changed |= *again; | |
883 | } | |
884 | else | |
885 | { | |
886 | /* Add page instructions back in as needed but we ignore | |
887 | the issue with sections (functions) crossing a page | |
888 | boundary until we have converged to an approximate | |
889 | solution (i.e. nothing has changed on this relaxation | |
890 | pass) and we then know roughly where the page boundaries | |
891 | will end up. | |
892 | ||
893 | After we have have converged to an approximate solution | |
894 | we set the final pass flag and continue relaxing. On these | |
895 | final passes if a section (function) cross page boundary | |
896 | we will add *all* the page instructions back into such | |
897 | sections. | |
898 | ||
899 | After adding *all* page instructions back into a section | |
900 | which crosses a page bounbdary we reset the final pass flag | |
901 | so the we will again interate until we find a new approximate | |
902 | solution which is closer to the final solution. */ | |
903 | ||
fd13ed0c DC |
904 | if (! ip2k_elf_relax_section_passN (abfd, sec, again, &final_pass, |
905 | &misc)) | |
906 | goto error_return; | |
cf88bb9f NC |
907 | |
908 | changed |= *again; | |
909 | ||
910 | /* If nothing has changed on this relaxation | |
911 | pass restart the final relaxaton pass. */ | |
912 | if (! changed && last_section == sec) | |
913 | { | |
914 | /* If this was the final pass and we didn't reset | |
915 | the final pass flag then we are done, otherwise | |
916 | do another final pass. */ | |
917 | if (! final_pass) | |
918 | { | |
919 | final_pass = true; | |
920 | *again = true; | |
921 | } | |
922 | } | |
923 | } | |
924 | ||
925 | /* Perform some house keeping after relaxing the section. */ | |
926 | ||
fd13ed0c DC |
927 | if (isymbuf != NULL |
928 | && symtab_hdr->contents != (unsigned char *) isymbuf) | |
cf88bb9f NC |
929 | { |
930 | if (! link_info->keep_memory) | |
fd13ed0c | 931 | free (isymbuf); |
cf88bb9f | 932 | else |
fd13ed0c | 933 | symtab_hdr->contents = (unsigned char *) isymbuf; |
cf88bb9f NC |
934 | } |
935 | ||
fd13ed0c DC |
936 | if (contents != NULL |
937 | && elf_section_data (sec)->this_hdr.contents != contents) | |
cf88bb9f NC |
938 | { |
939 | if (! link_info->keep_memory) | |
fd13ed0c | 940 | free (contents); |
cf88bb9f NC |
941 | else |
942 | { | |
fd13ed0c DC |
943 | /* Cache the section contents for elf_link_input_bfd. */ |
944 | elf_section_data (sec)->this_hdr.contents = contents; | |
cf88bb9f | 945 | } |
cf88bb9f NC |
946 | } |
947 | ||
fd13ed0c DC |
948 | if (internal_relocs != NULL |
949 | && elf_section_data (sec)->relocs != internal_relocs) | |
950 | free (internal_relocs); | |
cf88bb9f | 951 | |
fd13ed0c | 952 | return true; |
cf88bb9f | 953 | |
fd13ed0c DC |
954 | error_return: |
955 | if (isymbuf != NULL | |
956 | && symtab_hdr->contents != (unsigned char *) isymbuf) | |
957 | free (isymbuf); | |
958 | if (contents != NULL | |
959 | && elf_section_data (sec)->this_hdr.contents != contents) | |
960 | free (contents); | |
961 | if (internal_relocs != NULL | |
962 | && elf_section_data (sec)->relocs != internal_relocs) | |
963 | free (internal_relocs); | |
964 | return false; | |
cf88bb9f NC |
965 | } |
966 | ||
967 | /* This function handles relaxation during the first pass. */ | |
968 | ||
969 | static boolean | |
970 | ip2k_elf_relax_section_pass1 (abfd, sec, again, misc) | |
971 | bfd *abfd; | |
972 | asection *sec; | |
973 | boolean *again; | |
974 | struct misc * misc; | |
975 | { | |
976 | Elf_Internal_Rela *irelend = misc->irelbase + sec->reloc_count; | |
977 | Elf_Internal_Rela *irel; | |
978 | ||
979 | /* Walk thru the section looking for relaxation opertunities. */ | |
980 | for (irel = misc->irelbase; irel < irelend; irel++) | |
981 | { | |
982 | if (ELF32_R_TYPE (irel->r_info) == (int) R_IP2K_PAGE3) | |
983 | { | |
984 | bfd_byte code0 = bfd_get_8 (abfd, | |
985 | misc->contents + irel->r_offset); | |
986 | bfd_byte code1 = bfd_get_8 (abfd, | |
987 | misc->contents + irel->r_offset + 1); | |
988 | ||
989 | /* Verify that this is the PAGE opcode. */ | |
990 | if (IS_PAGE_OPCODE (code0, code1)) | |
991 | { | |
992 | /* Note that we've changed the relocs, section contents, etc. */ | |
993 | elf_section_data (sec)->relocs = misc->irelbase; | |
cf88bb9f | 994 | elf_section_data (sec)->this_hdr.contents = misc->contents; |
fd13ed0c | 995 | misc->symtab_hdr->contents = (bfd_byte *) misc->isymbuf; |
cf88bb9f NC |
996 | |
997 | /* Handle switch dispatch tables/prologues. */ | |
998 | if (! relax_switch_dispatch_tables_pass1 (abfd, sec, | |
999 | irel->r_offset, misc)) | |
1000 | return false; | |
1001 | ||
1002 | /* Fix the relocation's type. */ | |
1003 | irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), | |
1004 | R_IP2K_NONE); | |
1005 | ||
1006 | /* Delete the PAGE insn. */ | |
1007 | if (! ip2k_elf_relax_delete_bytes (abfd, sec, | |
1008 | irel->r_offset, | |
1009 | sizeof (page_opcode))) | |
1010 | return false; | |
1011 | ||
1012 | /* That will change things, so, we should relax again. | |
1013 | Note that this is not required, and it may be slow. */ | |
1014 | *again = true; | |
1015 | } | |
1016 | } | |
1017 | } | |
1018 | ||
1019 | return true; | |
1020 | } | |
1021 | ||
1022 | /* This function handles relaxation for 2nd and subsequent passes. */ | |
1023 | ||
1024 | static boolean | |
1025 | ip2k_elf_relax_section_passN (abfd, sec, again, final_pass, misc) | |
1026 | bfd *abfd; | |
1027 | asection *sec; | |
1028 | boolean *again; | |
1029 | boolean *final_pass; | |
1030 | struct misc * misc; | |
1031 | { | |
1032 | Elf_Internal_Rela *irelend = misc->irelbase + sec->reloc_count; | |
1033 | Elf_Internal_Rela *irel; | |
1034 | boolean add_all; | |
1035 | ||
1036 | /* If we are on the final relaxation pass and the section crosses | |
1037 | then set a flag to indicate that *all* page instructions need | |
1038 | to be added back into this section. */ | |
1039 | if (*final_pass) | |
1040 | { | |
1041 | add_all = (PAGENO (BASEADDR (sec)) | |
1042 | != PAGENO (BASEADDR (sec) + sec->_cooked_size)); | |
1043 | ||
1044 | /* If this section crosses a page boundary set the crossed | |
1045 | page boundary flag. */ | |
1046 | if (add_all) | |
1047 | sec->userdata = sec; | |
1048 | else | |
1049 | { | |
1050 | /* If the section had previously crossed a page boundary | |
1051 | but on this pass does not then reset crossed page | |
1052 | boundary flag and rerun the 1st relaxation pass on | |
1053 | this section. */ | |
1054 | if (sec->userdata) | |
1055 | { | |
1056 | sec->userdata = NULL; | |
1057 | if (! ip2k_elf_relax_section_pass1 (abfd, sec, again, misc)) | |
1058 | return false; | |
1059 | } | |
1060 | } | |
1061 | } | |
1062 | else | |
1063 | add_all = false; | |
1064 | ||
1065 | /* Walk thru the section looking for call/jmp | |
1066 | instructions which need a page instruction. */ | |
1067 | for (irel = misc->irelbase; irel < irelend; irel++) | |
1068 | { | |
1069 | if (ELF32_R_TYPE (irel->r_info) == (int) R_IP2K_ADDR16CJP) | |
1070 | { | |
1071 | /* Get the value of the symbol referred to by the reloc. */ | |
fd13ed0c | 1072 | bfd_vma symval = symbol_value (abfd, misc->symtab_hdr, misc->isymbuf, |
cf88bb9f NC |
1073 | irel); |
1074 | bfd_byte code0, code1; | |
1075 | ||
1076 | if (symval == UNDEFINED_SYMBOL) | |
1077 | { | |
1078 | /* This appears to be a reference to an undefined | |
1079 | symbol. Just ignore it--it will be caught by the | |
1080 | regular reloc processing. */ | |
1081 | continue; | |
1082 | } | |
1083 | ||
1084 | /* For simplicity of coding, we are going to modify the section | |
1085 | contents, the section relocs, and the BFD symbol table. We | |
1086 | must tell the rest of the code not to free up this | |
1087 | information. It would be possible to instead create a table | |
1088 | of changes which have to be made, as is done in coff-mips.c; | |
1089 | that would be more work, but would require less memory when | |
1090 | the linker is run. */ | |
1091 | ||
1092 | /* Get the opcode. */ | |
1093 | code0 = bfd_get_8 (abfd, misc->contents + irel->r_offset); | |
1094 | code1 = bfd_get_8 (abfd, misc->contents + irel->r_offset + 1); | |
1095 | ||
1096 | if (IS_JMP_OPCODE (code0, code1) || IS_CALL_OPCODE (code0, code1)) | |
1097 | { | |
1098 | if (*final_pass) | |
1099 | { | |
1100 | if (! unrelax_switch_dispatch_tables_passN (abfd, sec, | |
1101 | irel->r_offset, | |
1102 | again, misc)) | |
1103 | return false; | |
1104 | ||
1105 | if (*again) | |
1106 | add_all = false; | |
1107 | } | |
1108 | ||
1109 | code0 = bfd_get_8 (abfd, misc->contents + irel->r_offset - 2); | |
1110 | code1 = bfd_get_8 (abfd, misc->contents + irel->r_offset - 1); | |
1111 | ||
1112 | if (! IS_PAGE_OPCODE (code0, code1)) | |
1113 | { | |
1114 | bfd_vma value = symval + irel->r_addend; | |
1115 | bfd_vma addr = BASEADDR (sec) + irel->r_offset; | |
1116 | ||
1117 | if (add_all || PAGENO (addr) != PAGENO (value)) | |
1118 | { | |
1119 | if (! add_page_insn (abfd, sec, irel, misc)) | |
1120 | return false; | |
1121 | ||
1122 | /* That will have changed things, so, we must relax again. */ | |
1123 | *again = true; | |
1124 | } | |
1125 | } | |
1126 | } | |
1127 | } | |
1128 | } | |
1129 | ||
1130 | /* If anything changed reset the final pass flag. */ | |
1131 | if (*again) | |
1132 | *final_pass = false; | |
1133 | ||
1134 | return true; | |
1135 | } | |
1136 | ||
1137 | /* Parts of a Stabs entry. */ | |
1138 | ||
1139 | #define STRDXOFF (0) | |
1140 | #define TYPEOFF (4) | |
1141 | #define OTHEROFF (5) | |
1142 | #define DESCOFF (6) | |
1143 | #define VALOFF (8) | |
1144 | #define STABSIZE (12) | |
1145 | ||
1146 | /* Adjust all the relocations entries after adding or inserting instructions. */ | |
1147 | ||
1148 | static void | |
1149 | adjust_all_relocations (abfd, sec, addr, endaddr, count, noadj) | |
1150 | bfd *abfd; | |
1151 | asection *sec; | |
1152 | bfd_vma addr; | |
1153 | bfd_vma endaddr; | |
1154 | int count; | |
1155 | int noadj; | |
1156 | { | |
1157 | Elf_Internal_Shdr *symtab_hdr; | |
fd13ed0c DC |
1158 | Elf_Internal_Sym *isymbuf, *isym, *isymend; |
1159 | unsigned int shndx; | |
cf88bb9f NC |
1160 | bfd_byte *contents; |
1161 | Elf_Internal_Rela *irel, *irelend, *irelbase; | |
fd13ed0c DC |
1162 | struct elf_link_hash_entry **sym_hashes; |
1163 | struct elf_link_hash_entry **end_hashes; | |
1164 | unsigned int symcount; | |
cf88bb9f NC |
1165 | |
1166 | symtab_hdr = &elf_tdata (abfd)->symtab_hdr; | |
fd13ed0c | 1167 | isymbuf = (Elf32_Internal_Sym *) symtab_hdr->contents; |
cf88bb9f NC |
1168 | |
1169 | shndx = _bfd_elf_section_from_bfd_section (abfd, sec); | |
1170 | ||
1171 | contents = elf_section_data (sec)->this_hdr.contents; | |
1172 | ||
1173 | irelbase = elf_section_data (sec)->relocs; | |
1174 | irelend = irelbase + sec->reloc_count; | |
1175 | ||
1176 | for (irel = irelbase; irel < irelend; irel++) | |
1177 | { | |
1178 | if (ELF32_R_TYPE (irel->r_info) != R_IP2K_NONE) | |
1179 | { | |
1180 | /* Get the value of the symbol referred to by the reloc. */ | |
1181 | if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) | |
1182 | { | |
cf88bb9f | 1183 | asection *sym_sec; |
cf88bb9f NC |
1184 | |
1185 | /* A local symbol. */ | |
fd13ed0c DC |
1186 | isym = isymbuf + ELF32_R_SYM (irel->r_info); |
1187 | sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); | |
1188 | ||
1189 | if (isym->st_shndx == shndx) | |
cf88bb9f NC |
1190 | { |
1191 | bfd_vma baseaddr = BASEADDR (sec); | |
fd13ed0c | 1192 | bfd_vma symval = BASEADDR (sym_sec) + isym->st_value |
cf88bb9f NC |
1193 | + irel->r_addend; |
1194 | ||
1195 | if ((baseaddr + addr + noadj) <= symval | |
1196 | && symval < (baseaddr + endaddr)) | |
1197 | irel->r_addend += count; | |
1198 | } | |
1199 | } | |
1200 | } | |
1201 | ||
1202 | /* Do this only for PC space relocations. */ | |
1203 | if (addr <= irel->r_offset && irel->r_offset < endaddr) | |
1204 | irel->r_offset += count; | |
1205 | } | |
1206 | ||
cf88bb9f NC |
1207 | /* When adding an instruction back it is sometimes necessary to move any |
1208 | global or local symbol that was referencing the first instruction of | |
1209 | the moved block to refer to the first instruction of the inserted block. | |
1210 | ||
1211 | For example adding a PAGE instruction before a CALL or JMP requires | |
1212 | that any label on the CALL or JMP is moved to the PAGE insn. */ | |
1213 | addr += noadj; | |
1214 | ||
1215 | /* Adjust the local symbols defined in this section. */ | |
fd13ed0c DC |
1216 | isymend = isymbuf + symtab_hdr->sh_info; |
1217 | for (isym = isymbuf; isym < isymend; isym++) | |
cf88bb9f | 1218 | { |
fd13ed0c DC |
1219 | if (isym->st_shndx == shndx |
1220 | && addr <= isym->st_value | |
1221 | && isym->st_value < endaddr) | |
1222 | isym->st_value += count; | |
cf88bb9f NC |
1223 | } |
1224 | ||
fd13ed0c DC |
1225 | /* Now adjust the global symbols defined in this section. */ |
1226 | symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym) | |
1227 | - symtab_hdr->sh_info); | |
1228 | sym_hashes = elf_sym_hashes (abfd); | |
1229 | end_hashes = sym_hashes + symcount; | |
1230 | for (; sym_hashes < end_hashes; sym_hashes++) | |
cf88bb9f | 1231 | { |
fd13ed0c DC |
1232 | struct elf_link_hash_entry *sym_hash = *sym_hashes; |
1233 | if ((sym_hash->root.type == bfd_link_hash_defined | |
1234 | || sym_hash->root.type == bfd_link_hash_defweak) | |
1235 | && sym_hash->root.u.def.section == sec) | |
1236 | { | |
cf88bb9f NC |
1237 | if (addr <= sym_hash->root.u.def.value |
1238 | && sym_hash->root.u.def.value < endaddr) | |
1239 | { | |
cf88bb9f | 1240 | sym_hash->root.u.def.value += count; |
cf88bb9f | 1241 | } |
fd13ed0c | 1242 | } |
cf88bb9f NC |
1243 | } |
1244 | ||
1245 | return; | |
1246 | } | |
1247 | ||
1248 | static boolean | |
1249 | add_page_insn (abfd, sec, irel, misc) | |
1250 | bfd *abfd; | |
1251 | asection *sec; | |
1252 | Elf_Internal_Rela *irel; | |
1253 | struct misc *misc; | |
1254 | { | |
1255 | /* Note that we've changed the relocs, section contents, etc. */ | |
1256 | elf_section_data (sec)->relocs = misc->irelbase; | |
cf88bb9f | 1257 | elf_section_data (sec)->this_hdr.contents = misc->contents; |
fd13ed0c | 1258 | misc->symtab_hdr->contents = (bfd_byte *) misc->isymbuf; |
cf88bb9f NC |
1259 | |
1260 | /* Add the PAGE insn. */ | |
1261 | if (! ip2k_elf_relax_add_bytes (abfd, sec, irel->r_offset, | |
1262 | page_opcode, | |
1263 | sizeof (page_opcode), | |
1264 | sizeof (page_opcode))) | |
1265 | return false; | |
1266 | else | |
1267 | { | |
1268 | Elf32_Internal_Rela * jrel = irel - 1; | |
1269 | ||
1270 | /* Add relocation for PAGE insn added. */ | |
1271 | if (ELF32_R_TYPE (jrel->r_info) != R_IP2K_NONE) | |
1272 | { | |
1273 | bfd_byte code0, code1; | |
1274 | char *msg = NULL; | |
1275 | ||
1276 | /* Get the opcode. */ | |
1277 | code0 = bfd_get_8 (abfd, misc->contents + irel->r_offset); | |
1278 | code1 = bfd_get_8 (abfd, misc->contents + irel->r_offset + 1); | |
1279 | ||
1280 | if (IS_JMP_OPCODE (code0, code1)) | |
1281 | msg = "\tJMP instruction missing a preceeding PAGE instruction in %s\n\n"; | |
1282 | ||
1283 | else if (IS_CALL_OPCODE (code0, code1)) | |
1284 | msg = "\tCALL instruction missing a preceeding PAGE instruction in %s\n\n"; | |
1285 | ||
1286 | if (msg) | |
1287 | { | |
1288 | fprintf (stderr, "\n\t *** LINKER RELAXATION failure ***\n"); | |
1289 | fprintf (stderr, msg, sec->owner->filename); | |
1290 | } | |
1291 | ||
1292 | return false; | |
1293 | } | |
1294 | ||
1295 | jrel->r_addend = irel->r_addend; | |
1296 | jrel->r_offset = irel->r_offset - sizeof (page_opcode); | |
1297 | jrel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), | |
1298 | R_IP2K_PAGE3); | |
1299 | } | |
1300 | ||
1301 | return true; | |
1302 | } | |
1303 | ||
1304 | /* Insert bytes into a section while relaxing. */ | |
1305 | ||
1306 | static boolean | |
1307 | ip2k_elf_relax_add_bytes (abfd, sec, addr, bytes, count, noadj) | |
1308 | bfd *abfd; | |
1309 | asection *sec; | |
1310 | bfd_vma addr; | |
1311 | const bfd_byte *bytes; | |
1312 | int count; | |
1313 | int noadj; | |
1314 | { | |
1315 | bfd_byte *contents = elf_section_data (sec)->this_hdr.contents; | |
1316 | bfd_vma endaddr = sec->_cooked_size; | |
1317 | ||
1318 | /* Make room to insert the bytes. */ | |
1319 | memmove (contents + addr + count, contents + addr, endaddr - addr); | |
1320 | ||
1321 | /* Insert the bytes into the section. */ | |
1322 | memcpy (contents + addr, bytes, count); | |
1323 | ||
1324 | sec->_cooked_size += count; | |
1325 | ||
1326 | adjust_all_relocations (abfd, sec, addr, endaddr, count, noadj); | |
1327 | return true; | |
1328 | } | |
1329 | ||
1330 | /* Delete some bytes from a section while relaxing. */ | |
1331 | ||
1332 | static boolean | |
1333 | ip2k_elf_relax_delete_bytes (abfd, sec, addr, count) | |
1334 | bfd *abfd; | |
1335 | asection *sec; | |
1336 | bfd_vma addr; | |
1337 | int count; | |
1338 | { | |
1339 | bfd_byte *contents = elf_section_data (sec)->this_hdr.contents; | |
1340 | bfd_vma endaddr = sec->_cooked_size; | |
1341 | ||
1342 | /* Actually delete the bytes. */ | |
1343 | memmove (contents + addr, contents + addr + count, | |
1344 | endaddr - addr - count); | |
1345 | ||
1346 | sec->_cooked_size -= count; | |
1347 | ||
1348 | adjust_all_relocations (abfd, sec, addr + count, endaddr, -count, 0); | |
1349 | return true; | |
1350 | } | |
1351 | ||
1352 | /* -------------------------------------------------------------------- */ | |
1353 | ||
1354 | /* XXX: The following code is the result of a cut&paste. This unfortunate | |
1355 | practice is very widespread in the various target back-end files. */ | |
1356 | ||
1357 | /* Set the howto pointer for a IP2K ELF reloc. */ | |
1358 | ||
1359 | static void | |
1360 | ip2k_info_to_howto_rela (abfd, cache_ptr, dst) | |
1361 | bfd * abfd ATTRIBUTE_UNUSED; | |
1362 | arelent * cache_ptr; | |
1363 | Elf32_Internal_Rela * dst; | |
1364 | { | |
1365 | unsigned int r_type; | |
1366 | ||
1367 | r_type = ELF32_R_TYPE (dst->r_info); | |
1368 | switch (r_type) | |
1369 | { | |
1370 | default: | |
1371 | cache_ptr->howto = & ip2k_elf_howto_table [r_type]; | |
1372 | break; | |
1373 | } | |
1374 | } | |
1375 | ||
1376 | /* Perform a single relocation. | |
1377 | By default we use the standard BFD routines. */ | |
1378 | ||
1379 | static bfd_reloc_status_type | |
1380 | ip2k_final_link_relocate (howto, input_bfd, input_section, contents, rel, | |
1381 | relocation) | |
1382 | reloc_howto_type * howto; | |
1383 | bfd * input_bfd; | |
1384 | asection * input_section; | |
1385 | bfd_byte * contents; | |
1386 | Elf_Internal_Rela * rel; | |
1387 | bfd_vma relocation; | |
1388 | { | |
1389 | bfd_reloc_status_type r = bfd_reloc_ok; | |
1390 | ||
1391 | switch (howto->type) | |
1392 | { | |
1393 | /* Handle data space relocations. */ | |
1394 | case R_IP2K_FR9: | |
1395 | case R_IP2K_BANK: | |
1396 | if ((relocation & IP2K_DATA_MASK) == IP2K_DATA_VALUE) | |
1397 | relocation &= ~IP2K_DATA_MASK; | |
1398 | else | |
1399 | r = bfd_reloc_notsupported; | |
1400 | break; | |
1401 | ||
1402 | case R_IP2K_LO8DATA: | |
1403 | case R_IP2K_HI8DATA: | |
1404 | case R_IP2K_EX8DATA: | |
1405 | break; | |
1406 | ||
1407 | /* Handle insn space relocations. */ | |
1408 | case R_IP2K_ADDR16CJP: | |
1409 | case R_IP2K_PAGE3: | |
1410 | case R_IP2K_LO8INSN: | |
1411 | case R_IP2K_HI8INSN: | |
1412 | case R_IP2K_PC_SKIP: | |
1413 | if ((relocation & IP2K_INSN_MASK) == IP2K_INSN_VALUE) | |
1414 | relocation &= ~IP2K_INSN_MASK; | |
1415 | else | |
1416 | r = bfd_reloc_notsupported; | |
1417 | break; | |
1418 | ||
1419 | case R_IP2K_16: | |
1420 | /* If this is a relocation involving a TEXT | |
1421 | symbol, reduce it to a word address. */ | |
1422 | if ((relocation & IP2K_INSN_MASK) == IP2K_INSN_VALUE) | |
1423 | howto = &ip2k_elf_howto_table[ (int) R_IP2K_TEXT]; | |
1424 | break; | |
1425 | ||
1426 | /* Pass others through. */ | |
1427 | default: | |
1428 | break; | |
1429 | } | |
1430 | ||
1431 | /* Only install relocation if above tests did not disqualify it. */ | |
1432 | if (r == bfd_reloc_ok) | |
1433 | r = _bfd_final_link_relocate (howto, input_bfd, input_section, | |
1434 | contents, rel->r_offset, | |
1435 | relocation, rel->r_addend); | |
1436 | ||
1437 | return r; | |
1438 | } | |
1439 | ||
1440 | /* Relocate a IP2K ELF section. | |
cf88bb9f NC |
1441 | |
1442 | The RELOCATE_SECTION function is called by the new ELF backend linker | |
1443 | to handle the relocations for a section. | |
1444 | ||
1445 | The relocs are always passed as Rela structures; if the section | |
1446 | actually uses Rel structures, the r_addend field will always be | |
1447 | zero. | |
1448 | ||
1449 | This function is responsible for adjusting the section contents as | |
1450 | necessary, and (if using Rela relocs and generating a relocateable | |
1451 | output file) adjusting the reloc addend as necessary. | |
1452 | ||
1453 | This function does not have to worry about setting the reloc | |
1454 | address or the reloc symbol index. | |
1455 | ||
1456 | LOCAL_SYMS is a pointer to the swapped in local symbols. | |
1457 | ||
1458 | LOCAL_SECTIONS is an array giving the section in the input file | |
1459 | corresponding to the st_shndx field of each local symbol. | |
1460 | ||
1461 | The global hash table entry for the global symbols can be found | |
1462 | via elf_sym_hashes (input_bfd). | |
1463 | ||
1464 | When generating relocateable output, this function must handle | |
1465 | STB_LOCAL/STT_SECTION symbols specially. The output symbol is | |
1466 | going to be the section symbol corresponding to the output | |
1467 | section, which means that the addend must be adjusted | |
1468 | accordingly. */ | |
1469 | ||
1470 | static boolean | |
1471 | ip2k_elf_relocate_section (output_bfd, info, input_bfd, input_section, | |
1472 | contents, relocs, local_syms, local_sections) | |
1473 | bfd * output_bfd ATTRIBUTE_UNUSED; | |
1474 | struct bfd_link_info * info; | |
1475 | bfd * input_bfd; | |
1476 | asection * input_section; | |
1477 | bfd_byte * contents; | |
1478 | Elf_Internal_Rela * relocs; | |
1479 | Elf_Internal_Sym * local_syms; | |
1480 | asection ** local_sections; | |
1481 | { | |
1482 | Elf_Internal_Shdr * symtab_hdr; | |
1483 | struct elf_link_hash_entry ** sym_hashes; | |
1484 | Elf_Internal_Rela * rel; | |
1485 | Elf_Internal_Rela * relend; | |
1486 | ||
f0fe0e16 AM |
1487 | if (info->relocateable) |
1488 | return true; | |
1489 | ||
cf88bb9f NC |
1490 | symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr; |
1491 | sym_hashes = elf_sym_hashes (input_bfd); | |
1492 | relend = relocs + input_section->reloc_count; | |
1493 | ||
1494 | for (rel = relocs; rel < relend; rel ++) | |
1495 | { | |
1496 | reloc_howto_type * howto; | |
1497 | unsigned long r_symndx; | |
1498 | Elf_Internal_Sym * sym; | |
1499 | asection * sec; | |
1500 | struct elf_link_hash_entry * h; | |
1501 | bfd_vma relocation; | |
1502 | bfd_reloc_status_type r; | |
1503 | const char * name = NULL; | |
1504 | int r_type; | |
1505 | ||
f0fe0e16 | 1506 | /* This is a final link. */ |
cf88bb9f | 1507 | r_type = ELF32_R_TYPE (rel->r_info); |
cf88bb9f | 1508 | r_symndx = ELF32_R_SYM (rel->r_info); |
cf88bb9f NC |
1509 | howto = ip2k_elf_howto_table + ELF32_R_TYPE (rel->r_info); |
1510 | h = NULL; | |
1511 | sym = NULL; | |
1512 | sec = NULL; | |
1513 | ||
1514 | if (r_symndx < symtab_hdr->sh_info) | |
1515 | { | |
1516 | sym = local_syms + r_symndx; | |
1517 | sec = local_sections [r_symndx]; | |
1518 | relocation = BASEADDR (sec) + sym->st_value; | |
1519 | ||
1520 | name = bfd_elf_string_from_elf_section | |
1521 | (input_bfd, symtab_hdr->sh_link, sym->st_name); | |
1522 | name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name; | |
1523 | } | |
1524 | else | |
1525 | { | |
1526 | h = sym_hashes [r_symndx - symtab_hdr->sh_info]; | |
1527 | ||
1528 | while (h->root.type == bfd_link_hash_indirect | |
1529 | || h->root.type == bfd_link_hash_warning) | |
1530 | h = (struct elf_link_hash_entry *) h->root.u.i.link; | |
1531 | ||
1532 | name = h->root.root.string; | |
1533 | ||
1534 | if (h->root.type == bfd_link_hash_defined | |
1535 | || h->root.type == bfd_link_hash_defweak) | |
1536 | { | |
1537 | sec = h->root.u.def.section; | |
1538 | relocation = h->root.u.def.value + BASEADDR (sec); | |
1539 | } | |
1540 | else if (h->root.type == bfd_link_hash_undefweak) | |
1541 | { | |
1542 | relocation = 0; | |
1543 | } | |
1544 | else | |
1545 | { | |
1546 | if (! ((*info->callbacks->undefined_symbol) | |
1547 | (info, h->root.root.string, input_bfd, | |
1548 | input_section, rel->r_offset, | |
1549 | (! info->shared || info->no_undefined)))) | |
1550 | return false; | |
1551 | relocation = 0; | |
1552 | } | |
1553 | } | |
1554 | ||
1555 | /* Finally, the sole IP2K-specific part. */ | |
1556 | r = ip2k_final_link_relocate (howto, input_bfd, input_section, | |
1557 | contents, rel, relocation); | |
1558 | ||
1559 | if (r != bfd_reloc_ok) | |
1560 | { | |
1561 | const char * msg = (const char *) NULL; | |
1562 | ||
1563 | switch (r) | |
1564 | { | |
1565 | case bfd_reloc_overflow: | |
1566 | r = info->callbacks->reloc_overflow | |
1567 | (info, name, howto->name, (bfd_vma) 0, | |
1568 | input_bfd, input_section, rel->r_offset); | |
1569 | break; | |
1570 | ||
1571 | case bfd_reloc_undefined: | |
1572 | r = info->callbacks->undefined_symbol | |
1573 | (info, name, input_bfd, input_section, rel->r_offset, true); | |
1574 | break; | |
1575 | ||
1576 | case bfd_reloc_outofrange: | |
1577 | msg = _("internal error: out of range error"); | |
1578 | break; | |
1579 | ||
1580 | /* This is how ip2k_final_link_relocate tells us of a non-kosher | |
1581 | reference between insn & data address spaces. */ | |
1582 | case bfd_reloc_notsupported: | |
1583 | if (sym != NULL) /* Only if it's not an unresolved symbol. */ | |
1584 | msg = _("unsupported relocation between data/insn address spaces"); | |
1585 | break; | |
1586 | ||
1587 | case bfd_reloc_dangerous: | |
1588 | msg = _("internal error: dangerous relocation"); | |
1589 | break; | |
1590 | ||
1591 | default: | |
1592 | msg = _("internal error: unknown error"); | |
1593 | break; | |
1594 | } | |
1595 | ||
1596 | if (msg) | |
1597 | r = info->callbacks->warning | |
1598 | (info, msg, name, input_bfd, input_section, rel->r_offset); | |
1599 | ||
1600 | if (! r) | |
1601 | return false; | |
1602 | } | |
1603 | } | |
1604 | ||
1605 | return true; | |
1606 | } | |
1607 | ||
1608 | static asection * | |
1609 | ip2k_elf_gc_mark_hook (sec, info, rel, h, sym) | |
1610 | asection *sec; | |
1611 | struct bfd_link_info *info ATTRIBUTE_UNUSED; | |
1612 | Elf_Internal_Rela *rel; | |
1613 | struct elf_link_hash_entry *h; | |
1614 | Elf_Internal_Sym *sym; | |
1615 | { | |
1616 | if (h != NULL) | |
1617 | { | |
1618 | switch (ELF32_R_TYPE (rel->r_info)) | |
1619 | { | |
1620 | #if 0 | |
1621 | case R_IP2K_GNU_VTINHERIT: | |
1622 | case R_IP2K_GNU_VTENTRY: | |
1623 | break; | |
1624 | #endif | |
1625 | ||
1626 | default: | |
1627 | switch (h->root.type) | |
1628 | { | |
1629 | case bfd_link_hash_defined: | |
1630 | case bfd_link_hash_defweak: | |
1631 | return h->root.u.def.section; | |
1632 | ||
1633 | case bfd_link_hash_common: | |
1634 | return h->root.u.c.p->section; | |
1635 | ||
1636 | default: | |
1637 | break; | |
1638 | } | |
1639 | } | |
1640 | } | |
1641 | else | |
1642 | { | |
1643 | if (!(elf_bad_symtab (sec->owner) | |
1644 | && ELF_ST_BIND (sym->st_info) != STB_LOCAL) | |
1645 | && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE) | |
1646 | && sym->st_shndx != SHN_COMMON)) | |
1647 | { | |
1648 | return bfd_section_from_elf_index (sec->owner, sym->st_shndx); | |
1649 | } | |
1650 | } | |
1651 | return NULL; | |
1652 | } | |
1653 | ||
1654 | static boolean | |
1655 | ip2k_elf_gc_sweep_hook (abfd, info, sec, relocs) | |
1656 | bfd *abfd ATTRIBUTE_UNUSED; | |
1657 | struct bfd_link_info *info ATTRIBUTE_UNUSED; | |
1658 | asection *sec ATTRIBUTE_UNUSED; | |
1659 | const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED; | |
1660 | { | |
1661 | /* we don't use got and plt entries for ip2k */ | |
1662 | return true; | |
1663 | } | |
1664 | ||
1665 | ||
1666 | /* -------------------------------------------------------------------- */ | |
1667 | ||
1668 | ||
1669 | #define TARGET_BIG_SYM bfd_elf32_ip2k_vec | |
1670 | #define TARGET_BIG_NAME "elf32-ip2k" | |
1671 | ||
1672 | #define ELF_ARCH bfd_arch_ip2k | |
1673 | #define ELF_MACHINE_CODE EM_IP2K | |
1674 | #define ELF_MAXPAGESIZE 1 /* No pages on the IP2K */ | |
1675 | ||
cf88bb9f NC |
1676 | #define elf_info_to_howto_rel NULL |
1677 | #define elf_info_to_howto ip2k_info_to_howto_rela | |
1678 | ||
1679 | #define elf_backend_can_gc_sections 1 | |
f0fe0e16 | 1680 | #define elf_backend_rela_normal 1 |
cf88bb9f NC |
1681 | #define elf_backend_gc_mark_hook ip2k_elf_gc_mark_hook |
1682 | #define elf_backend_gc_sweep_hook ip2k_elf_gc_sweep_hook | |
1683 | ||
1684 | #define elf_backend_relocate_section ip2k_elf_relocate_section | |
1685 | ||
1686 | #define elf_symbol_leading_char '_' | |
1687 | #define bfd_elf32_bfd_reloc_type_lookup ip2k_reloc_type_lookup | |
1688 | #define bfd_elf32_bfd_relax_section ip2k_elf_relax_section | |
1689 | ||
1690 | ||
1691 | #include "elf32-target.h" | |
1692 |