00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #define SH64_ELF
00025
00026 #include "bfd.h"
00027 #include "sysdep.h"
00028 #include "libbfd.h"
00029 #include "elf-bfd.h"
00030 #include "elf/sh.h"
00031 #include "elf32-sh64.h"
00032 #include "../opcodes/sh64-opc.h"
00033
00034 static bfd_boolean sh64_address_in_cranges
00035 (asection *cranges, bfd_vma, sh64_elf_crange *);
00036
00037
00038
00039
00040 int
00041 _bfd_sh64_crange_qsort_cmpb (const void *p1, const void *p2)
00042 {
00043 bfd_vma a1 = bfd_getb32 (p1);
00044 bfd_vma a2 = bfd_getb32 (p2);
00045
00046
00047 if (a1 == a2)
00048 return (char *) p1 - (char *) p2;
00049
00050 return a1 - a2;
00051 }
00052
00053 int
00054 _bfd_sh64_crange_qsort_cmpl (const void *p1, const void *p2)
00055 {
00056 bfd_vma a1 = (bfd_vma) bfd_getl32 (p1);
00057 bfd_vma a2 = (bfd_vma) bfd_getl32 (p2);
00058
00059
00060 if (a1 == a2)
00061 return (char *) p1 - (char *) p2;
00062
00063 return a1 - a2;
00064 }
00065
00066 int
00067 _bfd_sh64_crange_bsearch_cmpb (const void *p1, const void *p2)
00068 {
00069 bfd_vma a1 = *(bfd_vma *) p1;
00070 bfd_vma a2 = (bfd_vma) bfd_getb32 (p2);
00071 bfd_size_type size
00072 = (bfd_size_type) bfd_getb32 (SH64_CRANGE_CR_SIZE_OFFSET + (char *) p2);
00073
00074 if (a1 >= a2 + size)
00075 return 1;
00076 if (a1 < a2)
00077 return -1;
00078 return 0;
00079 }
00080
00081 int
00082 _bfd_sh64_crange_bsearch_cmpl (const void *p1, const void *p2)
00083 {
00084 bfd_vma a1 = *(bfd_vma *) p1;
00085 bfd_vma a2 = (bfd_vma) bfd_getl32 (p2);
00086 bfd_size_type size
00087 = (bfd_size_type) bfd_getl32 (SH64_CRANGE_CR_SIZE_OFFSET + (char *) p2);
00088
00089 if (a1 >= a2 + size)
00090 return 1;
00091 if (a1 < a2)
00092 return -1;
00093 return 0;
00094 }
00095
00096
00097
00098
00099
00100 static bfd_boolean
00101 sh64_address_in_cranges (asection *cranges, bfd_vma addr,
00102 sh64_elf_crange *rangep)
00103 {
00104 bfd_byte *cranges_contents;
00105 bfd_byte *found_rangep;
00106 bfd_size_type cranges_size = cranges->size;
00107
00108
00109
00110 if ((cranges_size % SH64_CRANGE_SIZE) != 0)
00111 return FALSE;
00112
00113
00114 if (bfd_get_section_flags (cranges->owner, cranges) & SEC_RELOC)
00115 return FALSE;
00116
00117
00118
00119 if ((bfd_get_section_flags (cranges->owner, cranges) & SEC_IN_MEMORY)
00120 && elf_section_data (cranges)->this_hdr.sh_type == SHT_SH5_CR_SORTED)
00121 cranges_contents = cranges->contents;
00122 else
00123 {
00124 if (!bfd_malloc_and_get_section (cranges->owner, cranges,
00125 &cranges_contents))
00126 goto error_return;
00127
00128
00129 if (elf_section_data (cranges)->this_hdr.sh_type
00130 != SHT_SH5_CR_SORTED)
00131
00132 qsort (cranges_contents, cranges_size / SH64_CRANGE_SIZE,
00133 SH64_CRANGE_SIZE,
00134 bfd_big_endian (cranges->owner)
00135 ? _bfd_sh64_crange_qsort_cmpb : _bfd_sh64_crange_qsort_cmpl);
00136
00137
00138 cranges->contents = cranges_contents;
00139 bfd_set_section_flags (cranges->owner, cranges,
00140 bfd_get_section_flags (cranges->owner, cranges)
00141 | SEC_IN_MEMORY);
00142
00143
00144 elf_section_data (cranges)->this_hdr.sh_type = SHT_SH5_CR_SORTED;
00145 }
00146
00147
00148 found_rangep
00149 = bsearch (&addr, cranges_contents, cranges_size / SH64_CRANGE_SIZE,
00150 SH64_CRANGE_SIZE,
00151 bfd_big_endian (cranges->owner)
00152 ? _bfd_sh64_crange_bsearch_cmpb
00153 : _bfd_sh64_crange_bsearch_cmpl);
00154
00155
00156 if (found_rangep)
00157 {
00158 enum sh64_elf_cr_type cr_type
00159 = bfd_get_16 (cranges->owner,
00160 SH64_CRANGE_CR_TYPE_OFFSET + found_rangep);
00161 bfd_vma cr_addr
00162 = bfd_get_32 (cranges->owner,
00163 SH64_CRANGE_CR_ADDR_OFFSET
00164 + (char *) found_rangep);
00165 bfd_size_type cr_size
00166 = bfd_get_32 (cranges->owner,
00167 SH64_CRANGE_CR_SIZE_OFFSET
00168 + (char *) found_rangep);
00169
00170 rangep->cr_addr = cr_addr;
00171 rangep->cr_size = cr_size;
00172 rangep->cr_type = cr_type;
00173
00174 return TRUE;
00175 }
00176
00177
00178
00179 return FALSE;
00180
00181 error_return:
00182 if (cranges_contents != NULL)
00183 free (cranges_contents);
00184 return FALSE;
00185 }
00186
00187
00188
00189
00190 enum sh64_elf_cr_type
00191 sh64_get_contents_type (asection *sec, bfd_vma addr, sh64_elf_crange *rangep)
00192 {
00193 asection *cranges;
00194
00195
00196 if (bfd_get_flavour (sec->owner) == bfd_target_elf_flavour
00197 && elf_elfheader (sec->owner)->e_type == ET_EXEC)
00198 {
00199 rangep->cr_addr = bfd_get_section_vma (sec->owner, sec);
00200 rangep->cr_size = sec->size;
00201 rangep->cr_type = CRT_NONE;
00202 }
00203 else
00204 return FALSE;
00205
00206
00207
00208 if ((elf_section_data (sec)->this_hdr.sh_flags
00209 & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED)) == 0)
00210 {
00211 enum sh64_elf_cr_type cr_type
00212 = ((bfd_get_section_flags (sec->owner, sec) & SEC_CODE) != 0
00213 ? CRT_SH5_ISA16 : CRT_DATA);
00214 rangep->cr_type = cr_type;
00215 return cr_type;
00216 }
00217
00218
00219 if ((elf_section_data (sec)->this_hdr.sh_flags
00220 & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED)) == SHF_SH5_ISA32)
00221 {
00222 rangep->cr_type = CRT_SH5_ISA32;
00223 return CRT_SH5_ISA32;
00224 }
00225
00226
00227 cranges = bfd_get_section_by_name (sec->owner, SH64_CRANGES_SECTION_NAME);
00228
00229 if (cranges == NULL)
00230
00231
00232 return CRT_NONE;
00233
00234
00235
00236 sh64_address_in_cranges (cranges, addr, rangep);
00237
00238 return rangep->cr_type;
00239 }
00240
00241
00242
00243 bfd_boolean
00244 sh64_address_is_shmedia (asection *sec, bfd_vma addr)
00245 {
00246 sh64_elf_crange dummy;
00247 return sh64_get_contents_type (sec, addr, &dummy) == CRT_SH5_ISA32;
00248 }