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#ifndef RLD 24/* 25 * This file contains the routines to do relocation for the i860. Since this is 26 * a RISC machine that has items to be relocated that are not always 32 bits 27 * wide and that two different references to the same symbol may share the same 28 * high 16 bits scattered relocation can't be performed. It is treated as an 29 * error in the object file to see a scattered relocation entry. And it is an 30 * interal error if any section has fine relocations (this may be relaxed at 31 * some time in the future if all the cases can be delt with). 32 */ 33#include <stdlib.h> 34#include <stdio.h> 35#include <stdarg.h> 36#include <mach/mach.h> 37#include <mach-o/loader.h> 38#include <mach-o/reloc.h> 39#include <mach-o/i860/reloc.h> 40#include <mach-o/nlist.h> 41#include "stuff/bool.h" 42#include "stuff/bytesex.h" 43 44#include "ld.h" 45#include "live_refs.h" 46#include "objects.h" 47#include "sections.h" 48#include "pass1.h" 49#include "symbols.h" 50#include "pass2.h" 51#include "generic_reloc.h" 52#include "i860_reloc.h" 53#include "dylibs.h" 54 55/* 56 * i860_reloc() relocates the contents of the specified section for the 57 * relocation entries using the section map from the current object (cur_obj). 58 */ 59__private_extern__ 60void 61i860_reloc( 62char *contents, 63struct relocation_info *relocs, 64struct section_map *section_map) 65{ 66 unsigned long i, j, symbolnum, value; 67 unsigned long instruction, immediate; 68 struct nlist *nlists; 69 char *strings; 70 enum bool force_extern_reloc; 71 struct undefined_map *undefined_map; 72 struct merged_symbol *merged_symbol; 73 struct section_map *local_map, *pair_local_map; 74 struct relocation_info *reloc, *pair_reloc; 75 struct scattered_relocation_info *sreloc, *spair_reloc; 76 unsigned long r_address, r_symbolnum, r_pcrel, r_length, r_extern, 77 r_scattered, r_value, pair_r_symbolnum, pair_r_value; 78 enum reloc_type_i860 r_type, pair_r_type; 79 unsigned short other_half; 80 unsigned long offset; 81 82#ifdef DEBUG 83 /* 84 * The compiler "warnings: `merged_symbol', `local_map' and `immediate' 85 * may be used uninitialized in this function" can safely be ignored 86 */ 87 merged_symbol = NULL; 88 local_map = NULL; 89 immediate = 0; 90 pair_local_map = NULL; 91 pair_r_symbolnum = 0; 92 pair_r_value = 0; 93 other_half = 0; 94 offset = 0; 95#endif /* DEBUG */ 96 97 for(i = 0; i < section_map->s->nreloc; i++){ 98 force_extern_reloc = FALSE; 99 /* 100 * Break out the fields of the relocation entry and set pointer to 101 * the type of relocation entry it is (for updating later). 102 */ 103 if((relocs[i].r_address & R_SCATTERED) != 0){ 104 sreloc = (struct scattered_relocation_info *)(relocs + i); 105 reloc = NULL; 106 r_scattered = 1; 107 r_address = sreloc->r_address; 108 r_pcrel = sreloc->r_pcrel; 109 r_length = sreloc->r_length; 110 r_value = sreloc->r_value; 111 r_type = (enum reloc_type_i860)sreloc->r_type; 112 r_extern = 0; 113 /* 114 * Since the r_value field is reserved in a I860_RELOC_PAIR 115 * type to report the correct error a check for a stray 116 * I860_RELOC_PAIR relocation types needs to be done before 117 * it is assumed that r_value is legal. A I860_RELOC_PAIR 118 * only follows I860_RELOC_HIGH, I860_RELOC_HIGHADJ and 119 * I860_RELOC_SECTDIFF relocation types and it is an error 120 * to see one otherwise. 121 */ 122 if(r_type == I860_RELOC_PAIR){ 123 error_with_cur_obj("stray relocation I860_RELOC_PAIR entry " 124 "(%lu) in section (%.16s,%.16s)", i, 125 section_map->s->segname, section_map->s->sectname); 126 continue; 127 } 128 /* calculate the r_symbolnum (n_sect) from the r_value */ 129 r_symbolnum = 0; 130 for(j = 0; j < cur_obj->nsection_maps; j++){ 131 if(r_value >= cur_obj->section_maps[j].s->addr && 132 r_value < cur_obj->section_maps[j].s->addr + 133 cur_obj->section_maps[j].s->size){ 134 r_symbolnum = j + 1; 135 break; 136 } 137 } 138 if(r_symbolnum == 0){ 139 /* 140 * The edge case where the last address past then end of 141 * of the last section is referenced. 142 */ 143 for(j = 0; j < cur_obj->nsection_maps; j++){ 144 if(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 error_with_cur_obj("r_value (0x%x) field of relocation " 152 "entry %lu in section (%.16s,%.16s) out of range", 153 (unsigned int)r_value, i, section_map->s->segname, 154 section_map->s->sectname); 155 return; 156 } 157 } 158 } 159 else{ 160 reloc = relocs + i; 161 sreloc = NULL; 162 r_scattered = 0; 163 r_address = reloc->r_address; 164 r_pcrel = reloc->r_pcrel; 165 r_length = reloc->r_length; 166 r_extern = reloc->r_extern; 167 r_symbolnum = reloc->r_symbolnum; 168 r_type = (enum reloc_type_i860)reloc->r_type; 169 r_value = 0; 170 } 171 /* 172 * I860_RELOC_PAIR relocation types only follow I860_RELOC_HIGH, 173 * I860_RELOC_HIGHADJ and I860_RELOC_SECTDIFF relocation types and 174 * it is an error to see one otherwise. 175 */ 176 if(r_type == I860_RELOC_PAIR){ 177 error_with_cur_obj("stray relocation I860_RELOC_PAIR entry " 178 "(%lu) in section (%.16s,%.16s)", i, 179 section_map->s->segname, section_map->s->sectname); 180 continue; 181 } 182 /* 183 * The r_address field is really an offset into the contents of the 184 * section and must reference something inside the section (Note 185 * that this is not the case for I860_RELOC_PAIR entries but this 186 * can't be one with the above check). 187 */ 188 if(r_address >= section_map->s->size){ 189 error_with_cur_obj("r_address (0x%x) field of relocation entry " 190 "%lu in section (%.16s,%.16s) out of range", 191 (unsigned int)r_address, i, section_map->s->segname, 192 section_map->s->sectname); 193 return; 194 } 195 /* 196 * If this relocation type is to have a pair make sure it is there 197 * and then break out it's fields. 198 */ 199 pair_r_type = (enum reloc_type_i860)0; 200 pair_reloc = NULL; 201 spair_reloc = NULL; 202 if(r_type == I860_RELOC_HIGH || r_type == I860_RELOC_HIGHADJ){ 203 if(i + 1 < section_map->s->nreloc){ 204 pair_reloc = relocs + i + 1; 205 if((pair_reloc->r_address & R_SCATTERED) != 0){ 206 spair_reloc = (struct scattered_relocation_info *) 207 pair_reloc; 208 pair_reloc = NULL; 209 pair_r_type = (enum reloc_type_i860)spair_reloc->r_type; 210 other_half = spair_reloc->r_address & 0xffff; 211 } 212 else{ 213 pair_r_type = (enum reloc_type_i860)pair_reloc->r_type; 214 other_half = pair_reloc->r_address & 0xffff; 215 } 216 } 217 if((pair_reloc == NULL && spair_reloc == NULL) || 218 pair_r_type != I860_RELOC_PAIR){ 219 error_with_cur_obj("relocation entry (%lu) in section " 220 "(%.16s,%.16s) missing following associated " 221 "I860_RELOC_PAIR entry", i, section_map->s->segname, 222 section_map->s->sectname); 223 continue; 224 } 225 } 226 else if(r_type == I860_RELOC_SECTDIFF){ 227 if(r_scattered != 1){ 228 error_with_cur_obj("relocation entry (%lu) in section " 229 "(%.16s,%.16s) r_type is I860_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_i860)spair_reloc->r_type; 241 pair_r_value = spair_reloc->r_value; 242 } 243 else{ 244 error_with_cur_obj("relocation entry (%lu) in section " 245 "(%.16s,%.16s) following associated relocation " 246 "entry not scattered type", i, 247 section_map->s->segname, section_map->s->sectname); 248 continue; 249 } 250 } 251 if((pair_reloc == NULL && spair_reloc == NULL) || 252 pair_r_type != I860_RELOC_PAIR){ 253 error_with_cur_obj("relocation entry (%lu) in section " 254 "(%.16s,%.16s) missing following associated " 255 "I860_RELOC_PAIR entry", i, section_map->s->segname, 256 section_map->s->sectname); 257 continue; 258 } 259 /* 260 * Calculate the pair_r_symbolnum (n_sect) from the 261 * pair_r_value. 262 */ 263 pair_r_symbolnum = 0; 264 for(j = 0; j < cur_obj->nsection_maps; j++){ 265 if(pair_r_value >= cur_obj->section_maps[j].s->addr && 266 pair_r_value < cur_obj->section_maps[j].s->addr + 267 cur_obj->section_maps[j].s->size){ 268 pair_r_symbolnum = j + 1; 269 break; 270 } 271 } 272 if(pair_r_symbolnum == 0){ 273 error_with_cur_obj("r_value (0x%x) field of relocation " 274 "entry %lu in section (%.16s,%.16s) out of range", 275 (unsigned int)r_value, i + 1, section_map->s->segname, 276 section_map->s->sectname); 277 return; 278 } 279 } 280 /* 281 * If r_extern is set this relocation entry is an external entry 282 * else it is a local entry. 283 */ 284 if(r_extern){ 285 /* 286 * This is an external relocation entry. So the value to be 287 * added to the item to be relocated is the value of the symbol. 288 * r_symbolnum is an index into the input file's symbol table 289 * of the symbol being refered to. The symbol must be an 290 * undefined or coalesced symbol to be used in an external 291 * relocation entry. 292 */ 293 if(r_symbolnum >= cur_obj->symtab->nsyms){ 294 error_with_cur_obj("r_symbolnum (%lu) field of external " 295 "relocation entry %lu in section (%.16s,%.16s) out of " 296 "range", r_symbolnum, i, section_map->s->segname, 297 section_map->s->sectname); 298 return; 299 } 300 symbolnum = r_symbolnum; 301 undefined_map = bsearch(&symbolnum, cur_obj->undefined_maps, 302 cur_obj->nundefineds, sizeof(struct undefined_map), 303 (int (*)(const void *, const void *))undef_bsearch); 304 if(undefined_map != NULL){ 305 merged_symbol = undefined_map->merged_symbol; 306 } 307 else{ 308 nlists = (struct nlist *)(cur_obj->obj_addr + 309 cur_obj->symtab->symoff); 310 strings = (char *)(cur_obj->obj_addr + 311 cur_obj->symtab->stroff); 312 if((nlists[symbolnum].n_type & N_EXT) != N_EXT){ 313 error_with_cur_obj("r_symbolnum (%lu) field of external" 314 " relocation entry %lu in section (%.16s,%.16s) " 315 "refers to a non-external symbol", symbolnum, i, 316 section_map->s->segname, section_map->s->sectname); 317 return; 318 } 319 /* 320 * We must allow and create references to defined global 321 * coalesced symbols with external relocation entries so 322 * that the dynamic linker can relocate all references to 323 * the same symbol. 324 */ 325 if((nlists[symbolnum].n_type & N_TYPE) == N_SECT && 326 (cur_obj->section_maps[nlists[symbolnum].n_sect-1]. 327 s->flags & SECTION_TYPE) == S_COALESCED){ 328 merged_symbol = lookup_symbol(strings + 329 nlists[symbolnum].n_un.n_strx); 330 if(merged_symbol->name_len == 0){ 331 fatal("internal error, in i860_reloc() failed to " 332 "lookup coalesced symbol %s", strings + 333 nlists[symbolnum].n_un.n_strx); 334 } 335 } 336 else{ 337 if((nlists[symbolnum].n_type & N_EXT) != N_EXT || 338 (nlists[symbolnum].n_type & N_TYPE) != N_UNDF){ 339 error_with_cur_obj("r_symbolnum (%lu) field of " 340 "external relocation entry %lu in section " 341 "(%.16s,%.16s) refers to a non-undefined " 342 "symbol", symbolnum, i, section_map->s->segname, 343 section_map->s->sectname); 344 return; 345 } 346 print_obj_name(cur_obj); 347 fatal("internal error, in i860_reloc() symbol index %lu" 348 " in above file not in undefined map", symbolnum); 349 } 350 } 351 if((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 * If the symbol is undefined (or common) or a global coalesced 372 * symbol where we need to force an external relocation entry 373 * and we are not prebinding no relocation is done. Or if the 374 * output file is a multi module MH_DYLIB no relocation is done 375 * unless the symbol is a private extern or we are prebinding. 376 */ 377 if(((merged_symbol->nlist.n_type & N_TYPE) == N_UNDF) || 378 (force_extern_reloc == TRUE && prebinding == FALSE) || 379 ((filetype == MH_DYLIB && multi_module_dylib == TRUE) && 380 (((merged_symbol->nlist.n_type & N_PEXT) != N_PEXT) && 381 prebinding == FALSE) ) ) 382 value = 0; 383 else{ 384 value = merged_symbol->nlist.n_value; 385 /* 386 * To know which type (local or scattered) of relocation 387 * entry to convert this one to (if relocation entries are 388 * saved) the offset to be added to the symbol's value is 389 * needed to see if it reaches outside the block in which 390 * the symbol is in. In here if the offset is not zero then 391 * it is assumed to reach out of the block and a scattered 392 * relocation entry is used. 393 */ 394 if(r_type == I860_RELOC_VANILLA){ 395 switch(r_length){ 396 case 0: /* byte */ 397 offset = get_byte((char *)(contents + r_address)); 398 break; 399 case 1: /* word (2 byte) */ 400 offset = get_short((short *)(contents + r_address)); 401 break; 402 case 2: /* long (4 byte) */ 403 offset = get_long((long *)(contents + r_address)); 404 break; 405 default: 406 /* the error check is catched below */ 407 break; 408 } 409 if(r_pcrel) 410 offset += section_map->s->addr + r_address; 411 } 412 else{ 413 instruction = get_long((long *)(contents + r_address)); 414 switch(r_type){ 415 case I860_RELOC_HIGH: 416 offset = ((instruction & 0xffff) << 16) | 417 other_half; 418 break; 419 case I860_RELOC_HIGHADJ: 420 if(other_half & 0x8000) 421 offset = ((instruction & 0xffff) << 16) + 422 (other_half | 0xffff0000); 423 else 424 offset = ((instruction & 0xffff) << 16) + 425 other_half; 426 break; 427 case I860_RELOC_LOW0: 428 offset = instruction & 0xffff; 429 if((offset & 0x8000) != 0) 430 offset |= 0xffff0000; 431 break; 432 case I860_RELOC_LOW1: 433 offset = instruction & 0xfffe; 434 if((offset & 0x8000) != 0) 435 offset |= 0xffff0000; 436 break; 437 case I860_RELOC_LOW2: 438 offset = instruction & 0xfffc; 439 if((offset & 0x8000) != 0) 440 offset |= 0xffff0000; 441 break; 442 case I860_RELOC_LOW3: 443 offset = instruction & 0xfff8; 444 if((offset & 0x8000) != 0) 445 offset |= 0xffff0000; 446 break; 447 case I860_RELOC_LOW4: 448 offset = instruction &0xfff0; 449 if((offset & 0x8000) != 0) 450 offset |= 0xffff0000; 451 break; 452 case I860_RELOC_SPLIT0: 453 offset = ((instruction >> 5) & 0xf800) | 454 (instruction & 0x7ff); 455 if((offset & 0x8000) != 0) 456 offset |= 0xffff0000; 457 /* 458 * This is used both for a 16 bit immediate or a 459 * branch instruction. If it is a branch 460 * instruction then r_pcrel is set and the 461 * immediate is a 32 bit word displacement 462 * otherwise it is a byte displacement and r_pcrel 463 * is not set. 464 */ 465 if(r_pcrel) 466 offset <<= 2; /* long to byte address */ 467 break; 468 case I860_RELOC_SPLIT1: 469 offset = ((instruction >> 5) & 0xf800) | 470 (instruction & 0x7fe); 471 if((offset & 0x8000) != 0) 472 offset |= 0xffff0000; 473 break; 474 case I860_RELOC_SPLIT2: 475 offset = ((instruction >> 5) & 0xf800) | 476 (instruction & 0x7fc); 477 /* sign extend if needed */ 478 if((offset & 0x8000) != 0) 479 offset |= 0xffff0000; 480 break; 481 case I860_RELOC_BRADDR: 482 offset = instruction & 0x03ffffff; 483 if((offset & 0x02000000) != 0) 484 offset |= 0xfc000000; 485 /* 486 * The immediate is always a 32 bit word 487 * displacement. 488 */ 489 offset <<= 2; 490 break; 491 default: 492 /* the error check is catched below */ 493 break; 494 } 495 } 496 } 497 498 if((merged_symbol->nlist.n_type & N_TYPE) == N_SECT) 499 output_sections[merged_symbol->nlist.n_sect]->referenced = 500 TRUE; 501 } 502 else{ 503 /* 504 * This is a local relocation entry (the value to which the item 505 * to be relocated is refering to is defined in section number 506 * r_symbolnum). So the address of that section in the input 507 * file is subtracted and the value of that section in the 508 * output is added to the item being relocated. 509 */ 510 value = 0; 511 /* 512 * If the symbol is not in any section the value to be added to 513 * the item to be relocated is the zero above and any pc 514 * relative change in value added below. 515 */ 516 if(r_symbolnum != R_ABS){ 517 if(r_symbolnum > cur_obj->nsection_maps){ 518 error_with_cur_obj("r_symbolnum (%lu) field of local " 519 "relocation entry %lu in section (%.16s,%.16s) " 520 "out of range", r_symbolnum, i, 521 section_map->s->segname, section_map->s->sectname); 522 return; 523 } 524 local_map = &(cur_obj->section_maps[r_symbolnum - 1]); 525 local_map->output_section->referenced = TRUE; 526 if(local_map->s->flags & S_ATTR_DEBUG){ 527 error_with_cur_obj("illegal reference to debug section," 528 " from non-debug section (%.16s,%.16s) via " 529 "relocation entry (%lu) to section (%.16s,%.16s)", 530 section_map->s->segname, section_map->s->sectname, 531 i, local_map->s->segname, local_map->s->sectname); 532 return; 533 } 534 pair_local_map = NULL; 535 if(r_type == I860_RELOC_SECTDIFF){ 536 pair_local_map = 537 &(cur_obj->section_maps[pair_r_symbolnum - 1]); 538 pair_local_map->output_section->referenced = TRUE; 539 if(pair_local_map->s->flags & S_ATTR_DEBUG){ 540 error_with_cur_obj("illegal reference to debug " 541 "section, from non-debug section (%.16s,%.16s) " 542 "via relocation entry (%lu) to section (%.16s," 543 "%.16s)", section_map->s->segname, 544 section_map->s->sectname, i, 545 pair_local_map->s->segname, 546 pair_local_map->s->sectname); 547 return; 548 } 549 } 550 if(local_map->nfine_relocs == 0 && 551 (pair_local_map == NULL || 552 pair_local_map->nfine_relocs == 0) ){ 553 if(r_type == I860_RELOC_SECTDIFF){ 554 value = - local_map->s->addr 555 + (local_map->output_section->s.addr + 556 local_map->offset) 557 + pair_local_map->s->addr 558 - (pair_local_map->output_section->s.addr + 559 pair_local_map->offset); 560 } 561 else{ 562 value = - local_map->s->addr 563 + (local_map->output_section->s.addr + 564 local_map->offset); 565 } 566 } 567 else{ 568 /* 569 * For items to be relocated that refer to a section 570 * with fine relocation it is an interal error for the 571 * i860 cputype. 572 */ 573 fatal("internal error, in i860_reloc() section (%.16s," 574 "%.16s) has fine relocs", local_map->s->segname, 575 local_map->s->sectname); 576 } 577 } 578 } 579 if(r_pcrel){ 580 /* 581 * This is a relocation entry is also pc relative which means 582 * the value of the pc will get added to it when it is executed. 583 * The item being relocated has the value of the pc in the input 584 * file subtracted from it. So to relocate this the value of 585 * pc in the input file is added and then value of the output 586 * pc is subtracted (since the offset into the section remains 587 * constant it is not added in and then subtracted out). 588 */ 589 if(section_map->nfine_relocs == 0) 590 value += + section_map->s->addr /* + r_address */ 591 - (section_map->output_section->s.addr + 592 section_map->offset /* + r_address */); 593 else{ 594 /* 595 * For items to be relocated that refer to a section 596 * with fine relocation it is an interal error for the 597 * i860 cputype. 598 */ 599 fatal("internal error, in i860_reloc() section (%.16s," 600 "%.16s) has fine relocs", local_map->s->segname, 601 local_map->s->sectname); 602 } 603 } 604 605 /* 606 * Do "vanilla" and "sectdiff" relocation just like in 607 * generic_reloc() first. 608 */ 609 if(r_type == I860_RELOC_VANILLA || 610 r_type == I860_RELOC_SECTDIFF){ 611 switch(r_length){ 612 case 0: /* byte */ 613 value += get_byte((char *)(contents + r_address)); 614 if( (value & 0xffffff00) && 615 ((value & 0xffffff80) != 0xffffff80)) 616 error_with_cur_obj("relocation for entry %lu in section" 617 " (%.16s,%.16s) does not fit in 1 byte", i, 618 section_map->s->segname, section_map->s->sectname); 619 set_byte((char *)(contents + r_address), value); 620 break; 621 case 1: /* word (2 byte) */ 622 value += get_short((short *)(contents + r_address)); 623 if( (value & 0xffff0000) && 624 ((value & 0xffff8000) != 0xffff8000)) 625 error_with_cur_obj("relocation for entry %lu in section" 626 " (%.16s,%.16s) does not fit in 2 bytes", i, 627 section_map->s->segname, section_map->s->sectname); 628 set_short((short *)(contents + r_address), value); 629 break; 630 case 2: /* long (4 byte) */ 631 value += get_long((long *)(contents + r_address)); 632 set_long((long *)(contents + r_address), value); 633 break; 634 default: 635 error_with_cur_obj("r_length field of relocation entry %lu " 636 "in section (%.16s,%.16s) invalid", i, 637 section_map->s->segname, section_map->s->sectname); 638 return; 639 } 640 } 641 /* 642 * Do i860 specific relocation based on the r_type. 643 */ 644 else{ 645 instruction = get_long((long *)(contents + r_address)); 646 switch(r_type){ 647 case I860_RELOC_HIGH: 648 immediate = ((instruction & 0xffff) << 16) | other_half; 649 immediate += value; 650 instruction = (instruction & 0xffff0000) | 651 ((immediate >> 16) & 0xffff); 652 other_half = immediate & 0xffff; 653 break; 654 case I860_RELOC_HIGHADJ: 655 if(other_half & 0x8000) 656 immediate = ((instruction & 0xffff) << 16) + 657 (other_half | 0xffff0000); 658 else 659 immediate = ((instruction & 0xffff) << 16) + other_half; 660 immediate += value; 661 if(immediate & 0x8000) 662 instruction = (instruction & 0xffff0000) | 663 (((immediate >> 16) + 1) & 0xffff); 664 else 665 instruction = (instruction & 0xffff0000) | 666 ((immediate >> 16) & 0xffff); 667 other_half = immediate & 0xffff; 668 break; 669 case I860_RELOC_LOW0: 670 immediate = instruction & 0xffff; 671 if((immediate & 0x8000) != 0) 672 immediate |= 0xffff0000; 673 immediate += value; 674 instruction = (instruction & 0xffff0000) | 675 (immediate & 0xffff); 676 break; 677 case I860_RELOC_LOW1: 678 immediate = instruction & 0xfffe; 679 if((immediate & 0x8000) != 0) 680 immediate |= 0xffff0000; 681 immediate += value; 682 instruction = (instruction & 0xffff0001) | 683 (immediate & 0xfffe); 684 break; 685 case I860_RELOC_LOW2: 686 immediate = instruction & 0xfffc; 687 if((immediate & 0x8000) != 0) 688 immediate |= 0xffff0000; 689 immediate += value; 690 instruction = (instruction & 0xffff0003) | 691 (immediate & 0xfffc); 692 break; 693 case I860_RELOC_LOW3: 694 immediate = instruction & 0xfff8; 695 if((immediate & 0x8000) != 0) 696 immediate |= 0xffff0000; 697 immediate += value; 698 instruction = (instruction & 0xffff0007) | 699 (immediate & 0xfff8); 700 break; 701 case I860_RELOC_LOW4: 702 immediate = instruction &0xfff0; 703 if((immediate & 0x8000) != 0) 704 immediate |= 0xffff0000; 705 immediate += value; 706 instruction = (instruction & 0xffff000f) | 707 (immediate & 0xfff0); 708 break; 709 case I860_RELOC_SPLIT0: 710 immediate = ((instruction >> 5) & 0xf800) | 711 (instruction & 0x7ff); 712 if((immediate & 0x8000) != 0) 713 immediate |= 0xffff0000; 714 /* 715 * This is used both for a 16 bit immediate or a branch 716 * instruction. If it is a branch instruction then r_pcrel 717 * is set and the immediate is a 32 bit word displacement 718 * otherwise it is a byte displacement and r_pcrel is not 719 * set. 720 */ 721 if(r_pcrel) 722 immediate <<= 2; /* long to byte address */ 723 immediate += value; 724 if(r_pcrel) 725 immediate >>= 2; /* Back to long address */ 726 instruction = (instruction & 0xffe0f800) | 727 ((immediate & 0xf800) << 5) | 728 (immediate & 0x7ff); 729 break; 730 case I860_RELOC_SPLIT1: 731 immediate = ((instruction >> 5) & 0xf800) | 732 (instruction & 0x7fe); 733 if((immediate & 0x8000) != 0) 734 immediate |= 0xffff0000; 735 immediate += value; 736 instruction = (instruction & 0xffe0f801) | 737 ((immediate & 0xf800) << 5) | 738 (immediate & 0x7fe); 739 break; 740 case I860_RELOC_SPLIT2: 741 immediate = ((instruction >> 5) & 0xf800) | 742 (instruction & 0x7fc); 743 if((immediate & 0x8000) != 0) 744 immediate |= 0xffff0000; 745 immediate += value; 746 instruction = (instruction & 0xffe0f803) | 747 ((immediate & 0xf800) << 5) | 748 (immediate & 0x7FC); 749 break; 750 case I860_RELOC_BRADDR: 751 immediate = instruction & 0x03ffffff; 752 if((immediate & 0x02000000) != 0) 753 immediate |= 0xfc000000; 754 /* 755 * The immediate is always a 32 bit word displacement. 756 */ 757 immediate <<= 2; 758 immediate += value; 759 immediate >>= 2; 760 instruction = (instruction & 0xfc000000) | 761 (immediate & 0x03ffffff); 762 break; 763 case I860_RELOC_PAIR: 764 default: 765 error_with_cur_obj("r_type field of relocation entry %lu " 766 "in section (%.16s,%.16s) invalid", i, 767 section_map->s->segname, section_map->s->sectname); 768 continue; 769 } 770 set_long((long *)(contents + r_address), instruction); 771 } 772 773 /* 774 * If relocation entries are to be saved in the output file then 775 * update the entry for the output file. 776 */ 777 if(save_reloc || output_for_dyld){ 778 if(r_extern){ 779 /* 780 * For external relocation entries that the symbol is 781 * defined (not undefined or common) but not when we are 782 * forcing an external relocation entry for a global 783 * coalesced symbol and if the output file is not a multi 784 * module MH_DYLIB or the symbol is a private extern, it is 785 * changed to a local relocation entry using the section 786 * that symbol is defined in. If still undefined or forcing 787 * an external relocation entry for a global coalesced 788 * symbol, then the index of the symbol in the output file 789 * is set into r_symbolnum. 790 */ 791 if((merged_symbol->nlist.n_type & N_TYPE) != N_UNDF && 792 (merged_symbol->nlist.n_type & N_TYPE) != N_PBUD && 793 force_extern_reloc == FALSE && 794 ((filetype != MH_DYLIB || 795 multi_module_dylib == FALSE) || 796 (merged_symbol->nlist.n_type & N_PEXT) == N_PEXT)){ 797 reloc->r_extern = 0; 798 reloc->r_extern = 0; 799 /* 800 * If this symbol was in the base file then no futher 801 * relocation can ever be done (the symbols in the base 802 * file are fixed). Or if the symbol was an absolute 803 * symbol. 804 */ 805 if(merged_symbol->definition_object == base_obj || 806 (merged_symbol->nlist.n_type & N_TYPE) == N_ABS){ 807 reloc->r_symbolnum = R_ABS; 808 } 809 else{ 810 /* 811 * The symbol that this relocation entry is refering 812 * to is defined so convert this external relocation 813 * entry into a local or scattered relocation entry. 814 * If the item to be relocated has an offset added 815 * to the symbol's value make it a scattered 816 * relocation entry else make it a local relocation 817 * entry. 818 */ 819 if(offset == 0){ 820 reloc->r_symbolnum =merged_symbol->nlist.n_sect; 821 } 822 else{ 823 sreloc = (struct scattered_relocation_info *) 824 reloc; 825 r_scattered = 1; 826 sreloc->r_scattered = r_scattered; 827 sreloc->r_address = r_address; 828 sreloc->r_pcrel = r_pcrel; 829 sreloc->r_length = r_length; 830 sreloc->r_type = r_type; 831 sreloc->r_value = merged_symbol->nlist.n_value; 832 } 833 } 834 } 835 else{ 836 reloc->r_symbolnum = 837 merged_symbol_output_index(merged_symbol); 838 } 839 } 840 else if(r_scattered == 0){ 841 /* 842 * For local relocation entries the section number is 843 * changed to the section number in the output file. 844 */ 845 if(reloc->r_symbolnum != R_ABS) 846 reloc->r_symbolnum = 847 local_map->output_section->output_sectnum; 848 } 849 else{ 850 /* 851 * For scattered relocation entries the r_value field is 852 * relocated. 853 */ 854 sreloc->r_value += - local_map->s->addr 855 + (local_map->output_section->s.addr + 856 local_map->offset); 857 } 858 /* 859 * The offset in the r_address field has to be updated to where 860 * this contents appears in the output file. 861 */ 862 if(r_scattered == 0){ 863 reloc->r_address += section_map->offset; 864 } 865 else{ 866 sreloc->r_address += section_map->offset; 867 } 868 /* 869 * If their was a paired relocation entry then update the 870 * paired relocation entry. 871 */ 872 if(pair_r_type == I860_RELOC_PAIR){ 873 if(pair_reloc != NULL) 874 pair_reloc->r_address = other_half; 875 else if(spair_reloc != NULL){ 876 if(r_type == I860_RELOC_SECTDIFF){ 877 /* 878 * For I860_RELOC_SECTDIFF relocation entries (which 879 * are always scattered types) the r_value field is 880 * relocated. 881 */ 882 spair_reloc->r_value += 883 - pair_local_map->s->addr 884 + (pair_local_map->output_section->s.addr + 885 pair_local_map->offset); 886 } 887 else{ 888 spair_reloc->r_address = other_half; 889 } 890 } 891 else{ 892 fatal("internal error, in i860_reloc() pair_r_type " 893 "is I860_RELOC_PAIR but pair_reloc and spair_reloc " 894 "are NULL"); 895 } 896 } 897 } 898 /* 899 * If their was a paired relocation entry then it has been processed 900 * so skip it by incrementing the index of the relocation entry that 901 * is being processed. 902 */ 903 if(pair_r_type == I860_RELOC_PAIR) 904 i++; 905 } 906} 907#endif /* !defined(RLD) */ 908