s/boolean/bfd_boolean/ s/true/TRUE/ s/false/FALSE/. Simplify
[deliverable/binutils-gdb.git] / bfd / elf32-sh64-com.c
CommitLineData
9cba27b2 1/* Hitachi SH64-specific support for 32-bit ELF
b34976b6
AM
2 Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
3
9cba27b2 4 This file is part of BFD, the Binary File Descriptor library.
b34976b6 5
9cba27b2
JT
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.
b34976b6 10
9cba27b2
JT
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.
b34976b6 15
9cba27b2
JT
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. */
19
20#define SH64_ELF
21
22#include "bfd.h"
23#include "sysdep.h"
24#include "libbfd.h"
25#include "elf-bfd.h"
26#include "elf/sh.h"
27#include "../opcodes/sh64-opc.h"
28
b34976b6 29static bfd_boolean sh64_address_in_cranges
9cba27b2
JT
30 PARAMS ((asection *cranges, bfd_vma, sh64_elf_crange *));
31
32/* Ordering functions of a crange, for the qsort and bsearch calls and for
33 different endianness. */
34
35int
36_bfd_sh64_crange_qsort_cmpb (p1, p2)
37 const PTR p1;
38 const PTR p2;
39{
40 bfd_vma a1 = bfd_getb32 (p1);
41 bfd_vma a2 = bfd_getb32 (p2);
42
43 /* Preserve order if there's ambiguous contents. */
44 if (a1 == a2)
45 return (char *) p1 - (char *) p2;
46
47 return a1 - a2;
48}
49
50int
51_bfd_sh64_crange_qsort_cmpl (p1, p2)
52 const PTR p1;
53 const PTR p2;
54{
55 bfd_vma a1 = (bfd_vma) bfd_getl32 (p1);
56 bfd_vma a2 = (bfd_vma) bfd_getl32 (p2);
57
58 /* Preserve order if there's ambiguous contents. */
59 if (a1 == a2)
60 return (char *) p1 - (char *) p2;
61
62 return a1 - a2;
63}
64
65int
66_bfd_sh64_crange_bsearch_cmpb (p1, p2)
67 const PTR p1;
68 const PTR p2;
69{
70 bfd_vma a1 = *(bfd_vma *) p1;
71 bfd_vma a2 = (bfd_vma) bfd_getb32 (p2);
72 bfd_size_type size
73 = (bfd_size_type) bfd_getb32 (SH64_CRANGE_CR_SIZE_OFFSET + (char *) p2);
74
75 if (a1 >= a2 + size)
76 return 1;
77 if (a1 < a2)
78 return -1;
79 return 0;
80}
81
82int
83_bfd_sh64_crange_bsearch_cmpl (p1, p2)
84 const PTR p1;
85 const PTR p2;
86{
87 bfd_vma a1 = *(bfd_vma *) p1;
88 bfd_vma a2 = (bfd_vma) bfd_getl32 (p2);
89 bfd_size_type size
90 = (bfd_size_type) bfd_getl32 (SH64_CRANGE_CR_SIZE_OFFSET + (char *) p2);
91
92 if (a1 >= a2 + size)
93 return 1;
94 if (a1 < a2)
95 return -1;
96 return 0;
97}
98
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. */
102
b34976b6 103static bfd_boolean
9cba27b2
JT
104sh64_address_in_cranges (cranges, addr, rangep)
105 asection *cranges;
106 bfd_vma addr;
107 sh64_elf_crange *rangep;
108{
109 bfd_byte *cranges_contents;
110 bfd_byte *found_rangep;
111 bfd_size_type cranges_size = bfd_section_size (cranges->owner, cranges);
112
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)
b34976b6 116 return FALSE;
9cba27b2
JT
117
118 /* If this section has relocations, then we can't do anything sane. */
119 if (bfd_get_section_flags (cranges->owner, cranges) & SEC_RELOC)
b34976b6 120 return FALSE;
9cba27b2
JT
121
122 /* Has some kind soul (or previous call) left processed, sorted contents
123 for us? */
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;
127 else
128 {
129 cranges_contents
3463048e 130 = bfd_malloc (cranges->_cooked_size != 0
9cba27b2
JT
131 ? cranges->_cooked_size : cranges->_raw_size);
132 if (cranges_contents == NULL)
b34976b6 133 return FALSE;
9cba27b2
JT
134
135 if (! bfd_get_section_contents (cranges->owner, cranges,
136 cranges_contents, (file_ptr) 0,
137 cranges_size))
138 goto error_return;
139
140 /* Is it sorted? */
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,
145 SH64_CRANGE_SIZE,
146 bfd_big_endian (cranges->owner)
147 ? _bfd_sh64_crange_qsort_cmpb : _bfd_sh64_crange_qsort_cmpl);
148
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)
153 | SEC_IN_MEMORY);
154
155 /* It's sorted now. */
156 elf_section_data (cranges)->this_hdr.sh_type = SHT_SH5_CR_SORTED;
157 }
158
159 /* Try and find a matching range. */
160 found_rangep
161 = bsearch (&addr, cranges_contents, cranges_size / SH64_CRANGE_SIZE,
162 SH64_CRANGE_SIZE,
163 bfd_big_endian (cranges->owner)
164 ? _bfd_sh64_crange_bsearch_cmpb
165 : _bfd_sh64_crange_bsearch_cmpl);
166
167 /* Fill in a few return values if we found a matching range. */
168 if (found_rangep)
169 {
170 enum sh64_elf_cr_type cr_type
171 = bfd_get_16 (cranges->owner,
172 SH64_CRANGE_CR_TYPE_OFFSET + found_rangep);
173 bfd_vma cr_addr
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);
181
182 rangep->cr_addr = cr_addr;
183 rangep->cr_size = cr_size;
184 rangep->cr_type = cr_type;
185
b34976b6 186 return TRUE;
9cba27b2
JT
187 }
188
189 /* There is a .cranges section, but it does not have a descriptor
190 matching this address. */
b34976b6 191 return FALSE;
9cba27b2
JT
192
193error_return:
194 free (cranges_contents);
b34976b6 195 return FALSE;
9cba27b2
JT
196}
197
198/* Determine what ADDR points to in SEC, and fill in a range descriptor in
199 *RANGEP if it's non-NULL. */
200
201enum sh64_elf_cr_type
202sh64_get_contents_type (sec, addr, rangep)
203 asection *sec;
204 bfd_vma addr;
205 sh64_elf_crange *rangep;
206{
207 asection *cranges;
208
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)
212 {
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;
216 }
217 else
b34976b6 218 return FALSE;
9cba27b2
JT
219
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)
224 {
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;
229 return cr_type;
230 }
231
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)
235 {
236 rangep->cr_type = CRT_SH5_ISA32;
237 return CRT_SH5_ISA32;
238 }
239
240 /* Otherwise, we have to look up the .cranges section. */
241 cranges = bfd_get_section_by_name (sec->owner, SH64_CRANGES_SECTION_NAME);
242
243 if (cranges == NULL)
244 /* A mixed section but there's no .cranges section. This is probably
245 bad input; it does not comply to specs. */
246 return CRT_NONE;
247
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);
251
252 return rangep->cr_type;
253}
254
255/* This is a simpler exported interface for the benefit of gdb et al. */
256
b34976b6 257bfd_boolean
9cba27b2
JT
258sh64_address_is_shmedia (sec, addr)
259 asection *sec;
260 bfd_vma addr;
261{
262 sh64_elf_crange dummy;
263 return sh64_get_contents_type (sec, addr, &dummy) == CRT_SH5_ISA32;
264}
This page took 0.111773 seconds and 4 git commands to generate.