1 /* D30V-specific support for 32-bit ELF
2 Copyright (C) 1997 Free Software Foundation, Inc.
3 Contributed by Martin Hunt (hunt@cygnus.com).
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"