reloc.c (103315) | reloc.c (107071) |
---|---|
1/* $NetBSD: mdreloc.c,v 1.5 2001/04/25 12:24:51 kleink Exp $ */ 2 3/*- 4 * Copyright (c) 2000 Eduardo Horvath. 5 * Copyright (c) 1999 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation --- 22 unchanged lines hidden (view full) --- 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 * | 1/* $NetBSD: mdreloc.c,v 1.5 2001/04/25 12:24:51 kleink Exp $ */ 2 3/*- 4 * Copyright (c) 2000 Eduardo Horvath. 5 * Copyright (c) 1999 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation --- 22 unchanged lines hidden (view full) --- 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 * |
39 * $FreeBSD: head/libexec/rtld-elf/sparc64/reloc.c 103315 2002-09-14 12:14:24Z tmm $ | 39 * $FreeBSD: head/libexec/rtld-elf/sparc64/reloc.c 107071 2002-11-18 22:08:50Z tmm $ |
40 */ 41 42#include <sys/param.h> 43#include <sys/mman.h> 44 45#include <errno.h> 46#include <stdio.h> 47#include <stdlib.h> --- 405 unchanged lines hidden (view full) --- 453 for (rela = obj->pltrela; rela < relalim; rela++) { 454 assert(ELF_R_TYPE(rela->r_info) == R_SPARC_JMP_SLOT); 455 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 456 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 457 true, NULL); 458 if (def == NULL) 459 return -1; 460 target = (Elf_Addr)(defobj->relocbase + def->st_value); | 40 */ 41 42#include <sys/param.h> 43#include <sys/mman.h> 44 45#include <errno.h> 46#include <stdio.h> 47#include <stdlib.h> --- 405 unchanged lines hidden (view full) --- 453 for (rela = obj->pltrela; rela < relalim; rela++) { 454 assert(ELF_R_TYPE(rela->r_info) == R_SPARC_JMP_SLOT); 455 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 456 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 457 true, NULL); 458 if (def == NULL) 459 return -1; 460 target = (Elf_Addr)(defobj->relocbase + def->st_value); |
461 reloc_jmpslot(where, target, defobj); | 461 reloc_jmpslot(where, target, defobj, obj, (Elf_Rel *)rela); |
462 } 463 obj->jmpslots_done = true; 464 return (0); 465} 466 467Elf_Addr | 462 } 463 obj->jmpslots_done = true; 464 return (0); 465} 466 467Elf_Addr |
468reloc_jmpslot(Elf_Addr *wherep, Elf_Addr target, const Obj_Entry *obj) | 468reloc_jmpslot(Elf_Addr *wherep, Elf_Addr target, const Obj_Entry *obj, 469 const Obj_Entry *refobj, const Elf_Rel *rel) |
469{ | 470{ |
471 const Elf_Rela *rela = (const Elf_Rela *)rel; |
|
470 Elf_Addr offset; 471 Elf_Half *where; 472 | 472 Elf_Addr offset; 473 Elf_Half *where; 474 |
473 /* 474 * At the PLT entry pointed at by `where', we now construct 475 * a direct transfer to the now fully resolved function 476 * address. 477 * 478 * A PLT entry is supposed to start by looking like this: 479 * 480 * sethi %hi(. - .PLT0), %g1 481 * ba,a %xcc, .PLT1 482 * nop 483 * nop 484 * nop 485 * nop 486 * nop 487 * nop 488 * 489 * When we replace these entries we start from the second 490 * entry and do it in reverse order so the last thing we 491 * do is replace the branch. That allows us to change this 492 * atomically. 493 * 494 * We now need to find out how far we need to jump. We 495 * have a choice of several different relocation techniques 496 * which are increasingly expensive. 497 */ 498 499 where = (Elf_Half *)wherep; 500 offset = ((Elf_Addr)where) - target; 501 if (offset <= (1L<<20) && offset >= -(1L<<20)) { 502 /* 503 * We're within 1MB -- we can use a direct branch insn. | 475 if (rela - refobj->pltrela < 32764) { 476 /* 477 * At the PLT entry pointed at by `where', we now construct 478 * a direct transfer to the now fully resolved function 479 * address. |
504 * | 480 * |
505 * We can generate this pattern: | 481 * A PLT entry is supposed to start by looking like this: |
506 * | 482 * |
507 * sethi %hi(. - .PLT0), %g1 508 * ba,a %xcc, addr | 483 * sethi (. - .PLT0), %g1 484 * ba,a %xcc, .PLT1 |
509 * nop 510 * nop 511 * nop 512 * nop 513 * nop 514 * nop 515 * | 485 * nop 486 * nop 487 * nop 488 * nop 489 * nop 490 * nop 491 * |
516 */ 517 where[1] = BAA | ((offset >> 2) &0x3fffff); 518 flush(where, 4); 519 } else if (target >= 0 && target < (1L<<32)) { 520 /* 521 * We're withing 32-bits of address zero. | 492 * When we replace these entries we start from the second 493 * entry and do it in reverse order so the last thing we 494 * do is replace the branch. That allows us to change this 495 * atomically. |
522 * | 496 * |
523 * The resulting code in the jump slot is: 524 * 525 * sethi %hi(. - .PLT0), %g1 526 * sethi %hi(addr), %g1 527 * jmp %g1+%lo(addr) 528 * nop 529 * nop 530 * nop 531 * nop 532 * nop 533 * | 497 * We now need to find out how far we need to jump. We 498 * have a choice of several different relocation techniques 499 * which are increasingly expensive. |
534 */ | 500 */ |
535 where[2] = JMP | LOVAL(target); 536 flush(where, 8); 537 where[1] = SETHI | HIVAL(target, 10); 538 flush(where, 4); 539 } else if (target <= 0 && target > -(1L<<32)) { 540 /* 541 * We're withing 32-bits of address -1. 542 * 543 * The resulting code in the jump slot is: 544 * 545 * sethi %hi(. - .PLT0), %g1 546 * sethi %hix(addr), %g1 547 * xor %g1, %lox(addr), %g1 548 * jmp %g1 549 * nop 550 * nop 551 * nop 552 * nop 553 * 554 */ 555 where[3] = JMP; 556 flush(where, 12); 557 where[2] = XOR | ((~target) & 0x00001fff); 558 flush(where, 8); 559 where[1] = SETHI | HIVAL(~target, 10); 560 flush(where, 4); 561 } else if (offset <= (1L<<32) && offset >= -((1L<<32) - 4)) { 562 /* 563 * We're withing 32-bits -- we can use a direct call insn 564 * 565 * The resulting code in the jump slot is: 566 * 567 * sethi %hi(. - .PLT0), %g1 568 * mov %o7, %g1 569 * call (.+offset) 570 * mov %g1, %o7 571 * nop 572 * nop 573 * nop 574 * nop 575 * 576 */ 577 where[3] = MOV17; 578 flush(where, 12); 579 where[2] = CALL | ((offset >> 4) & 0x3fffffff); 580 flush(where, 8); 581 where[1] = MOV71; 582 flush(where, 4); 583 } else if (offset >= 0 && offset < (1L<<44)) { 584 /* 585 * We're withing 44 bits. We can generate this pattern: 586 * 587 * The resulting code in the jump slot is: 588 * 589 * sethi %hi(. - .PLT0), %g1 590 * sethi %h44(addr), %g1 591 * or %g1, %m44(addr), %g1 592 * sllx %g1, 12, %g1 593 * jmp %g1+%l44(addr) 594 * nop 595 * nop 596 * nop 597 * 598 */ 599 where[4] = JMP | LOVAL(offset); 600 flush(where, 16); 601 where[3] = SLLX | 12; 602 flush(where, 12); 603 where[2] = OR | (((offset) >> 12) & 0x00001fff); 604 flush(where, 8); 605 where[1] = SETHI | HIVAL(offset, 22); 606 flush(where, 4); 607 } else if (offset < 0 && offset > -(1L<<44)) { 608 /* 609 * We're withing 44 bits. We can generate this pattern: 610 * 611 * The resulting code in the jump slot is: 612 * 613 * sethi %hi(. - .PLT0), %g1 614 * sethi %h44(-addr), %g1 615 * xor %g1, %m44(-addr), %g1 616 * sllx %g1, 12, %g1 617 * jmp %g1+%l44(addr) 618 * nop 619 * nop 620 * nop 621 * 622 */ 623 where[4] = JMP | LOVAL(offset); 624 flush(where, 16); 625 where[3] = SLLX | 12; 626 flush(where, 12); 627 where[2] = XOR | (((~offset) >> 12) & 0x00001fff); 628 flush(where, 8); 629 where[1] = SETHI | HIVAL(~offset, 22); 630 flush(where, 4); | 501 where = (Elf_Half *)wherep; 502 offset = ((Elf_Addr)where) - target; 503 if (offset <= (1L<<20) && offset >= -(1L<<20)) { 504 /* 505 * We're within 1MB -- we can use a direct branch insn. 506 * 507 * We can generate this pattern: 508 * 509 * sethi %hi(. - .PLT0), %g1 510 * ba,a %xcc, addr 511 * nop 512 * nop 513 * nop 514 * nop 515 * nop 516 * nop 517 * 518 */ 519 where[1] = BAA | ((offset >> 2) &0x3fffff); 520 flush(where, 4); 521 } else if (target >= 0 && target < (1L<<32)) { 522 /* 523 * We're withing 32-bits of address zero. 524 * 525 * The resulting code in the jump slot is: 526 * 527 * sethi %hi(. - .PLT0), %g1 528 * sethi %hi(addr), %g1 529 * jmp %g1+%lo(addr) 530 * nop 531 * nop 532 * nop 533 * nop 534 * nop 535 * 536 */ 537 where[2] = JMP | LOVAL(target); 538 flush(where, 8); 539 where[1] = SETHI | HIVAL(target, 10); 540 flush(where, 4); 541 } else if (target <= 0 && target > -(1L<<32)) { 542 /* 543 * We're withing 32-bits of address -1. 544 * 545 * The resulting code in the jump slot is: 546 * 547 * sethi %hi(. - .PLT0), %g1 548 * sethi %hix(addr), %g1 549 * xor %g1, %lox(addr), %g1 550 * jmp %g1 551 * nop 552 * nop 553 * nop 554 * nop 555 * 556 */ 557 where[3] = JMP; 558 flush(where, 12); 559 where[2] = XOR | ((~target) & 0x00001fff); 560 flush(where, 8); 561 where[1] = SETHI | HIVAL(~target, 10); 562 flush(where, 4); 563 } else if (offset <= (1L<<32) && offset >= -((1L<<32) - 4)) { 564 /* 565 * We're withing 32-bits -- we can use a direct call 566 * insn 567 * 568 * The resulting code in the jump slot is: 569 * 570 * sethi %hi(. - .PLT0), %g1 571 * mov %o7, %g1 572 * call (.+offset) 573 * mov %g1, %o7 574 * nop 575 * nop 576 * nop 577 * nop 578 * 579 */ 580 where[3] = MOV17; 581 flush(where, 12); 582 where[2] = CALL | ((offset >> 4) & 0x3fffffff); 583 flush(where, 8); 584 where[1] = MOV71; 585 flush(where, 4); 586 } else if (offset >= 0 && offset < (1L<<44)) { 587 /* 588 * We're withing 44 bits. We can generate this pattern: 589 * 590 * The resulting code in the jump slot is: 591 * 592 * sethi %hi(. - .PLT0), %g1 593 * sethi %h44(addr), %g1 594 * or %g1, %m44(addr), %g1 595 * sllx %g1, 12, %g1 596 * jmp %g1+%l44(addr) 597 * nop 598 * nop 599 * nop 600 * 601 */ 602 where[4] = JMP | LOVAL(offset); 603 flush(where, 16); 604 where[3] = SLLX | 12; 605 flush(where, 12); 606 where[2] = OR | (((offset) >> 12) & 0x00001fff); 607 flush(where, 8); 608 where[1] = SETHI | HIVAL(offset, 22); 609 flush(where, 4); 610 } else if (offset < 0 && offset > -(1L<<44)) { 611 /* 612 * We're withing 44 bits. We can generate this pattern: 613 * 614 * The resulting code in the jump slot is: 615 * 616 * sethi %hi(. - .PLT0), %g1 617 * sethi %h44(-addr), %g1 618 * xor %g1, %m44(-addr), %g1 619 * sllx %g1, 12, %g1 620 * jmp %g1+%l44(addr) 621 * nop 622 * nop 623 * nop 624 * 625 */ 626 where[4] = JMP | LOVAL(offset); 627 flush(where, 16); 628 where[3] = SLLX | 12; 629 flush(where, 12); 630 where[2] = XOR | (((~offset) >> 12) & 0x00001fff); 631 flush(where, 8); 632 where[1] = SETHI | HIVAL(~offset, 22); 633 flush(where, 4); 634 } else { 635 /* 636 * We need to load all 64-bits 637 * 638 * The resulting code in the jump slot is: 639 * 640 * sethi %hi(. - .PLT0), %g1 641 * sethi %hh(addr), %g1 642 * sethi %lm(addr), %g5 643 * or %g1, %hm(addr), %g1 644 * sllx %g1, 32, %g1 645 * or %g1, %g5, %g1 646 * jmp %g1+%lo(addr) 647 * nop 648 * 649 */ 650 where[6] = JMP | LOVAL(target); 651 flush(where, 24); 652 where[5] = ORG5; 653 flush(where, 20); 654 where[4] = SLLX | 12; 655 flush(where, 16); 656 where[3] = OR | LOVAL((target) >> 32); 657 flush(where, 12); 658 where[2] = SETHIG5 | HIVAL(target, 10); 659 flush(where, 8); 660 where[1] = SETHI | HIVAL(target, 42); 661 flush(where, 4); 662 } |
631 } else { | 663 } else { |
632 /* 633 * We need to load all 64-bits 634 * 635 * The resulting code in the jump slot is: 636 * 637 * sethi %hi(. - .PLT0), %g1 638 * sethi %hh(addr), %g1 639 * sethi %lm(addr), %g5 640 * or %g1, %hm(addr), %g1 641 * sllx %g1, 32, %g1 642 * or %g1, %g5, %g1 643 * jmp %g1+%lo(addr) 644 * nop 645 * | 664 /* 665 * This is a high PLT slot; the relocation offset specifies a 666 * pointer that needs to be frobbed; no actual code needs to 667 * be modified. The pointer to be calculated needs the addend 668 * added and the reference object relocation base subtraced. |
646 */ | 669 */ |
647 where[6] = JMP | LOVAL(target); 648 flush(where, 24); 649 where[5] = ORG5; 650 flush(where, 20); 651 where[4] = SLLX | 12; 652 flush(where, 16); 653 where[3] = OR | LOVAL((target) >> 32); 654 flush(where, 12); 655 where[2] = SETHIG5 | HIVAL(target, 10); 656 flush(where, 8); 657 where[1] = SETHI | HIVAL(target, 42); 658 flush(where, 4); | 670 *wherep = target + rela->r_addend - 671 (Elf_Addr)refobj->relocbase; |
659 } 660 661 return (target); 662} 663 664/* 665 * Install rtld function call into this PLT slot. 666 */ --- 42 unchanged lines hidden --- | 672 } 673 674 return (target); 675} 676 677/* 678 * Install rtld function call into this PLT slot. 679 */ --- 42 unchanged lines hidden --- |