Add support for PIC code.

Add support for ld.so
This commit is contained in:
mark 1997-10-17 21:25:42 +00:00
parent 1849d27507
commit 919c9148f3
8 changed files with 906 additions and 192 deletions

View 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;*/
}

View File

@ -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 * Copyright (C) 1996 Wolfgang Solfrank
* *
* Redistribution and use in source and binary forms, with or without * 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 * 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement: * must display the following acknowledgement:
* This product includes software developed by Wolfgang Solfrank. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -30,7 +33,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * 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 <sys/param.h>
#include <stdio.h> #include <stdio.h>
@ -41,9 +44,40 @@
#include <a.out.h> #include <a.out.h>
#include <stab.h> #include <stab.h>
#include <string.h> #include <string.h>
#ifdef RTLD
#include <machine/sysarch.h>
#include <sys/syscall.h>
#endif /* RTLD */
#include "ld.h" #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 * Get relocation addend corresponding to relocation record RP
* from address ADDR * from address ADDR
@ -67,7 +101,21 @@ unsigned char *addr;
break; break;
case 3: /* looks like a special hack for b & bl */ case 3: /* looks like a special hack for b & bl */
rel = (((long)get_long(addr) & 0xffffff) << 8) >> 6; 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; break;
default: default:
errx(1, "Unsupported relocation size: %x", errx(1, "Unsupported relocation size: %x",
@ -79,8 +127,9 @@ unsigned char *addr;
/* /*
* Put RELOCATION at ADDR according to relocation record RP. * 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 void
md_relocate(rp, relocation, addr, relocatable_output) md_relocate(rp, relocation, addr, relocatable_output)
struct relocation_info *rp; struct relocation_info *rp;
@ -88,13 +137,25 @@ long relocation;
unsigned char *addr; unsigned char *addr;
int relocatable_output; 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 */ if (rp == rrs_reloc /* HACK HACK HACK XXX */
|| (RELOC_PCREL_P(rp) && relocatable_output)) { || (RELOC_PCREL_P(rp) && relocatable_output)) {
rrs_reloc = NULL; rrs_reloc = NULL;
return; return;
} }
rrs_reloc = NULL; rrs_reloc = NULL;
#endif
if (rp->r_neg) /* Not sure, whether this works in all cases XXX */ if (rp->r_neg) /* Not sure, whether this works in all cases XXX */
relocation = -relocation; relocation = -relocation;
@ -108,11 +169,15 @@ int relocatable_output;
case 2: case 2:
put_long(addr, relocation); put_long(addr, relocation);
break; break;
case 3: case 3: {
int a;
a = (get_long(addr)&0xff000000)
| ((relocation&0x3ffffff) >> 2);
put_long(addr, put_long(addr,
(get_long(addr)&0xff000000) (get_long(addr)&0xff000000)
| ((relocation&0x3ffffff) >> 2)); | ((relocation&0x3ffffff) >> 2));
break; break;
}
default: default:
errx(1, "Unsupported relocation size: %x", errx(1, "Unsupported relocation size: %x",
rp->r_length); rp->r_length);
@ -129,9 +194,10 @@ md_make_reloc(rp, r, type)
struct relocation_info *rp, *r; struct relocation_info *rp, *r;
int type; int type;
{ {
#ifdef HACK
if (type == RELTYPE_EXTERN) if (type == RELTYPE_EXTERN)
rrs_reloc = rp; /* HACK HACK HACK XXX */ rrs_reloc = rp; /* HACK HACK HACK XXX */
#endif
/* Copy most attributes */ /* Copy most attributes */
r->r_pcrel = rp->r_pcrel; r->r_pcrel = rp->r_pcrel;
r->r_length = rp->r_length; r->r_length = rp->r_length;
@ -154,11 +220,21 @@ jmpslot_t *sp;
long offset; long offset;
long index; long index;
{ {
u_long fudge = - (offset + 12); /*
* Build the jump slot as follows
sp->opcode1 = SAVEPC; *
sp->opcode2 = CALL | ((fudge >> 2) & 0xffffff); * 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; 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, * jmpslot at OFFSET to ADDR. Used by `ld' when the SYMBOLIC flag is on,
* and by `ld.so' after resolving the symbol. * and by `ld.so' after resolving the symbol.
*/ */
#ifdef RTLD
extern void binder_entry __P((void));
#endif
void void
md_fix_jmpslot(sp, offset, addr) md_fix_jmpslot(sp, offset, addr)
jmpslot_t *sp; jmpslot_t *sp;
@ -173,12 +254,59 @@ long offset;
u_long addr; u_long addr;
{ {
/* /*
* Generate the following sequence: * For jmpslot 0 (the binder)
* ldr pc, [pc] * generate
* sub ip, pc, ip
* ldr pc, [pc, #-4]
* .word addr * .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; #ifdef RTLD
sp->reloc_index = addr; 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_baserel = 1;
r->r_jmptable = 0; r->r_jmptable = 0;
r->r_relative = 0; r->r_relative = 0;
} }
/* /*
@ -236,6 +365,9 @@ long *savep;
{ {
*savep = *(long *)where; *savep = *(long *)where;
*(long *)where = TRAP; *(long *)where = TRAP;
#ifdef RTLD
iflush((long *)where, sizeof(long));
#endif /* RTLD */
} }
#ifndef RTLD #ifndef RTLD
@ -255,7 +387,7 @@ int magic, flags;
if (!(link_mode & SHAREABLE)) if (!(link_mode & SHAREABLE))
hp->a_entry = PAGSIZ; hp->a_entry = PAGSIZ;
} }
#endif /* RTLD */ #endif /* RTLD */
#ifdef NEED_SWAP #ifdef NEED_SWAP
@ -283,49 +415,6 @@ struct exec *h;
swap_longs((long *)h + skip, sizeof(*h)/sizeof(long) - skip); 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 void
md_swapout_jmpslot(j, n) md_swapout_jmpslot(j, n)
jmpslot_t *j; jmpslot_t *j;
@ -339,3 +428,75 @@ int n;
} }
#endif /* NEED_SWAP */ #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
}
}

View File

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -13,10 +16,10 @@
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software * 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement: * must display the following acknowledgement:
* This product includes software developed by Wolfgang Solfrank. * This product includes software developed by Paul Kranenburg.
* 4. Neither the name of the University nor the names of its contributors * This product includes software developed by Causality Limited
* may be used to endorse or promote products derived from this software * 4. The name of the author may not be used to endorse or promote products
* without specific prior written permission. * derived from this software without specific prior written permission
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * 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. * 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)) #define MAX_ALIGNMENT (sizeof (long))
#ifdef NetBSD
#define PAGSIZ __LDPGSZ #define PAGSIZ __LDPGSZ
#else
#define PAGSIZ 4096
#endif
#define N_SET_FLAG(ex,f) (N_SETMAGIC(ex, \ #define N_SET_FLAG(ex,f) (N_SETMAGIC(ex, \
N_GETMAGIC(ex), \ N_GETMAGIC(ex), \
MID_MACHINE, \ MID_MACHINE, \
N_GETFLAG(ex)|(f))) N_GETFLAG(ex)|(f)))
#define N_IS_DYNAMIC(ex) ((N_GETFLAG(ex) & EX_DYNAMIC)) #define N_IS_DYNAMIC(ex) ((N_GETFLAG(ex) & EX_DYNAMIC))
@ -59,10 +70,10 @@
: (TEXT_START(ex) + (ex).a_text + __LDPGSZ - 1) & ~(__LDPGSZ - 1)) : (TEXT_START(ex) + (ex).a_text + __LDPGSZ - 1) & ~(__LDPGSZ - 1))
#endif #endif
#define RELOC_STATICS_THROUGH_GOT_P(r) 0 /* ??? */ #define RELOC_STATICS_THROUGH_GOT_P(r) (1)
#define JMPSLOT_NEEDS_RELOC 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) #define md_get_rt_segment_addend(r,a) md_get_addend(r,a)
@ -71,16 +82,26 @@
typedef long got_t; typedef long got_t;
typedef struct jmpslot { typedef struct jmpslot {
u_long opcode1; /* mov ip, lr */ u_long opcode1; /* ldr ip, [pc] */
u_long opcode2; /* call */ u_long opcode2; /* add pc, pc, ip */
u_long reloc_index; /* used as destination after fixup */ u_long address; /* binder/function address */
u_long reloc_index; /* relocation index */
#define JMPSLOT_RELOC_MASK 0xffffffff #define JMPSLOT_RELOC_MASK 0xffffffff
} jmpslot_t; } jmpslot_t;
#define SAVEPC 0xe1a0c00e /* MOV ip, lr */ #define SAVEPC 0xe1a0c00e /* MOV ip, lr */
#define CALL 0xeb000000 /* CALL opcode */ #define CALL 0xeb000000 /* CALL opcode */
#define JUMP 0xe59ff000 /* LDR pc, [pc] (used as JMP) */ #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 * Byte swap defs for cross linking
@ -94,8 +115,6 @@ typedef struct jmpslot {
#define md_swapout_symbols(s,n) #define md_swapout_symbols(s,n)
#define md_swapin_zsymbols(s,n) #define md_swapin_zsymbols(s,n)
#define md_swapout_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_swapin__dynamic(l)
#define md_swapout__dynamic(l) #define md_swapout__dynamic(l)
#define md_swapin_section_dispatch_table(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_byte(p) ( ((unsigned char *)(p))[0] )
#define get_short(p) ( ( ((unsigned char *)(p))[1] << 8) | \ #define get_short(p) ( ( ((unsigned char *)(p))[0] << 8) | \
( ((unsigned char *)(p))[0] ) \ ( ((unsigned char *)(p))[1] ) \
) )
#define get_long(p) ( ( ((unsigned char *)(p))[3] << 24) | \ #define get_long(p) ( ( ((unsigned char *)(p))[0] << 24) | \
( ((unsigned char *)(p))[2] << 16) | \ ( ((unsigned char *)(p))[1] << 16) | \
( ((unsigned char *)(p))[1] << 8 ) | \ ( ((unsigned char *)(p))[2] << 8 ) | \
( ((unsigned char *)(p))[0] ) \ ( ((unsigned char *)(p))[3] ) \
) )
#define put_byte(p, v) { ((unsigned char *)(p))[0] = ((unsigned long)(v)); } #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 long)(v)) >> 8) & 0xff); \
((unsigned char *)(p))[0] = \ ((unsigned char *)(p))[1] = \
((((unsigned long)(v)) ) & 0xff); } ((((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 long)(v)) >> 24) & 0xff); \
((unsigned char *)(p))[2] = \
((((unsigned long)(v)) >> 16) & 0xff); \
((unsigned char *)(p))[1] = \ ((unsigned char *)(p))[1] = \
((((unsigned long)(v)) >> 16) & 0xff); \
((unsigned char *)(p))[2] = \
((((unsigned long)(v)) >> 8) & 0xff); \ ((((unsigned long)(v)) >> 8) & 0xff); \
((unsigned char *)(p))[0] = \ ((unsigned char *)(p))[3] = \
((((unsigned long)(v)) ) & 0xff); } ((((unsigned long)(v)) ) & 0xff); }
#ifdef NEED_SWAP #ifdef NEED_SWAP
@ -149,8 +168,6 @@ typedef struct jmpslot {
void md_swapin_exec_hdr __P((struct exec *)); void md_swapin_exec_hdr __P((struct exec *));
void md_swapout_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)); void md_swapout_jmpslot __P((jmpslot_t *, int));
#define md_swapin_symbols(s,n) swap_symbols(s,n) #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_COPY_P(r) (0)
#define RELOC_LAZY_P(r) ((r)->r_jmptable) #define RELOC_LAZY_P(r) ((r)->r_jmptable)
#define CHECK_GOT_RELOC(r) RELOC_PCREL_P(r) /*#define CHECK_GOT_RELOC(r) RELOC_PCREL_P(r)*/
#define RELOC_PIC_TYPE(r) ((r)->r_baserel?\ #define CHECK_GOT_RELOC(r) (((r)->r_pcrel == 1) && ((r)->r_length == 2))
PIC_TYPE_LARGE:PIC_TYPE_NONE)
/*
* 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) #define RELOC_INIT_SEGMENT_RELOC(r)

View 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

View 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;*/
}

View File

@ -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 * Copyright (C) 1996 Wolfgang Solfrank
* *
* Redistribution and use in source and binary forms, with or without * 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 * 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement: * must display the following acknowledgement:
* This product includes software developed by Wolfgang Solfrank. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -30,7 +33,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * 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 <sys/param.h>
#include <stdio.h> #include <stdio.h>
@ -41,9 +44,40 @@
#include <a.out.h> #include <a.out.h>
#include <stab.h> #include <stab.h>
#include <string.h> #include <string.h>
#ifdef RTLD
#include <machine/sysarch.h>
#include <sys/syscall.h>
#endif /* RTLD */
#include "ld.h" #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 * Get relocation addend corresponding to relocation record RP
* from address ADDR * from address ADDR
@ -67,7 +101,21 @@ unsigned char *addr;
break; break;
case 3: /* looks like a special hack for b & bl */ case 3: /* looks like a special hack for b & bl */
rel = (((long)get_long(addr) & 0xffffff) << 8) >> 6; 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; break;
default: default:
errx(1, "Unsupported relocation size: %x", errx(1, "Unsupported relocation size: %x",
@ -79,8 +127,9 @@ unsigned char *addr;
/* /*
* Put RELOCATION at ADDR according to relocation record RP. * 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 void
md_relocate(rp, relocation, addr, relocatable_output) md_relocate(rp, relocation, addr, relocatable_output)
struct relocation_info *rp; struct relocation_info *rp;
@ -88,13 +137,25 @@ long relocation;
unsigned char *addr; unsigned char *addr;
int relocatable_output; 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 */ if (rp == rrs_reloc /* HACK HACK HACK XXX */
|| (RELOC_PCREL_P(rp) && relocatable_output)) { || (RELOC_PCREL_P(rp) && relocatable_output)) {
rrs_reloc = NULL; rrs_reloc = NULL;
return; return;
} }
rrs_reloc = NULL; rrs_reloc = NULL;
#endif
if (rp->r_neg) /* Not sure, whether this works in all cases XXX */ if (rp->r_neg) /* Not sure, whether this works in all cases XXX */
relocation = -relocation; relocation = -relocation;
@ -108,11 +169,15 @@ int relocatable_output;
case 2: case 2:
put_long(addr, relocation); put_long(addr, relocation);
break; break;
case 3: case 3: {
int a;
a = (get_long(addr)&0xff000000)
| ((relocation&0x3ffffff) >> 2);
put_long(addr, put_long(addr,
(get_long(addr)&0xff000000) (get_long(addr)&0xff000000)
| ((relocation&0x3ffffff) >> 2)); | ((relocation&0x3ffffff) >> 2));
break; break;
}
default: default:
errx(1, "Unsupported relocation size: %x", errx(1, "Unsupported relocation size: %x",
rp->r_length); rp->r_length);
@ -129,9 +194,10 @@ md_make_reloc(rp, r, type)
struct relocation_info *rp, *r; struct relocation_info *rp, *r;
int type; int type;
{ {
#ifdef HACK
if (type == RELTYPE_EXTERN) if (type == RELTYPE_EXTERN)
rrs_reloc = rp; /* HACK HACK HACK XXX */ rrs_reloc = rp; /* HACK HACK HACK XXX */
#endif
/* Copy most attributes */ /* Copy most attributes */
r->r_pcrel = rp->r_pcrel; r->r_pcrel = rp->r_pcrel;
r->r_length = rp->r_length; r->r_length = rp->r_length;
@ -154,11 +220,21 @@ jmpslot_t *sp;
long offset; long offset;
long index; long index;
{ {
u_long fudge = - (offset + 12); /*
* Build the jump slot as follows
sp->opcode1 = SAVEPC; *
sp->opcode2 = CALL | ((fudge >> 2) & 0xffffff); * 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; 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, * jmpslot at OFFSET to ADDR. Used by `ld' when the SYMBOLIC flag is on,
* and by `ld.so' after resolving the symbol. * and by `ld.so' after resolving the symbol.
*/ */
#ifdef RTLD
extern void binder_entry __P((void));
#endif
void void
md_fix_jmpslot(sp, offset, addr) md_fix_jmpslot(sp, offset, addr)
jmpslot_t *sp; jmpslot_t *sp;
@ -173,12 +254,59 @@ long offset;
u_long addr; u_long addr;
{ {
/* /*
* Generate the following sequence: * For jmpslot 0 (the binder)
* ldr pc, [pc] * generate
* sub ip, pc, ip
* ldr pc, [pc, #-4]
* .word addr * .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; #ifdef RTLD
sp->reloc_index = addr; 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_baserel = 1;
r->r_jmptable = 0; r->r_jmptable = 0;
r->r_relative = 0; r->r_relative = 0;
} }
/* /*
@ -236,6 +365,9 @@ long *savep;
{ {
*savep = *(long *)where; *savep = *(long *)where;
*(long *)where = TRAP; *(long *)where = TRAP;
#ifdef RTLD
iflush((long *)where, sizeof(long));
#endif /* RTLD */
} }
#ifndef RTLD #ifndef RTLD
@ -255,7 +387,7 @@ int magic, flags;
if (!(link_mode & SHAREABLE)) if (!(link_mode & SHAREABLE))
hp->a_entry = PAGSIZ; hp->a_entry = PAGSIZ;
} }
#endif /* RTLD */ #endif /* RTLD */
#ifdef NEED_SWAP #ifdef NEED_SWAP
@ -283,49 +415,6 @@ struct exec *h;
swap_longs((long *)h + skip, sizeof(*h)/sizeof(long) - skip); 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 void
md_swapout_jmpslot(j, n) md_swapout_jmpslot(j, n)
jmpslot_t *j; jmpslot_t *j;
@ -339,3 +428,75 @@ int n;
} }
#endif /* NEED_SWAP */ #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
}
}

View File

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -13,10 +16,10 @@
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software * 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement: * must display the following acknowledgement:
* This product includes software developed by Wolfgang Solfrank. * This product includes software developed by Paul Kranenburg.
* 4. Neither the name of the University nor the names of its contributors * This product includes software developed by Causality Limited
* may be used to endorse or promote products derived from this software * 4. The name of the author may not be used to endorse or promote products
* without specific prior written permission. * derived from this software without specific prior written permission
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * 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. * 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)) #define MAX_ALIGNMENT (sizeof (long))
#ifdef NetBSD
#define PAGSIZ __LDPGSZ #define PAGSIZ __LDPGSZ
#else
#define PAGSIZ 4096
#endif
#define N_SET_FLAG(ex,f) (N_SETMAGIC(ex, \ #define N_SET_FLAG(ex,f) (N_SETMAGIC(ex, \
N_GETMAGIC(ex), \ N_GETMAGIC(ex), \
MID_MACHINE, \ MID_MACHINE, \
N_GETFLAG(ex)|(f))) N_GETFLAG(ex)|(f)))
#define N_IS_DYNAMIC(ex) ((N_GETFLAG(ex) & EX_DYNAMIC)) #define N_IS_DYNAMIC(ex) ((N_GETFLAG(ex) & EX_DYNAMIC))
@ -59,10 +70,10 @@
: (TEXT_START(ex) + (ex).a_text + __LDPGSZ - 1) & ~(__LDPGSZ - 1)) : (TEXT_START(ex) + (ex).a_text + __LDPGSZ - 1) & ~(__LDPGSZ - 1))
#endif #endif
#define RELOC_STATICS_THROUGH_GOT_P(r) 0 /* ??? */ #define RELOC_STATICS_THROUGH_GOT_P(r) (1)
#define JMPSLOT_NEEDS_RELOC 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) #define md_get_rt_segment_addend(r,a) md_get_addend(r,a)
@ -71,16 +82,26 @@
typedef long got_t; typedef long got_t;
typedef struct jmpslot { typedef struct jmpslot {
u_long opcode1; /* mov ip, lr */ u_long opcode1; /* ldr ip, [pc] */
u_long opcode2; /* call */ u_long opcode2; /* add pc, pc, ip */
u_long reloc_index; /* used as destination after fixup */ u_long address; /* binder/function address */
u_long reloc_index; /* relocation index */
#define JMPSLOT_RELOC_MASK 0xffffffff #define JMPSLOT_RELOC_MASK 0xffffffff
} jmpslot_t; } jmpslot_t;
#define SAVEPC 0xe1a0c00e /* MOV ip, lr */ #define SAVEPC 0xe1a0c00e /* MOV ip, lr */
#define CALL 0xeb000000 /* CALL opcode */ #define CALL 0xeb000000 /* CALL opcode */
#define JUMP 0xe59ff000 /* LDR pc, [pc] (used as JMP) */ #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 * Byte swap defs for cross linking
@ -94,8 +115,6 @@ typedef struct jmpslot {
#define md_swapout_symbols(s,n) #define md_swapout_symbols(s,n)
#define md_swapin_zsymbols(s,n) #define md_swapin_zsymbols(s,n)
#define md_swapout_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_swapin__dynamic(l)
#define md_swapout__dynamic(l) #define md_swapout__dynamic(l)
#define md_swapin_section_dispatch_table(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_byte(p) ( ((unsigned char *)(p))[0] )
#define get_short(p) ( ( ((unsigned char *)(p))[1] << 8) | \ #define get_short(p) ( ( ((unsigned char *)(p))[0] << 8) | \
( ((unsigned char *)(p))[0] ) \ ( ((unsigned char *)(p))[1] ) \
) )
#define get_long(p) ( ( ((unsigned char *)(p))[3] << 24) | \ #define get_long(p) ( ( ((unsigned char *)(p))[0] << 24) | \
( ((unsigned char *)(p))[2] << 16) | \ ( ((unsigned char *)(p))[1] << 16) | \
( ((unsigned char *)(p))[1] << 8 ) | \ ( ((unsigned char *)(p))[2] << 8 ) | \
( ((unsigned char *)(p))[0] ) \ ( ((unsigned char *)(p))[3] ) \
) )
#define put_byte(p, v) { ((unsigned char *)(p))[0] = ((unsigned long)(v)); } #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 long)(v)) >> 8) & 0xff); \
((unsigned char *)(p))[0] = \ ((unsigned char *)(p))[1] = \
((((unsigned long)(v)) ) & 0xff); } ((((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 long)(v)) >> 24) & 0xff); \
((unsigned char *)(p))[2] = \
((((unsigned long)(v)) >> 16) & 0xff); \
((unsigned char *)(p))[1] = \ ((unsigned char *)(p))[1] = \
((((unsigned long)(v)) >> 16) & 0xff); \
((unsigned char *)(p))[2] = \
((((unsigned long)(v)) >> 8) & 0xff); \ ((((unsigned long)(v)) >> 8) & 0xff); \
((unsigned char *)(p))[0] = \ ((unsigned char *)(p))[3] = \
((((unsigned long)(v)) ) & 0xff); } ((((unsigned long)(v)) ) & 0xff); }
#ifdef NEED_SWAP #ifdef NEED_SWAP
@ -149,8 +168,6 @@ typedef struct jmpslot {
void md_swapin_exec_hdr __P((struct exec *)); void md_swapin_exec_hdr __P((struct exec *));
void md_swapout_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)); void md_swapout_jmpslot __P((jmpslot_t *, int));
#define md_swapin_symbols(s,n) swap_symbols(s,n) #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_COPY_P(r) (0)
#define RELOC_LAZY_P(r) ((r)->r_jmptable) #define RELOC_LAZY_P(r) ((r)->r_jmptable)
#define CHECK_GOT_RELOC(r) RELOC_PCREL_P(r) /*#define CHECK_GOT_RELOC(r) RELOC_PCREL_P(r)*/
#define RELOC_PIC_TYPE(r) ((r)->r_baserel?\ #define CHECK_GOT_RELOC(r) (((r)->r_pcrel == 1) && ((r)->r_length == 2))
PIC_TYPE_LARGE:PIC_TYPE_NONE)
/*
* 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) #define RELOC_INIT_SEGMENT_RELOC(r)

View 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