1 /* ARM Mach-O support for BFD. 2 Copyright (C) 2015-2022 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 "bfd.h" 23 #include "libbfd.h" 24 #include "libiberty.h" 25 #include "mach-o.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 bfd_cleanup 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 bfd_cleanup 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 bool 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, 4, 32, false, 0, 76 complain_overflow_bitfield, 77 NULL, "32", 78 false, 0xffffffff, 0xffffffff, false), 79 HOWTO (BFD_RELOC_16, 0, 2, 16, false, 0, 80 complain_overflow_bitfield, 81 NULL, "16", 82 false, 0xffff, 0xffff, false), 83 HOWTO (BFD_RELOC_8, 0, 1, 8, false, 0, 84 complain_overflow_bitfield, 85 NULL, "8", 86 false, 0xff, 0xff, false), 87 HOWTO (BFD_RELOC_32_PCREL, 0, 4, 32, true, 0, 88 complain_overflow_bitfield, 89 NULL, "DISP32", 90 false, 0xffffffff, 0xffffffff, true), 91 /* 4 */ 92 HOWTO (BFD_RELOC_16_PCREL, 0, 2, 16, true, 0, 93 complain_overflow_bitfield, 94 NULL, "DISP16", 95 false, 0xffff, 0xffff, true), 96 HOWTO (BFD_RELOC_MACH_O_SECTDIFF, 0, 4, 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, 4, 32, false, 0, 101 complain_overflow_bitfield, 102 NULL, "LSECTDIFF_32", 103 false, 0xffffffff, 0xffffffff, false), 104 HOWTO (BFD_RELOC_MACH_O_PAIR, 0, 4, 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, 2, 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, 2, 16, false, 0, 114 complain_overflow_bitfield, 115 NULL, "LSECTDIFF_16", 116 false, 0xffff, 0xffff, false), 117 HOWTO (BFD_RELOC_MACH_O_PAIR, 0, 2, 16, false, 0, 118 complain_overflow_bitfield, 119 NULL, "PAIR_16", 120 false, 0xffff, 0xffff, false), 121 HOWTO (BFD_RELOC_ARM_PCREL_CALL, 2, 4, 24, true, 0, 122 complain_overflow_signed, 123 NULL, "BR24", 124 false, 0x00ffffff, 0x00ffffff, true), 125 /* 12 */ 126 HOWTO (BFD_RELOC_ARM_MOVW, 0, 4, 16, false, 0, 127 complain_overflow_dont, 128 NULL, "MOVW", 129 false, 0x000f0fff, 0x000f0fff, false), 130 HOWTO (BFD_RELOC_MACH_O_PAIR, 0, 4, 16, false, 0, 131 complain_overflow_bitfield, 132 NULL, "PAIR_W", 133 false, 0x000f0fff, 0x000f0fff, false), 134 HOWTO (BFD_RELOC_ARM_MOVT, 0, 4, 16, false, 0, 135 complain_overflow_bitfield, 136 NULL, "MOVT", 137 false, 0x000f0fff, 0x000f0fff, false), 138 HOWTO (BFD_RELOC_MACH_O_PAIR, 0, 4, 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, 4, 24, true, 0, 144 complain_overflow_signed, 145 NULL, "TBR22", 146 false, 0x07ff2fff, 0x07ff2fff, true) 147 }; 148 149 static bool 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 { 169 _bfd_error_handler (_("malformed mach-o ARM reloc pair: " 170 "reloc is first reloc")); 171 return false; 172 } 173 if (reloc.r_length == 2) 174 { 175 res->howto = &arm_howto_table[7]; 176 res->address = res[-1].address; 177 return true; 178 } 179 else if (reloc.r_length == 1) 180 { 181 res->howto = &arm_howto_table[10]; 182 res->address = res[-1].address; 183 return true; 184 } 185 _bfd_error_handler (_("malformed mach-o ARM reloc pair: " 186 "invalid length: %d"), reloc.r_length); 187 return false; 188 189 case BFD_MACH_O_ARM_RELOC_SECTDIFF: 190 if (reloc.r_length == 2) 191 { 192 res->howto = &arm_howto_table[5]; 193 return true; 194 } 195 else if (reloc.r_length == 1) 196 { 197 res->howto = &arm_howto_table[8]; 198 return true; 199 } 200 _bfd_error_handler (_("malformed mach-o ARM sectdiff reloc: " 201 "invalid length: %d"), reloc.r_length); 202 return false; 203 204 case BFD_MACH_O_ARM_RELOC_LOCAL_SECTDIFF: 205 if (reloc.r_length == 2) 206 { 207 res->howto = &arm_howto_table[6]; 208 return true; 209 } 210 else if (reloc.r_length == 1) 211 { 212 res->howto = &arm_howto_table[9]; 213 return true; 214 } 215 _bfd_error_handler (_("malformed mach-o ARM local sectdiff reloc: " 216 "invalid length: %d"), 217 reloc.r_length); 218 return false; 219 220 case BFD_MACH_O_ARM_RELOC_HALF_SECTDIFF: 221 switch (reloc.r_length) 222 { 223 case 2: /* :lower16: for movw arm. */ 224 res->howto = &arm_howto_table[12]; 225 return true; 226 case 3: /* :upper16: for movt arm. */ 227 res->howto = &arm_howto_table[14]; 228 return true; 229 } 230 _bfd_error_handler (_("malformed mach-o ARM half sectdiff reloc: " 231 "invalid length: %d"), 232 reloc.r_length); 233 return false; 234 235 default: 236 break; 237 } 238 } 239 else 240 { 241 switch (reloc.r_type) 242 { 243 case BFD_MACH_O_ARM_RELOC_VANILLA: 244 switch ((reloc.r_length << 1) | reloc.r_pcrel) 245 { 246 case 0: /* len = 0, pcrel = 0 */ 247 res->howto = &arm_howto_table[2]; 248 return true; 249 case 2: /* len = 1, pcrel = 0 */ 250 res->howto = &arm_howto_table[1]; 251 return true; 252 case 3: /* len = 1, pcrel = 1 */ 253 res->howto = &arm_howto_table[4]; 254 return true; 255 case 4: /* len = 2, pcrel = 0 */ 256 res->howto = &arm_howto_table[0]; 257 return true; 258 case 5: /* len = 2, pcrel = 1 */ 259 res->howto = &arm_howto_table[3]; 260 return true; 261 default: 262 _bfd_error_handler (_("malformed mach-o ARM vanilla reloc: " 263 "invalid length: %d (pcrel: %d)"), 264 reloc.r_length, reloc.r_pcrel); 265 return false; 266 } 267 break; 268 269 case BFD_MACH_O_ARM_RELOC_BR24: 270 if (reloc.r_length == 2 && reloc.r_pcrel == 1) 271 { 272 res->howto = &arm_howto_table[11]; 273 return true; 274 } 275 break; 276 277 case BFD_MACH_O_THUMB_RELOC_BR22: 278 if (reloc.r_length == 2 && reloc.r_pcrel == 1) 279 { 280 res->howto = &arm_howto_table[16]; 281 return true; 282 } 283 break; 284 285 case BFD_MACH_O_ARM_RELOC_HALF: 286 if (reloc.r_pcrel == 0) 287 switch (reloc.r_length) 288 { 289 case 0: /* :lower16: for movw arm. */ 290 res->howto = &arm_howto_table[12]; 291 return true; 292 case 1: /* :upper16: for movt arm. */ 293 res->howto = &arm_howto_table[14]; 294 return true; 295 } 296 break; 297 298 case BFD_MACH_O_ARM_RELOC_PAIR: 299 if (res == res_base) 300 { 301 _bfd_error_handler (_("malformed mach-o ARM reloc pair: " 302 "reloc is first reloc")); 303 return false; 304 } 305 if (res[-1].howto == &arm_howto_table[12] 306 && reloc.r_length == 0) 307 { 308 /* Pair for :lower16: of movw arm. */ 309 res->howto = &arm_howto_table[13]; 310 /* This reloc contains the other half in its r_address field. */ 311 res[-1].addend += (res->address & 0xffff) << 16; 312 res->address = res[-1].address; 313 return true; 314 } 315 else if (res[-1].howto == &arm_howto_table[14] 316 && reloc.r_length == 1) 317 { 318 /* Pair for :upper16: of movt arm. */ 319 res->howto = &arm_howto_table[15]; 320 /* This reloc contains the other half in its r_address field. */ 321 res[-1].addend += res->address & 0xffff; 322 res->address = res[-1].address; 323 return true; 324 } 325 break; 326 327 default: 328 break; 329 } 330 } 331 332 _bfd_error_handler (_("malformed mach-o ARM reloc: " 333 "unknown reloc type: %d"), reloc.r_length); 334 return false; 335 } 336 337 static reloc_howto_type * 338 bfd_mach_o_arm_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, 339 bfd_reloc_code_real_type code) 340 { 341 unsigned int i; 342 343 for (i = 0; i < sizeof (arm_howto_table) / sizeof (*arm_howto_table); i++) 344 if (code == arm_howto_table[i].type) 345 return &arm_howto_table[i]; 346 return NULL; 347 } 348 349 static reloc_howto_type * 350 bfd_mach_o_arm_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, 351 const char *name ATTRIBUTE_UNUSED) 352 { 353 return NULL; 354 } 355 356 #define TARGET_NAME arm_mach_o_vec 357 #define TARGET_STRING "mach-o-arm" 358 #define TARGET_ARCHITECTURE bfd_arch_arm 359 #define TARGET_PAGESIZE 4096 360 #define TARGET_BIG_ENDIAN 0 361 #define TARGET_ARCHIVE 0 362 #define TARGET_PRIORITY 0 363 #include "mach-o-target.c" 364