1
/* Hitachi SH64-specific support for 32-bit ELF
2
Copyright (C) 2000, 2001, 2002 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. */
27
#include "../opcodes/sh64-opc.h"
29
static boolean sh64_address_in_cranges
30
PARAMS ((asection *cranges, bfd_vma, sh64_elf_crange *));
32
/* Ordering functions of a crange, for the qsort and bsearch calls and for
33
different endianness. */
36
_bfd_sh64_crange_qsort_cmpb (p1, p2)
40
bfd_vma a1 = bfd_getb32 (p1);
41
bfd_vma a2 = bfd_getb32 (p2);
43
/* Preserve order if there's ambiguous contents. */
45
return (char *) p1 - (char *) p2;
51
_bfd_sh64_crange_qsort_cmpl (p1, p2)
55
bfd_vma a1 = (bfd_vma) bfd_getl32 (p1);
56
bfd_vma a2 = (bfd_vma) bfd_getl32 (p2);
58
/* Preserve order if there's ambiguous contents. */
60
return (char *) p1 - (char *) p2;
66
_bfd_sh64_crange_bsearch_cmpb (p1, p2)
70
bfd_vma a1 = *(bfd_vma *) p1;
71
bfd_vma a2 = (bfd_vma) bfd_getb32 (p2);
73
= (bfd_size_type) bfd_getb32 (SH64_CRANGE_CR_SIZE_OFFSET + (char *) p2);
83
_bfd_sh64_crange_bsearch_cmpl (p1, p2)
87
bfd_vma a1 = *(bfd_vma *) p1;
88
bfd_vma a2 = (bfd_vma) bfd_getl32 (p2);
90
= (bfd_size_type) bfd_getl32 (SH64_CRANGE_CR_SIZE_OFFSET + (char *) p2);
99
/* Check whether a specific address is specified within a .cranges
100
section. Return FALSE if not found, and TRUE if found, and the region
101
filled into RANGEP if non-NULL. */
104
sh64_address_in_cranges (cranges, addr, rangep)
107
sh64_elf_crange *rangep;
109
bfd_byte *cranges_contents;
110
bfd_byte *found_rangep;
111
bfd_size_type cranges_size = bfd_section_size (cranges->owner, cranges);
113
/* If the size is not a multiple of the cranges entry size, then
114
something is badly wrong. */
115
if ((cranges_size % SH64_CRANGE_SIZE) != 0)
118
/* If this section has relocations, then we can't do anything sane. */
119
if (bfd_get_section_flags (cranges->owner, cranges) & SEC_RELOC)
122
/* Has some kind soul (or previous call) left processed, sorted contents
124
if ((bfd_get_section_flags (cranges->owner, cranges) & SEC_IN_MEMORY)
125
&& elf_section_data (cranges)->this_hdr.sh_type == SHT_SH5_CR_SORTED)
126
cranges_contents = cranges->contents;
130
= bfd_malloc (cranges->_cooked_size == 0
131
? cranges->_cooked_size : cranges->_raw_size);
132
if (cranges_contents == NULL)
135
if (! bfd_get_section_contents (cranges->owner, cranges,
136
cranges_contents, (file_ptr) 0,
141
if (elf_section_data (cranges)->this_hdr.sh_type
142
!= SHT_SH5_CR_SORTED)
143
/* Nope. Lets sort it. */
144
qsort (cranges_contents, cranges_size / SH64_CRANGE_SIZE,
146
bfd_big_endian (cranges->owner)
147
? _bfd_sh64_crange_qsort_cmpb : _bfd_sh64_crange_qsort_cmpl);
149
/* Let's keep it around. */
150
cranges->contents = cranges_contents;
151
bfd_set_section_flags (cranges->owner, cranges,
152
bfd_get_section_flags (cranges->owner, cranges)
155
/* It's sorted now. */
156
elf_section_data (cranges)->this_hdr.sh_type = SHT_SH5_CR_SORTED;
159
/* Try and find a matching range. */
161
= bsearch (&addr, cranges_contents, cranges_size / SH64_CRANGE_SIZE,
163
bfd_big_endian (cranges->owner)
164
? _bfd_sh64_crange_bsearch_cmpb
165
: _bfd_sh64_crange_bsearch_cmpl);
167
/* Fill in a few return values if we found a matching range. */
170
enum sh64_elf_cr_type cr_type
171
= bfd_get_16 (cranges->owner,
172
SH64_CRANGE_CR_TYPE_OFFSET + found_rangep);
174
= bfd_get_32 (cranges->owner,
175
SH64_CRANGE_CR_ADDR_OFFSET
176
+ (char *) found_rangep);
177
bfd_size_type cr_size
178
= bfd_get_32 (cranges->owner,
179
SH64_CRANGE_CR_SIZE_OFFSET
180
+ (char *) found_rangep);
182
rangep->cr_addr = cr_addr;
183
rangep->cr_size = cr_size;
184
rangep->cr_type = cr_type;
189
/* There is a .cranges section, but it does not have a descriptor
190
matching this address. */
194
free (cranges_contents);
198
/* Determine what ADDR points to in SEC, and fill in a range descriptor in
199
*RANGEP if it's non-NULL. */
201
enum sh64_elf_cr_type
202
sh64_get_contents_type (sec, addr, rangep)
205
sh64_elf_crange *rangep;
209
/* Fill in the range with the boundaries of the section as a default. */
210
if (bfd_get_flavour (sec->owner) == bfd_target_elf_flavour
211
&& elf_elfheader (sec->owner)->e_type == ET_EXEC)
213
rangep->cr_addr = bfd_get_section_vma (sec->owner, sec);
214
rangep->cr_size = bfd_section_size (sec->owner, sec);
215
rangep->cr_type = CRT_NONE;
220
/* If none of the pertinent bits are set, then it's a SHcompact (or at
221
least not SHmedia). */
222
if ((elf_section_data (sec)->this_hdr.sh_flags
223
& (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED)) == 0)
225
enum sh64_elf_cr_type cr_type
226
= ((bfd_get_section_flags (sec->owner, sec) & SEC_CODE) != 0
227
? CRT_SH5_ISA16 : CRT_DATA);
228
rangep->cr_type = cr_type;
232
/* If only the SHF_SH5_ISA32 bit is set, then we have SHmedia. */
233
if ((elf_section_data (sec)->this_hdr.sh_flags
234
& (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED)) == SHF_SH5_ISA32)
236
rangep->cr_type = CRT_SH5_ISA32;
237
return CRT_SH5_ISA32;
240
/* Otherwise, we have to look up the .cranges section. */
241
cranges = bfd_get_section_by_name (sec->owner, SH64_CRANGES_SECTION_NAME);
244
/* A mixed section but there's no .cranges section. This is probably
245
bad input; it does not comply to specs. */
248
/* If this call fails, we will still have CRT_NONE in rangep->cr_type
249
and that will be suitable to return. */
250
sh64_address_in_cranges (cranges, addr, rangep);
252
return rangep->cr_type;
255
/* This is a simpler exported interface for the benefit of gdb et al. */
258
sh64_address_is_shmedia (sec, addr)
262
sh64_elf_crange dummy;
263
return sh64_get_contents_type (sec, addr, &dummy) == CRT_SH5_ISA32;