Deleted Added
full compact
245,246c245,252
< /* XXX */
< printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
---
> /*
> * Add 4 bytes to hit the low half of this 64-bit
> * big-endian address.
> */
> rel->r_offset = s->dofs_offset +
> dofr[j].dofr_offset + 4;
> rel->r_info = ELF32_R_INFO(count + dep->de_global,
> R_PPC_REL32);
426c432,435
< /* XXX */
---
> rel->r_offset = s->dofs_offset +
> dofr[j].dofr_offset;
> rel->r_info = ELF64_R_INFO(count + dep->de_global,
> R_PPC64_REL64);
826a836,845
> /* The sentinel is 'xor r3,r3,r3'. */
> #define DT_OP_XOR_R3 0x7c631a78
>
> #define DT_OP_NOP 0x60000000
> #define DT_OP_BLR 0x4e800020
>
> /* This captures all forms of branching to address. */
> #define DT_IS_BRANCH(inst) ((inst & 0xfc000000) == 0x48000000)
> #define DT_IS_BL(inst) (DT_IS_BRANCH(inst) && (inst & 0x01))
>
832c851,913
< printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
---
> uint32_t *ip;
>
> if ((rela->r_offset & (sizeof (uint32_t) - 1)) != 0)
> return (-1);
>
> /*LINTED*/
> ip = (uint32_t *)(p + rela->r_offset);
>
> /*
> * We only know about some specific relocation types.
> */
> if (GELF_R_TYPE(rela->r_info) != R_PPC_REL24 &&
> GELF_R_TYPE(rela->r_info) != R_PPC_PLTREL24)
> return (-1);
>
> /*
> * We may have already processed this object file in an earlier linker
> * invocation. Check to see if the present instruction sequence matches
> * the one we would install below.
> */
> if (isenabled) {
> if (ip[0] == DT_OP_XOR_R3) {
> (*off) += sizeof (ip[0]);
> return (0);
> }
> } else {
> if (ip[0] == DT_OP_NOP) {
> (*off) += sizeof (ip[0]);
> return (0);
> }
> }
>
> /*
> * We only expect branch to address instructions.
> */
> if (!DT_IS_BRANCH(ip[0])) {
> dt_dprintf("found %x instead of a branch instruction at %llx\n",
> ip[0], (u_longlong_t)rela->r_offset);
> return (-1);
> }
>
> if (isenabled) {
> /*
> * It would necessarily indicate incorrect usage if an is-
> * enabled probe were tail-called so flag that as an error.
> * It's also potentially (very) tricky to handle gracefully,
> * but could be done if this were a desired use scenario.
> */
> if (!DT_IS_BL(ip[0])) {
> dt_dprintf("tail call to is-enabled probe at %llx\n",
> (u_longlong_t)rela->r_offset);
> return (-1);
> }
>
> ip[0] = DT_OP_XOR_R3;
> (*off) += sizeof (ip[0]);
> } else {
> if (DT_IS_BL(ip[0]))
> ip[0] = DT_OP_NOP;
> else
> ip[0] = DT_OP_BLR;
> }
>