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