Deleted Added
full compact
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 ---