1 /* ARM Mach-O support for BFD. 2 Copyright (C) 2015-2018 Free Software Foundation, Inc. 3 4 This file is part of BFD, the Binary File Descriptor library. 5 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 3 of the License, or 9 (at your option) any later version. 10 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. 15 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 18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 19 MA 02110-1301, USA. */ 20 21 #include "sysdep.h" 22 #include "mach-o.h" 23 #include "bfd.h" 24 #include "libbfd.h" 25 #include "libiberty.h" 26 #include "mach-o/arm.h" 27 28 #define bfd_mach_o_object_p bfd_mach_o_arm_object_p 29 #define bfd_mach_o_core_p bfd_mach_o_arm_core_p 30 #define bfd_mach_o_mkobject bfd_mach_o_arm_mkobject 31 32 #define bfd_mach_o_canonicalize_one_reloc bfd_mach_o_arm_canonicalize_one_reloc 33 #define bfd_mach_o_swap_reloc_out NULL 34 #define bfd_mach_o_bfd_reloc_type_lookup bfd_mach_o_arm_bfd_reloc_type_lookup 35 #define bfd_mach_o_bfd_reloc_name_lookup bfd_mach_o_arm_bfd_reloc_name_lookup 36 37 #define bfd_mach_o_print_thread NULL 38 #define bfd_mach_o_tgt_seg_table NULL 39 #define bfd_mach_o_section_type_valid_for_tgt NULL 40 41 static const bfd_target * 42 bfd_mach_o_arm_object_p (bfd *abfd) 43 { 44 return bfd_mach_o_header_p (abfd, 0, 0, BFD_MACH_O_CPU_TYPE_ARM); 45 } 46 47 static const bfd_target * 48 bfd_mach_o_arm_core_p (bfd *abfd) 49 { 50 return bfd_mach_o_header_p (abfd, 0, 51 BFD_MACH_O_MH_CORE, BFD_MACH_O_CPU_TYPE_ARM); 52 } 53 54 static bfd_boolean 55 bfd_mach_o_arm_mkobject (bfd *abfd) 56 { 57 bfd_mach_o_data_struct *mdata; 58 59 if (!bfd_mach_o_mkobject_init (abfd)) 60 return FALSE; 61 62 mdata = bfd_mach_o_get_data (abfd); 63 mdata->header.magic = BFD_MACH_O_MH_MAGIC; 64 mdata->header.cputype = BFD_MACH_O_CPU_TYPE_ARM; 65 mdata->header.cpusubtype = BFD_MACH_O_CPU_SUBTYPE_ARM_ALL; 66 mdata->header.byteorder = BFD_ENDIAN_LITTLE; 67 mdata->header.version = 1; 68 69 return TRUE; 70 } 71 72 static reloc_howto_type arm_howto_table[]= 73 { 74 /* 0 */ 75 HOWTO (BFD_RELOC_32, 0, 2, 32, FALSE, 0, 76 complain_overflow_bitfield, 77 NULL, "32", 78 FALSE, 0xffffffff, 0xffffffff, FALSE), 79 HOWTO (BFD_RELOC_16, 0, 1, 16, FALSE, 0, 80 complain_overflow_bitfield, 81 NULL, "16", 82 FALSE, 0xffff, 0xffff, FALSE), 83 HOWTO (BFD_RELOC_8, 0, 0, 8, FALSE, 0, 84 complain_overflow_bitfield, 85 NULL, "8", 86 FALSE, 0xff, 0xff, FALSE), 87 HOWTO (BFD_RELOC_32_PCREL, 0, 2, 32, TRUE, 0, 88 complain_overflow_bitfield, 89 NULL, "DISP32", 90 FALSE, 0xffffffff, 0xffffffff, TRUE), 91 /* 4 */ 92 HOWTO (BFD_RELOC_16_PCREL, 0, 1, 16, TRUE, 0, 93 complain_overflow_bitfield, 94 NULL, "DISP16", 95 FALSE, 0xffff, 0xffff, TRUE), 96 HOWTO (BFD_RELOC_MACH_O_SECTDIFF, 0, 2, 32, FALSE, 0, 97 complain_overflow_bitfield, 98 NULL, "SECTDIFF_32", 99 FALSE, 0xffffffff, 0xffffffff, FALSE), 100 HOWTO (BFD_RELOC_MACH_O_LOCAL_SECTDIFF, 0, 2, 32, FALSE, 0, 101 complain_overflow_bitfield, 102 NULL, "LSECTDIFF_32", 103 FALSE, 0xffffffff, 0xffffffff, FALSE), 104 HOWTO (BFD_RELOC_MACH_O_PAIR, 0, 2, 32, FALSE, 0, 105 complain_overflow_bitfield, 106 NULL, "PAIR_32", 107 FALSE, 0xffffffff, 0xffffffff, FALSE), 108 /* 8 */ 109 HOWTO (BFD_RELOC_MACH_O_SECTDIFF, 0, 1, 16, FALSE, 0, 110 complain_overflow_bitfield, 111 NULL, "SECTDIFF_16", 112 FALSE, 0xffff, 0xffff, FALSE), 113 HOWTO (BFD_RELOC_MACH_O_LOCAL_SECTDIFF, 0, 1, 16, FALSE, 0, 114 complain_overflow_bitfield, 115 NULL, "LSECTDIFF_16", 116 FALSE, 0xffff, 0xffff, FALSE), 117 HOWTO (BFD_RELOC_MACH_O_PAIR, 0, 1, 16, FALSE, 0, 118 complain_overflow_bitfield, 119 NULL, "PAIR_16", 120 FALSE, 0xffff, 0xffff, FALSE), 121 HOWTO (BFD_RELOC_ARM_PCREL_CALL, 2, 2, 24, TRUE, 0, 122 complain_overflow_signed, 123 NULL, "BR24", 124 FALSE, 0x00ffffff, 0x00ffffff, TRUE), 125 /* 12 */ 126 HOWTO (BFD_RELOC_ARM_MOVW, 0, 2, 16, FALSE, 0, 127 complain_overflow_dont, 128 NULL, "MOVW", 129 FALSE, 0x000f0fff, 0x000f0fff, FALSE), 130 HOWTO (BFD_RELOC_MACH_O_PAIR, 0, 2, 16, FALSE, 0, 131 complain_overflow_bitfield, 132 NULL, "PAIR_W", 133 FALSE, 0x000f0fff, 0x000f0fff, FALSE), 134 HOWTO (BFD_RELOC_ARM_MOVT, 0, 2, 16, FALSE, 0, 135 complain_overflow_bitfield, 136 NULL, "MOVT", 137 FALSE, 0x000f0fff, 0x000f0fff, FALSE), 138 HOWTO (BFD_RELOC_MACH_O_PAIR, 0, 2, 16, FALSE, 0, 139 complain_overflow_bitfield, 140 NULL, "PAIR_T", 141 FALSE, 0x000f0fff, 0x000f0fff, FALSE), 142 /* 16 */ 143 HOWTO (BFD_RELOC_THUMB_PCREL_BLX, 2, 2, 24, TRUE, 0, 144 complain_overflow_signed, 145 NULL, "TBR22", 146 FALSE, 0x07ff2fff, 0x07ff2fff, TRUE) 147 }; 148 149 static bfd_boolean 150 bfd_mach_o_arm_canonicalize_one_reloc (bfd * abfd, 151 struct mach_o_reloc_info_external * raw, 152 arelent * res, 153 asymbol ** syms, 154 arelent * res_base) 155 { 156 bfd_mach_o_reloc_info reloc; 157 158 if (!bfd_mach_o_pre_canonicalize_one_reloc (abfd, raw, &reloc, res, syms)) 159 return FALSE; 160 161 if (reloc.r_scattered) 162 { 163 switch (reloc.r_type) 164 { 165 case BFD_MACH_O_ARM_RELOC_PAIR: 166 /* PR 21813: Check for a corrupt PAIR reloc at the start. */ 167 if (res == res_base) 168 return FALSE; 169 if (reloc.r_length == 2) 170 { 171 res->howto = &arm_howto_table[7]; 172 res->address = res[-1].address; 173 return TRUE; 174 } 175 else if (reloc.r_length == 1) 176 { 177 res->howto = &arm_howto_table[10]; 178 res->address = res[-1].address; 179 return TRUE; 180 } 181 return FALSE; 182 183 case BFD_MACH_O_ARM_RELOC_SECTDIFF: 184 if (reloc.r_length == 2) 185 { 186 res->howto = &arm_howto_table[5]; 187 return TRUE; 188 } 189 else if (reloc.r_length == 1) 190 { 191 res->howto = &arm_howto_table[8]; 192 return TRUE; 193 } 194 return FALSE; 195 196 case BFD_MACH_O_ARM_RELOC_LOCAL_SECTDIFF: 197 if (reloc.r_length == 2) 198 { 199 res->howto = &arm_howto_table[6]; 200 return TRUE; 201 } 202 else if (reloc.r_length == 1) 203 { 204 res->howto = &arm_howto_table[9]; 205 return TRUE; 206 } 207 return FALSE; 208 209 case BFD_MACH_O_ARM_RELOC_HALF_SECTDIFF: 210 switch (reloc.r_length) 211 { 212 case 2: /* :lower16: for movw arm. */ 213 res->howto = &arm_howto_table[12]; 214 return TRUE; 215 case 3: /* :upper16: for movt arm. */ 216 res->howto = &arm_howto_table[14]; 217 return TRUE; 218 } 219 return FALSE; 220 221 default: 222 break; 223 } 224 } 225 else 226 { 227 switch (reloc.r_type) 228 { 229 case BFD_MACH_O_ARM_RELOC_VANILLA: 230 switch ((reloc.r_length << 1) | reloc.r_pcrel) 231 { 232 case 0: /* len = 0, pcrel = 0 */ 233 res->howto = &arm_howto_table[2]; 234 return TRUE; 235 case 2: /* len = 1, pcrel = 0 */ 236 res->howto = &arm_howto_table[1]; 237 return TRUE; 238 case 3: /* len = 1, pcrel = 1 */ 239 res->howto = &arm_howto_table[4]; 240 return TRUE; 241 case 4: /* len = 2, pcrel = 0 */ 242 res->howto = &arm_howto_table[0]; 243 return TRUE; 244 case 5: /* len = 2, pcrel = 1 */ 245 res->howto = &arm_howto_table[3]; 246 return TRUE; 247 default: 248 return FALSE; 249 } 250 break; 251 252 case BFD_MACH_O_ARM_RELOC_BR24: 253 if (reloc.r_length == 2 && reloc.r_pcrel == 1) 254 { 255 res->howto = &arm_howto_table[11]; 256 return TRUE; 257 } 258 break; 259 260 case BFD_MACH_O_THUMB_RELOC_BR22: 261 if (reloc.r_length == 2 && reloc.r_pcrel == 1) 262 { 263 res->howto = &arm_howto_table[16]; 264 return TRUE; 265 } 266 break; 267 268 case BFD_MACH_O_ARM_RELOC_HALF: 269 if (reloc.r_pcrel == 0) 270 switch (reloc.r_length) 271 { 272 case 0: /* :lower16: for movw arm. */ 273 res->howto = &arm_howto_table[12]; 274 return TRUE; 275 case 1: /* :upper16: for movt arm. */ 276 res->howto = &arm_howto_table[14]; 277 return TRUE; 278 } 279 break; 280 281 case BFD_MACH_O_ARM_RELOC_PAIR: 282 if (res[-1].howto == &arm_howto_table[12] 283 && reloc.r_length == 0) 284 { 285 /* Pair for :lower16: of movw arm. */ 286 res->howto = &arm_howto_table[13]; 287 /* This reloc contains the other half in its r_address field. */ 288 res[-1].addend += (res->address & 0xffff) << 16; 289 res->address = res[-1].address; 290 return TRUE; 291 } 292 else if (res[-1].howto == &arm_howto_table[14] 293 && reloc.r_length == 1) 294 { 295 /* Pair for :upper16: of movt arm. */ 296 res->howto = &arm_howto_table[15]; 297 /* This reloc contains the other half in its r_address field. */ 298 res[-1].addend += res->address & 0xffff; 299 res->address = res[-1].address; 300 return TRUE; 301 } 302 break; 303 304 default: 305 break; 306 } 307 } 308 309 return FALSE; 310 } 311 312 static reloc_howto_type * 313 bfd_mach_o_arm_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, 314 bfd_reloc_code_real_type code) 315 { 316 unsigned int i; 317 318 for (i = 0; i < sizeof (arm_howto_table) / sizeof (*arm_howto_table); i++) 319 if (code == arm_howto_table[i].type) 320 return &arm_howto_table[i]; 321 return NULL; 322 } 323 324 static reloc_howto_type * 325 bfd_mach_o_arm_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, 326 const char *name ATTRIBUTE_UNUSED) 327 { 328 return NULL; 329 } 330 331 #define TARGET_NAME arm_mach_o_vec 332 #define TARGET_STRING "mach-o-arm" 333 #define TARGET_ARCHITECTURE bfd_arch_arm 334 #define TARGET_PAGESIZE 4096 335 #define TARGET_BIG_ENDIAN 0 336 #define TARGET_ARCHIVE 0 337 #define TARGET_PRIORITY 0 338 #include "mach-o-target.c" 339