1/* 2 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23#ifdef SHLIB 24#include "shlib.h" 25#endif /* SHLIB */ 26/* 27 * This file contains the routines to do relocation for the arm. 28 */ 29#include <stdlib.h> 30#if !(defined(KLD) && defined(__STATIC__)) 31#include <stdio.h> 32#include <mach/mach.h> 33#else /* defined(KLD) && defined(__STATIC__) */ 34#include <mach/kern_return.h> 35#endif /* !(defined(KLD) && defined(__STATIC__)) */ 36#include <string.h> 37#include <stdarg.h> 38#include <mach-o/loader.h> 39#include <mach-o/reloc.h> 40#include <mach-o/arm/reloc.h> 41#include <mach-o/nlist.h> 42#include "stuff/bool.h" 43#include "stuff/bytesex.h" 44 45#include "ld.h" 46#include "live_refs.h" 47#include "objects.h" 48#include "sections.h" 49#include "pass1.h" 50#include "symbols.h" 51#include "pass2.h" 52#include "generic_reloc.h" 53#include "arm_reloc.h" 54#include "indirect_sections.h" 55#include "dylibs.h" 56 57#define U_ABS(l) (((long)(l))<0 ? (unsigned long)(-(l)) : (l)) 58 59/* 60 * arm_reloc() relocates the contents of the specified section for the 61 * relocation entries using the section map from the current object (cur_obj). 62 * 63 * Or if refs is not NULL it is being called by to get the addresses or 64 * merged_symbols from the item being referenced by the relocation entry(s) at 65 * reloc_index. This is used by mark_fine_relocs_references_live() when 66 * -dead_strip is specified to determined what is being referenced and is only 67 * called when all sections have fine_relocs (that is why refs is only filled 68 * in when nfine_relocs != 0). When refs is not NULL, only refs is filled in 69 * and returned and the contents are not relocated. 70 */ 71__private_extern__ 72void 73arm_reloc( 74char *contents, 75struct relocation_info *relocs, 76struct section_map *section_map, 77struct live_refs *refs, 78unsigned long reloc_index) 79{ 80 unsigned long i, j, symbolnum, value, input_pc, output_pc; 81 unsigned long instruction, immediate, low_bit; 82 struct nlist *nlists; 83 char *strings; 84 enum bool force_extern_reloc, relocated_extern_thumb_symbol; 85 enum bool relocated_extern_arm_symbol; 86 struct undefined_map *undefined_map; 87 struct merged_symbol *merged_symbol; 88 struct section_map *local_map, *pair_local_map; 89 struct relocation_info *reloc, *pair_reloc; 90 struct scattered_relocation_info *sreloc, *spair_reloc; 91 unsigned long r_address, r_symbolnum, r_pcrel, r_length, r_extern, 92 r_scattered, r_value, pair_r_symbolnum, pair_r_value; 93 enum reloc_type_arm r_type, pair_r_type; 94 unsigned long other_half; 95 unsigned long offset; 96 unsigned long br14_disp_sign; 97 98#if defined(DEBUG) || defined(RLD) 99 /* 100 * The compiler "warnings: ... may be used uninitialized in this 101 * function" can safely be ignored 102 */ 103 merged_symbol = NULL; 104 local_map = NULL; 105 instruction = 0; 106 other_half = 0; 107 immediate = 0; 108 offset = 0; 109 pair_r_symbolnum = 0; 110 pair_r_value = 0; 111 pair_local_map = NULL; 112#endif /* defined(DEBUG) || defined(RLD) */ 113 114 if(refs != NULL) 115 memset(refs, '\0', sizeof(struct live_refs)); 116 else 117 reloc_index = 0; 118 for(i = reloc_index; i < section_map->s->nreloc; i++){ 119 br14_disp_sign = 0; 120 force_extern_reloc = FALSE; 121 relocated_extern_thumb_symbol = FALSE; 122 relocated_extern_arm_symbol = FALSE; 123 /* 124 * Break out the fields of the relocation entry and set pointer to 125 * the type of relocation entry it is (for updating later). 126 */ 127 if((relocs[i].r_address & R_SCATTERED) != 0){ 128 sreloc = (struct scattered_relocation_info *)(relocs + i); 129 reloc = NULL; 130 r_scattered = 1; 131 r_address = sreloc->r_address; 132 r_pcrel = sreloc->r_pcrel; 133 r_length = sreloc->r_length; 134 r_value = sreloc->r_value; 135 r_type = (enum reloc_type_arm)sreloc->r_type; 136 r_extern = 0; 137 /* 138 * Since the r_value field is reserved in a ARM_RELOC_PAIR 139 * type to report the correct error a check for a stray 140 * ARM_RELOC_PAIR relocation types needs to be done before 141 * it is assumed that r_value is legal. A ARM_RELOC_PAIR 142 * only follows ARM_RELOC_{SECTDIFF,LOCAL_SECTDIFF} relocation 143 * types and it is an error to see one otherwise. 144 */ 145 if(r_type == ARM_RELOC_PAIR){ 146 error_with_cur_obj("stray relocation ARM_RELOC_PAIR entry " 147 "(%lu) in section (%.16s,%.16s)", i, 148 section_map->s->segname, section_map->s->sectname); 149 continue; 150 } 151 /* calculate the r_symbolnum (n_sect) from the r_value */ 152 r_symbolnum = 0; 153 for(j = 0; j < cur_obj->nsection_maps; j++){ 154 if(r_value >= cur_obj->section_maps[j].s->addr && 155 r_value < cur_obj->section_maps[j].s->addr + 156 cur_obj->section_maps[j].s->size){ 157 r_symbolnum = j + 1; 158 break; 159 } 160 } 161 if(r_symbolnum == 0){ 162 /* 163 * The edge case where the last address past then end of 164 * of the last section is referenced. 165 */ 166 for(j = 0; j < cur_obj->nsection_maps; j++){ 167 if(r_value == cur_obj->section_maps[j].s->addr + 168 cur_obj->section_maps[j].s->size){ 169 r_symbolnum = j + 1; 170 break; 171 } 172 } 173 if(r_symbolnum == 0){ 174 error_with_cur_obj("r_value (0x%x) field of relocation " 175 "entry %lu in section (%.16s,%.16s) out of range", 176 (unsigned int)r_value, i, section_map->s->segname, 177 section_map->s->sectname); 178 return; 179 } 180 } 181 } 182 else{ 183 reloc = relocs + i; 184 sreloc = NULL; 185 r_scattered = 0; 186 r_address = reloc->r_address; 187 r_pcrel = reloc->r_pcrel; 188 r_length = reloc->r_length; 189 r_extern = reloc->r_extern; 190 r_symbolnum = reloc->r_symbolnum; 191 r_type = (enum reloc_type_arm)reloc->r_type; 192 r_value = 0; 193 } 194 /* 195 * ARM_RELOC_PAIR relocation types only follows ARM_RELOC_{SECTDIFF, 196 * LOCAL_SECTDIFF} relocation types and it is an error to see one 197 * otherwise. 198 */ 199 if(r_type == ARM_RELOC_PAIR){ 200 error_with_cur_obj("stray relocation ARM_RELOC_PAIR entry " 201 "(%lu) in section (%.16s,%.16s)", i, 202 section_map->s->segname, section_map->s->sectname); 203 continue; 204 } 205 /* 206 * The r_address field is really an offset into the contents of the 207 * section and must reference something inside the section (Note 208 * that this is not the case for ARM_RELOC_PAIR entries but this 209 * can't be one with the above checks). 210 */ 211 if(r_address >= section_map->s->size){ 212 error_with_cur_obj("r_address (0x%x) field of relocation entry " 213 "%lu in section (%.16s,%.16s) out of range", 214 (unsigned int)r_address, i, section_map->s->segname, 215 section_map->s->sectname); 216 return; 217 } 218 /* 219 * If this relocation type is to have a pair make sure it is there 220 * and then break out it's fields. 221 */ 222 pair_r_type = (enum reloc_type_arm)0; 223 pair_reloc = NULL; 224 spair_reloc = NULL; 225 if(r_type == ARM_RELOC_SECTDIFF || 226 r_type == ARM_RELOC_LOCAL_SECTDIFF){ 227 if(r_scattered != 1){ 228 error_with_cur_obj("relocation entry (%lu) in section " 229 "(%.16s,%.16s) r_type is ARM_RELOC_SECTDIFF but " 230 "relocation entry not scattered type", i, 231 section_map->s->segname, section_map->s->sectname); 232 continue; 233 } 234 if(i + 1 < section_map->s->nreloc){ 235 pair_reloc = relocs + i + 1; 236 if((pair_reloc->r_address & R_SCATTERED) != 0){ 237 spair_reloc = (struct scattered_relocation_info *) 238 pair_reloc; 239 pair_reloc = NULL; 240 pair_r_type = (enum reloc_type_arm)spair_reloc->r_type; 241 pair_r_value = spair_reloc->r_value; 242 other_half = spair_reloc->r_address; 243 } 244 else{ 245 error_with_cur_obj("relocation entry (%lu) in section " 246 "(%.16s,%.16s) following associated relocation " 247 "entry not scattered type", i, 248 section_map->s->segname, section_map->s->sectname); 249 continue; 250 } 251 } 252 if((pair_reloc == NULL && spair_reloc == NULL) || 253 pair_r_type != ARM_RELOC_PAIR){ 254 error_with_cur_obj("relocation entry (%lu) in section " 255 "(%.16s,%.16s) missing following associated " 256 "ARM_RELOC_PAIR entry", i, section_map->s->segname, 257 section_map->s->sectname); 258 continue; 259 } 260 /* 261 * Calculate the pair_r_symbolnum (n_sect) from the 262 * pair_r_value. 263 */ 264 pair_r_symbolnum = 0; 265 for(j = 0; j < cur_obj->nsection_maps; j++){ 266 if(pair_r_value >= cur_obj->section_maps[j].s->addr && 267 pair_r_value < cur_obj->section_maps[j].s->addr + 268 cur_obj->section_maps[j].s->size){ 269 pair_r_symbolnum = j + 1; 270 break; 271 } 272 } 273 if(pair_r_symbolnum == 0){ 274 error_with_cur_obj("r_value (0x%x) field of relocation " 275 "entry %lu in section (%.16s,%.16s) out of range", 276 (unsigned int)r_value, i + 1, section_map->s->segname, 277 section_map->s->sectname); 278 return; 279 } 280 } 281 /* 282 * If r_extern is set this relocation entry is an external entry 283 * else it is a local entry (or scattered entry). 284 */ 285 if(r_extern){ 286 /* 287 * This is an external relocation entry. So the value to be 288 * added to the item to be relocated is the value of the symbol. 289 * r_symbolnum is an index into the input file's symbol table 290 * of the symbol being refered to. The symbol must be an 291 * undefined or coalesced symbol to be used in an external 292 * relocation entry. 293 */ 294 if(r_symbolnum >= cur_obj->symtab->nsyms){ 295 error_with_cur_obj("r_symbolnum (%lu) field of external " 296 "relocation entry %lu in section (%.16s,%.16s) out of " 297 "range", r_symbolnum, i, section_map->s->segname, 298 section_map->s->sectname); 299 return; 300 } 301 symbolnum = r_symbolnum; 302 undefined_map = bsearch(&symbolnum, cur_obj->undefined_maps, 303 cur_obj->nundefineds, sizeof(struct undefined_map), 304 (int (*)(const void *, const void *))undef_bsearch); 305 if(undefined_map != NULL){ 306 merged_symbol = undefined_map->merged_symbol; 307 } 308 else{ 309 nlists = (struct nlist *)(cur_obj->obj_addr + 310 cur_obj->symtab->symoff); 311 strings = (char *)(cur_obj->obj_addr + 312 cur_obj->symtab->stroff); 313 if((nlists[symbolnum].n_type & N_EXT) != N_EXT){ 314 error_with_cur_obj("r_symbolnum (%lu) field of external" 315 " relocation entry %lu in section (%.16s,%.16s) " 316 "refers to a non-external symbol", symbolnum, i, 317 section_map->s->segname, section_map->s->sectname); 318 return; 319 } 320 /* 321 * We must allow and create references to defined global 322 * coalesced symbols with external relocation entries so 323 * that the dynamic linker can relocate all references to 324 * the same symbol. 325 */ 326 if((nlists[symbolnum].n_type & N_TYPE) == N_SECT && 327 (cur_obj->section_maps[nlists[symbolnum].n_sect-1]. 328 s->flags & SECTION_TYPE) == S_COALESCED){ 329 merged_symbol = lookup_symbol(strings + 330 nlists[symbolnum].n_un.n_strx); 331 if(merged_symbol->name_len == 0){ 332 fatal("internal error, in arm_reloc() failed to " 333 "lookup coalesced symbol %s", strings + 334 nlists[symbolnum].n_un.n_strx); 335 } 336 } 337 else{ 338 if((nlists[symbolnum].n_type & N_EXT) != N_EXT || 339 (nlists[symbolnum].n_type & N_TYPE) != N_UNDF){ 340 error_with_cur_obj("r_symbolnum (%lu) field of " 341 "external relocation entry %lu in section " 342 "(%.16s,%.16s) refers to a non-undefined " 343 "symbol", symbolnum, i, section_map->s->segname, 344 section_map->s->sectname); 345 return; 346 } 347 print_obj_name(cur_obj); 348 fatal("internal error, in arm_reloc() symbol index %lu " 349 "in above file not in undefined map", symbolnum); 350 } 351 } 352 if(refs == NULL && 353 ((merged_symbol->nlist.n_type & N_TYPE) == N_SECT && 354 (get_output_section(merged_symbol->nlist.n_sect)-> 355 flags & SECTION_TYPE) == S_COALESCED)){ 356 if(((merged_symbol->nlist.n_type & N_PEXT) == N_PEXT && 357 keep_private_externs == FALSE) || 358 dynamic == FALSE || 359 (output_for_dyld && has_dynamic_linker_command)) 360 force_extern_reloc = FALSE; 361 else 362 force_extern_reloc = TRUE; 363 } 364 /* 365 * If this is an indirect symbol resolve indirection (all chains 366 * of indirect symbols have been resolved so that they point at 367 * a symbol that is not an indirect symbol). 368 */ 369 if((merged_symbol->nlist.n_type & N_TYPE) == N_INDR) 370 merged_symbol = (struct merged_symbol *) 371 merged_symbol->nlist.n_value; 372 373 /* 374 * If we are being called only to get the references for this 375 * relocation entry fill it in and return. 376 */ 377 if(refs != NULL){ 378 refs->ref1.ref_type = LIVE_REF_SYMBOL; 379 refs->ref1.merged_symbol = merged_symbol; 380 refs->ref2.ref_type = LIVE_REF_NONE; 381 return; 382 } 383 384 /* 385 * If the symbol is undefined (or common) or a global coalesced 386 * symbol where we need to force an external relocation entry 387 * and we are not prebinding no relocation is done. Or if the 388 * output file is a multi module MH_DYLIB no relocation is done 389 * unless the symbol is a private extern or we are prebinding. 390 */ 391 if(((merged_symbol->nlist.n_type & N_TYPE) == N_UNDF) || 392 (force_extern_reloc == TRUE && prebinding == FALSE) || 393 ((filetype == MH_DYLIB && multi_module_dylib == TRUE) && 394 (((merged_symbol->nlist.n_type & N_PEXT) != N_PEXT) && 395 prebinding == FALSE) ) ) 396 value = 0; 397 else{ 398 value = merged_symbol->nlist.n_value; 399 /* 400 * Pointers to thumb symbols must have their low bit set 401 * only after they have been relocated. Also arm BL 402 * instructions to thumb symbols must be conveted to BLX 403 * instructions. This external relocation entry will be 404 * relocated, so if it is for a thumb symbol then set 405 * relocated_extern_thumb_symbol so it can be used later. 406 */ 407 if((merged_symbol->nlist.n_desc & N_ARM_THUMB_DEF)) 408 relocated_extern_thumb_symbol = TRUE; 409 else 410 relocated_extern_arm_symbol = TRUE; 411 /* 412 * To know which type (local or scattered) of relocation 413 * entry to convert this one to (if relocation entries are 414 * saved) the offset to be added to the symbol's value is 415 * needed to see if it reaches outside the block in which 416 * the symbol is in. In here if the offset is not zero then 417 * it is assumed to reach out of the block and a scattered 418 * relocation entry is used. 419 */ 420 input_pc = section_map->s->addr + r_address; 421 if(r_type == ARM_RELOC_VANILLA){ 422 switch(r_length){ 423 case 0: /* byte */ 424 offset = get_byte((char *)(contents + r_address)); 425 break; 426 case 1: /* word (2 byte) */ 427 offset = get_short((short *)(contents + r_address)); 428 break; 429 case 2: /* long (4 byte) */ 430 offset = get_long((long *)(contents + r_address)); 431 break; 432 default: 433 /* the error check is catched below */ 434 break; 435 } 436 if(r_pcrel) 437 offset += input_pc; 438 } 439 else{ 440 instruction = get_long((long *)(contents + r_address)); 441 switch(r_type){ 442 case ARM_RELOC_BR24: 443 offset = instruction & 0x00ffffff; 444 /* sign extend if needed */ 445 if((offset & 0x00800000) != 0) 446 offset |= 0xff000000; 447 /* The value in the instruction is shifted by 2 */ 448 offset = offset << 2; 449 /* 450 * Note the pc added will be +8 from the pc of the 451 * branch instruction. And the assembler creating 452 * this instruction takes that into account when 453 * calculating the displacement in the instruction. 454 */ 455 if(r_pcrel) 456 offset += input_pc; 457 break; 458 case ARM_THUMB_RELOC_BR22: 459 /* 460 * The code below assumes ARM is little endian 461 * such that "the first 16-bit thumb instruction" 462 * is the low 16 bits and "the second 16-bit thumb 463 * instruction" is the high 16 bits of the 32-bits 464 * in the variable instruction. 465 */ 466 /* the first instruction has the upper eleven bits 467 of the two byte displacement */ 468 offset = (instruction & 0x7FF) << 12; 469 /* sign extend if needed */ 470 if((offset & 0x400000) != 0) 471 offset |= 0xFF800000; 472 /* the second instruction has the lower eleven bits 473 of the two byte displacement. Add that times 474 two to get the offset added to the symbol */ 475 offset += 2*((instruction >> 16) & 0x7FF); 476 /* 477 * Note the pc added will be +4 from the pc of the 478 * branch instruction. And the assembler creating 479 * this instruction takes that into account when 480 * calculating the displacement in the instruction. 481 */ 482 if(r_pcrel) 483 offset += input_pc; 484 break; 485 default: 486 /* the error check is catched below */ 487 break; 488 } 489 } 490 } 491 492 if((merged_symbol->nlist.n_type & N_TYPE) == N_SECT) 493 output_sections[merged_symbol->nlist.n_sect]->referenced = 494 TRUE; 495 } 496 else{ 497 /* 498 * This is a local relocation entry (the value to which the item 499 * to be relocated is refering to is defined in section number 500 * r_symbolnum). So the address of that section in the input 501 * file is subtracted and the value of that section in the 502 * output is added to the item being relocated. 503 */ 504 value = 0; 505 /* 506 * If the symbol is not in any section the value to be added to 507 * the item to be relocated is the zero above and any pc 508 * relative change in value added below. 509 */ 510 if(r_symbolnum == R_ABS){ 511 /* 512 * If we are being called only to get the references for 513 * this relocation entry fill in it has none and return. 514 */ 515 if(refs != NULL){ 516 refs->ref1.ref_type = LIVE_REF_NONE; 517 refs->ref2.ref_type = LIVE_REF_NONE; 518 return; 519 } 520 } 521 else{ 522 if(r_symbolnum > cur_obj->nsection_maps){ 523 error_with_cur_obj("r_symbolnum (%lu) field of local " 524 "relocation entry %lu in section (%.16s,%.16s) " 525 "out of range", r_symbolnum, i, 526 section_map->s->segname, section_map->s->sectname); 527 return; 528 } 529 local_map = &(cur_obj->section_maps[r_symbolnum - 1]); 530 local_map->output_section->referenced = TRUE; 531 pair_local_map = NULL; 532 if(r_type == ARM_RELOC_SECTDIFF || 533 r_type == ARM_RELOC_LOCAL_SECTDIFF){ 534 pair_local_map = 535 &(cur_obj->section_maps[pair_r_symbolnum - 1]); 536 pair_local_map->output_section->referenced = TRUE; 537 } 538 if(local_map->nfine_relocs == 0 && 539 (pair_local_map == NULL || 540 pair_local_map->nfine_relocs == 0) ){ 541 if(r_type == ARM_RELOC_SECTDIFF || 542 r_type == ARM_RELOC_LOCAL_SECTDIFF){ 543 value = - local_map->s->addr 544 + (local_map->output_section->s.addr + 545 local_map->offset) 546 + pair_local_map->s->addr 547 - (pair_local_map->output_section->s.addr + 548 pair_local_map->offset); 549 } 550 else{ 551 value = - local_map->s->addr 552 + (local_map->output_section->s.addr + 553 local_map->offset); 554 } 555 } 556 else{ 557 /* 558 * For items to be relocated that refer to a section 559 * with fine relocation the value is set (not adjusted 560 * with addition). So the new value is directly 561 * calculated from the old value. 562 */ 563 if(r_pcrel){ 564 input_pc = section_map->s->addr + 565 r_address; 566 if(section_map->nfine_relocs == 0) 567 output_pc = section_map->output_section->s.addr 568 + section_map->offset + 569 r_address; 570 else 571 output_pc = section_map->output_section->s.addr 572 + 573 fine_reloc_output_offset(section_map, 574 r_address); 575 } 576 else{ 577 input_pc = 0; 578 output_pc = 0; 579 } 580 /* 581 * Get the value of the expresion of the item to be 582 * relocated. 583 */ 584 if(r_type == ARM_RELOC_VANILLA || 585 r_type == ARM_RELOC_SECTDIFF || 586 r_type == ARM_RELOC_LOCAL_SECTDIFF){ 587 switch(r_length){ 588 case 0: /* byte */ 589 value = get_byte((char *)(contents + 590 r_address)); 591 break; 592 case 1: /* word (2 byte) */ 593 value = get_short((short *)(contents + 594 r_address)); 595 break; 596 case 2: /* long (4 byte) */ 597 value = get_long((long *)(contents + 598 r_address)); 599 break; 600 default: 601 /* the error check is catched below */ 602 break; 603 } 604 } 605 else{ 606 instruction = get_long((long *)(contents + 607 r_address)); 608 switch(r_type){ 609 case ARM_RELOC_BR24: 610 value = instruction & 0x00ffffff; 611 if((value & 0x00800000) != 0) 612 value |= 0xff000000; 613 /* The value (displacement) is shifted by 2 */ 614 value = value << 2; 615 /* 616 * For a BLX instruction, set bit[1] of the 617 * result to the H bit. 618 */ 619 if((instruction & 0xff000000) == 0xfb000000) 620 value |= 0x2; 621 /* The pc added will be +8 from the pc */ 622 value += 8; 623 break; 624 case ARM_THUMB_RELOC_BR22: 625 /* 626 * The code below assumes ARM is little endian 627 * such that "the first 16-bit thumb 628 * instruction" is the low 16 bits and "the 629 * second 16-bit thumb instruction" is the high 630 * 16 bits of the 32-bits in the variable 631 * instruction. 632 */ 633 /* the first instruction has the upper eleven 634 bits of the two byte displacement */ 635 value = (instruction & 0x7FF) << 12; 636 /* sign extend if needed */ 637 if((value & 0x400000) != 0) 638 value |= 0xFF800000; 639 /* the second instruction has the lower eleven 640 bits of the two byte displacement. Add that 641 times two to get the target address */ 642 value += 2*((instruction >> 16) & 0x7FF); 643 /* The pc added will be +4 from the pc */ 644 value += 4; 645 /* 646 * For BLX, the resulting address is forced to 647 * be word-aligned by clearing bit[1]. 648 */ 649 if(((instruction & 0x18000000) == 0x08000000) && 650 ((input_pc + value) & 0x2)) 651 value -= 2; 652 break; 653 default: 654 /* the error check is catched below */ 655 break; 656 } 657 } 658 if(r_type == ARM_RELOC_SECTDIFF || 659 r_type == ARM_RELOC_LOCAL_SECTDIFF){ 660 /* 661 * For ARM_RELOC_SECTDIFF's the item to be 662 * relocated, in value, is the value of the 663 * expression: 664 * r_value - pair_r_value + offset 665 * To set the value of the relocated expression, 666 * it is set from relocating the two r_value's and 667 * adding back in the offset. So here get the 668 * offset from the value of the expression. 669 */ 670 value += input_pc; /* adjust for pcrel */ 671 offset = value - r_value + pair_r_value; 672 673 /* 674 * If we are being called only to get the references 675 * for this relocation entry fill it in and return. 676 */ 677 if(refs != NULL){ 678 fine_reloc_output_ref( 679 local_map, 680 r_value - local_map->s->addr, 681 &(refs->ref1) ); 682 fine_reloc_output_ref( 683 local_map, 684 pair_r_value - local_map->s->addr, 685 &(refs->ref2) ); 686 return; 687 } 688 689 /* 690 * Now build up the value of the relocated 691 * expression one part at a time. First set the 692 * new value to the relocated r_value. 693 */ 694 if(local_map->nfine_relocs != 0){ 695 /* 696 * Check to see if this reference is legal with 697 * respect to indirect sections. 698 */ 699 legal_reference(section_map, r_address, 700 local_map, r_value - local_map->s->addr, 701 i, 702 r_type != ARM_RELOC_LOCAL_SECTDIFF); 703 value = fine_reloc_output_address(local_map, 704 r_value - local_map->s->addr, 705 local_map->output_section->s.addr); 706 } 707 else{ 708 value = local_map->output_section->s.addr + 709 local_map->offset + 710 r_value - local_map->s->addr; 711 } 712 /* Second subtract the relocated pair_r_value. */ 713 if(pair_local_map->nfine_relocs != 0){ 714 /* 715 * Check to see if this reference is legal with 716 * respect to indirect sections. 717 */ 718 legal_reference(section_map, r_address, 719 pair_local_map, pair_r_value - 720 pair_local_map->s->addr, i, TRUE); 721 value -= 722 fine_reloc_output_address(pair_local_map, 723 pair_r_value - pair_local_map->s->addr, 724 pair_local_map->output_section->s.addr); 725 } 726 else{ 727 value -= 728 pair_local_map->output_section->s.addr + 729 pair_local_map->offset + 730 pair_r_value - pair_local_map->s->addr; 731 } 732 /* Third add in the offset. */ 733 value += offset; 734 value -= output_pc; /* adjust for pcrel */ 735 } 736 else{ 737 /* 738 * If the relocation entry is not a scattered 739 * relocation entry then the relocation is based on 740 * the value of value of the expresion of the item 741 * to be relocated. If it is a scattered relocation 742 * entry then the relocation is based on the r_value 743 * in the relocation entry and the offset part of 744 * the expression at the item to be relocated is 745 * extracted so it can be added after the relocation 746 * is done. 747 */ 748 value += input_pc; 749 if(r_scattered == 0){ 750 r_value = value; 751 offset = 0; 752 } 753 else{ 754 offset = value - r_value; 755 } 756 /* 757 * Check to see if this reference is legal with 758 * respect to indirect sections. 759 */ 760 legal_reference(section_map, r_address, local_map, 761 r_value - local_map->s->addr + offset, i, 762 FALSE); 763 764 /* 765 * If we are being called only to get the references 766 * for this relocation entry fill it in and return. 767 */ 768 if(refs != NULL){ 769 fine_reloc_output_ref( 770 local_map, 771 r_value - local_map->s->addr, 772 &(refs->ref1) ); 773 refs->ref2.ref_type = LIVE_REF_NONE; 774 return; 775 } 776 777 value = fine_reloc_output_address(local_map, 778 r_value - local_map->s->addr, 779 local_map->output_section->s.addr); 780 value -= output_pc; 781 value += offset; 782 } 783 if(r_type == ARM_RELOC_VANILLA || 784 r_type == ARM_RELOC_LOCAL_SECTDIFF || 785 r_type == ARM_RELOC_SECTDIFF){ 786 switch(r_length){ 787 case 0: /* byte */ 788 if( (value & 0xffffff00) && 789 ((value & 0xffffff80) != 0xffffff80)) 790 error_with_cur_obj("relocation for entry " 791 "%lu in section (%.16s,%.16s) does not " 792 "fit in 1 byte", i, 793 section_map->s->segname, 794 section_map->s->sectname); 795 set_byte((char *)(contents + r_address), value); 796 break; 797 case 1: /* word (2 byte) */ 798 if( (value & 0xffff0000) && 799 ((value & 0xffff8000) != 0xffff8000)) 800 error_with_cur_obj("relocation for entry " 801 "%lu in section (%.16s,%.16s) does not " 802 "fit in 2 bytes", i, 803 section_map->s->segname, 804 section_map->s->sectname); 805 set_short((short *)(contents + r_address), 806 value); 807 break; 808 case 2: /* long (4 byte) */ 809 set_long((long *)(contents + r_address), value); 810 break; 811 default: 812 error_with_cur_obj("r_length field of " 813 "relocation entry %lu in section (%.16s," 814 "%.16s) invalid", i, 815 section_map->s->segname, 816 section_map->s->sectname); 817 return; 818 } 819 } 820 else{ 821 switch(r_type){ 822 case ARM_RELOC_BR24: 823 /* The pc added will be +8 from the pc */ 824 value -= 8; 825 /* 826 * An ARM BLX targetting an ARM symbol or 827 * a local symbol needs to be converted to a 828 * BL. This could happen if it was originally 829 * targetting a thumb stub which will be 830 * optimized away. 831 */ 832 if(((fine_reloc_arm(local_map, 833 r_value - local_map->s->addr) == TRUE) || 834 (fine_reloc_local(local_map, 835 r_value - local_map->s->addr) == TRUE)) && 836 ((instruction & 0xfe000000) == 0xfa000000)) 837 instruction = 0xeb000000; 838 /* 839 * For arm branch instructions if the target is 840 * a thumb symbol it must be converted to a 841 * branch and exchange instruction (unless it 842 * already is one). 843 */ 844 if((fine_reloc_thumb(local_map, 845 r_value - local_map->s->addr) == TRUE) || 846 ((instruction & 0xfe000000) == 0xfa000000)){ 847 /* 848 * Only unconditional BL can be converted 849 * to BLX 850 */ 851 if(((instruction & 0xff000000) != 0xeb000000) && 852 ((instruction & 0xfe000000) != 0xfa000000)) 853 error_with_cur_obj("relocation error " 854 "for relocation entry %lu in " 855 "section (%.16s,%.16s) (branch " 856 "cannot be converted to BLX)", i, 857 section_map->s->segname, 858 section_map->s->sectname); 859 /* 860 * The H bit of the BLX instruction (bit 24) 861 * contains bit 1 of the target address. 862 */ 863 instruction = (0xfa000000 | 864 ((value & 0x2) << 23)); 865 /* 866 * This code assumes the thumb symbol 867 * address is two byte aligned. This next 868 * line clears the last two bits so the next 869 * test will not cause an error 870 */ 871 value &= ~0x2; 872 } 873 if((value & 0x3) != 0) 874 error_with_cur_obj("relocation error " 875 "for relocation entry %lu in section " 876 "(%.16s,%.16s) (displacement not a " 877 "multiple of 4 bytes)", i, 878 section_map->s->segname, 879 section_map->s->sectname); 880 if((value & 0xfe000000) != 0xfe000000 && 881 (value & 0xfe000000) != 0x00000000) 882 error_with_cur_obj("relocation overflow " 883 "for relocation entry %lu in section " 884 "(%.16s,%.16s) (displacement too large)" 885 , i, section_map->s->segname, 886 section_map->s->sectname); 887 instruction = (instruction & 0xff000000) | 888 ((value >> 2) & 0x00ffffff); 889 break; 890 case ARM_THUMB_RELOC_BR22: 891 /* The pc added will be +4 from the pc */ 892 value -= 4; 893 /* 894 * Here we have a BL instruction targetting an 895 * arm symbol -- convert it to a BLX 896 */ 897 if((fine_reloc_arm(local_map, 898 r_value - local_map->s->addr) == TRUE) && 899 ((instruction & 0xf800f800) == 0xf800f000)) 900 instruction &= 0xefffffff; 901 /* 902 * Here we have a BLX instruction targetting a 903 * thumb symbol or a local symbol (which we will 904 * boldly assume to be thumb in the absence of 905 * any evidence to the contrary) -- convert it 906 * to a BL 907 */ 908 if(((fine_reloc_thumb(local_map, 909 r_value - local_map->s->addr) == TRUE) || 910 (fine_reloc_local(local_map, 911 r_value - local_map->s->addr) == TRUE)) && 912 ((instruction & 0xf800f800) == 0xe800f000)) 913 instruction |= 0x10000000; 914 /* immediate must be multiple of four bytes. 915 * This enforces the requirement that 916 * instruction[0] must be zero for a BLX. 917 */ 918 if((instruction & 0xf800f800) == 0xe800f000 && 919 (value & 0x2) != 0) 920 value += 2; 921 instruction = (instruction & 0xf800f800) | 922 (value & 0x7ff000) >> 12 | 923 (value & 0xffe) << 15; 924 break; 925 default: 926 error_with_cur_obj("r_type field of " 927 "relocation entry %lu in section (%.16s," 928 "%.16s) invalid", i, 929 section_map->s->segname, 930 section_map->s->sectname); 931 return; 932 } 933 set_long((long *)(contents + r_address), 934 instruction); 935 } 936 937 goto update_reloc; 938 } 939 } 940 } 941 if(r_pcrel){ 942 /* 943 * This is a relocation entry is also pc relative which means 944 * the value of the pc will get added to it when it is executed. 945 * The item being relocated has the value of the pc in the input 946 * file subtracted from it. So to relocate this the value of 947 * pc in the input file is added and then value of the output 948 * pc is subtracted (since the offset into the section remains 949 * constant it is not added in and then subtracted out). 950 */ 951 if(section_map->nfine_relocs == 0) 952 value += + section_map->s->addr /* + r_address */ 953 - (section_map->output_section->s.addr + 954 section_map->offset /* + r_address */); 955 else 956 value += + section_map->s->addr + r_address 957 - (section_map->output_section->s.addr + 958 fine_reloc_output_offset(section_map, 959 r_address)); 960 } 961 if(r_type == ARM_RELOC_VANILLA || 962 r_type == ARM_RELOC_LOCAL_SECTDIFF || 963 r_type == ARM_RELOC_SECTDIFF){ 964 /* 965 * Pointers to thumb symbols must have their low bit set, but 966 * only after they have been relocated. Code above determined 967 * if this is and external relocation entry for a thumb symbol 968 * that is being relocated and if so set 969 * relocated_extern_thumb_symbol. So now if this is a VANILLA 970 * relocation entry for a pointer set the low bit from 971 * relocated_extern_thumb_symbol. 972 */ 973 if(r_type == ARM_RELOC_VANILLA) 974 low_bit = (relocated_extern_thumb_symbol == TRUE) ? 1 : 0; 975 else 976 low_bit = 0; 977 /* 978 * This is part of the cctools_aek-thumb-hack branch. It seems 979 * like a reasonable error check but I don't see how it could 980 * ever get triggered by any code going though the assember. 981 */ 982 if(r_type == ARM_RELOC_VANILLA && 983 relocated_extern_thumb_symbol == TRUE && r_pcrel) 984 error_with_cur_obj("relocation for entry %lu in section " 985 "(%.16s,%.16s) is VANILLA PC-relative to a thumb " 986 "symbol %s", i, section_map->s->segname, 987 section_map->s->sectname, 988 merged_symbol->nlist.n_un.n_name); 989 switch(r_length){ 990 case 0: /* byte */ 991 value += get_byte((char *)(contents + r_address)); 992 if( (value & 0xffffff00) && 993 ((value & 0xffffff80) != 0xffffff80)) 994 error_with_cur_obj("relocation for entry %lu in section" 995 " (%.16s,%.16s) does not fit in 1 byte", i, 996 section_map->s->segname, section_map->s->sectname); 997 set_byte((char *)(contents + r_address), value | low_bit); 998 break; 999 case 1: /* word (2 byte) */ 1000 value += get_short((short *)(contents + r_address)); 1001 if( (value & 0xffff0000) && 1002 ((value & 0xffff8000) != 0xffff8000)) 1003 error_with_cur_obj("relocation for entry %lu in section" 1004 " (%.16s,%.16s) does not fit in 2 bytes", i, 1005 section_map->s->segname, section_map->s->sectname); 1006 set_short((short *)(contents + r_address), value | low_bit); 1007 break; 1008 case 2: /* long (4 byte) */ 1009 value += get_long((long *)(contents + r_address)); 1010 set_long((long *)(contents + r_address), value | low_bit); 1011 break; 1012 default: 1013 error_with_cur_obj("r_length field of relocation entry %lu " 1014 "in section (%.16s,%.16s) invalid", i, 1015 section_map->s->segname, section_map->s->sectname); 1016 return; 1017 } 1018 } 1019 /* 1020 * Do arm specific relocation based on the r_type. 1021 */ 1022 else{ 1023 instruction = get_long((long *)(contents + r_address)); 1024 switch(r_type){ 1025 case ARM_RELOC_BR24: 1026 immediate = instruction & 0x00ffffff; 1027 if((immediate & 0x00800000) != 0) 1028 immediate |= 0xff000000; 1029 /* The value in the instruction is shifted by 2 */ 1030 immediate = immediate << 2; 1031 /* In a BLX, bit 1 of the immediate is at bit 24 1032 * of the instruction. 1033 */ 1034 if((instruction & 0xfe000000) == 0xfa000000) 1035 immediate |= (instruction & 0x01000000) >> 23; 1036 immediate += value; 1037 /* 1038 * Here we have a BLX instruction that targets an 1039 * arm symbol -- convert it to a BL instruction. 1040 */ 1041 if((r_extern == TRUE) && 1042 (relocated_extern_arm_symbol == TRUE) && 1043 ((instruction & 0xfe000000) == 0xfa000000)) 1044 instruction = 0xeb000000; 1045 /* 1046 * For arm branch instructions if the target is a thumb 1047 * symbol it must be converted to a branch and exchange 1048 * instruction (unless it already is one). 1049 */ 1050 else if(((r_extern == TRUE) && 1051 (relocated_extern_thumb_symbol == TRUE)) || 1052 ((instruction & 0xfe000000) == 0xfa000000)){ 1053 /* only unconditional BL can be converted to BLX */ 1054 if(((instruction & 0xff000000) != 0xeb000000) && 1055 ((instruction & 0xfe000000) != 0xfa000000)) 1056 error_with_cur_obj("relocation error for relocation" 1057 " entry %lu in section (%.16s,%.16s) (branch " 1058 "cannot be converted to BLX)", i, 1059 section_map->s->segname, 1060 section_map->s->sectname); 1061 /* the H bit of the BLX instruction (bit 24) contains 1062 bit 1 of the target address */ 1063 instruction = (0xfa000000 | ((immediate & 0x2) << 23)); 1064 /* this code assumes the thumb symbol address is two 1065 byte aligned. This next line clears the last two 1066 bits so the next test will not cause an error */ 1067 immediate &= ~0x2; 1068 } 1069 if((immediate & 0x3) != 0) 1070 error_with_cur_obj("relocation error for relocation " 1071 "entry %lu in section (%.16s,%.16s) (displacement " 1072 "not a multiple of 4 bytes)", i, 1073 section_map->s->segname, section_map->s->sectname); 1074 if((immediate & 0xfe000000) != 0xfe000000 && 1075 (immediate & 0xfe000000) != 0x00000000) 1076 error_with_cur_obj("relocation overflow for relocation " 1077 "entry %lu in section (%.16s,%.16s) (displacement " 1078 "too large)", i, section_map->s->segname, 1079 section_map->s->sectname); 1080 instruction = (instruction & 0xff000000) | 1081 (immediate & 0x03ffffff) >> 2; 1082 break; 1083 case ARM_THUMB_RELOC_BR22: 1084 /* 1085 * The code below assumes ARM is little endian such that 1086 * "the first 16-bit thumb instruction" is the low 16 bits 1087 * and "the second 16-bit thumb instruction" is the high 16 1088 * bits of the 32-bits in the variable instruction. 1089 */ 1090 /* the first instruction has the upper eleven bits of the 1091 two byte displacement */ 1092 immediate = (instruction & 0x7FF) << 12; 1093 /* sign extend if needed */ 1094 if((immediate & 0x400000) != 0) 1095 immediate |= 0xFF800000; 1096 /* the second instruction has the lower eleven bits of the 1097 two byte displacement. Add that times two to get the 1098 target address */ 1099 immediate += 2*((instruction >> 16) & 0x7FF); 1100 /* 1101 * For BLX, the resulting address is forced to be word- 1102 * aligned by clearing bit[1]. 1103 */ 1104 if((instruction & 0xf800f800) == 0xe800f000 && 1105 (r_address & 0x2)) 1106 immediate -= 2; 1107 immediate += value; 1108 /* 1109 * The target address for a thumb branch must be to a 1110 * two-byte address. 1111 */ 1112 if((immediate & 0x1) != 0) 1113 error_with_cur_obj("relocation error for relocation " 1114 "entry %lu in section (%.16s,%.16s) (displacement " 1115 "not a multiple of 2 bytes)", i, 1116 section_map->s->segname, section_map->s->sectname); 1117 /* 1118 * Here we have a BLX instruction that targets a 1119 * thumb symbol -- convert it to a BL instruction. 1120 */ 1121 if((r_extern == TRUE) && 1122 (relocated_extern_thumb_symbol == TRUE) && 1123 ((instruction & 0xf800f800) == 0xe800f000)) 1124 instruction |= 0x10000000; 1125 /* 1126 * For thumb branch instructions if the target is not a 1127 * thumb symbol (an arm symbol) it must be converted to a 1128 * branch and exchange instruction (if it is not already 1129 * one). 1130 */ 1131 if(r_extern == TRUE && 1132 relocated_extern_arm_symbol == TRUE && 1133 (instruction & 0xf800f800) != 0xe800f000){ 1134 /* Make sure we have a high+low BL */ 1135 if((instruction & 0xf800f800) != 0xf800f000) 1136 error_with_cur_obj("relocation error for relocation" 1137 " entry %lu in section (%.16s,%.16s) (unknown " 1138 "branch type)", i, section_map->s->segname, 1139 section_map->s->sectname); 1140 /* Convert BL to BLX: clear top H bit of second insr */ 1141 instruction &= 0xefffffff; 1142 } 1143 /* immediate must be multiple of four bytes. 1144 * This enforces the requirement that 1145 * instruction[0] must be zero for a BLX. 1146 */ 1147 if((instruction & 0xf800f800) == 0xe800f000 && 1148 (immediate & 0x2) != 0) 1149 immediate += 2; 1150 if((immediate & 0xffc00000) != 0xffc00000 && 1151 (immediate & 0xffc00000) != 0x00000000) 1152 error_with_cur_obj("relocation overflow for relocation " 1153 "entry %lu in section (%.16s,%.16s) (displacement " 1154 "too large)", i, section_map->s->segname, 1155 section_map->s->sectname); 1156 instruction = (instruction & 0xf800f800) | 1157 (immediate & 0x7ff000) >> 12 | 1158 (immediate & 0xffe) << 15; 1159 break; 1160 case ARM_THUMB_32BIT_BRANCH: 1161 break; 1162 default: 1163 error_with_cur_obj("r_type field of relocation entry %lu " 1164 "in section (%.16s,%.16s) invalid", i, 1165 section_map->s->segname, section_map->s->sectname); 1166 continue; 1167 } 1168 set_long((long *)(contents + r_address), instruction); 1169 } 1170 1171 /* 1172 * If relocation entries are to be saved in the output file then 1173 * update the entry for the output file. 1174 */ 1175update_reloc: 1176 ; 1177#ifndef RLD 1178 if(save_reloc || output_for_dyld){ 1179 if(r_extern){ 1180 /* 1181 * If we are prebinding and this is a lazy pointer section 1182 * change the relocation entry to a ARM_RELOC_PB_LA_PTR 1183 * type. This stuffs the value of the lazy pointer as it 1184 * wouldn't be prebound in the r_value field. So if the 1185 * prebounding can't be used at runtime the value of the 1186 * lazy pointer will get set back to the r_value by dyld. 1187 */ 1188 if(prebinding == TRUE && 1189 (section_map->s->flags & SECTION_TYPE) == 1190 S_LAZY_SYMBOL_POINTERS){ 1191 sreloc = (struct scattered_relocation_info *)reloc; 1192 r_scattered = 1; 1193 sreloc->r_scattered = r_scattered; 1194 sreloc->r_address = r_address; 1195 sreloc->r_pcrel = r_pcrel; 1196 sreloc->r_length = r_length; 1197 sreloc->r_type = ARM_RELOC_PB_LA_PTR; 1198 sreloc->r_value = value; 1199 } 1200 /* 1201 * For external relocation entries that the symbol is 1202 * defined (not undefined or common) but not when we are 1203 * forcing an external relocation entry for a global 1204 * coalesced symbol and if the output file is not a multi 1205 * module MH_DYLIB or the symbol is a private extern, it is 1206 * changed to a local relocation entry using the section 1207 * that symbol is defined in. If still undefined or forcing 1208 * an external relocation entry for a global coalesced 1209 * symbol, then the index of the symbol in the output file 1210 * is set into r_symbolnum. 1211 */ 1212 else if((merged_symbol->nlist.n_type & N_TYPE) != N_UNDF && 1213 (merged_symbol->nlist.n_type & N_TYPE) != N_PBUD && 1214 force_extern_reloc == FALSE && 1215 ((filetype != MH_DYLIB || 1216 multi_module_dylib == FALSE) || 1217 (merged_symbol->nlist.n_type & N_PEXT) == N_PEXT)){ 1218 reloc->r_extern = 0; 1219 /* 1220 * If this symbol was in the base file then no futher 1221 * relocation can ever be done (the symbols in the base 1222 * file are fixed). Or if the symbol was an absolute 1223 * symbol. 1224 */ 1225 if(merged_symbol->definition_object == base_obj || 1226 (merged_symbol->nlist.n_type & N_TYPE) == N_ABS){ 1227 reloc->r_symbolnum = R_ABS; 1228 } 1229 else{ 1230 /* 1231 * The symbol that this relocation entry is refering 1232 * to is defined so convert this external relocation 1233 * entry into a local or scattered relocation entry. 1234 * If the item to be relocated has an offset added 1235 * to the symbol's value and the output is not for 1236 * dyld make it a scattered relocation entry else 1237 * make it a local relocation entry. 1238 */ 1239 if(offset == 0 || output_for_dyld){ 1240 reloc->r_symbolnum =merged_symbol->nlist.n_sect; 1241 } 1242 else{ 1243 sreloc = (struct scattered_relocation_info *) 1244 reloc; 1245 r_scattered = 1; 1246 sreloc->r_scattered = r_scattered; 1247 sreloc->r_address = r_address; 1248 sreloc->r_pcrel = r_pcrel; 1249 sreloc->r_length = r_length; 1250 sreloc->r_type = r_type; 1251 sreloc->r_value = merged_symbol->nlist.n_value; 1252 } 1253 } 1254 } 1255 else{ 1256 reloc->r_symbolnum = 1257 merged_symbol_output_index(merged_symbol); 1258 } 1259 } 1260 else if(r_scattered == 0){ 1261 /* 1262 * If we are prebinding and this is a lazy pointer section 1263 * change the relocation entry to a ARM_RELOC_PB_LA_PTR 1264 * type. This stuffs the value of the lazy pointer as it 1265 * wouldn't be prebound in the r_value field. So if the 1266 * prebounding can't be used at runtime the value of the 1267 * lazy pointer will get set back to the r_value by dyld. 1268 */ 1269 if(prebinding == TRUE && 1270 (section_map->s->flags & SECTION_TYPE) == 1271 S_LAZY_SYMBOL_POINTERS){ 1272 sreloc = (struct scattered_relocation_info *)reloc; 1273 r_scattered = 1; 1274 sreloc->r_scattered = r_scattered; 1275 sreloc->r_address = r_address; 1276 sreloc->r_pcrel = r_pcrel; 1277 sreloc->r_length = r_length; 1278 sreloc->r_type = ARM_RELOC_PB_LA_PTR; 1279 sreloc->r_value = value; 1280 } 1281 /* 1282 * For local relocation entries the section number is 1283 * changed to the section number in the output file. 1284 */ 1285 else if(reloc->r_symbolnum != R_ABS){ 1286 if(local_map->nfine_relocs == 0){ 1287 reloc->r_symbolnum = 1288 local_map->output_section->output_sectnum; 1289 } 1290 else{ 1291 reloc->r_symbolnum = 1292 fine_reloc_output_sectnum(local_map, 1293 r_value - local_map->s->addr); 1294 } 1295 } 1296 } 1297 else{ 1298 /* 1299 * This is a scattered relocation entry. If the output is 1300 * for dyld convert it to a local relocation entry so as 1301 * to not overflow the 24-bit r_address field in a scattered 1302 * relocation entry. The overflow would happen in 1303 * reloc_output_for_dyld() in sections.c when it adjusts 1304 * the r_address fields of the relocation entries. 1305 */ 1306 if(output_for_dyld){ 1307 reloc = (struct relocation_info *)sreloc; 1308 r_scattered = 0; 1309 reloc->r_address = r_address; 1310 reloc->r_pcrel = r_pcrel; 1311 reloc->r_extern = 0; 1312 reloc->r_length = r_length; 1313 reloc->r_type = r_type; 1314 if(local_map->nfine_relocs == 0){ 1315 reloc->r_symbolnum = 1316 local_map->output_section->output_sectnum; 1317 } 1318 else{ 1319 reloc->r_symbolnum = 1320 fine_reloc_output_sectnum(local_map, 1321 r_value - local_map->s->addr); 1322 } 1323 } 1324 else{ 1325 /* 1326 * For scattered relocation entries the r_value field is 1327 * relocated. 1328 */ 1329 if(local_map->nfine_relocs == 0) 1330 sreloc->r_value += 1331 - local_map->s->addr 1332 + local_map->output_section->s.addr + 1333 local_map->offset; 1334 else 1335 sreloc->r_value = 1336 fine_reloc_output_address(local_map, 1337 r_value - local_map->s->addr, 1338 local_map->output_section->s.addr); 1339 } 1340 } 1341 /* 1342 * If this section that the reloation is being done for has fine 1343 * relocation then the offset in the r_address field has to be 1344 * set to where it will end up in the output file. Otherwise 1345 * it simply has to have the offset to where this contents 1346 * appears in the output file. 1347 */ 1348 if(r_scattered == 0){ 1349 if(section_map->nfine_relocs == 0){ 1350 reloc->r_address += section_map->offset; 1351 } 1352 else{ 1353 reloc->r_address = fine_reloc_output_offset(section_map, 1354 r_address); 1355 } 1356 } 1357 else{ 1358 if(section_map->nfine_relocs == 0){ 1359 /* this can overflow the 24-bit sreloc->r_address */ 1360 sreloc->r_address += section_map->offset; 1361 } 1362 else{ 1363 sreloc->r_address =fine_reloc_output_offset(section_map, 1364 r_address); 1365 } 1366 } 1367 /* 1368 * If their was a paired relocation entry then update the 1369 * paired relocation entry. 1370 */ 1371 if(pair_r_type == ARM_RELOC_PAIR){ 1372 if(pair_reloc != NULL){ 1373 /* I don't think arm has any pairs that are not 1374 scattered relocs so this should never happen */ 1375 pair_reloc->r_address = other_half; 1376 } 1377 else if(spair_reloc != NULL){ 1378 if(r_type == ARM_RELOC_SECTDIFF || 1379 r_type == ARM_RELOC_LOCAL_SECTDIFF){ 1380 /* 1381 * For ARM_RELOC_SECTDIFF relocation entries (which 1382 * are always scattered types) the r_value field is 1383 * relocated. 1384 */ 1385 if(pair_local_map->nfine_relocs == 0) 1386 spair_reloc->r_value += 1387 - pair_local_map->s->addr 1388 + (pair_local_map->output_section->s.addr + 1389 pair_local_map->offset); 1390 else 1391 spair_reloc->r_value = 1392 fine_reloc_output_address(pair_local_map, 1393 pair_r_value - pair_local_map->s->addr, 1394 pair_local_map->output_section->s.addr); 1395 } 1396 } 1397 else{ 1398 fatal("internal error, in arm_reloc() pair_r_type " 1399 "is ARM_RELOC_PAIR but pair_reloc and spair_reloc " 1400 "are NULL"); 1401 } 1402 } 1403 } 1404#endif /* !defined(RLD) */ 1405 /* 1406 * If their was a paired relocation entry then it has been processed 1407 * so skip it by incrementing the index of the relocation entry that 1408 * is being processed. 1409 */ 1410 if(pair_r_type == ARM_RELOC_PAIR) 1411 i++; 1412 } 1413} 1414