1 /* TXVU-specific support for 32-bit ELF.
2 Copyright (C) 1997, 1998 Free Software Foundation, Inc.
4 This file is part of BFD, the Binary File Descriptor library.
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.
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.
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. */
26 static reloc_howto_type
*bfd_elf32_bfd_reloc_type_lookup
27 PARAMS ((bfd
*abfd
, bfd_reloc_code_real_type code
));
28 static void txvu_info_to_howto_rel
29 PARAMS ((bfd
*, arelent
*, Elf32_Internal_Rela
*));
30 static boolean txvu_elf_relocate_section
31 PARAMS ((bfd
*, struct bfd_link_info
*, bfd
*, asection
*, bfd_byte
*,
32 Elf_Internal_Rela
*, Elf_Internal_Sym
*, asection
**));
34 /* Use RELA, not REL. REL incurs complications one would rather not
38 static reloc_howto_type txvu_elf_howto_table
[] =
40 /* This reloc does nothing. */
41 HOWTO (R_TXVU_NONE
, /* type */
43 2, /* size (0 = byte, 1 = short, 2 = long) */
45 false, /* pc_relative */
47 complain_overflow_bitfield
, /* complain_on_overflow */
48 bfd_elf_generic_reloc
, /* special_function */
49 "R_TXVU_NONE", /* name */
50 false, /* partial_inplace */
53 false), /* pcrel_offset */
55 /* A PC Relative 11-bit relocation, shifted by 3.
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. */
65 HOWTO (R_TXVU_11_PCREL
, /* type */
67 2, /* size (0 = byte, 1 = short, 2 = long) */
69 true, /* pc_relative */
71 complain_overflow_signed
, /* complain_on_overflow */
72 bfd_elf_generic_reloc
, /* special_function */
73 "R_TXVU_11_PCREL", /* name */
74 false, /* partial_inplace */
77 true), /* pcrel_offset */
80 /* Map BFD reloc types to TXVU ELF reloc types. */
84 unsigned char bfd_reloc_val
;
85 unsigned char elf_reloc_val
;
88 static const struct txvu_reloc_map txvu_reloc_map
[] =
90 { BFD_RELOC_NONE
, R_TXVU_NONE
},
91 { BFD_RELOC_TXVU_11_PCREL
, R_TXVU_11_PCREL
}
94 static reloc_howto_type
*
95 bfd_elf32_bfd_reloc_type_lookup (abfd
, code
)
97 bfd_reloc_code_real_type code
;
102 i
< sizeof (txvu_reloc_map
) / sizeof (struct txvu_reloc_map
);
105 if (txvu_reloc_map
[i
].bfd_reloc_val
== code
)
106 return &txvu_elf_howto_table
[txvu_reloc_map
[i
].elf_reloc_val
];
112 /* Set the howto pointer for an TXVU ELF reloc. */
115 txvu_info_to_howto_rel (abfd
, cache_ptr
, dst
)
118 Elf32_Internal_Rela
*dst
;
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
];
125 /* Relocate a TXVU ELF section.
127 The RELOCATE_SECTION function is called by the new ELF backend linker
128 to handle the relocations for a section.
130 The relocs are always passed as Rela structures; if the section
131 actually uses Rel structures, the r_addend field will always be
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
139 This function does not have to worry about setting the reloc
140 address or the reloc symbol index.
142 LOCAL_SYMS is a pointer to the swapped in local symbols.
144 LOCAL_SECTIONS is an array giving the section in the input file
145 corresponding to the st_shndx field of each local symbol.
147 The global hash table entry for the global symbols can be found
148 via elf_sym_hashes (input_bfd).
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
157 txvu_elf_relocate_section (output_bfd
, info
, input_bfd
, input_section
,
158 contents
, relocs
, local_syms
, local_sections
)
160 struct bfd_link_info
*info
;
162 asection
*input_section
;
164 Elf_Internal_Rela
*relocs
;
165 Elf_Internal_Sym
*local_syms
;
166 asection
**local_sections
;
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. */
176 relend
= relocs
+ input_section
->reloc_count
;
177 for (; rel
< relend
; rel
++)
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
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
;
192 const char *sym_name
;
193 bfd_reloc_status_type r
;
194 const char *errmsg
= NULL
;
196 r_type
= ELF32_R_TYPE (rel
->r_info
);
197 if (r_type
< 0 || r_type
>= (int) R_TXVU_max
)
199 (*_bfd_error_handler
) ("%s: unknown relocation type %d",
200 bfd_get_filename (input_bfd
),
202 bfd_set_error (bfd_error_bad_value
);
207 howto
= txvu_elf_howto_table
+ r_type
;
208 r_symndx
= ELF32_R_SYM (rel
->r_info
);
210 if (info
->relocateable
)
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. */
217 if (r_symndx
>= symtab_hdr
->sh_info
)
219 /* External 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
)
229 /* Symbol isn't associated with a section. Nothing to do. */
233 sec
= local_sections
[r_symndx
];
234 addend
+= sec
->output_offset
+ sym
->st_value
;
235 rel
->r_addend
= addend
;
237 /* Addends are stored with relocs. We're done. */
244 /* This is a final link. */
249 if (r_symndx
< symtab_hdr
->sh_info
)
252 sym
= local_syms
+ r_symndx
;
253 sec
= local_sections
[r_symndx
];
254 sym_name
= "<local symbol>";
255 relocation
= (sec
->output_section
->vma
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
;
268 if (h
->root
.type
== bfd_link_hash_defined
269 || h
->root
.type
== bfd_link_hash_defweak
)
271 sec
= h
->root
.u
.def
.section
;
272 if (sec
->output_section
== NULL
)
275 relocation
= (h
->root
.u
.def
.value
276 + sec
->output_section
->vma
277 + sec
->output_offset
);
279 else if (h
->root
.type
== bfd_link_hash_undefweak
)
283 if (! ((*info
->callbacks
->undefined_symbol
)
284 (info
, h
->root
.root
.string
, input_bfd
,
285 input_section
, offset
)))
291 /* Sanity check the address. */
292 if (offset
> input_section
->_raw_size
)
294 r
= bfd_reloc_outofrange
;
298 switch ((int) r_type
)
300 /* insert reloc handling code here */
302 r
= _bfd_final_link_relocate (howto
, input_bfd
, input_section
,
311 if (r
!= bfd_reloc_ok
)
313 /* FIXME: This should be generic enough to go in a utility. */
317 name
= h
->root
.root
.string
;
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
);
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
)))
338 case bfd_reloc_undefined
:
339 if (! ((*info
->callbacks
->undefined_symbol
)
340 (info
, name
, input_bfd
, input_section
,
345 case bfd_reloc_outofrange
:
346 errmsg
= "internal error: out of range error";
349 case bfd_reloc_notsupported
:
350 errmsg
= "internal error: unsupported relocation error";
353 case bfd_reloc_dangerous
:
354 errmsg
= "internal error: dangerous error";
358 errmsg
= "internal error: unknown error";
362 if (!((*info
->callbacks
->warning
)
363 (info
, errmsg
, name
, input_bfd
, input_section
,
374 #define ELF_ARCH bfd_arch_txvu
375 #define ELF_MACHINE_CODE EM_CYGNUS_TXVU
376 #define ELF_MAXPAGESIZE 0x1000
378 #define TARGET_BIG_SYM bfd_elf32_txvu_vec
379 #define TARGET_BIG_NAME "elf32-txvu"
381 #define elf_info_to_howto txvu_info_to_howto_rel
382 #define elf_backend_relocate_section txvu_elf_relocate_section
384 #include "elf32-target.h"