OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [binutils-2.20.1/] [bfd/] [elf32-sh64-com.c] - Blame information for rev 843

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 205 julius
/* SuperH SH64-specific support for 32-bit ELF
2
   Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2007
3
   Free Software Foundation, Inc.
4
 
5
   This file is part of BFD, the Binary File Descriptor library.
6
 
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 3 of the License, or
10
   (at your option) any later version.
11
 
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.
16
 
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
19
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20
   MA 02110-1301, USA.  */
21
 
22
#define SH64_ELF
23
 
24
#include "sysdep.h"
25
#include "bfd.h"
26
#include "libbfd.h"
27
#include "elf-bfd.h"
28
#include "elf/sh.h"
29
#include "elf32-sh64.h"
30
#include "../opcodes/sh64-opc.h"
31
 
32
static bfd_boolean sh64_address_in_cranges
33
  (asection *cranges, bfd_vma, sh64_elf_crange *);
34
 
35
/* Ordering functions of a crange, for the qsort and bsearch calls and for
36
   different endianness.  */
37
 
38
int
39
_bfd_sh64_crange_qsort_cmpb (const void *p1, const void *p2)
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
 
51
int
52
_bfd_sh64_crange_qsort_cmpl (const void *p1, const void *p2)
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
 
64
int
65
_bfd_sh64_crange_bsearch_cmpb (const void *p1, const void *p2)
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
 
79
int
80
_bfd_sh64_crange_bsearch_cmpl (const void *p1, const void *p2)
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
 
98
static bfd_boolean
99
sh64_address_in_cranges (asection *cranges, bfd_vma addr,
100
                         sh64_elf_crange *rangep)
101
{
102
  bfd_byte *cranges_contents;
103
  bfd_byte *found_rangep;
104
  bfd_size_type cranges_size = cranges->size;
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)
109
    return FALSE;
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)
113
    return FALSE;
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
    {
122
      if (!bfd_malloc_and_get_section (cranges->owner, cranges,
123
                                       &cranges_contents))
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
 
172
      return TRUE;
173
    }
174
 
175
  /* There is a .cranges section, but it does not have a descriptor
176
     matching this address.  */
177
  return FALSE;
178
 
179
error_return:
180
  if (cranges_contents != NULL)
181
    free (cranges_contents);
182
  return FALSE;
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
 
188
enum sh64_elf_cr_type
189
sh64_get_contents_type (asection *sec, bfd_vma addr, sh64_elf_crange *rangep)
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);
198
      rangep->cr_size = sec->size;
199
      rangep->cr_type = CRT_NONE;
200
    }
201
  else
202
    return FALSE;
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
 
241
bfd_boolean
242
sh64_address_is_shmedia (asection *sec, bfd_vma addr)
243
{
244
  sh64_elf_crange dummy;
245
  return sh64_get_contents_type (sec, addr, &dummy) == CRT_SH5_ISA32;
246
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.