1 /* D30V-specific support for 32-bit ELF
2 Copyright (C) 1997 Free Software Foundation, Inc.
5 This file is part of BFD, the Binary File Descriptor library.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
26 static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
27 PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
28 static void d30v_info_to_howto_rel
29 PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
30 static bfd_reloc_status_type bfd_elf_d30v_reloc PARAMS ((
35 asection *input_section,
37 char **error_message));
39 /* Use REL instead of RELA to save space */
56 static reloc_howto_type elf_d30v_howto_table[] =
58 /* This reloc does nothing. */
59 HOWTO (R_D30V_NONE, /* type */
61 2, /* size (0 = byte, 1 = short, 2 = long) */
63 false, /* pc_relative */
65 complain_overflow_bitfield, /* complain_on_overflow */
66 bfd_elf_generic_reloc, /* special_function */
67 "R_D30V_NONE", /* name */
68 false, /* partial_inplace */
71 false), /* pcrel_offset */
73 /* A 6 bit absolute relocation */
74 HOWTO (R_D30V_6, /* type */
76 2, /* size (0 = byte, 1 = short, 2 = long) */
78 false, /* pc_relative */
80 complain_overflow_bitfield, /* complain_on_overflow */
81 bfd_elf_generic_reloc, /* special_function */
82 "R_D30V_6", /* name */
83 false, /* partial_inplace */
86 false), /* pcrel_offset */
88 /* An absolute 15 bit relocation, right shifted by 3 */
89 HOWTO (R_D30V_15, /* type */
91 2, /* size (0 = byte, 1 = short, 2 = long) */
93 false, /* pc_relative */
95 complain_overflow_signed, /* complain_on_overflow */
96 bfd_elf_generic_reloc, /* special_function */
97 "R_D30V_15", /* name */
98 false, /* partial_inplace */
100 0xfff, /* dst_mask */
101 false), /* pcrel_offset */
103 /* A relative 15 bit relocation, right shifted by 3 */
104 HOWTO (R_D30V_15_PCREL, /* type */
106 2, /* size (0 = byte, 1 = short, 2 = long) */
108 true, /* pc_relative */
110 complain_overflow_signed, /* complain_on_overflow */
111 bfd_elf_generic_reloc, /* special_function */
112 "R_D30V_15_PCREL", /* name */
113 false, /* partial_inplace */
114 0xfff, /* src_mask */
115 0xfff, /* dst_mask */
116 true), /* pcrel_offset */
118 /* An absolute 21 bit relocation, right shifted by 3 */
119 HOWTO (R_D30V_21_PCREL, /* type */
121 2, /* size (0 = byte, 1 = short, 2 = long) */
123 false, /* pc_relative */
125 complain_overflow_signed, /* complain_on_overflow */
126 bfd_elf_generic_reloc, /* special_function */
127 "R_D30V_21", /* name */
128 false, /* partial_inplace */
129 0x3ffff, /* src_mask */
130 0x3ffff, /* dst_mask */
131 false), /* pcrel_offset */
133 /* A relative 21 bit relocation, right shifted by 3 */
134 HOWTO (R_D30V_21_PCREL, /* type */
136 2, /* size (0 = byte, 1 = short, 2 = long) */
138 true, /* pc_relative */
140 complain_overflow_signed, /* complain_on_overflow */
141 bfd_elf_generic_reloc, /* special_function */
142 "R_D30V_21_PCREL", /* name */
143 false, /* partial_inplace */
144 0x3ffff, /* src_mask */
145 0x3ffff, /* dst_mask */
146 true), /* pcrel_offset */
148 /* A D30V 32 bit absolute relocation */
149 HOWTO (R_D30V_32, /* type */
151 4, /* size (0 = byte, 1 = short, 2 = long) */
153 false, /* pc_relative */
155 complain_overflow_bitfield, /* complain_on_overflow */
156 bfd_elf_d30v_reloc, /* special_function */
157 "R_D30V_32", /* name */
158 false, /* partial_inplace */
159 0xffffffff, /* src_mask */
160 0xffffffff, /* dst_mask */
161 false), /* pcrel_offset */
163 /* A relative 32 bit relocation */
164 HOWTO (R_D30V_32_PCREL, /* type */
166 4, /* size (0 = byte, 1 = short, 2 = long) */
168 true, /* pc_relative */
170 complain_overflow_signed, /* complain_on_overflow */
171 bfd_elf_d30v_reloc, /* special_function */
172 "R_D30V_32_PCREL", /* name */
173 false, /* partial_inplace */
174 0xffffffff, /* src_mask */
175 0xffffffff, /* dst_mask */
176 true), /* pcrel_offset */
178 /* A regular 32 bit absolute relocation */
179 HOWTO (R_D30V_32_NORMAL, /* type */
181 4, /* size (0 = byte, 1 = short, 2 = long) */
183 false, /* pc_relative */
185 complain_overflow_bitfield, /* complain_on_overflow */
186 bfd_elf_generic_reloc, /* special_function */
187 "R_D30V_32_NORMAL", /* name */
188 false, /* partial_inplace */
189 0xffffffff, /* src_mask */
190 0xffffffff, /* dst_mask */
191 false), /* pcrel_offset */
195 static bfd_reloc_status_type
196 bfd_elf_d30v_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message)
198 arelent *reloc_entry;
201 asection *input_section;
203 char **error_message;
207 bfd_reloc_status_type r;
208 asection *reloc_target_output_section;
209 bfd_size_type addr = reloc_entry->address;
210 bfd_reloc_status_type flag = bfd_reloc_ok;
211 bfd_vma output_base = 0;
212 reloc_howto_type *howto = reloc_entry->howto;
214 r = bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
215 input_section, output_bfd, error_message);
216 if (r != bfd_reloc_continue)
219 /* a hacked-up version of bfd_perform_reloc() follows */
221 /* Is the address of the relocation really within the section? */
222 if (reloc_entry->address > input_section->_cooked_size)
223 return bfd_reloc_outofrange;
225 /* Work out which section the relocation is targetted at and the
226 initial relocation command value. */
228 /* Get symbol value. (Common symbols are special.) */
229 if (bfd_is_com_section (symbol->section))
232 relocation = symbol->value;
235 reloc_target_output_section = symbol->section->output_section;
237 /* Convert input-section-relative symbol value to absolute. */
241 output_base = reloc_target_output_section->vma;
243 relocation += output_base + symbol->section->output_offset;
245 /* Add in supplied addend. */
246 relocation += reloc_entry->addend;
248 /* Here the variable relocation holds the final address of the
249 symbol we are relocating against, plus any addend. */
251 if (howto->pc_relative == true)
253 relocation -= input_section->output_section->vma + input_section->output_offset;
255 if (howto->pcrel_offset == true)
256 relocation -= reloc_entry->address;
259 if (output_bfd != (bfd *) NULL)
261 /* This is a partial relocation, and we want to apply the relocation
262 to the reloc entry rather than the raw data. Modify the reloc
263 inplace to reflect what we now know. */
264 reloc_entry->addend = relocation;
265 reloc_entry->address += input_section->output_offset;
269 reloc_entry->addend = 0;
271 in1 = bfd_get_32 (abfd, (bfd_byte *) data + addr);
272 in2 = bfd_get_32 (abfd, (bfd_byte *) data + addr + 4);
274 printf("D30V 32-bit reloc at addr 0x%lx insn=0x%08x%08x\n",(long)relocation, (int)in1, (int)in2);
275 bfd_put_32 (abfd, in1, (bfd_byte *) data + addr);
276 bfd_put_32 (abfd, in2, (bfd_byte *) data + addr + 4);
281 /* Map BFD reloc types to D30V ELF reloc types. */
283 struct d30v_reloc_map
285 unsigned char bfd_reloc_val;
286 unsigned char elf_reloc_val;
290 static const struct d30v_reloc_map d30v_reloc_map[] =
292 { BFD_RELOC_NONE, R_D30V_NONE, },
293 { BFD_RELOC_D30V_6, R_D30V_6 },
294 { BFD_RELOC_D30V_15, R_D30V_15 },
295 { BFD_RELOC_D30V_15_PCREL, R_D30V_15_PCREL },
296 { BFD_RELOC_D30V_21, R_D30V_21 },
297 { BFD_RELOC_D30V_21_PCREL, R_D30V_21_PCREL },
298 { BFD_RELOC_D30V_32, R_D30V_32 },
299 { BFD_RELOC_D30V_32_PCREL, R_D30V_32_PCREL },
300 { BFD_RELOC_32, R_D30V_32_NORMAL },
303 static reloc_howto_type *
304 bfd_elf32_bfd_reloc_type_lookup (abfd, code)
306 bfd_reloc_code_real_type code;
311 i < sizeof (d30v_reloc_map) / sizeof (struct d30v_reloc_map);
314 if (d30v_reloc_map[i].bfd_reloc_val == code)
315 return &elf_d30v_howto_table[d30v_reloc_map[i].elf_reloc_val];
321 /* Set the howto pointer for an D30V ELF reloc. */
324 d30v_info_to_howto_rel (abfd, cache_ptr, dst)
327 Elf32_Internal_Rel *dst;
331 r_type = ELF32_R_TYPE (dst->r_info);
332 BFD_ASSERT (r_type < (unsigned int) R_D30V_max);
333 cache_ptr->howto = &elf_d30v_howto_table[r_type];
336 #define ELF_ARCH bfd_arch_d30v
337 #define ELF_MACHINE_CODE EM_CYGNUS_D30V
338 #define ELF_MAXPAGESIZE 0x1000
340 #define TARGET_BIG_SYM bfd_elf32_d30v_vec
341 #define TARGET_BIG_NAME "elf32-d30v"
343 #define elf_info_to_howto 0
344 #define elf_info_to_howto_rel d30v_info_to_howto_rel
345 #define elf_backend_object_p 0
346 #define elf_backend_final_write_processing 0
348 #include "elf32-target.h"