gdb/
[deliverable/binutils-gdb.git] / bfd / elf32-sh64-com.c
CommitLineData
ef230218 1/* SuperH SH64-specific support for 32-bit ELF
3db64b00
AM
2 Copyright 2000, 2001, 2002, 2003, 2004, 2007
3 Free Software Foundation, Inc.
b34976b6 4
9cba27b2 5 This file is part of BFD, the Binary File Descriptor library.
b34976b6 6
9cba27b2
JT
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
cd123cb7 9 the Free Software Foundation; either version 3 of the License, or
9cba27b2 10 (at your option) any later version.
b34976b6 11
9cba27b2
JT
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.
b34976b6 16
9cba27b2
JT
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
cd123cb7
NC
19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
9cba27b2
JT
21
22#define SH64_ELF
23
9cba27b2 24#include "sysdep.h"
3db64b00 25#include "bfd.h"
9cba27b2
JT
26#include "libbfd.h"
27#include "elf-bfd.h"
28#include "elf/sh.h"
f0abc2a1 29#include "elf32-sh64.h"
9cba27b2
JT
30#include "../opcodes/sh64-opc.h"
31
b34976b6 32static bfd_boolean sh64_address_in_cranges
09fd220b 33 (asection *cranges, bfd_vma, sh64_elf_crange *);
9cba27b2
JT
34
35/* Ordering functions of a crange, for the qsort and bsearch calls and for
36 different endianness. */
37
38int
09fd220b 39_bfd_sh64_crange_qsort_cmpb (const void *p1, const void *p2)
9cba27b2
JT
40{
41 bfd_vma a1 = bfd_getb32 (p1);
42 bfd_vma a2 = bfd_getb32 (p2);
43
44 /* Preserve order if there's ambiguous contents. */
45 if (a1 == a2)
46 return (char *) p1 - (char *) p2;
47
48 return a1 - a2;
49}
50
51int
09fd220b 52_bfd_sh64_crange_qsort_cmpl (const void *p1, const void *p2)
9cba27b2
JT
53{
54 bfd_vma a1 = (bfd_vma) bfd_getl32 (p1);
55 bfd_vma a2 = (bfd_vma) bfd_getl32 (p2);
56
57 /* Preserve order if there's ambiguous contents. */
58 if (a1 == a2)
59 return (char *) p1 - (char *) p2;
60
61 return a1 - a2;
62}
63
64int
09fd220b 65_bfd_sh64_crange_bsearch_cmpb (const void *p1, const void *p2)
9cba27b2
JT
66{
67 bfd_vma a1 = *(bfd_vma *) p1;
68 bfd_vma a2 = (bfd_vma) bfd_getb32 (p2);
69 bfd_size_type size
70 = (bfd_size_type) bfd_getb32 (SH64_CRANGE_CR_SIZE_OFFSET + (char *) p2);
71
72 if (a1 >= a2 + size)
73 return 1;
74 if (a1 < a2)
75 return -1;
76 return 0;
77}
78
79int
09fd220b 80_bfd_sh64_crange_bsearch_cmpl (const void *p1, const void *p2)
9cba27b2
JT
81{
82 bfd_vma a1 = *(bfd_vma *) p1;
83 bfd_vma a2 = (bfd_vma) bfd_getl32 (p2);
84 bfd_size_type size
85 = (bfd_size_type) bfd_getl32 (SH64_CRANGE_CR_SIZE_OFFSET + (char *) p2);
86
87 if (a1 >= a2 + size)
88 return 1;
89 if (a1 < a2)
90 return -1;
91 return 0;
92}
93
94/* Check whether a specific address is specified within a .cranges
95 section. Return FALSE if not found, and TRUE if found, and the region
96 filled into RANGEP if non-NULL. */
97
b34976b6 98static bfd_boolean
09fd220b
KK
99sh64_address_in_cranges (asection *cranges, bfd_vma addr,
100 sh64_elf_crange *rangep)
9cba27b2
JT
101{
102 bfd_byte *cranges_contents;
103 bfd_byte *found_rangep;
eea6121a 104 bfd_size_type cranges_size = cranges->size;
9cba27b2
JT
105
106 /* If the size is not a multiple of the cranges entry size, then
107 something is badly wrong. */
108 if ((cranges_size % SH64_CRANGE_SIZE) != 0)
b34976b6 109 return FALSE;
9cba27b2
JT
110
111 /* If this section has relocations, then we can't do anything sane. */
112 if (bfd_get_section_flags (cranges->owner, cranges) & SEC_RELOC)
b34976b6 113 return FALSE;
9cba27b2
JT
114
115 /* Has some kind soul (or previous call) left processed, sorted contents
116 for us? */
117 if ((bfd_get_section_flags (cranges->owner, cranges) & SEC_IN_MEMORY)
118 && elf_section_data (cranges)->this_hdr.sh_type == SHT_SH5_CR_SORTED)
119 cranges_contents = cranges->contents;
120 else
121 {
eea6121a
AM
122 if (!bfd_malloc_and_get_section (cranges->owner, cranges,
123 &cranges_contents))
9cba27b2
JT
124 goto error_return;
125
126 /* Is it sorted? */
127 if (elf_section_data (cranges)->this_hdr.sh_type
128 != SHT_SH5_CR_SORTED)
129 /* Nope. Lets sort it. */
130 qsort (cranges_contents, cranges_size / SH64_CRANGE_SIZE,
131 SH64_CRANGE_SIZE,
132 bfd_big_endian (cranges->owner)
133 ? _bfd_sh64_crange_qsort_cmpb : _bfd_sh64_crange_qsort_cmpl);
134
135 /* Let's keep it around. */
136 cranges->contents = cranges_contents;
137 bfd_set_section_flags (cranges->owner, cranges,
138 bfd_get_section_flags (cranges->owner, cranges)
139 | SEC_IN_MEMORY);
140
141 /* It's sorted now. */
142 elf_section_data (cranges)->this_hdr.sh_type = SHT_SH5_CR_SORTED;
143 }
144
145 /* Try and find a matching range. */
146 found_rangep
147 = bsearch (&addr, cranges_contents, cranges_size / SH64_CRANGE_SIZE,
148 SH64_CRANGE_SIZE,
149 bfd_big_endian (cranges->owner)
150 ? _bfd_sh64_crange_bsearch_cmpb
151 : _bfd_sh64_crange_bsearch_cmpl);
152
153 /* Fill in a few return values if we found a matching range. */
154 if (found_rangep)
155 {
156 enum sh64_elf_cr_type cr_type
157 = bfd_get_16 (cranges->owner,
158 SH64_CRANGE_CR_TYPE_OFFSET + found_rangep);
159 bfd_vma cr_addr
160 = bfd_get_32 (cranges->owner,
161 SH64_CRANGE_CR_ADDR_OFFSET
162 + (char *) found_rangep);
163 bfd_size_type cr_size
164 = bfd_get_32 (cranges->owner,
165 SH64_CRANGE_CR_SIZE_OFFSET
166 + (char *) found_rangep);
167
168 rangep->cr_addr = cr_addr;
169 rangep->cr_size = cr_size;
170 rangep->cr_type = cr_type;
171
b34976b6 172 return TRUE;
9cba27b2
JT
173 }
174
175 /* There is a .cranges section, but it does not have a descriptor
176 matching this address. */
b34976b6 177 return FALSE;
9cba27b2
JT
178
179error_return:
eea6121a
AM
180 if (cranges_contents != NULL)
181 free (cranges_contents);
b34976b6 182 return FALSE;
9cba27b2
JT
183}
184
185/* Determine what ADDR points to in SEC, and fill in a range descriptor in
186 *RANGEP if it's non-NULL. */
187
188enum sh64_elf_cr_type
09fd220b 189sh64_get_contents_type (asection *sec, bfd_vma addr, sh64_elf_crange *rangep)
9cba27b2
JT
190{
191 asection *cranges;
192
193 /* Fill in the range with the boundaries of the section as a default. */
194 if (bfd_get_flavour (sec->owner) == bfd_target_elf_flavour
195 && elf_elfheader (sec->owner)->e_type == ET_EXEC)
196 {
197 rangep->cr_addr = bfd_get_section_vma (sec->owner, sec);
eea6121a 198 rangep->cr_size = sec->size;
9cba27b2
JT
199 rangep->cr_type = CRT_NONE;
200 }
201 else
b34976b6 202 return FALSE;
9cba27b2
JT
203
204 /* If none of the pertinent bits are set, then it's a SHcompact (or at
205 least not SHmedia). */
206 if ((elf_section_data (sec)->this_hdr.sh_flags
207 & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED)) == 0)
208 {
209 enum sh64_elf_cr_type cr_type
210 = ((bfd_get_section_flags (sec->owner, sec) & SEC_CODE) != 0
211 ? CRT_SH5_ISA16 : CRT_DATA);
212 rangep->cr_type = cr_type;
213 return cr_type;
214 }
215
216 /* If only the SHF_SH5_ISA32 bit is set, then we have SHmedia. */
217 if ((elf_section_data (sec)->this_hdr.sh_flags
218 & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED)) == SHF_SH5_ISA32)
219 {
220 rangep->cr_type = CRT_SH5_ISA32;
221 return CRT_SH5_ISA32;
222 }
223
224 /* Otherwise, we have to look up the .cranges section. */
225 cranges = bfd_get_section_by_name (sec->owner, SH64_CRANGES_SECTION_NAME);
226
227 if (cranges == NULL)
228 /* A mixed section but there's no .cranges section. This is probably
229 bad input; it does not comply to specs. */
230 return CRT_NONE;
231
232 /* If this call fails, we will still have CRT_NONE in rangep->cr_type
233 and that will be suitable to return. */
234 sh64_address_in_cranges (cranges, addr, rangep);
235
236 return rangep->cr_type;
237}
238
239/* This is a simpler exported interface for the benefit of gdb et al. */
240
b34976b6 241bfd_boolean
09fd220b 242sh64_address_is_shmedia (asection *sec, bfd_vma addr)
9cba27b2
JT
243{
244 sh64_elf_crange dummy;
245 return sh64_get_contents_type (sec, addr, &dummy) == CRT_SH5_ISA32;
246}
This page took 0.328226 seconds and 4 git commands to generate.