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