Add support for PIC code.
Add support for ld.so
This commit is contained in:
parent
1849d27507
commit
919c9148f3
71
gnu/usr.bin/ld/arch/arm32/md-static-funcs.c
Normal file
71
gnu/usr.bin/ld/arch/arm32/md-static-funcs.c
Normal file
@ -0,0 +1,71 @@
|
||||
/* $NetBSD: md-static-funcs.c,v 1.1 1997/10/17 21:25:42 mark Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1997 Mark Brinicombe
|
||||
* Copyright (C) 1997 Causality Limited
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Causality Limited.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Called by ld.so when onanating.
|
||||
* This *must* be a static function, so it is not called through a jmpslot.
|
||||
*/
|
||||
|
||||
#define RELOC_32 0x04
|
||||
#define RELOC_JMPSLOT 0x06 /* See note below */
|
||||
#define RELOC_GOT32 0x24
|
||||
|
||||
/*
|
||||
* The value is RELOC_JMPSLOT is special. Really it should be 0x46 i.e.
|
||||
* have the r_jmptable bit set however due to the usage of the
|
||||
* relocation bits outside the linker the r_jmptable is only used
|
||||
* internal to the linker and thus this bit get lost when the
|
||||
* relocations are written out.
|
||||
*/
|
||||
|
||||
static void
|
||||
md_relocate_simple(r, relocation, addr)
|
||||
struct relocation_info *r;
|
||||
long relocation;
|
||||
char *addr;
|
||||
{
|
||||
int index;
|
||||
|
||||
index = r->r_pcrel | (r->r_length << 1) | (r->r_extern << 3)
|
||||
| (r->r_neg << 4) | (r->r_baserel << 5);
|
||||
|
||||
if (index == RELOC_JMPSLOT)
|
||||
*(long *)addr += relocation;
|
||||
else if (index == RELOC_GOT32)
|
||||
*(long *)addr += relocation;
|
||||
else if (index == RELOC_32)
|
||||
*(long *)addr += relocation;
|
||||
|
||||
/* if (r->r_relative)
|
||||
*(long *)addr += relocation;*/
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
/* $NetBSD: md.c,v 1.2 1996/08/21 18:43:29 mark Exp $ */
|
||||
/* $NetBSD: md.c,v 1.3 1997/10/17 21:25:49 mark Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1997 Mark Brinicombe
|
||||
* Copyright (C) 1997 Causality Limited
|
||||
* Copyright (C) 1996 Wolfgang Solfrank
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -14,6 +16,7 @@
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Wolfgang Solfrank.
|
||||
* This product includes software developed by Causality Limited.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
@ -30,7 +33,7 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* First cut for arm32 (currently a simple copy of i386 code) */
|
||||
/* Second cut for arm32 (used to be a simple copy of i386 code) */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <stdio.h>
|
||||
@ -41,9 +44,40 @@
|
||||
#include <a.out.h>
|
||||
#include <stab.h>
|
||||
#include <string.h>
|
||||
#ifdef RTLD
|
||||
#include <machine/sysarch.h>
|
||||
#include <sys/syscall.h>
|
||||
#endif /* RTLD */
|
||||
|
||||
#include "ld.h"
|
||||
|
||||
#ifdef RTLD
|
||||
/*
|
||||
* Flush the instruction cache of the specified address
|
||||
* Some processors have separate instruction caches and
|
||||
* as such may need a flush following a jump slot fixup.
|
||||
*/
|
||||
__inline void
|
||||
iflush(addr, len)
|
||||
void *addr;
|
||||
int len;
|
||||
{
|
||||
struct arm32_sync_icache_args p;
|
||||
|
||||
/*
|
||||
* This is not an efficient way to flush a chunk of memory
|
||||
* if we need to flush lots of small chunks i.e. a jmpslot
|
||||
* per function call.
|
||||
*/
|
||||
p.addr = (u_int)addr;
|
||||
p.len = len;
|
||||
|
||||
__asm __volatile("mov r0, %0; mov r1, %1; swi %2"
|
||||
: : "I" (ARM32_SYNC_ICACHE), "r" (&p), "J" (SYS_sysarch));
|
||||
}
|
||||
#endif /* RTLD */
|
||||
|
||||
|
||||
/*
|
||||
* Get relocation addend corresponding to relocation record RP
|
||||
* from address ADDR
|
||||
@ -67,7 +101,21 @@ unsigned char *addr;
|
||||
break;
|
||||
case 3: /* looks like a special hack for b & bl */
|
||||
rel = (((long)get_long(addr) & 0xffffff) << 8) >> 6;
|
||||
rel -= rp->r_address; /* really? XXX */
|
||||
/*
|
||||
* XXX
|
||||
* Address the addend to be relative to the start of the file
|
||||
* The implecation of doing this is that this adjustment is
|
||||
* done every time the reloc goes through ld.
|
||||
* This means that the adjustment can be applied multiple
|
||||
* times if ld -r is used to do a partial link.
|
||||
*
|
||||
* Solution:
|
||||
* 1. Put a hack in md_relocate so that PC relative
|
||||
* relocations are not modified if
|
||||
* relocatable_output == 1
|
||||
* 2. Modify the assembler to apply this adjustment.
|
||||
*/
|
||||
rel -= rp->r_address;
|
||||
break;
|
||||
default:
|
||||
errx(1, "Unsupported relocation size: %x",
|
||||
@ -79,8 +127,9 @@ unsigned char *addr;
|
||||
/*
|
||||
* Put RELOCATION at ADDR according to relocation record RP.
|
||||
*/
|
||||
static struct relocation_info *rrs_reloc; /* HACK HACK HACK XXX */
|
||||
|
||||
#ifdef HACK
|
||||
static struct relocation_info *rrs_reloc; /* HACK HACK HACK XXX */
|
||||
#endif
|
||||
void
|
||||
md_relocate(rp, relocation, addr, relocatable_output)
|
||||
struct relocation_info *rp;
|
||||
@ -88,13 +137,25 @@ long relocation;
|
||||
unsigned char *addr;
|
||||
int relocatable_output;
|
||||
{
|
||||
/*
|
||||
* XXX
|
||||
* See comments above in md_get_addend
|
||||
*/
|
||||
#ifndef RTLD
|
||||
if (RELOC_PCREL_P(rp) && relocatable_output)
|
||||
relocation += (rp->r_address + pc_relocation);
|
||||
if (rp->r_pcrel && rp->r_length == 2 && relocatable_output)
|
||||
relocation -= rp->r_address;
|
||||
#endif
|
||||
|
||||
#ifdef HACK
|
||||
if (rp == rrs_reloc /* HACK HACK HACK XXX */
|
||||
|| (RELOC_PCREL_P(rp) && relocatable_output)) {
|
||||
rrs_reloc = NULL;
|
||||
return;
|
||||
}
|
||||
rrs_reloc = NULL;
|
||||
|
||||
#endif
|
||||
if (rp->r_neg) /* Not sure, whether this works in all cases XXX */
|
||||
relocation = -relocation;
|
||||
|
||||
@ -108,11 +169,15 @@ int relocatable_output;
|
||||
case 2:
|
||||
put_long(addr, relocation);
|
||||
break;
|
||||
case 3:
|
||||
case 3: {
|
||||
int a;
|
||||
a = (get_long(addr)&0xff000000)
|
||||
| ((relocation&0x3ffffff) >> 2);
|
||||
put_long(addr,
|
||||
(get_long(addr)&0xff000000)
|
||||
| ((relocation&0x3ffffff) >> 2));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
errx(1, "Unsupported relocation size: %x",
|
||||
rp->r_length);
|
||||
@ -129,9 +194,10 @@ md_make_reloc(rp, r, type)
|
||||
struct relocation_info *rp, *r;
|
||||
int type;
|
||||
{
|
||||
#ifdef HACK
|
||||
if (type == RELTYPE_EXTERN)
|
||||
rrs_reloc = rp; /* HACK HACK HACK XXX */
|
||||
|
||||
#endif
|
||||
/* Copy most attributes */
|
||||
r->r_pcrel = rp->r_pcrel;
|
||||
r->r_length = rp->r_length;
|
||||
@ -154,11 +220,21 @@ jmpslot_t *sp;
|
||||
long offset;
|
||||
long index;
|
||||
{
|
||||
u_long fudge = - (offset + 12);
|
||||
|
||||
sp->opcode1 = SAVEPC;
|
||||
sp->opcode2 = CALL | ((fudge >> 2) & 0xffffff);
|
||||
/*
|
||||
* Build the jump slot as follows
|
||||
*
|
||||
* ldr ip, [pc]
|
||||
* add pc, pc, ip
|
||||
* .word new_addr
|
||||
* .word reloc_index
|
||||
*/
|
||||
sp->opcode1 = GETRELADDR;
|
||||
sp->opcode2 = ADDPC;
|
||||
sp->address = - (offset + 12);
|
||||
sp->reloc_index = index;
|
||||
#ifdef RTLD
|
||||
iflush(sp, sizeof(jmpslot_t));
|
||||
#endif /* RTLD */
|
||||
}
|
||||
|
||||
/*
|
||||
@ -166,6 +242,11 @@ long index;
|
||||
* jmpslot at OFFSET to ADDR. Used by `ld' when the SYMBOLIC flag is on,
|
||||
* and by `ld.so' after resolving the symbol.
|
||||
*/
|
||||
|
||||
#ifdef RTLD
|
||||
extern void binder_entry __P((void));
|
||||
#endif
|
||||
|
||||
void
|
||||
md_fix_jmpslot(sp, offset, addr)
|
||||
jmpslot_t *sp;
|
||||
@ -173,12 +254,59 @@ long offset;
|
||||
u_long addr;
|
||||
{
|
||||
/*
|
||||
* Generate the following sequence:
|
||||
* ldr pc, [pc]
|
||||
* For jmpslot 0 (the binder)
|
||||
* generate
|
||||
* sub ip, pc, ip
|
||||
* ldr pc, [pc, #-4]
|
||||
* .word addr
|
||||
* <unused>
|
||||
*
|
||||
* For jump slots generated by the linker (i.e. -Bsymbolic)
|
||||
* build a direct jump to the absolute address
|
||||
* i.e.
|
||||
* ldr pc, [pc]
|
||||
* <unused>
|
||||
* .word new_addr
|
||||
* <unused>
|
||||
*
|
||||
* For other jump slots generated (fixed by ld.so)
|
||||
* just modify the address offset since the slot
|
||||
* will have been created with md_make_jmpslot().
|
||||
* i.e.
|
||||
* ldr ip, [pc]
|
||||
* add pc, pc, ip
|
||||
* .word new_rel_addr
|
||||
* <unused>
|
||||
*/
|
||||
sp->opcode1 = JUMP;
|
||||
sp->reloc_index = addr;
|
||||
#ifdef RTLD
|
||||
if ((void *)addr == binder_entry) {
|
||||
#else
|
||||
if (offset == 0) {
|
||||
#endif
|
||||
/* Build binder jump slot */
|
||||
sp->opcode1 = GETSLOTADDR;
|
||||
sp->opcode2 = LDRPCADDR;
|
||||
sp->address = addr;
|
||||
#ifdef RTLD
|
||||
iflush(sp, sizeof(jmpslot_t));
|
||||
#endif /* RTLD */
|
||||
} else {
|
||||
#ifdef RTLD
|
||||
/*
|
||||
* Change the relative offset to the binder
|
||||
* into a relative offset to the function
|
||||
*/
|
||||
sp->address = (addr - (long)sp - 12);
|
||||
/* iflush(sp, sizeof(jmpslot_t));*/
|
||||
#else
|
||||
/*
|
||||
* Build a direct transfer jump slot
|
||||
* as we not doing a run time fixup.
|
||||
*/
|
||||
sp->opcode1 = JUMP;
|
||||
sp->address = addr;
|
||||
#endif /* RTLD */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -212,6 +340,7 @@ int type;
|
||||
r->r_baserel = 1;
|
||||
r->r_jmptable = 0;
|
||||
r->r_relative = 0;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@ -236,6 +365,9 @@ long *savep;
|
||||
{
|
||||
*savep = *(long *)where;
|
||||
*(long *)where = TRAP;
|
||||
#ifdef RTLD
|
||||
iflush((long *)where, sizeof(long));
|
||||
#endif /* RTLD */
|
||||
}
|
||||
|
||||
#ifndef RTLD
|
||||
@ -255,7 +387,7 @@ int magic, flags;
|
||||
if (!(link_mode & SHAREABLE))
|
||||
hp->a_entry = PAGSIZ;
|
||||
}
|
||||
#endif /* RTLD */
|
||||
#endif /* RTLD */
|
||||
|
||||
|
||||
#ifdef NEED_SWAP
|
||||
@ -283,49 +415,6 @@ struct exec *h;
|
||||
swap_longs((long *)h + skip, sizeof(*h)/sizeof(long) - skip);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
md_swapin_reloc(r, n)
|
||||
struct relocation_info *r;
|
||||
int n;
|
||||
{
|
||||
int bits;
|
||||
|
||||
for (; n; n--, r++) {
|
||||
r->r_address = md_swap_long(r->r_address);
|
||||
bits = ((int *)r)[1];
|
||||
r->r_symbolnum = md_swap_long(bits) & 0x00ffffff;
|
||||
r->r_pcrel = (bits & 1);
|
||||
r->r_length = (bits >> 1) & 3;
|
||||
r->r_extern = (bits >> 3) & 1;
|
||||
r->r_neg = (bits >> 4) & 1;
|
||||
r->r_baserel = (bits >> 5) & 1;
|
||||
r->r_jmptable = (bits >> 6) & 1;
|
||||
r->r_relative = (bits >> 7) & 1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
md_swapout_reloc(r, n)
|
||||
struct relocation_info *r;
|
||||
int n;
|
||||
{
|
||||
int bits;
|
||||
|
||||
for (; n; n--, r++) {
|
||||
r->r_address = md_swap_long(r->r_address);
|
||||
bits = md_swap_long(r->r_symbolnum) & 0xffffff00;
|
||||
bits |= (r->r_pcrel & 1);
|
||||
bits |= (r->r_length & 3) << 1;
|
||||
bits |= (r->r_extern & 1) << 3;
|
||||
bits |= (r->r_neg & 1) << 4;
|
||||
bits |= (r->r_baserel & 1) << 5;
|
||||
bits |= (r->r_jmptable & 1) << 6;
|
||||
bits |= (r->r_relative & 1) << 7;
|
||||
((int *)r)[1] = bits;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
md_swapout_jmpslot(j, n)
|
||||
jmpslot_t *j;
|
||||
@ -339,3 +428,75 @@ int n;
|
||||
}
|
||||
|
||||
#endif /* NEED_SWAP */
|
||||
|
||||
/*
|
||||
* md_swapin_reloc()
|
||||
*
|
||||
* As well as provide bit swapping for cross compiling with different
|
||||
* endianness we need to munge some of the reloc bits.
|
||||
* This munging is due to the assemble packing all the PIC related
|
||||
* relocs so that only 1 extra bit in the reloc structure is needed
|
||||
* The result is that jmpslot branches are packed as a baserel branch
|
||||
* Spot this case and internally use a jmptable bit.
|
||||
*/
|
||||
|
||||
void
|
||||
md_swapin_reloc(r, n)
|
||||
struct relocation_info *r;
|
||||
int n;
|
||||
{
|
||||
int bits;
|
||||
|
||||
for (; n; n--, r++) {
|
||||
#ifdef NEED_SWAP
|
||||
r->r_address = md_swap_long(r->r_address);
|
||||
bits = ((int *)r)[1];
|
||||
r->r_symbolnum = md_swap_long(bits) & 0x00ffffff;
|
||||
r->r_pcrel = (bits & 1);
|
||||
r->r_length = (bits >> 1) & 3;
|
||||
r->r_extern = (bits >> 3) & 1;
|
||||
r->r_neg = (bits >> 4) & 1;
|
||||
r->r_baserel = (bits >> 5) & 1;
|
||||
r->r_jmptable = (bits >> 6) & 1;
|
||||
r->r_relative = (bits >> 7) & 1;
|
||||
#endif
|
||||
/* Look for PIC relocation */
|
||||
if (r->r_baserel) {
|
||||
/* Look for baserel branch */
|
||||
if (r->r_length == 3 && r->r_pcrel == 0) {
|
||||
r->r_jmptable = 1;
|
||||
}
|
||||
/* Look for GOTPC reloc */
|
||||
if (r->r_length == 2 && r->r_pcrel == 1)
|
||||
r->r_baserel = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
md_swapout_reloc(r, n)
|
||||
struct relocation_info *r;
|
||||
int n;
|
||||
{
|
||||
int bits;
|
||||
|
||||
for (; n; n--, r++) {
|
||||
/* Look for jmptable relocation */
|
||||
if (r->r_jmptable && r->r_pcrel == 0 && r->r_length == 3) {
|
||||
r->r_jmptable = 0;
|
||||
r->r_baserel = 1;
|
||||
}
|
||||
#ifdef NEED_SWAP
|
||||
r->r_address = md_swap_long(r->r_address);
|
||||
bits = md_swap_long(r->r_symbolnum) & 0xffffff00;
|
||||
bits |= (r->r_pcrel & 1);
|
||||
bits |= (r->r_length & 3) << 1;
|
||||
bits |= (r->r_extern & 1) << 3;
|
||||
bits |= (r->r_neg & 1) << 4;
|
||||
bits |= (r->r_baserel & 1) << 5;
|
||||
bits |= (r->r_jmptable & 1) << 6;
|
||||
bits |= (r->r_relative & 1) << 7;
|
||||
((int *)r)[1] = bits;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,10 @@
|
||||
/* $NetBSD: md.h,v 1.1 1996/05/17 21:51:10 mark Exp $ */
|
||||
/* $NetBSD: md.h,v 1.2 1997/10/17 21:25:54 mark Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1996 Wolfgang Solfrank
|
||||
* Copyright (c) 1997 Mark Brinicombe
|
||||
* Copyright (c) 1997 Causality Limited
|
||||
* Copyright (c) 1993 Paul Kranenburg
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -13,10 +16,10 @@
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Wolfgang Solfrank.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* This product includes software developed by Paul Kranenburg.
|
||||
* This product includes software developed by Causality Limited
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
@ -30,16 +33,24 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* First cut for arm32 */
|
||||
/* Second cut for arm32 */
|
||||
|
||||
#if defined(CROSS_LINKER) && defined(XHOST) && XHOST==sparc
|
||||
#define NEED_SWAP
|
||||
#endif
|
||||
|
||||
#define MAX_ALIGNMENT (sizeof (long))
|
||||
|
||||
#ifdef NetBSD
|
||||
#define PAGSIZ __LDPGSZ
|
||||
#else
|
||||
#define PAGSIZ 4096
|
||||
#endif
|
||||
|
||||
#define N_SET_FLAG(ex,f) (N_SETMAGIC(ex, \
|
||||
N_GETMAGIC(ex), \
|
||||
MID_MACHINE, \
|
||||
N_GETFLAG(ex)|(f)))
|
||||
N_GETMAGIC(ex), \
|
||||
MID_MACHINE, \
|
||||
N_GETFLAG(ex)|(f)))
|
||||
|
||||
#define N_IS_DYNAMIC(ex) ((N_GETFLAG(ex) & EX_DYNAMIC))
|
||||
|
||||
@ -59,10 +70,10 @@
|
||||
: (TEXT_START(ex) + (ex).a_text + __LDPGSZ - 1) & ~(__LDPGSZ - 1))
|
||||
#endif
|
||||
|
||||
#define RELOC_STATICS_THROUGH_GOT_P(r) 0 /* ??? */
|
||||
#define JMPSLOT_NEEDS_RELOC 1
|
||||
#define RELOC_STATICS_THROUGH_GOT_P(r) (1)
|
||||
#define JMPSLOT_NEEDS_RELOC (1)
|
||||
|
||||
#define md_got_reloc(r) 0
|
||||
#define md_got_reloc(r) (-r->r_address)
|
||||
|
||||
#define md_get_rt_segment_addend(r,a) md_get_addend(r,a)
|
||||
|
||||
@ -71,16 +82,26 @@
|
||||
typedef long got_t;
|
||||
|
||||
typedef struct jmpslot {
|
||||
u_long opcode1; /* mov ip, lr */
|
||||
u_long opcode2; /* call */
|
||||
u_long reloc_index; /* used as destination after fixup */
|
||||
u_long opcode1; /* ldr ip, [pc] */
|
||||
u_long opcode2; /* add pc, pc, ip */
|
||||
u_long address; /* binder/function address */
|
||||
u_long reloc_index; /* relocation index */
|
||||
#define JMPSLOT_RELOC_MASK 0xffffffff
|
||||
} jmpslot_t;
|
||||
|
||||
#define SAVEPC 0xe1a0c00e /* MOV ip, lr */
|
||||
#define CALL 0xeb000000 /* CALL opcode */
|
||||
#define JUMP 0xe59ff000 /* LDR pc, [pc] (used as JMP) */
|
||||
#define TRAP 0xe6000010 /* Undefined Instruction (used for bpt) */
|
||||
#define TRAP 0xe6000011 /* Undefined Instruction (used for bpt) */
|
||||
|
||||
#define GETSLOTADDR 0xe04fc00c /* sub ip, pc, ip */
|
||||
#define ADDPC 0xe08ff00c /* add pc, pc, ip */
|
||||
#define LDRPCADDR 0xe51ff004 /* ldr pc, [pc, #-4] */
|
||||
#define GETRELADDR 0xe59fc000 /* ldr ip, [pc] */
|
||||
|
||||
|
||||
void md_swapin_reloc __P((struct relocation_info *, int));
|
||||
void md_swapout_reloc __P((struct relocation_info *, int));
|
||||
|
||||
/*
|
||||
* Byte swap defs for cross linking
|
||||
@ -94,8 +115,6 @@ typedef struct jmpslot {
|
||||
#define md_swapout_symbols(s,n)
|
||||
#define md_swapin_zsymbols(s,n)
|
||||
#define md_swapout_zsymbols(s,n)
|
||||
#define md_swapin_reloc(r,n)
|
||||
#define md_swapout_reloc(r,n)
|
||||
#define md_swapin__dynamic(l)
|
||||
#define md_swapout__dynamic(l)
|
||||
#define md_swapin_section_dispatch_table(l)
|
||||
@ -117,30 +136,30 @@ typedef struct jmpslot {
|
||||
|
||||
#define get_byte(p) ( ((unsigned char *)(p))[0] )
|
||||
|
||||
#define get_short(p) ( ( ((unsigned char *)(p))[1] << 8) | \
|
||||
( ((unsigned char *)(p))[0] ) \
|
||||
#define get_short(p) ( ( ((unsigned char *)(p))[0] << 8) | \
|
||||
( ((unsigned char *)(p))[1] ) \
|
||||
)
|
||||
|
||||
#define get_long(p) ( ( ((unsigned char *)(p))[3] << 24) | \
|
||||
( ((unsigned char *)(p))[2] << 16) | \
|
||||
( ((unsigned char *)(p))[1] << 8 ) | \
|
||||
( ((unsigned char *)(p))[0] ) \
|
||||
#define get_long(p) ( ( ((unsigned char *)(p))[0] << 24) | \
|
||||
( ((unsigned char *)(p))[1] << 16) | \
|
||||
( ((unsigned char *)(p))[2] << 8 ) | \
|
||||
( ((unsigned char *)(p))[3] ) \
|
||||
)
|
||||
|
||||
#define put_byte(p, v) { ((unsigned char *)(p))[0] = ((unsigned long)(v)); }
|
||||
|
||||
#define put_short(p, v) { ((unsigned char *)(p))[1] = \
|
||||
#define put_short(p, v) { ((unsigned char *)(p))[0] = \
|
||||
((((unsigned long)(v)) >> 8) & 0xff); \
|
||||
((unsigned char *)(p))[0] = \
|
||||
((unsigned char *)(p))[1] = \
|
||||
((((unsigned long)(v)) ) & 0xff); }
|
||||
|
||||
#define put_long(p, v) { ((unsigned char *)(p))[3] = \
|
||||
#define put_long(p, v) { ((unsigned char *)(p))[0] = \
|
||||
((((unsigned long)(v)) >> 24) & 0xff); \
|
||||
((unsigned char *)(p))[2] = \
|
||||
((((unsigned long)(v)) >> 16) & 0xff); \
|
||||
((unsigned char *)(p))[1] = \
|
||||
((((unsigned long)(v)) >> 16) & 0xff); \
|
||||
((unsigned char *)(p))[2] = \
|
||||
((((unsigned long)(v)) >> 8) & 0xff); \
|
||||
((unsigned char *)(p))[0] = \
|
||||
((unsigned char *)(p))[3] = \
|
||||
((((unsigned long)(v)) ) & 0xff); }
|
||||
|
||||
#ifdef NEED_SWAP
|
||||
@ -149,8 +168,6 @@ typedef struct jmpslot {
|
||||
|
||||
void md_swapin_exec_hdr __P((struct exec *));
|
||||
void md_swapout_exec_hdr __P((struct exec *));
|
||||
void md_swapin_reloc __P((struct relocation_info *, int));
|
||||
void md_swapout_reloc __P((struct relocation_info *, int));
|
||||
void md_swapout_jmpslot __P((jmpslot_t *, int));
|
||||
|
||||
#define md_swapin_symbols(s,n) swap_symbols(s,n)
|
||||
@ -220,8 +237,24 @@ void md_swapout_jmpslot __P((jmpslot_t *, int));
|
||||
#define RELOC_COPY_P(r) (0)
|
||||
#define RELOC_LAZY_P(r) ((r)->r_jmptable)
|
||||
|
||||
#define CHECK_GOT_RELOC(r) RELOC_PCREL_P(r)
|
||||
#define RELOC_PIC_TYPE(r) ((r)->r_baserel?\
|
||||
PIC_TYPE_LARGE:PIC_TYPE_NONE)
|
||||
/*#define CHECK_GOT_RELOC(r) RELOC_PCREL_P(r)*/
|
||||
#define CHECK_GOT_RELOC(r) (((r)->r_pcrel == 1) && ((r)->r_length == 2))
|
||||
|
||||
/*
|
||||
* Define the range of usable Global Offset Table offsets
|
||||
* when using arm LDR instructions with 12 bit offset (-4092 -> 4092);
|
||||
* this is the case if the object files are compiles with -fpic'.
|
||||
* IF a "large" model is used (i.e. -fPIC'), .word instructions
|
||||
* are generated instead providing 32-bit addressability of the GOT table.
|
||||
*/
|
||||
|
||||
#define MAX_GOTOFF(t) ((t) == PIC_TYPE_SMALL ? 4092 : LONG_MAX)
|
||||
#define MIN_GOTOFF(t) ((t) == PIC_TYPE_SMALL ? -4092 : LONG_MIN)
|
||||
|
||||
#define RELOC_PIC_TYPE(r) ((r)->r_baserel ? \
|
||||
((r)->r_length == 1 ? \
|
||||
PIC_TYPE_SMALL : \
|
||||
PIC_TYPE_LARGE) : \
|
||||
PIC_TYPE_NONE)
|
||||
|
||||
#define RELOC_INIT_SEGMENT_RELOC(r)
|
||||
|
92
gnu/usr.bin/ld/arch/arm32/mdprologue.S
Normal file
92
gnu/usr.bin/ld/arch/arm32/mdprologue.S
Normal file
@ -0,0 +1,92 @@
|
||||
/* $NetBSD: mdprologue.S,v 1.1 1997/10/17 21:25:59 mark Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1996 Wolfgang Solfrank
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Wolfgang Solfrank.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* arm run-time link editor entry points.
|
||||
*/
|
||||
|
||||
#include <machine/asm.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
.text
|
||||
|
||||
/*
|
||||
* _rtl(int version, struct crt_ldso *crtp)
|
||||
*/
|
||||
|
||||
.align 0
|
||||
.type _rtl,#function
|
||||
_rtl: @ crt0 calls us here
|
||||
mov ip, sp @ Allocate stack frame
|
||||
stmfd sp!, {sl, fp, ip, lr, pc}
|
||||
sub fp, ip, #4
|
||||
|
||||
ldr r3, [r1, #0] @ base address of ld.so (first field)
|
||||
@ setup arguments for rtld()
|
||||
ldr sl, GOTaddr @ get pc-rel offset for GOT
|
||||
add sl, pc, sl @ here is the GOT
|
||||
L1:
|
||||
ldr r2, DYNAMICaddr
|
||||
ldr r2, [sl, r2] @ 1st entry in GOT is our __DYNAMIC
|
||||
add r2, r2, r3 @ add load address
|
||||
ldr lr, rtldaddr @ get GOT offset for function
|
||||
ldr lr, [sl, lr] @ get function address
|
||||
add r3, lr, r3 @ and relocate
|
||||
mov lr, pc
|
||||
mov pc, r3 @ _rtld(version, crtp, DYNAMIC)
|
||||
|
||||
ldmea fp, {sl, fp, ip, pc}
|
||||
|
||||
.align 0
|
||||
GOTaddr:
|
||||
.word __GLOBAL_OFFSET_TABLE_ + (. - (L1+4) )
|
||||
DYNAMICaddr:
|
||||
.word __DYNAMIC
|
||||
rtldaddr:
|
||||
.word _rtld
|
||||
|
||||
@ First call to a procedure generally comes through here for
|
||||
@ binding.
|
||||
|
||||
ENTRY(binder_entry)
|
||||
stmfd sp!, {r0-fp, ip, lr, pc} @ save all regs in standard frame
|
||||
@ (ip and lr to be fixed later)
|
||||
add fp, sp, #(15-1)*4 @ get new fp
|
||||
add r0, fp, #4 @ compute old sp
|
||||
str r0, [fp, #-8] @ fixup saved ip
|
||||
|
||||
sub r0, ip, #(8+12) @ make it point to the jmpslot
|
||||
|
||||
bl _binder
|
||||
str r0, [fp] @ return value from _binder()
|
||||
@ == actual address of function
|
||||
ldmfa fp, {r0-fp, sp, lr, pc} @ restore regs
|
71
libexec/ld.aout_so/arch/arm32/md-static-funcs.c
Normal file
71
libexec/ld.aout_so/arch/arm32/md-static-funcs.c
Normal file
@ -0,0 +1,71 @@
|
||||
/* $NetBSD: md-static-funcs.c,v 1.1 1997/10/17 21:25:42 mark Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1997 Mark Brinicombe
|
||||
* Copyright (C) 1997 Causality Limited
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Causality Limited.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Called by ld.so when onanating.
|
||||
* This *must* be a static function, so it is not called through a jmpslot.
|
||||
*/
|
||||
|
||||
#define RELOC_32 0x04
|
||||
#define RELOC_JMPSLOT 0x06 /* See note below */
|
||||
#define RELOC_GOT32 0x24
|
||||
|
||||
/*
|
||||
* The value is RELOC_JMPSLOT is special. Really it should be 0x46 i.e.
|
||||
* have the r_jmptable bit set however due to the usage of the
|
||||
* relocation bits outside the linker the r_jmptable is only used
|
||||
* internal to the linker and thus this bit get lost when the
|
||||
* relocations are written out.
|
||||
*/
|
||||
|
||||
static void
|
||||
md_relocate_simple(r, relocation, addr)
|
||||
struct relocation_info *r;
|
||||
long relocation;
|
||||
char *addr;
|
||||
{
|
||||
int index;
|
||||
|
||||
index = r->r_pcrel | (r->r_length << 1) | (r->r_extern << 3)
|
||||
| (r->r_neg << 4) | (r->r_baserel << 5);
|
||||
|
||||
if (index == RELOC_JMPSLOT)
|
||||
*(long *)addr += relocation;
|
||||
else if (index == RELOC_GOT32)
|
||||
*(long *)addr += relocation;
|
||||
else if (index == RELOC_32)
|
||||
*(long *)addr += relocation;
|
||||
|
||||
/* if (r->r_relative)
|
||||
*(long *)addr += relocation;*/
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
/* $NetBSD: md.c,v 1.2 1996/08/21 18:43:29 mark Exp $ */
|
||||
/* $NetBSD: md.c,v 1.3 1997/10/17 21:25:49 mark Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1997 Mark Brinicombe
|
||||
* Copyright (C) 1997 Causality Limited
|
||||
* Copyright (C) 1996 Wolfgang Solfrank
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -14,6 +16,7 @@
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Wolfgang Solfrank.
|
||||
* This product includes software developed by Causality Limited.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
@ -30,7 +33,7 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* First cut for arm32 (currently a simple copy of i386 code) */
|
||||
/* Second cut for arm32 (used to be a simple copy of i386 code) */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <stdio.h>
|
||||
@ -41,9 +44,40 @@
|
||||
#include <a.out.h>
|
||||
#include <stab.h>
|
||||
#include <string.h>
|
||||
#ifdef RTLD
|
||||
#include <machine/sysarch.h>
|
||||
#include <sys/syscall.h>
|
||||
#endif /* RTLD */
|
||||
|
||||
#include "ld.h"
|
||||
|
||||
#ifdef RTLD
|
||||
/*
|
||||
* Flush the instruction cache of the specified address
|
||||
* Some processors have separate instruction caches and
|
||||
* as such may need a flush following a jump slot fixup.
|
||||
*/
|
||||
__inline void
|
||||
iflush(addr, len)
|
||||
void *addr;
|
||||
int len;
|
||||
{
|
||||
struct arm32_sync_icache_args p;
|
||||
|
||||
/*
|
||||
* This is not an efficient way to flush a chunk of memory
|
||||
* if we need to flush lots of small chunks i.e. a jmpslot
|
||||
* per function call.
|
||||
*/
|
||||
p.addr = (u_int)addr;
|
||||
p.len = len;
|
||||
|
||||
__asm __volatile("mov r0, %0; mov r1, %1; swi %2"
|
||||
: : "I" (ARM32_SYNC_ICACHE), "r" (&p), "J" (SYS_sysarch));
|
||||
}
|
||||
#endif /* RTLD */
|
||||
|
||||
|
||||
/*
|
||||
* Get relocation addend corresponding to relocation record RP
|
||||
* from address ADDR
|
||||
@ -67,7 +101,21 @@ unsigned char *addr;
|
||||
break;
|
||||
case 3: /* looks like a special hack for b & bl */
|
||||
rel = (((long)get_long(addr) & 0xffffff) << 8) >> 6;
|
||||
rel -= rp->r_address; /* really? XXX */
|
||||
/*
|
||||
* XXX
|
||||
* Address the addend to be relative to the start of the file
|
||||
* The implecation of doing this is that this adjustment is
|
||||
* done every time the reloc goes through ld.
|
||||
* This means that the adjustment can be applied multiple
|
||||
* times if ld -r is used to do a partial link.
|
||||
*
|
||||
* Solution:
|
||||
* 1. Put a hack in md_relocate so that PC relative
|
||||
* relocations are not modified if
|
||||
* relocatable_output == 1
|
||||
* 2. Modify the assembler to apply this adjustment.
|
||||
*/
|
||||
rel -= rp->r_address;
|
||||
break;
|
||||
default:
|
||||
errx(1, "Unsupported relocation size: %x",
|
||||
@ -79,8 +127,9 @@ unsigned char *addr;
|
||||
/*
|
||||
* Put RELOCATION at ADDR according to relocation record RP.
|
||||
*/
|
||||
static struct relocation_info *rrs_reloc; /* HACK HACK HACK XXX */
|
||||
|
||||
#ifdef HACK
|
||||
static struct relocation_info *rrs_reloc; /* HACK HACK HACK XXX */
|
||||
#endif
|
||||
void
|
||||
md_relocate(rp, relocation, addr, relocatable_output)
|
||||
struct relocation_info *rp;
|
||||
@ -88,13 +137,25 @@ long relocation;
|
||||
unsigned char *addr;
|
||||
int relocatable_output;
|
||||
{
|
||||
/*
|
||||
* XXX
|
||||
* See comments above in md_get_addend
|
||||
*/
|
||||
#ifndef RTLD
|
||||
if (RELOC_PCREL_P(rp) && relocatable_output)
|
||||
relocation += (rp->r_address + pc_relocation);
|
||||
if (rp->r_pcrel && rp->r_length == 2 && relocatable_output)
|
||||
relocation -= rp->r_address;
|
||||
#endif
|
||||
|
||||
#ifdef HACK
|
||||
if (rp == rrs_reloc /* HACK HACK HACK XXX */
|
||||
|| (RELOC_PCREL_P(rp) && relocatable_output)) {
|
||||
rrs_reloc = NULL;
|
||||
return;
|
||||
}
|
||||
rrs_reloc = NULL;
|
||||
|
||||
#endif
|
||||
if (rp->r_neg) /* Not sure, whether this works in all cases XXX */
|
||||
relocation = -relocation;
|
||||
|
||||
@ -108,11 +169,15 @@ int relocatable_output;
|
||||
case 2:
|
||||
put_long(addr, relocation);
|
||||
break;
|
||||
case 3:
|
||||
case 3: {
|
||||
int a;
|
||||
a = (get_long(addr)&0xff000000)
|
||||
| ((relocation&0x3ffffff) >> 2);
|
||||
put_long(addr,
|
||||
(get_long(addr)&0xff000000)
|
||||
| ((relocation&0x3ffffff) >> 2));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
errx(1, "Unsupported relocation size: %x",
|
||||
rp->r_length);
|
||||
@ -129,9 +194,10 @@ md_make_reloc(rp, r, type)
|
||||
struct relocation_info *rp, *r;
|
||||
int type;
|
||||
{
|
||||
#ifdef HACK
|
||||
if (type == RELTYPE_EXTERN)
|
||||
rrs_reloc = rp; /* HACK HACK HACK XXX */
|
||||
|
||||
#endif
|
||||
/* Copy most attributes */
|
||||
r->r_pcrel = rp->r_pcrel;
|
||||
r->r_length = rp->r_length;
|
||||
@ -154,11 +220,21 @@ jmpslot_t *sp;
|
||||
long offset;
|
||||
long index;
|
||||
{
|
||||
u_long fudge = - (offset + 12);
|
||||
|
||||
sp->opcode1 = SAVEPC;
|
||||
sp->opcode2 = CALL | ((fudge >> 2) & 0xffffff);
|
||||
/*
|
||||
* Build the jump slot as follows
|
||||
*
|
||||
* ldr ip, [pc]
|
||||
* add pc, pc, ip
|
||||
* .word new_addr
|
||||
* .word reloc_index
|
||||
*/
|
||||
sp->opcode1 = GETRELADDR;
|
||||
sp->opcode2 = ADDPC;
|
||||
sp->address = - (offset + 12);
|
||||
sp->reloc_index = index;
|
||||
#ifdef RTLD
|
||||
iflush(sp, sizeof(jmpslot_t));
|
||||
#endif /* RTLD */
|
||||
}
|
||||
|
||||
/*
|
||||
@ -166,6 +242,11 @@ long index;
|
||||
* jmpslot at OFFSET to ADDR. Used by `ld' when the SYMBOLIC flag is on,
|
||||
* and by `ld.so' after resolving the symbol.
|
||||
*/
|
||||
|
||||
#ifdef RTLD
|
||||
extern void binder_entry __P((void));
|
||||
#endif
|
||||
|
||||
void
|
||||
md_fix_jmpslot(sp, offset, addr)
|
||||
jmpslot_t *sp;
|
||||
@ -173,12 +254,59 @@ long offset;
|
||||
u_long addr;
|
||||
{
|
||||
/*
|
||||
* Generate the following sequence:
|
||||
* ldr pc, [pc]
|
||||
* For jmpslot 0 (the binder)
|
||||
* generate
|
||||
* sub ip, pc, ip
|
||||
* ldr pc, [pc, #-4]
|
||||
* .word addr
|
||||
* <unused>
|
||||
*
|
||||
* For jump slots generated by the linker (i.e. -Bsymbolic)
|
||||
* build a direct jump to the absolute address
|
||||
* i.e.
|
||||
* ldr pc, [pc]
|
||||
* <unused>
|
||||
* .word new_addr
|
||||
* <unused>
|
||||
*
|
||||
* For other jump slots generated (fixed by ld.so)
|
||||
* just modify the address offset since the slot
|
||||
* will have been created with md_make_jmpslot().
|
||||
* i.e.
|
||||
* ldr ip, [pc]
|
||||
* add pc, pc, ip
|
||||
* .word new_rel_addr
|
||||
* <unused>
|
||||
*/
|
||||
sp->opcode1 = JUMP;
|
||||
sp->reloc_index = addr;
|
||||
#ifdef RTLD
|
||||
if ((void *)addr == binder_entry) {
|
||||
#else
|
||||
if (offset == 0) {
|
||||
#endif
|
||||
/* Build binder jump slot */
|
||||
sp->opcode1 = GETSLOTADDR;
|
||||
sp->opcode2 = LDRPCADDR;
|
||||
sp->address = addr;
|
||||
#ifdef RTLD
|
||||
iflush(sp, sizeof(jmpslot_t));
|
||||
#endif /* RTLD */
|
||||
} else {
|
||||
#ifdef RTLD
|
||||
/*
|
||||
* Change the relative offset to the binder
|
||||
* into a relative offset to the function
|
||||
*/
|
||||
sp->address = (addr - (long)sp - 12);
|
||||
/* iflush(sp, sizeof(jmpslot_t));*/
|
||||
#else
|
||||
/*
|
||||
* Build a direct transfer jump slot
|
||||
* as we not doing a run time fixup.
|
||||
*/
|
||||
sp->opcode1 = JUMP;
|
||||
sp->address = addr;
|
||||
#endif /* RTLD */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -212,6 +340,7 @@ int type;
|
||||
r->r_baserel = 1;
|
||||
r->r_jmptable = 0;
|
||||
r->r_relative = 0;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@ -236,6 +365,9 @@ long *savep;
|
||||
{
|
||||
*savep = *(long *)where;
|
||||
*(long *)where = TRAP;
|
||||
#ifdef RTLD
|
||||
iflush((long *)where, sizeof(long));
|
||||
#endif /* RTLD */
|
||||
}
|
||||
|
||||
#ifndef RTLD
|
||||
@ -255,7 +387,7 @@ int magic, flags;
|
||||
if (!(link_mode & SHAREABLE))
|
||||
hp->a_entry = PAGSIZ;
|
||||
}
|
||||
#endif /* RTLD */
|
||||
#endif /* RTLD */
|
||||
|
||||
|
||||
#ifdef NEED_SWAP
|
||||
@ -283,49 +415,6 @@ struct exec *h;
|
||||
swap_longs((long *)h + skip, sizeof(*h)/sizeof(long) - skip);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
md_swapin_reloc(r, n)
|
||||
struct relocation_info *r;
|
||||
int n;
|
||||
{
|
||||
int bits;
|
||||
|
||||
for (; n; n--, r++) {
|
||||
r->r_address = md_swap_long(r->r_address);
|
||||
bits = ((int *)r)[1];
|
||||
r->r_symbolnum = md_swap_long(bits) & 0x00ffffff;
|
||||
r->r_pcrel = (bits & 1);
|
||||
r->r_length = (bits >> 1) & 3;
|
||||
r->r_extern = (bits >> 3) & 1;
|
||||
r->r_neg = (bits >> 4) & 1;
|
||||
r->r_baserel = (bits >> 5) & 1;
|
||||
r->r_jmptable = (bits >> 6) & 1;
|
||||
r->r_relative = (bits >> 7) & 1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
md_swapout_reloc(r, n)
|
||||
struct relocation_info *r;
|
||||
int n;
|
||||
{
|
||||
int bits;
|
||||
|
||||
for (; n; n--, r++) {
|
||||
r->r_address = md_swap_long(r->r_address);
|
||||
bits = md_swap_long(r->r_symbolnum) & 0xffffff00;
|
||||
bits |= (r->r_pcrel & 1);
|
||||
bits |= (r->r_length & 3) << 1;
|
||||
bits |= (r->r_extern & 1) << 3;
|
||||
bits |= (r->r_neg & 1) << 4;
|
||||
bits |= (r->r_baserel & 1) << 5;
|
||||
bits |= (r->r_jmptable & 1) << 6;
|
||||
bits |= (r->r_relative & 1) << 7;
|
||||
((int *)r)[1] = bits;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
md_swapout_jmpslot(j, n)
|
||||
jmpslot_t *j;
|
||||
@ -339,3 +428,75 @@ int n;
|
||||
}
|
||||
|
||||
#endif /* NEED_SWAP */
|
||||
|
||||
/*
|
||||
* md_swapin_reloc()
|
||||
*
|
||||
* As well as provide bit swapping for cross compiling with different
|
||||
* endianness we need to munge some of the reloc bits.
|
||||
* This munging is due to the assemble packing all the PIC related
|
||||
* relocs so that only 1 extra bit in the reloc structure is needed
|
||||
* The result is that jmpslot branches are packed as a baserel branch
|
||||
* Spot this case and internally use a jmptable bit.
|
||||
*/
|
||||
|
||||
void
|
||||
md_swapin_reloc(r, n)
|
||||
struct relocation_info *r;
|
||||
int n;
|
||||
{
|
||||
int bits;
|
||||
|
||||
for (; n; n--, r++) {
|
||||
#ifdef NEED_SWAP
|
||||
r->r_address = md_swap_long(r->r_address);
|
||||
bits = ((int *)r)[1];
|
||||
r->r_symbolnum = md_swap_long(bits) & 0x00ffffff;
|
||||
r->r_pcrel = (bits & 1);
|
||||
r->r_length = (bits >> 1) & 3;
|
||||
r->r_extern = (bits >> 3) & 1;
|
||||
r->r_neg = (bits >> 4) & 1;
|
||||
r->r_baserel = (bits >> 5) & 1;
|
||||
r->r_jmptable = (bits >> 6) & 1;
|
||||
r->r_relative = (bits >> 7) & 1;
|
||||
#endif
|
||||
/* Look for PIC relocation */
|
||||
if (r->r_baserel) {
|
||||
/* Look for baserel branch */
|
||||
if (r->r_length == 3 && r->r_pcrel == 0) {
|
||||
r->r_jmptable = 1;
|
||||
}
|
||||
/* Look for GOTPC reloc */
|
||||
if (r->r_length == 2 && r->r_pcrel == 1)
|
||||
r->r_baserel = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
md_swapout_reloc(r, n)
|
||||
struct relocation_info *r;
|
||||
int n;
|
||||
{
|
||||
int bits;
|
||||
|
||||
for (; n; n--, r++) {
|
||||
/* Look for jmptable relocation */
|
||||
if (r->r_jmptable && r->r_pcrel == 0 && r->r_length == 3) {
|
||||
r->r_jmptable = 0;
|
||||
r->r_baserel = 1;
|
||||
}
|
||||
#ifdef NEED_SWAP
|
||||
r->r_address = md_swap_long(r->r_address);
|
||||
bits = md_swap_long(r->r_symbolnum) & 0xffffff00;
|
||||
bits |= (r->r_pcrel & 1);
|
||||
bits |= (r->r_length & 3) << 1;
|
||||
bits |= (r->r_extern & 1) << 3;
|
||||
bits |= (r->r_neg & 1) << 4;
|
||||
bits |= (r->r_baserel & 1) << 5;
|
||||
bits |= (r->r_jmptable & 1) << 6;
|
||||
bits |= (r->r_relative & 1) << 7;
|
||||
((int *)r)[1] = bits;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,10 @@
|
||||
/* $NetBSD: md.h,v 1.1 1996/05/17 21:51:10 mark Exp $ */
|
||||
/* $NetBSD: md.h,v 1.2 1997/10/17 21:25:54 mark Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1996 Wolfgang Solfrank
|
||||
* Copyright (c) 1997 Mark Brinicombe
|
||||
* Copyright (c) 1997 Causality Limited
|
||||
* Copyright (c) 1993 Paul Kranenburg
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -13,10 +16,10 @@
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Wolfgang Solfrank.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* This product includes software developed by Paul Kranenburg.
|
||||
* This product includes software developed by Causality Limited
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
@ -30,16 +33,24 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* First cut for arm32 */
|
||||
/* Second cut for arm32 */
|
||||
|
||||
#if defined(CROSS_LINKER) && defined(XHOST) && XHOST==sparc
|
||||
#define NEED_SWAP
|
||||
#endif
|
||||
|
||||
#define MAX_ALIGNMENT (sizeof (long))
|
||||
|
||||
#ifdef NetBSD
|
||||
#define PAGSIZ __LDPGSZ
|
||||
#else
|
||||
#define PAGSIZ 4096
|
||||
#endif
|
||||
|
||||
#define N_SET_FLAG(ex,f) (N_SETMAGIC(ex, \
|
||||
N_GETMAGIC(ex), \
|
||||
MID_MACHINE, \
|
||||
N_GETFLAG(ex)|(f)))
|
||||
N_GETMAGIC(ex), \
|
||||
MID_MACHINE, \
|
||||
N_GETFLAG(ex)|(f)))
|
||||
|
||||
#define N_IS_DYNAMIC(ex) ((N_GETFLAG(ex) & EX_DYNAMIC))
|
||||
|
||||
@ -59,10 +70,10 @@
|
||||
: (TEXT_START(ex) + (ex).a_text + __LDPGSZ - 1) & ~(__LDPGSZ - 1))
|
||||
#endif
|
||||
|
||||
#define RELOC_STATICS_THROUGH_GOT_P(r) 0 /* ??? */
|
||||
#define JMPSLOT_NEEDS_RELOC 1
|
||||
#define RELOC_STATICS_THROUGH_GOT_P(r) (1)
|
||||
#define JMPSLOT_NEEDS_RELOC (1)
|
||||
|
||||
#define md_got_reloc(r) 0
|
||||
#define md_got_reloc(r) (-r->r_address)
|
||||
|
||||
#define md_get_rt_segment_addend(r,a) md_get_addend(r,a)
|
||||
|
||||
@ -71,16 +82,26 @@
|
||||
typedef long got_t;
|
||||
|
||||
typedef struct jmpslot {
|
||||
u_long opcode1; /* mov ip, lr */
|
||||
u_long opcode2; /* call */
|
||||
u_long reloc_index; /* used as destination after fixup */
|
||||
u_long opcode1; /* ldr ip, [pc] */
|
||||
u_long opcode2; /* add pc, pc, ip */
|
||||
u_long address; /* binder/function address */
|
||||
u_long reloc_index; /* relocation index */
|
||||
#define JMPSLOT_RELOC_MASK 0xffffffff
|
||||
} jmpslot_t;
|
||||
|
||||
#define SAVEPC 0xe1a0c00e /* MOV ip, lr */
|
||||
#define CALL 0xeb000000 /* CALL opcode */
|
||||
#define JUMP 0xe59ff000 /* LDR pc, [pc] (used as JMP) */
|
||||
#define TRAP 0xe6000010 /* Undefined Instruction (used for bpt) */
|
||||
#define TRAP 0xe6000011 /* Undefined Instruction (used for bpt) */
|
||||
|
||||
#define GETSLOTADDR 0xe04fc00c /* sub ip, pc, ip */
|
||||
#define ADDPC 0xe08ff00c /* add pc, pc, ip */
|
||||
#define LDRPCADDR 0xe51ff004 /* ldr pc, [pc, #-4] */
|
||||
#define GETRELADDR 0xe59fc000 /* ldr ip, [pc] */
|
||||
|
||||
|
||||
void md_swapin_reloc __P((struct relocation_info *, int));
|
||||
void md_swapout_reloc __P((struct relocation_info *, int));
|
||||
|
||||
/*
|
||||
* Byte swap defs for cross linking
|
||||
@ -94,8 +115,6 @@ typedef struct jmpslot {
|
||||
#define md_swapout_symbols(s,n)
|
||||
#define md_swapin_zsymbols(s,n)
|
||||
#define md_swapout_zsymbols(s,n)
|
||||
#define md_swapin_reloc(r,n)
|
||||
#define md_swapout_reloc(r,n)
|
||||
#define md_swapin__dynamic(l)
|
||||
#define md_swapout__dynamic(l)
|
||||
#define md_swapin_section_dispatch_table(l)
|
||||
@ -117,30 +136,30 @@ typedef struct jmpslot {
|
||||
|
||||
#define get_byte(p) ( ((unsigned char *)(p))[0] )
|
||||
|
||||
#define get_short(p) ( ( ((unsigned char *)(p))[1] << 8) | \
|
||||
( ((unsigned char *)(p))[0] ) \
|
||||
#define get_short(p) ( ( ((unsigned char *)(p))[0] << 8) | \
|
||||
( ((unsigned char *)(p))[1] ) \
|
||||
)
|
||||
|
||||
#define get_long(p) ( ( ((unsigned char *)(p))[3] << 24) | \
|
||||
( ((unsigned char *)(p))[2] << 16) | \
|
||||
( ((unsigned char *)(p))[1] << 8 ) | \
|
||||
( ((unsigned char *)(p))[0] ) \
|
||||
#define get_long(p) ( ( ((unsigned char *)(p))[0] << 24) | \
|
||||
( ((unsigned char *)(p))[1] << 16) | \
|
||||
( ((unsigned char *)(p))[2] << 8 ) | \
|
||||
( ((unsigned char *)(p))[3] ) \
|
||||
)
|
||||
|
||||
#define put_byte(p, v) { ((unsigned char *)(p))[0] = ((unsigned long)(v)); }
|
||||
|
||||
#define put_short(p, v) { ((unsigned char *)(p))[1] = \
|
||||
#define put_short(p, v) { ((unsigned char *)(p))[0] = \
|
||||
((((unsigned long)(v)) >> 8) & 0xff); \
|
||||
((unsigned char *)(p))[0] = \
|
||||
((unsigned char *)(p))[1] = \
|
||||
((((unsigned long)(v)) ) & 0xff); }
|
||||
|
||||
#define put_long(p, v) { ((unsigned char *)(p))[3] = \
|
||||
#define put_long(p, v) { ((unsigned char *)(p))[0] = \
|
||||
((((unsigned long)(v)) >> 24) & 0xff); \
|
||||
((unsigned char *)(p))[2] = \
|
||||
((((unsigned long)(v)) >> 16) & 0xff); \
|
||||
((unsigned char *)(p))[1] = \
|
||||
((((unsigned long)(v)) >> 16) & 0xff); \
|
||||
((unsigned char *)(p))[2] = \
|
||||
((((unsigned long)(v)) >> 8) & 0xff); \
|
||||
((unsigned char *)(p))[0] = \
|
||||
((unsigned char *)(p))[3] = \
|
||||
((((unsigned long)(v)) ) & 0xff); }
|
||||
|
||||
#ifdef NEED_SWAP
|
||||
@ -149,8 +168,6 @@ typedef struct jmpslot {
|
||||
|
||||
void md_swapin_exec_hdr __P((struct exec *));
|
||||
void md_swapout_exec_hdr __P((struct exec *));
|
||||
void md_swapin_reloc __P((struct relocation_info *, int));
|
||||
void md_swapout_reloc __P((struct relocation_info *, int));
|
||||
void md_swapout_jmpslot __P((jmpslot_t *, int));
|
||||
|
||||
#define md_swapin_symbols(s,n) swap_symbols(s,n)
|
||||
@ -220,8 +237,24 @@ void md_swapout_jmpslot __P((jmpslot_t *, int));
|
||||
#define RELOC_COPY_P(r) (0)
|
||||
#define RELOC_LAZY_P(r) ((r)->r_jmptable)
|
||||
|
||||
#define CHECK_GOT_RELOC(r) RELOC_PCREL_P(r)
|
||||
#define RELOC_PIC_TYPE(r) ((r)->r_baserel?\
|
||||
PIC_TYPE_LARGE:PIC_TYPE_NONE)
|
||||
/*#define CHECK_GOT_RELOC(r) RELOC_PCREL_P(r)*/
|
||||
#define CHECK_GOT_RELOC(r) (((r)->r_pcrel == 1) && ((r)->r_length == 2))
|
||||
|
||||
/*
|
||||
* Define the range of usable Global Offset Table offsets
|
||||
* when using arm LDR instructions with 12 bit offset (-4092 -> 4092);
|
||||
* this is the case if the object files are compiles with -fpic'.
|
||||
* IF a "large" model is used (i.e. -fPIC'), .word instructions
|
||||
* are generated instead providing 32-bit addressability of the GOT table.
|
||||
*/
|
||||
|
||||
#define MAX_GOTOFF(t) ((t) == PIC_TYPE_SMALL ? 4092 : LONG_MAX)
|
||||
#define MIN_GOTOFF(t) ((t) == PIC_TYPE_SMALL ? -4092 : LONG_MIN)
|
||||
|
||||
#define RELOC_PIC_TYPE(r) ((r)->r_baserel ? \
|
||||
((r)->r_length == 1 ? \
|
||||
PIC_TYPE_SMALL : \
|
||||
PIC_TYPE_LARGE) : \
|
||||
PIC_TYPE_NONE)
|
||||
|
||||
#define RELOC_INIT_SEGMENT_RELOC(r)
|
||||
|
92
libexec/ld.aout_so/arch/arm32/mdprologue.S
Normal file
92
libexec/ld.aout_so/arch/arm32/mdprologue.S
Normal file
@ -0,0 +1,92 @@
|
||||
/* $NetBSD: mdprologue.S,v 1.1 1997/10/17 21:25:59 mark Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1996 Wolfgang Solfrank
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Wolfgang Solfrank.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* arm run-time link editor entry points.
|
||||
*/
|
||||
|
||||
#include <machine/asm.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
.text
|
||||
|
||||
/*
|
||||
* _rtl(int version, struct crt_ldso *crtp)
|
||||
*/
|
||||
|
||||
.align 0
|
||||
.type _rtl,#function
|
||||
_rtl: @ crt0 calls us here
|
||||
mov ip, sp @ Allocate stack frame
|
||||
stmfd sp!, {sl, fp, ip, lr, pc}
|
||||
sub fp, ip, #4
|
||||
|
||||
ldr r3, [r1, #0] @ base address of ld.so (first field)
|
||||
@ setup arguments for rtld()
|
||||
ldr sl, GOTaddr @ get pc-rel offset for GOT
|
||||
add sl, pc, sl @ here is the GOT
|
||||
L1:
|
||||
ldr r2, DYNAMICaddr
|
||||
ldr r2, [sl, r2] @ 1st entry in GOT is our __DYNAMIC
|
||||
add r2, r2, r3 @ add load address
|
||||
ldr lr, rtldaddr @ get GOT offset for function
|
||||
ldr lr, [sl, lr] @ get function address
|
||||
add r3, lr, r3 @ and relocate
|
||||
mov lr, pc
|
||||
mov pc, r3 @ _rtld(version, crtp, DYNAMIC)
|
||||
|
||||
ldmea fp, {sl, fp, ip, pc}
|
||||
|
||||
.align 0
|
||||
GOTaddr:
|
||||
.word __GLOBAL_OFFSET_TABLE_ + (. - (L1+4) )
|
||||
DYNAMICaddr:
|
||||
.word __DYNAMIC
|
||||
rtldaddr:
|
||||
.word _rtld
|
||||
|
||||
@ First call to a procedure generally comes through here for
|
||||
@ binding.
|
||||
|
||||
ENTRY(binder_entry)
|
||||
stmfd sp!, {r0-fp, ip, lr, pc} @ save all regs in standard frame
|
||||
@ (ip and lr to be fixed later)
|
||||
add fp, sp, #(15-1)*4 @ get new fp
|
||||
add r0, fp, #4 @ compute old sp
|
||||
str r0, [fp, #-8] @ fixup saved ip
|
||||
|
||||
sub r0, ip, #(8+12) @ make it point to the jmpslot
|
||||
|
||||
bl _binder
|
||||
str r0, [fp] @ return value from _binder()
|
||||
@ == actual address of function
|
||||
ldmfa fp, {r0-fp, sp, lr, pc} @ restore regs
|
Loading…
Reference in New Issue
Block a user