1/* 2 * Copyright (c) 1999 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 generic relocation. Which can be used 28 * for such machines that have simple 1, 2, and 4 byte relocation lengths. 29 */ 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 <stdlib.h> 37#include <string.h> 38#include <stdarg.h> 39#include <mach-o/loader.h> 40#include <mach-o/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 "indirect_sections.h" 54#include "dylibs.h" 55 56/* 57 * generic_reloc() relocates the contents of the specified section for the 58 * relocation entries using the section map from the current object (cur_obj). 59 * 60 * Or if refs is not NULL it is being called by to get the addresses or 61 * merged_symbols from the item being referenced by the relocation entry(s) at 62 * reloc_index. This is used by mark_fine_relocs_references_live() when 63 * -dead_strip is specified to determined what is being referenced and is only 64 * called when all sections have fine_relocs (that is why refs is only filled 65 * in when nfine_relocs != 0). When refs is not NULL, only refs is filled in 66 * and returned and the contents are not relocated. 67 */ 68__private_extern__ 69void 70generic_reloc( 71char *contents, 72struct relocation_info *relocs, 73struct section_map *section_map, 74long pcrel_at_end_of_disp, 75struct live_refs *refs, 76unsigned long reloc_index) 77{ 78 unsigned long i, j, symbolnum, value, input_pc, output_pc; 79 struct nlist *nlists; 80 char *strings; 81 enum bool force_extern_reloc; 82 struct undefined_map *undefined_map; 83 struct merged_symbol *merged_symbol; 84 struct section_map *local_map, *pair_local_map; 85 struct relocation_info *reloc, *pair_reloc; 86 struct scattered_relocation_info *sreloc, *spair_reloc; 87 unsigned long r_address, r_symbolnum, r_pcrel, r_length, r_extern, 88 r_scattered, r_value, pair_r_symbolnum, pair_r_value; 89 enum reloc_type_generic r_type, pair_r_type; 90 unsigned long offset; 91 92#if defined(DEBUG) || defined(RLD) 93 /* 94 * The compiler "warnings: `merged_symbol', `local_map' and `offset' 95 * may be used uninitialized in this function" can safely be ignored 96 */ 97 merged_symbol = NULL; 98 local_map = NULL; 99 offset = 0; 100 pair_r_symbolnum = 0; 101 pair_r_value = 0; 102 pair_local_map = 0; 103#endif /* DEBUG */ 104 105 if(refs != NULL) 106 memset(refs, '\0', sizeof(struct live_refs)); 107 else 108 reloc_index = 0; 109 for(i = reloc_index; i < section_map->s->nreloc; i++){ 110 force_extern_reloc = FALSE; 111 /* 112 * Break out the fields of the relocation entry and set pointer to 113 * the type of relocation entry it is (for updating later). 114 */ 115 if((relocs[i].r_address & R_SCATTERED) != 0){ 116 sreloc = (struct scattered_relocation_info *)(relocs + i); 117 reloc = NULL; 118 r_scattered = 1; 119 r_address = sreloc->r_address; 120 r_pcrel = sreloc->r_pcrel; 121 r_length = sreloc->r_length; 122 r_value = sreloc->r_value; 123 r_type = (enum reloc_type_generic)sreloc->r_type; 124 r_extern = 0; 125 /* 126 * Since the r_value field is reserved in a GENERIC_RELOC_PAIR 127 * type to report the correct error a check for a stray 128 * GENERIC_RELOC_PAIR relocation types needs to be done before 129 * it is assumed that r_value is legal. A GENERIC_RELOC_PAIR 130 * only follows a GENERIC_RELOC_SECTDIFF or 131 * GENERIC_RELOC_LOCAL_SECTDIFF relocation type and it 132 * is an error to see one otherwise. 133 */ 134 if(r_type == GENERIC_RELOC_PAIR){ 135 error_with_cur_obj("stray relocation GENERIC_RELOC_PAIR " 136 "entry (%lu) in section (%.16s,%.16s)", i, 137 section_map->s->segname, section_map->s->sectname); 138 continue; 139 } 140 /* calculate the r_symbolnum (n_sect) from the r_value */ 141 r_symbolnum = 0; 142 for(j = 0; j < cur_obj->nsection_maps; j++){ 143 if(r_value >= cur_obj->section_maps[j].s->addr && 144 r_value < cur_obj->section_maps[j].s->addr + 145 cur_obj->section_maps[j].s->size){ 146 r_symbolnum = j + 1; 147 break; 148 } 149 } 150 if(r_symbolnum == 0){ 151 /* 152 * The edge case where the last address past then end of 153 * of the last section is referenced. 154 */ 155 for(j = 0; j < cur_obj->nsection_maps; j++){ 156 if(r_value == cur_obj->section_maps[j].s->addr + 157 cur_obj->section_maps[j].s->size){ 158 r_symbolnum = j + 1; 159 break; 160 } 161 } 162 if(r_symbolnum == 0){ 163 error_with_cur_obj("r_value (0x%x) field of relocation " 164 "entry %lu in section (%.16s,%.16s) out of range", 165 (unsigned int)r_value, i, section_map->s->segname, 166 section_map->s->sectname); 167 return; 168 } 169 } 170 } 171 else{ 172 reloc = relocs + i; 173 sreloc = NULL; 174 r_scattered = 0; 175 r_address = reloc->r_address; 176 r_pcrel = reloc->r_pcrel; 177 r_length = reloc->r_length; 178 r_extern = reloc->r_extern; 179 r_symbolnum = reloc->r_symbolnum; 180 r_type = (enum reloc_type_generic)reloc->r_type; 181 r_value = 0; 182 } 183 /* 184 * GENERIC_RELOC_PAIR relocation types only follow a 185 * GENERIC_RELOC_SECTDIFF or GENERIC_RELOC_LOCAL_SECTDIFF 186 * relocation type and it is an error to 187 * see one otherwise. 188 */ 189 if(r_type == GENERIC_RELOC_PAIR){ 190 error_with_cur_obj("stray relocation GENERIC_RELOC_PAIR entry " 191 "(%lu) in section (%.16s,%.16s)", i, 192 section_map->s->segname, section_map->s->sectname); 193 continue; 194 } 195 /* 196 * The r_address field is really an offset into the contents of the 197 * section and must reference something inside the section. 198 */ 199 if(r_address >= section_map->s->size){ 200 error_with_cur_obj("r_address (0x%x) field of relocation entry " 201 "%lu in section (%.16s,%.16s) out of range", 202 (unsigned int)r_address, i, section_map->s->segname, 203 section_map->s->sectname); 204 return; 205 } 206 /* 207 * If this relocation type is to have a pair make sure it is there 208 * and then break out it's fields. Currently only the relocation 209 * types GENERIC_RELOC_SECTDIFF and GENERIC_RELOC_LOCAL_SECTDIFF 210 * can have a pair and itself and it's 211 * pair must be scattered relocation types. 212 */ 213 pair_r_type = (enum reloc_type_generic)0; 214 pair_reloc = NULL; 215 spair_reloc = NULL; 216 if(r_type == GENERIC_RELOC_SECTDIFF || 217 r_type == GENERIC_RELOC_LOCAL_SECTDIFF){ 218 if(r_scattered != 1){ 219 error_with_cur_obj("relocation entry (%lu) in section " 220 "(%.16s,%.16s) r_type is section difference but " 221 "relocation entry not scattered type", i, 222 section_map->s->segname, section_map->s->sectname); 223 continue; 224 } 225 if(i + 1 < section_map->s->nreloc){ 226 pair_reloc = relocs + i + 1; 227 if((pair_reloc->r_address & R_SCATTERED) != 0){ 228 spair_reloc = (struct scattered_relocation_info *) 229 pair_reloc; 230 pair_reloc = NULL; 231 pair_r_type = (enum reloc_type_generic) 232 spair_reloc->r_type; 233 pair_r_value = spair_reloc->r_value; 234 } 235 else{ 236 error_with_cur_obj("relocation entry (%lu) in section " 237 "(%.16s,%.16s) following associated relocation " 238 "entry not scattered type", i, 239 section_map->s->segname, section_map->s->sectname); 240 continue; 241 } 242 } 243 if((pair_reloc == NULL && spair_reloc == NULL) || 244 pair_r_type != GENERIC_RELOC_PAIR){ 245 error_with_cur_obj("relocation entry (%lu) in section " 246 "(%.16s,%.16s) missing following associated " 247 "GENERIC_RELOC_PAIR entry", i, section_map->s->segname, 248 section_map->s->sectname); 249 continue; 250 } 251 /* 252 * Calculate the pair_r_symbolnum (n_sect) from the 253 * pair_r_value. 254 */ 255 pair_r_symbolnum = 0; 256 for(j = 0; j < cur_obj->nsection_maps; j++){ 257 if(pair_r_value >= cur_obj->section_maps[j].s->addr && 258 pair_r_value < cur_obj->section_maps[j].s->addr + 259 cur_obj->section_maps[j].s->size){ 260 pair_r_symbolnum = j + 1; 261 break; 262 } 263 } 264 if(pair_r_symbolnum == 0){ 265 error_with_cur_obj("r_value (0x%x) field of relocation " 266 "entry %lu in section (%.16s,%.16s) out of range", 267 (unsigned int)r_value, i + 1, section_map->s->segname, 268 section_map->s->sectname); 269 return; 270 } 271 } 272 else if(r_type != GENERIC_RELOC_VANILLA){ 273 error_with_cur_obj("r_type field of relocation entry %lu in " 274 "section (%.16s,%.16s) invalid", i, section_map->s->segname, 275 section_map->s->sectname); 276 continue; 277 } 278 /* 279 * If r_extern is set this relocation entry is an external entry 280 * else it is a local entry (or scattered entry). 281 */ 282 if(r_extern){ 283 /* 284 * This is an external relocation entry. So the value to be 285 * added to the item to be relocated is the value of the symbol. 286 * r_symbolnum is an index into the input file's symbol table 287 * of the symbol being refered to. The symbol must be an 288 * undefined or coalesced symbol to be used in an external 289 * external relocation entry. 290 */ 291 if(r_symbolnum >= cur_obj->symtab->nsyms){ 292 error_with_cur_obj("r_symbolnum (%lu) field of external " 293 "relocation entry %lu in section (%.16s,%.16s) out of " 294 "range", r_symbolnum, i, section_map->s->segname, 295 section_map->s->sectname); 296 return; 297 } 298 symbolnum = r_symbolnum; 299 undefined_map = bsearch(&symbolnum, cur_obj->undefined_maps, 300 cur_obj->nundefineds, sizeof(struct undefined_map), 301 (int (*)(const void *, const void *))undef_bsearch); 302 if(undefined_map != NULL){ 303 merged_symbol = undefined_map->merged_symbol; 304 } 305 else{ 306 nlists = (struct nlist *)(cur_obj->obj_addr + 307 cur_obj->symtab->symoff); 308 strings = (char *)(cur_obj->obj_addr + 309 cur_obj->symtab->stroff); 310 if((nlists[symbolnum].n_type & N_EXT) != N_EXT){ 311 error_with_cur_obj("r_symbolnum (%lu) field of external" 312 " relocation entry %lu in section (%.16s,%.16s) " 313 "refers to a non-external symbol", symbolnum, i, 314 section_map->s->segname, section_map->s->sectname); 315 return; 316 } 317 /* 318 * We must allow and create references to defined global 319 * coalesced symbols with external relocation entries so 320 * that the dynamic linker can relocate all references to 321 * the same symbol. 322 */ 323 if((nlists[symbolnum].n_type & N_TYPE) == N_SECT && 324 (cur_obj->section_maps[nlists[symbolnum].n_sect-1]. 325 s->flags & SECTION_TYPE) == S_COALESCED){ 326 merged_symbol = lookup_symbol(strings + 327 nlists[symbolnum].n_un.n_strx); 328 if(merged_symbol->name_len == 0){ 329 fatal("internal error, in generic_reloc() failed " 330 "to lookup coalesced symbol %s", strings + 331 nlists[symbolnum].n_un.n_strx); 332 } 333 } 334 else{ 335 if((nlists[symbolnum].n_type & N_EXT) != N_EXT || 336 (nlists[symbolnum].n_type & N_TYPE) != N_UNDF){ 337 error_with_cur_obj("r_symbolnum (%lu) field of " 338 "external relocation entry %lu in section " 339 "(%.16s,%.16s) refers to a non-undefined " 340 "symbol", symbolnum, i, section_map->s->segname, 341 section_map->s->sectname); 342 return; 343 } 344 print_obj_name(cur_obj); 345 fatal("internal error, in generic_reloc() symbol index " 346 "%lu in above file not in undefined map", 347 symbolnum); 348 } 349 } 350 if(refs == NULL && 351 ((merged_symbol->nlist.n_type & N_TYPE) == N_SECT && 352 (get_output_section(merged_symbol->nlist.n_sect)-> 353 flags & SECTION_TYPE) == S_COALESCED)){ 354 if(((merged_symbol->nlist.n_type & N_PEXT) == N_PEXT && 355 keep_private_externs == FALSE) || 356 dynamic == FALSE || 357 (output_for_dyld && has_dynamic_linker_command)) 358 force_extern_reloc = FALSE; 359 else 360 force_extern_reloc = TRUE; 361 } 362 /* 363 * If this is an indirect symbol resolve indirection (all chains 364 * of indirect symbols have been resolved so that they point at 365 * a symbol that is not an indirect symbol). 366 */ 367 if((merged_symbol->nlist.n_type & N_TYPE) == N_INDR) 368 merged_symbol = (struct merged_symbol *) 369 merged_symbol->nlist.n_value; 370 371 /* 372 * If we are being called only to get the references for this 373 * relocation entry fill it in and return. 374 */ 375 if(refs != NULL){ 376 refs->ref1.ref_type = LIVE_REF_SYMBOL; 377 refs->ref1.merged_symbol = merged_symbol; 378 refs->ref2.ref_type = LIVE_REF_NONE; 379 return; 380 } 381 382 /* 383 * If the symbol is undefined (or common) or a global coalesced 384 * symbol where we need to force an external relocation entry 385 * and we are not prebinding no relocation is done. Or if the 386 * output file is a multi module MH_DYLIB no relocation is done 387 * unless the symbol is a private extern or we are prebinding. 388 */ 389 if(((merged_symbol->nlist.n_type & N_TYPE) == N_UNDF) || 390 (force_extern_reloc == TRUE && prebinding == FALSE) || 391 ((filetype == MH_DYLIB && multi_module_dylib == TRUE) && 392 (((merged_symbol->nlist.n_type & N_PEXT) != N_PEXT) && 393 prebinding == FALSE) ) ) 394 value = 0; 395 else{ 396 value = merged_symbol->nlist.n_value; 397 /* 398 * To know which type (local or scattered) of relocation 399 * entry to convert this one to (if relocation entries are 400 * saved) the offset to be added to the symbol's value is 401 * needed to see if it reaches outside the block in which 402 * the symbol is in. In here if the offset is not zero then 403 * it is assumed to reach out of the block and a scattered 404 * relocation entry is used. 405 */ 406 switch(r_length){ 407 case 0: /* byte */ 408 offset = get_byte((char *)(contents + r_address)); 409 break; 410 case 1: /* word (2 byte) */ 411 offset = get_short((short *)(contents + r_address)); 412 break; 413 case 2: /* long (4 byte) */ 414 offset = get_long((long *)(contents + r_address)); 415 break; 416 default: 417 /* the error check is catched below */ 418 break; 419 } 420 /* 421 * If the offset is pc-relative then adjust it. 422 */ 423 if(r_pcrel){ 424 input_pc = section_map->s->addr + r_address; 425 if(pcrel_at_end_of_disp){ 426 switch(r_length){ 427 case 0: /* byte */ 428 input_pc += sizeof(char); 429 break; 430 case 1: /* word (2 byte) */ 431 input_pc += sizeof(short); 432 break; 433 case 2: /* long (4 byte) */ 434 input_pc += sizeof(long); 435 break; 436 default: 437 /* the error check is catched below */ 438 break; 439 } 440 } 441 offset += input_pc; 442 } 443 } 444 445 if((merged_symbol->nlist.n_type & N_TYPE) == N_SECT) 446 output_sections[merged_symbol->nlist.n_sect]->referenced = 447 TRUE; 448 } 449 else{ 450 /* 451 * This is a local relocation entry (the value to which the item 452 * to be relocated is refering to is defined in section number 453 * r_symbolnum). So the address of that section in the input 454 * file is subtracted and the value of that section in the 455 * output is added to the item being relocated. 456 */ 457 value = 0; 458 /* 459 * If the symbol is not in any section the value to be added to 460 * the item to be relocated is the zero above and any pc 461 * relative change in value added below. 462 */ 463 if(r_symbolnum == R_ABS){ 464 /* 465 * If we are being called only to get the references for 466 * this relocation entry fill in it has none and return. 467 */ 468 if(refs != NULL){ 469 refs->ref1.ref_type = LIVE_REF_NONE; 470 refs->ref2.ref_type = LIVE_REF_NONE; 471 return; 472 } 473 } 474 else{ 475 if(r_symbolnum > cur_obj->nsection_maps){ 476 error_with_cur_obj("r_symbolnum (%lu) field of local " 477 "relocation entry %lu in section (%.16s,%.16s) " 478 "out of range", r_symbolnum, i, 479 section_map->s->segname, section_map->s->sectname); 480 return; 481 } 482 local_map = &(cur_obj->section_maps[r_symbolnum - 1]); 483 local_map->output_section->referenced = TRUE; 484 if(local_map->s->flags & S_ATTR_DEBUG){ 485 error_with_cur_obj("illegal reference to debug section," 486 " from non-debug section (%.16s,%.16s) via " 487 "relocation entry (%lu) to section (%.16s,%.16s)", 488 section_map->s->segname, section_map->s->sectname, 489 i, local_map->s->segname, local_map->s->sectname); 490 return; 491 } 492 pair_local_map = NULL; 493 if(r_type == GENERIC_RELOC_SECTDIFF || 494 r_type == GENERIC_RELOC_LOCAL_SECTDIFF){ 495 pair_local_map = 496 &(cur_obj->section_maps[pair_r_symbolnum - 1]); 497 pair_local_map->output_section->referenced = TRUE; 498 if(pair_local_map->s->flags & S_ATTR_DEBUG){ 499 error_with_cur_obj("illegal reference to debug " 500 "section, from non-debug section (%.16s,%.16s) " 501 "via relocation entry (%lu) to section (%.16s," 502 "%.16s)", section_map->s->segname, 503 section_map->s->sectname, i, 504 pair_local_map->s->segname, 505 pair_local_map->s->sectname); 506 return; 507 } 508 } 509 if(local_map->nfine_relocs == 0 && 510 (pair_local_map == NULL || 511 pair_local_map->nfine_relocs == 0) ){ 512 if(r_type == GENERIC_RELOC_SECTDIFF || 513 r_type == GENERIC_RELOC_LOCAL_SECTDIFF){ 514 value = - local_map->s->addr 515 + (local_map->output_section->s.addr + 516 local_map->offset) 517 + pair_local_map->s->addr 518 - (pair_local_map->output_section->s.addr + 519 pair_local_map->offset); 520 } 521 else{ 522 value = - local_map->s->addr 523 + (local_map->output_section->s.addr + 524 local_map->offset); 525 } 526 } 527 else{ 528 /* 529 * For items to be relocated that refer to a section 530 * with fine relocation the value is set (not adjusted 531 * with addition). So the new value is directly 532 * calculated from the old value. 533 */ 534 if(r_pcrel){ 535 input_pc = section_map->s->addr + 536 r_address; 537 if(section_map->nfine_relocs == 0) 538 output_pc = section_map->output_section->s.addr 539 + section_map->offset + 540 r_address; 541 else 542 output_pc = section_map->output_section->s.addr 543 + 544 fine_reloc_output_offset(section_map, 545 r_address); 546 if(pcrel_at_end_of_disp){ 547 switch(r_length){ 548 case 0: /* byte */ 549 input_pc += sizeof(char); 550 output_pc += sizeof(char); 551 break; 552 case 1: /* word (2 byte) */ 553 input_pc += sizeof(short); 554 output_pc += sizeof(short); 555 break; 556 case 2: /* long (4 byte) */ 557 input_pc += sizeof(long); 558 output_pc += sizeof(long); 559 break; 560 default: 561 /* the error check is catched below */ 562 break; 563 } 564 } 565 } 566 else{ 567 input_pc = 0; 568 output_pc = 0; 569 } 570 /* 571 * Get the value of the expresion of the item to be 572 * relocated (errors of r_length are checked later). 573 */ 574 switch(r_length){ 575 case 0: /* byte */ 576 value = get_byte((char *)(contents + r_address)); 577 break; 578 case 1: /* word (2 byte) */ 579 value = get_short((short *)(contents + r_address)); 580 break; 581 case 2: /* long (4 byte) */ 582 value = get_long((long *)(contents + r_address)); 583 break; 584 } 585 if(r_type == GENERIC_RELOC_SECTDIFF || 586 r_type == GENERIC_RELOC_LOCAL_SECTDIFF){ 587 /* 588 * For GENERIC_RELOC_SECTDIFF's the item to be 589 * relocated, in value, is the value of the 590 * expression: 591 * r_value - pair_r_value + offset 592 * To set the value of the relocated expression, 593 * it is set from relocating the two r_value's and 594 * adding back in the offset. So here get the 595 * offset from the value of the expression. 596 */ 597 value += input_pc; /* adjust for pcrel */ 598 offset = value - r_value + pair_r_value; 599 600 /* 601 * If we are being called only to get the references 602 * for this relocation entry fill it in and return. 603 */ 604 if(refs != NULL){ 605 fine_reloc_output_ref( 606 local_map, 607 r_value - local_map->s->addr, 608 &(refs->ref1) ); 609 fine_reloc_output_ref( 610 local_map, 611 pair_r_value - local_map->s->addr, 612 &(refs->ref2) ); 613 return; 614 } 615 616 /* 617 * Now build up the value of the relocated 618 * expression one part at a time. First set the 619 * new value to the relocated r_value. 620 */ 621 if(local_map->nfine_relocs != 0){ 622 /* 623 * Check to see if this reference is legal with 624 * respect to indirect sections. 625 */ 626 legal_reference(section_map, r_address, 627 local_map, r_value - local_map->s->addr + 628 offset, i, 629 r_type != GENERIC_RELOC_LOCAL_SECTDIFF); 630 value = fine_reloc_output_address(local_map, 631 r_value - local_map->s->addr, 632 local_map->output_section->s.addr); 633 } 634 else{ 635 value = local_map->output_section->s.addr + 636 local_map->offset + 637 r_value - local_map->s->addr; 638 } 639 /* Second subtract the relocated pair_r_value. */ 640 if(pair_local_map->nfine_relocs != 0){ 641 /* 642 * Check to see if this reference is legal with 643 * respect to indirect sections. 644 */ 645 legal_reference(section_map, r_address, 646 pair_local_map, pair_r_value - 647 pair_local_map->s->addr, i, TRUE); 648 value -= 649 fine_reloc_output_address(pair_local_map, 650 pair_r_value - pair_local_map->s->addr, 651 pair_local_map->output_section->s.addr); 652 } 653 else{ 654 value -= 655 pair_local_map->output_section->s.addr + 656 pair_local_map->offset + 657 pair_r_value - pair_local_map->s->addr; 658 } 659 /* Third add in the offset. */ 660 value += offset; 661 value -= output_pc; /* adjust for pcrel */ 662 } 663 else{ 664 /* 665 * If the relocation entry is not a scattered 666 * relocation entry then the relocation is based on 667 * the value of value of the expresion of the item 668 * to be relocated. If it is a scattered relocation 669 * entry then the relocation is based on the r_value 670 * in the relocation entry and the offset part of 671 * the expression at the item to be relocated is 672 * extracted so it can be added after the relocation 673 * is done. 674 */ 675 value += input_pc; 676 if(r_scattered == 0){ 677 r_value = value; 678 offset = 0; 679 } 680 else{ 681 offset = value - r_value; 682 } 683 /* 684 * Check to see if this reference is legal with 685 * respect to indirect sections. 686 */ 687 legal_reference(section_map, r_address, local_map, 688 r_value - local_map->s->addr + offset, i, 689 FALSE); 690 691 /* 692 * If we are being called only to get the references 693 * for this relocation entry fill it in and return. 694 */ 695 if(refs != NULL){ 696 fine_reloc_output_ref( 697 local_map, 698 r_value - local_map->s->addr, 699 &(refs->ref1) ); 700 refs->ref2.ref_type = LIVE_REF_NONE; 701 return; 702 } 703 704 value = fine_reloc_output_address(local_map, 705 r_value - local_map->s->addr, 706 local_map->output_section->s.addr); 707 value -= output_pc; 708 value += offset; 709 } 710 switch(r_length){ 711 case 0: /* byte */ 712 if( (value & 0xffffff00) && 713 ((value & 0xffffff80) != 0xffffff80)) 714 error_with_cur_obj("relocation for entry %lu in" 715 " section (%.16s,%.16s) does not fit in 1 " 716 "byte", i, section_map->s->segname, 717 section_map->s->sectname); 718 set_byte((char *)(contents + r_address), value); 719 break; 720 case 1: /* word (2 byte) */ 721 if( (value & 0xffff0000) && 722 ((value & 0xffff8000) != 0xffff8000)) 723 error_with_cur_obj("relocation for entry %lu in" 724 " section (%.16s,%.16s) does not fit in 2 " 725 "bytes", i, section_map->s->segname, 726 section_map->s->sectname); 727 set_short((short *)(contents + r_address), value); 728 break; 729 case 2: /* long (4 byte) */ 730 set_long((long *)(contents + r_address), value); 731 break; 732 default: 733 error_with_cur_obj("r_length field of relocation " 734 "entry %lu in section (%.16s,%.16s) invalid", 735 i, section_map->s->segname, 736 section_map->s->sectname); 737 return; 738 } 739 goto update_reloc; 740 } 741 } 742 } 743 if(r_pcrel){ 744 /* 745 * This is a relocation entry is also pc relative which means 746 * the value of the pc will get added to it when it is executed. 747 * The item being relocated has the value of the pc in the input 748 * file subtracted from it. So to relocate this the value of 749 * pc in the input file is added and then value of the output 750 * pc is subtracted (since the offset into the section remains 751 * constant it is not added in and then subtracted out). 752 */ 753 if(section_map->nfine_relocs == 0) 754 value += + section_map->s->addr /* + r_address */ 755 - (section_map->output_section->s.addr + 756 section_map->offset /* + r_address */); 757 else 758 value += + section_map->s->addr + r_address 759 - (section_map->output_section->s.addr + 760 fine_reloc_output_offset(section_map, 761 r_address)); 762 } 763 switch(r_length){ 764 case 0: /* byte */ 765 value += get_byte((char *)(contents + r_address)); 766 if( (value & 0xffffff00) && 767 ((value & 0xffffff80) != 0xffffff80)) 768 error_with_cur_obj("relocation for entry %lu in section " 769 "(%.16s,%.16s) does not fit in 1 byte", i, 770 section_map->s->segname, section_map->s->sectname); 771 set_byte((char *)(contents + r_address), value); 772 break; 773 case 1: /* word (2 byte) */ 774 value += get_short((short *)(contents + r_address)); 775 if( (value & 0xffff0000) && 776 ((value & 0xffff8000) != 0xffff8000)) 777 error_with_cur_obj("relocation for entry %lu in section " 778 "(%.16s,%.16s) does not fit in 2 bytes", i, 779 section_map->s->segname, section_map->s->sectname); 780 set_short((short *)(contents + r_address), value); 781 break; 782 case 2: /* long (4 byte) */ 783 value += get_long((long *)(contents + r_address)); 784 set_long((long *)(contents + r_address), value); 785 break; 786 default: 787 error_with_cur_obj("r_length field of relocation entry %lu in " 788 "section (%.16s,%.16s) invalid", i, 789 section_map->s->segname, section_map->s->sectname); 790 return; 791 } 792 /* 793 * If relocation entries are to be saved in the output file then 794 * update the entry for the output file. 795 */ 796update_reloc: 797 ; 798#ifndef RLD 799 if(save_reloc || output_for_dyld){ 800 if(r_extern){ 801 /* 802 * If we are prebinding and this is a lazy pointer section 803 * change the relocation entry to a GENERIC_RELOC_PB_LA_PTR 804 * type. This stuffs the value of the lazy pointer as it 805 * wouldn't be prebound in the r_value field. So if the 806 * prebounding can't be used at runtime the value of the 807 * lazy pointer will get set back to the r_value by dyld. 808 */ 809 if(prebinding == TRUE && 810 (section_map->s->flags & SECTION_TYPE) == 811 S_LAZY_SYMBOL_POINTERS){ 812 sreloc = (struct scattered_relocation_info *)reloc; 813 r_scattered = 1; 814 sreloc->r_scattered = r_scattered; 815 if((r_address & 0x00ffffff) != r_address) 816 error_with_cur_obj("Can't create valid output " 817 "file (r_address field of relocation " 818 "entry %lu in section (%.16s,%.16s) would " 819 "overflow)", i, section_map->s->segname, 820 section_map->s->sectname); 821 sreloc->r_address = r_address; 822 sreloc->r_pcrel = r_pcrel; 823 sreloc->r_length = r_length; 824 sreloc->r_type = GENERIC_RELOC_PB_LA_PTR; 825 sreloc->r_value = value; 826 } 827 /* 828 * For external relocation entries that the symbol is 829 * defined (not undefined or common) but not when we are 830 * forcing an external relocation entry for a global 831 * coalesced symbol and if the output file is not a multi 832 * module MH_DYLIB or the symbol is a private extern, it is 833 * changed to a local relocation entry using the section 834 * that symbol is defined in. If still undefined or forcing 835 * an external relocation entry for a global coalesced 836 * symbol, then the index of the symbol in the output file 837 * is set into r_symbolnum. 838 */ 839 else if((merged_symbol->nlist.n_type & N_TYPE) != N_UNDF && 840 (merged_symbol->nlist.n_type & N_TYPE) != N_PBUD && 841 force_extern_reloc == FALSE && 842 ((filetype != MH_DYLIB || 843 multi_module_dylib == FALSE) || 844 (merged_symbol->nlist.n_type & N_PEXT) == N_PEXT)){ 845 reloc->r_extern = 0; 846 /* 847 * If this symbol was in the base file then no futher 848 * relocation can ever be done (the symbols in the base 849 * file are fixed). Or if the symbol was an absolute 850 * symbol. 851 */ 852 if(merged_symbol->definition_object == base_obj || 853 (merged_symbol->nlist.n_type & N_TYPE) == N_ABS){ 854 reloc->r_symbolnum = R_ABS; 855 } 856 else{ 857 /* 858 * The symbol that this relocation entry is refering 859 * to is defined so convert this external relocation 860 * entry into a local or scattered relocation entry. 861 * If the item to be relocated has an offset added 862 * to the symbol's value and the output is not for 863 * dyld make it a scattered relocation entry else 864 * make it a local relocation entry. 865 */ 866 if(offset == 0 || output_for_dyld){ 867 reloc->r_symbolnum =merged_symbol->nlist.n_sect; 868 } 869 else{ 870 sreloc = (struct scattered_relocation_info *) 871 reloc; 872 r_scattered = 1; 873 sreloc->r_scattered = r_scattered; 874 if((r_address & 0x00ffffff) != r_address) 875 error_with_cur_obj("Can't create valid " 876 "output file (r_address field of " 877 "relocation entry %lu in section " 878 "(%.16s,%.16s) would overflow)", i, 879 section_map->s->segname, 880 section_map->s->sectname); 881 sreloc->r_address = r_address; 882 sreloc->r_pcrel = r_pcrel; 883 sreloc->r_length = r_length; 884 sreloc->r_type = 0; 885 sreloc->r_value = merged_symbol->nlist.n_value; 886 } 887 } 888 } 889 else{ 890 reloc->r_symbolnum = 891 merged_symbol_output_index(merged_symbol); 892 } 893 } 894 else if(r_scattered == 0){ 895 /* 896 * If we are prebinding and this is a lazy pointer section 897 * change the relocation entry to a GENERIC_RELOC_PB_LA_PTR 898 * type. This stuffs the value of the lazy pointer as it 899 * wouldn't be prebound in the r_value field. So if the 900 * prebounding can't be used at runtime the value of the 901 * lazy pointer will get set back to the r_value by dyld. 902 */ 903 if(prebinding == TRUE && 904 (section_map->s->flags & SECTION_TYPE) == 905 S_LAZY_SYMBOL_POINTERS){ 906 sreloc = (struct scattered_relocation_info *)reloc; 907 r_scattered = 1; 908 sreloc->r_scattered = r_scattered; 909 if((r_address & 0x00ffffff) != r_address) 910 error_with_cur_obj("Can't create valid output " 911 "file (r_address field of relocation " 912 "entry %lu in section (%.16s,%.16s) would " 913 "overflow)", i, section_map->s->segname, 914 section_map->s->sectname); 915 sreloc->r_address = r_address; 916 sreloc->r_pcrel = r_pcrel; 917 sreloc->r_length = r_length; 918 sreloc->r_type = GENERIC_RELOC_PB_LA_PTR; 919 sreloc->r_value = value; 920 } 921 /* 922 * For local relocation entries the section number is 923 * changed to the section number in the output file. 924 */ 925 else if(reloc->r_symbolnum != R_ABS){ 926 if(local_map->nfine_relocs == 0){ 927 reloc->r_symbolnum = 928 local_map->output_section->output_sectnum; 929 } 930 else{ 931 reloc->r_symbolnum = 932 fine_reloc_output_sectnum(local_map, 933 r_value - local_map->s->addr); 934 } 935 } 936 } 937 else{ 938 /* 939 * This is a scattered relocation entry. If the output is 940 * for dyld convert it to a local relocation entry so as 941 * to not overflow the 24-bit r_address field in a scattered 942 * relocation entry. The overflow would happen in 943 * reloc_output_for_dyld() in sections.c when it adjusts 944 * the r_address fields of the relocation entries. 945 */ 946 if(output_for_dyld){ 947 reloc = (struct relocation_info *)sreloc; 948 r_scattered = 0; 949 reloc->r_address = r_address; 950 reloc->r_pcrel = r_pcrel; 951 reloc->r_extern = 0; 952 reloc->r_length = r_length; 953 reloc->r_type = r_type; 954 if(local_map->nfine_relocs == 0){ 955 reloc->r_symbolnum = 956 local_map->output_section->output_sectnum; 957 } 958 else{ 959 reloc->r_symbolnum = 960 fine_reloc_output_sectnum(local_map, 961 r_value - local_map->s->addr); 962 } 963 } 964 else{ 965 /* 966 * For scattered relocation entries the r_value field is 967 * relocated. 968 */ 969 if(local_map->nfine_relocs == 0) 970 sreloc->r_value += 971 - local_map->s->addr 972 + local_map->output_section->s.addr + 973 local_map->offset; 974 else 975 sreloc->r_value = 976 fine_reloc_output_address(local_map, 977 r_value - local_map->s->addr, 978 local_map->output_section->s.addr); 979 } 980 } 981 /* 982 * If this section that the reloation is being done for has fine 983 * relocation then the offset in the r_address field has to be 984 * set to where it will end up in the output file. Otherwise 985 * it simply has to have the offset to where this contents 986 * appears in the output file. 987 */ 988 if(r_scattered == 0){ 989 if(section_map->nfine_relocs == 0){ 990 reloc->r_address += section_map->offset; 991 } 992 else{ 993 reloc->r_address = fine_reloc_output_offset(section_map, 994 r_address); 995 } 996 } 997 else{ 998 if(section_map->nfine_relocs == 0){ 999 if(((sreloc->r_address + section_map->offset) & 1000 0x00ffffff) != 1001 sreloc->r_address + section_map->offset) 1002 error_with_cur_obj("Can't create valid output " 1003 "file (r_address field of relocation " 1004 "entry %lu in section (%.16s,%.16s) would " 1005 "overflow)", i, section_map->s->segname, 1006 section_map->s->sectname); 1007 sreloc->r_address += section_map->offset; 1008 } 1009 else{ 1010 r_address = fine_reloc_output_offset(section_map, 1011 r_address); 1012 if((r_address & 0x00ffffff) != r_address) 1013 error_with_cur_obj("Can't create valid output " 1014 "file (r_address field of relocation " 1015 "entry %lu in section (%.16s,%.16s) would " 1016 "overflow)", i, section_map->s->segname, 1017 section_map->s->sectname); 1018 sreloc->r_address = r_address; 1019 } 1020 } 1021 /* 1022 * If their was a paired relocation entry then update the 1023 * paired relocation entry. 1024 */ 1025 if(pair_r_type == GENERIC_RELOC_PAIR){ 1026 if(spair_reloc != NULL){ 1027 /* 1028 * For scattered relocation entries the r_value field is 1029 * relocated. 1030 */ 1031 if(pair_local_map->nfine_relocs == 0) 1032 spair_reloc->r_value += 1033 - pair_local_map->s->addr 1034 + (pair_local_map->output_section->s.addr + 1035 pair_local_map->offset); 1036 else 1037 spair_reloc->r_value = 1038 fine_reloc_output_address(pair_local_map, 1039 pair_r_value - pair_local_map->s->addr, 1040 pair_local_map->output_section->s.addr); 1041 } 1042 else{ 1043 fatal("internal error, in generic_reloc() pair_r_type " 1044 "is GENERIC_RELOC_PAIR but spair_reloc is NULL"); 1045 } 1046 } 1047 } 1048#endif /* !defined(RLD) */ 1049 /* 1050 * If their was a paired relocation entry then it has been processed 1051 * so skip it by incrementing the index of the relocation entry that 1052 * is being processed. 1053 */ 1054 if(pair_r_type == GENERIC_RELOC_PAIR) 1055 i++; 1056 } 1057} 1058 1059__private_extern__ 1060int 1061undef_bsearch( 1062const unsigned long *index, 1063const struct undefined_map *undefined_map) 1064{ 1065 return(*index - undefined_map->index); 1066} 1067