comment fix
[deliverable/binutils-gdb.git] / bfd / elf32-txvu.c
CommitLineData
20b2c808 1/* TXVU-specific support for 32-bit ELF.
d707219d 2 Copyright (C) 1997, 1998 Free Software Foundation, Inc.
20b2c808
DE
3
4This file is part of BFD, the Binary File Descriptor library.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, 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/txvu.h"
25
26static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
27 PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
28static void txvu_info_to_howto_rel
29 PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
30static boolean txvu_elf_relocate_section
31 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
32 Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
33
34/* Use RELA, not REL. REL incurs complications one would rather not
35 deal with. */
36/*#define USE_REL*/
37
38static reloc_howto_type txvu_elf_howto_table[] =
39{
40 /* This reloc does nothing. */
41 HOWTO (R_TXVU_NONE, /* type */
42 0, /* rightshift */
43 2, /* size (0 = byte, 1 = short, 2 = long) */
44 32, /* bitsize */
45 false, /* pc_relative */
46 0, /* bitpos */
47 complain_overflow_bitfield, /* complain_on_overflow */
48 bfd_elf_generic_reloc, /* special_function */
49 "R_TXVU_NONE", /* name */
50 false, /* partial_inplace */
51 0, /* src_mask */
52 0, /* dst_mask */
53 false), /* pcrel_offset */
54
d707219d 55 /* A PC Relative 11-bit relocation, shifted by 3.
0820c2f8
DE
56 Fortunately, the lower instruction has the lower address in the 64 bit
57 pair. Thus we can treat the address of the instruction as a whole
58 as the address of the lower instruction (the one with the branch),
59 and pretend the instruction size is 32 bits.
60 Otherwise, we'd have to either perform the relocation on all 64 bits
61 (since the pc relative address is the start of the pair), or set the
62 address of the reloc as the address of the lower instruction and do what
63 is done for R_M32R_10_PCREL which is to mask off the lower 3 bits of the
64 pc before performing the reloc. */
d707219d
DE
65 HOWTO (R_TXVU_11_PCREL, /* type */
66 3, /* rightshift */
0820c2f8 67 2, /* size (0 = byte, 1 = short, 2 = long) */
d707219d
DE
68 11, /* bitsize */
69 true, /* pc_relative */
70 0, /* bitpos */
71 complain_overflow_signed, /* complain_on_overflow */
72 bfd_elf_generic_reloc, /* special_function */
73 "R_TXVU_11_PCREL", /* name */
74 false, /* partial_inplace */
75 0x1ff, /* src_mask */
76 0x1ff, /* dst_mask */
77 true), /* pcrel_offset */
20b2c808
DE
78};
79\f
80/* Map BFD reloc types to TXVU ELF reloc types. */
81
82struct txvu_reloc_map
83{
84 unsigned char bfd_reloc_val;
85 unsigned char elf_reloc_val;
86};
87
88static const struct txvu_reloc_map txvu_reloc_map[] =
89{
90 { BFD_RELOC_NONE, R_TXVU_NONE },
d707219d 91 { BFD_RELOC_TXVU_11_PCREL, R_TXVU_11_PCREL }
20b2c808
DE
92};
93
94static reloc_howto_type *
95bfd_elf32_bfd_reloc_type_lookup (abfd, code)
96 bfd *abfd;
97 bfd_reloc_code_real_type code;
98{
99 unsigned int i;
100
101 for (i = 0;
102 i < sizeof (txvu_reloc_map) / sizeof (struct txvu_reloc_map);
103 i++)
104 {
105 if (txvu_reloc_map[i].bfd_reloc_val == code)
106 return &txvu_elf_howto_table[txvu_reloc_map[i].elf_reloc_val];
107 }
108
109 return NULL;
110}
111
112/* Set the howto pointer for an TXVU ELF reloc. */
113
114static void
115txvu_info_to_howto_rel (abfd, cache_ptr, dst)
116 bfd *abfd;
117 arelent *cache_ptr;
118 Elf32_Internal_Rela *dst;
119{
120 unsigned int r_type = ELF32_R_TYPE (dst->r_info);
121 BFD_ASSERT (r_type < (unsigned int) R_TXVU_max);
122 cache_ptr->howto = &txvu_elf_howto_table[r_type];
123}
124\f
125/* Relocate a TXVU ELF section.
126
127 The RELOCATE_SECTION function is called by the new ELF backend linker
128 to handle the relocations for a section.
129
130 The relocs are always passed as Rela structures; if the section
131 actually uses Rel structures, the r_addend field will always be
132 zero.
133
134 This function is responsible for adjust the section contents as
135 necessary, and (if using Rela relocs and generating a
136 relocateable output file) adjusting the reloc addend as
137 necessary.
138
139 This function does not have to worry about setting the reloc
140 address or the reloc symbol index.
141
142 LOCAL_SYMS is a pointer to the swapped in local symbols.
143
144 LOCAL_SECTIONS is an array giving the section in the input file
145 corresponding to the st_shndx field of each local symbol.
146
147 The global hash table entry for the global symbols can be found
148 via elf_sym_hashes (input_bfd).
149
150 When generating relocateable output, this function must handle
151 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
152 going to be the section symbol corresponding to the output
153 section, which means that the addend must be adjusted
154 accordingly. */
155
156static boolean
157txvu_elf_relocate_section (output_bfd, info, input_bfd, input_section,
158 contents, relocs, local_syms, local_sections)
159 bfd *output_bfd;
160 struct bfd_link_info *info;
161 bfd *input_bfd;
162 asection *input_section;
163 bfd_byte *contents;
164 Elf_Internal_Rela *relocs;
165 Elf_Internal_Sym *local_syms;
166 asection **local_sections;
167{
168 Elf_Internal_Shdr *symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
169 struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
170 Elf_Internal_Rela *rel, *relend;
171 bfd *dynobj = elf_hash_table (info)->dynobj;
172 /* Assume success. */
173 boolean ret = true;
174
175 rel = relocs;
176 relend = relocs + input_section->reloc_count;
177 for (; rel < relend; rel++)
178 {
179 int r_type;
180 reloc_howto_type *howto;
181 unsigned long r_symndx;
182 /* We can't modify r_addend here as elf_link_input_bfd has an assert to
183 ensure it's zero (we use REL relocs, not RELA). Therefore this
184 should be assigning zero to `addend', but for clarity we use
185 `r_addend'. */
186 /* ??? The previous comment is old, revisit and delete. */
187 bfd_vma addend = rel->r_addend;
188 bfd_vma offset = rel->r_offset;
189 struct elf_link_hash_entry *h;
190 Elf_Internal_Sym *sym;
191 asection *sec;
192 const char *sym_name;
193 bfd_reloc_status_type r;
194 const char *errmsg = NULL;
195
196 r_type = ELF32_R_TYPE (rel->r_info);
197 if (r_type < 0 || r_type >= (int) R_TXVU_max)
198 {
199 (*_bfd_error_handler) ("%s: unknown relocation type %d",
200 bfd_get_filename (input_bfd),
201 (int) r_type);
202 bfd_set_error (bfd_error_bad_value);
203 ret = false;
204 continue;
205 }
206
207 howto = txvu_elf_howto_table + r_type;
208 r_symndx = ELF32_R_SYM (rel->r_info);
209
210 if (info->relocateable)
211 {
212 /* This is a relocateable link. We don't have to change
213 anything, unless the reloc is against a section symbol,
214 in which case we have to adjust according to where the
215 section symbol winds up in the output section. */
216 sec = NULL;
217 if (r_symndx >= symtab_hdr->sh_info)
218 {
219 /* External symbol. */
220 continue;
221 }
222
223 /* Local symbol. */
224 sym = local_syms + r_symndx;
225 sym_name = "<local symbol>";
226 /* STT_SECTION: symbol is associated with a section. */
227 if (ELF_ST_TYPE (sym->st_info) != STT_SECTION)
228 {
229 /* Symbol isn't associated with a section. Nothing to do. */
230 continue;
231 }
232
233 sec = local_sections[r_symndx];
234 addend += sec->output_offset + sym->st_value;
235 rel->r_addend = addend;
236
237 /* Addends are stored with relocs. We're done. */
238 continue;
239 }
240 else
241 {
242 bfd_vma relocation;
243
244 /* This is a final link. */
245 h = NULL;
246 sym = NULL;
247 sec = NULL;
248
249 if (r_symndx < symtab_hdr->sh_info)
250 {
251 /* Local symbol. */
252 sym = local_syms + r_symndx;
253 sec = local_sections[r_symndx];
254 sym_name = "<local symbol>";
255 relocation = (sec->output_section->vma
256 + sec->output_offset
257 + sym->st_value);
258 }
259 else
260 {
261 /* External symbol. */
262 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
263 while (h->root.type == bfd_link_hash_indirect
264 || h->root.type == bfd_link_hash_warning)
265 h = (struct elf_link_hash_entry *) h->root.u.i.link;
266 sym_name = h->root.root.string;
267
268 if (h->root.type == bfd_link_hash_defined
269 || h->root.type == bfd_link_hash_defweak)
270 {
271 sec = h->root.u.def.section;
272 if (sec->output_section == NULL)
273 relocation = 0;
274 else
275 relocation = (h->root.u.def.value
276 + sec->output_section->vma
277 + sec->output_offset);
278 }
279 else if (h->root.type == bfd_link_hash_undefweak)
280 relocation = 0;
281 else
282 {
283 if (! ((*info->callbacks->undefined_symbol)
284 (info, h->root.root.string, input_bfd,
285 input_section, offset)))
286 return false;
287 relocation = 0;
288 }
289 }
290
291 /* Sanity check the address. */
292 if (offset > input_section->_raw_size)
293 {
294 r = bfd_reloc_outofrange;
295 goto check_reloc;
296 }
297
298 switch ((int) r_type)
299 {
300 /* insert reloc handling code here */
301 default :
302 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
303 contents, offset,
304 relocation, addend);
305 break;
306 }
307 }
308
309 check_reloc:
310
311 if (r != bfd_reloc_ok)
312 {
313 /* FIXME: This should be generic enough to go in a utility. */
314 const char *name;
315
316 if (h != NULL)
317 name = h->root.root.string;
318 else
319 {
320 name = (bfd_elf_string_from_elf_section
321 (input_bfd, symtab_hdr->sh_link, sym->st_name));
322 if (name == NULL || *name == '\0')
323 name = bfd_section_name (input_bfd, sec);
324 }
325
326 if (errmsg != NULL)
327 goto common_error;
328
329 switch (r)
330 {
331 case bfd_reloc_overflow:
332 if (! ((*info->callbacks->reloc_overflow)
333 (info, name, howto->name, (bfd_vma) 0,
334 input_bfd, input_section, offset)))
335 return false;
336 break;
337
338 case bfd_reloc_undefined:
339 if (! ((*info->callbacks->undefined_symbol)
340 (info, name, input_bfd, input_section,
341 offset)))
342 return false;
343 break;
344
345 case bfd_reloc_outofrange:
346 errmsg = "internal error: out of range error";
347 goto common_error;
348
349 case bfd_reloc_notsupported:
350 errmsg = "internal error: unsupported relocation error";
351 goto common_error;
352
353 case bfd_reloc_dangerous:
354 errmsg = "internal error: dangerous error";
355 goto common_error;
356
357 default:
358 errmsg = "internal error: unknown error";
359 /* fall through */
360
361 common_error:
362 if (!((*info->callbacks->warning)
363 (info, errmsg, name, input_bfd, input_section,
364 offset)))
365 return false;
366 break;
367 }
368 }
369 }
370
371 return ret;
372}
373\f
374#define ELF_ARCH bfd_arch_txvu
375#define ELF_MACHINE_CODE EM_CYGNUS_TXVU
376#define ELF_MAXPAGESIZE 0x1000
377
378#define TARGET_BIG_SYM bfd_elf32_txvu_vec
379#define TARGET_BIG_NAME "elf32-txvu"
380
381#define elf_info_to_howto txvu_info_to_howto_rel
382#define elf_backend_relocate_section txvu_elf_relocate_section
383
384#include "elf32-target.h"
This page took 0.037201 seconds and 4 git commands to generate.