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