summaryrefslogtreecommitdiff
path: root/gnu/usr.bin/ld
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1996-06-17 00:10:45 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1996-06-17 00:10:45 +0000
commit64628d0eb8885ed0a6beca03bd26129c63695a12 (patch)
treefde850d8ecf5657d21d200eef59c32e1e488ec93 /gnu/usr.bin/ld
parentb46ab1262deb25c3a5b968bb3676968ab90adf7e (diff)
from netbsd
Diffstat (limited to 'gnu/usr.bin/ld')
-rw-r--r--gnu/usr.bin/ld/arm32/md.c342
-rw-r--r--gnu/usr.bin/ld/arm32/md.h228
2 files changed, 570 insertions, 0 deletions
diff --git a/gnu/usr.bin/ld/arm32/md.c b/gnu/usr.bin/ld/arm32/md.c
new file mode 100644
index 00000000000..88d7cc6882f
--- /dev/null
+++ b/gnu/usr.bin/ld/arm32/md.c
@@ -0,0 +1,342 @@
+/* $OpenBSD: md.c,v 1.1 1996/06/17 00:10:44 deraadt Exp $ */
+/* $NetBSD$ */
+
+/*
+ * 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.
+ */
+
+/* First cut for arm32 (currently a simple copy of i386 code) */
+
+#include <sys/param.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <err.h>
+#include <fcntl.h>
+#include <a.out.h>
+#include <stab.h>
+#include <string.h>
+
+#include "ld.h"
+
+/*
+ * Get relocation addend corresponding to relocation record RP
+ * from address ADDR
+ */
+long
+md_get_addend(rp, addr)
+struct relocation_info *rp;
+unsigned char *addr;
+{
+ long rel;
+
+ switch (rp->r_length) {
+ case 0:
+ rel = get_byte(addr);
+ break;
+ case 1:
+ rel = get_short(addr);
+ break;
+ case 2:
+ rel = get_long(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 */
+ break;
+ default:
+ errx(1, "Unsupported relocation size: %x",
+ rp->r_length);
+ }
+ return rp->r_neg ? -rel : rel; /* Hack to make r_neg work */
+}
+
+/*
+ * Put RELOCATION at ADDR according to relocation record RP.
+ */
+static struct relocation_info *rrs_reloc; /* HACK HACK HACK XXX */
+
+void
+md_relocate(rp, relocation, addr, relocatable_output)
+struct relocation_info *rp;
+long relocation;
+unsigned char *addr;
+int relocatable_output;
+{
+ if (rp == rrs_reloc /* HACK HACK HACK XXX */
+ || (RELOC_PCREL_P(rp) && relocatable_output)) {
+ rrs_reloc = NULL;
+ return;
+ }
+ rrs_reloc = NULL;
+
+ if (rp->r_neg) /* Not sure, whether this works in all cases XXX */
+ relocation = -relocation;
+
+ switch (rp->r_length) {
+ case 0:
+ put_byte(addr, relocation);
+ break;
+ case 1:
+ put_short(addr, relocation);
+ break;
+ case 2:
+ put_long(addr, relocation);
+ break;
+ case 3:
+ put_long(addr,
+ (get_long(addr)&0xff000000)
+ | ((relocation&0x3ffffff) >> 2));
+ break;
+ default:
+ errx(1, "Unsupported relocation size: %x",
+ rp->r_length);
+ }
+}
+
+#ifndef RTLD
+/*
+ * Machine dependent part of claim_rrs_reloc().
+ * Set RRS relocation type.
+ */
+int
+md_make_reloc(rp, r, type)
+struct relocation_info *rp, *r;
+int type;
+{
+ if (type == RELTYPE_EXTERN)
+ rrs_reloc = rp; /* HACK HACK HACK XXX */
+
+ /* Copy most attributes */
+ r->r_pcrel = rp->r_pcrel;
+ r->r_length = rp->r_length;
+ r->r_neg = rp->r_neg;
+ r->r_baserel = rp->r_baserel;
+ r->r_jmptable = rp->r_jmptable;
+ r->r_relative = rp->r_relative;
+
+ return 0;
+}
+#endif /* RTLD */
+
+/*
+ * Set up a transfer from jmpslot at OFFSET (relative to the PLT table)
+ * to the binder slot (which is at offset 0 of the PLT).
+ */
+void
+md_make_jmpslot(sp, offset, index)
+jmpslot_t *sp;
+long offset;
+long index;
+{
+ u_long fudge = - (offset + 12);
+
+ sp->opcode1 = SAVEPC;
+ sp->opcode2 = CALL | ((fudge >> 2) & 0xffffff);
+ sp->reloc_index = index;
+}
+
+/*
+ * Set up a "direct" transfer (ie. not through the run-time binder) from
+ * jmpslot at OFFSET to ADDR. Used by `ld' when the SYMBOLIC flag is on,
+ * and by `ld.so' after resolving the symbol.
+ */
+void
+md_fix_jmpslot(sp, offset, addr)
+jmpslot_t *sp;
+long offset;
+u_long addr;
+{
+ /*
+ * Generate the following sequence:
+ * ldr pc, [pc]
+ * .word addr
+ */
+ sp->opcode1 = JUMP;
+ sp->reloc_index = addr;
+}
+
+/*
+ * Update the relocation record for a RRS jmpslot.
+ */
+void
+md_make_jmpreloc(rp, r, type)
+struct relocation_info *rp, *r;
+int type;
+{
+ r->r_address += 8;
+ r->r_pcrel = 0;
+ r->r_length = 2;
+ r->r_neg = 0;
+ r->r_baserel = 0;
+ r->r_jmptable = 1;
+ r->r_relative = 0;
+}
+
+/*
+ * Set relocation type for a RRS GOT relocation.
+ */
+void
+md_make_gotreloc(rp, r, type)
+struct relocation_info *rp, *r;
+int type;
+{
+ r->r_pcrel = 0;
+ r->r_length = 2;
+ r->r_neg = 0;
+ r->r_baserel = 1;
+ r->r_jmptable = 0;
+ r->r_relative = 0;
+}
+
+/*
+ * Set relocation type for a RRS copy operation.
+ */
+void
+md_make_cpyreloc(rp, r)
+struct relocation_info *rp, *r;
+{
+ r->r_pcrel = 0;
+ r->r_length = 2;
+ r->r_neg = 0;
+ r->r_baserel = 0;
+ r->r_jmptable = 0;
+ r->r_relative = 0;
+}
+
+void
+md_set_breakpoint(where, savep)
+long where;
+long *savep;
+{
+ *savep = *(long *)where;
+ *(long *)where = TRAP;
+}
+
+#ifndef RTLD
+
+/*
+ * Initialize (output) exec header such that useful values are
+ * obtained from subsequent N_*() macro evaluations.
+ */
+void
+md_init_header(hp, magic, flags)
+struct exec *hp;
+int magic, flags;
+{
+ N_SETMAGIC((*hp), magic, MID_ARM6, flags);
+
+ /* TEXT_START depends on the value of outheader.a_entry. */
+ if (!(link_mode & SHAREABLE))
+ hp->a_entry = PAGSIZ;
+}
+#endif /* RTLD */
+
+
+#ifdef NEED_SWAP
+/*
+ * Byte swap routines for cross-linking.
+ */
+
+void
+md_swapin_exec_hdr(h)
+struct exec *h;
+{
+ /* NetBSD: Always leave magic alone */
+ int skip = 1;
+
+ swap_longs((long *)h + skip, sizeof(*h)/sizeof(long) - skip);
+}
+
+void
+md_swapout_exec_hdr(h)
+struct exec *h;
+{
+ /* NetBSD: Always leave magic alone */
+ int skip = 1;
+
+ 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;
+int n;
+{
+ for (; n; n--, j++) {
+ j->opcode1 = md_swap_long(j->opcode1);
+ j->opcode2 = md_swap_long(j->opcode2);
+ j->reloc_index = md_swap_long(j->reloc_index);
+ }
+}
+
+#endif /* NEED_SWAP */
diff --git a/gnu/usr.bin/ld/arm32/md.h b/gnu/usr.bin/ld/arm32/md.h
new file mode 100644
index 00000000000..1100b094252
--- /dev/null
+++ b/gnu/usr.bin/ld/arm32/md.h
@@ -0,0 +1,228 @@
+/* $OpenBSD: md.h,v 1.1 1996/06/17 00:10:44 deraadt Exp $ */
+/* $NetBSD: md.h,v 1.1 1996/05/17 21:51:10 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.
+ */
+
+/* First cut for arm32 */
+
+#define MAX_ALIGNMENT (sizeof (long))
+
+#define PAGSIZ __LDPGSZ
+
+#define N_SET_FLAG(ex,f) (N_SETMAGIC(ex, \
+ N_GETMAGIC(ex), \
+ MID_MACHINE, \
+ N_GETFLAG(ex)|(f)))
+
+#define N_IS_DYNAMIC(ex) ((N_GETFLAG(ex) & EX_DYNAMIC))
+
+#define N_BADMID(ex) (N_GETMID(ex) != MID_MACHINE)
+
+/*
+ * Should be handled by a.out.h ?
+ */
+#define N_ADJUST(ex) (((ex).a_entry < PAGSIZ) ? -PAGSIZ : 0)
+#ifdef __notyet__
+#define TEXT_START(ex) (N_TXTADDR(ex) + N_ADJUST(ex))
+#define DATA_START(ex) (N_DATADDR(ex) + N_ADJUST(ex))
+#else
+#define TEXT_START(ex) ((ex).a_entry < PAGSIZ ? 0 : 0x001000)
+#define DATA_START(ex) (N_GETMAGIC(ex) == OMAGIC \
+ ? TEXT_START(ex) + (ex).a_text \
+ : (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 md_got_reloc(r) 0
+
+#define md_get_rt_segment_addend(r,a) md_get_addend(r,a)
+
+/* Width of a Global Offset Table entry */
+#define GOT_ENTRY_SIZE 4
+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 */
+#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) */
+
+/*
+ * Byte swap defs for cross linking
+ */
+
+#if !defined(NEED_SWAP)
+
+#define md_swapin_exec_hdr(h)
+#define md_swapout_exec_hdr(h)
+#define md_swapin_symbols(s,n)
+#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)
+#define md_swapout_section_dispatch_table(l)
+#define md_swapin_so_debug(d)
+#define md_swapout_so_debug(d)
+#define md_swapin_rrs_hash(f,n)
+#define md_swapout_rrs_hash(f,n)
+#define md_swapin_sod(l,n)
+#define md_swapout_sod(l,n)
+#define md_swapout_jmpslot(j,n)
+#define md_swapout_got(g,n)
+#define md_swapin_ranlib_hdr(h,n)
+#define md_swapout_ranlib_hdr(h,n)
+
+#endif /* NEED_SWAP */
+
+#ifdef CROSS_LINKER
+
+#define get_byte(p) ( ((unsigned char *)(p))[0] )
+
+#define get_short(p) ( ( ((unsigned char *)(p))[1] << 8) | \
+ ( ((unsigned char *)(p))[0] ) \
+ )
+
+#define get_long(p) ( ( ((unsigned char *)(p))[3] << 24) | \
+ ( ((unsigned char *)(p))[2] << 16) | \
+ ( ((unsigned char *)(p))[1] << 8 ) | \
+ ( ((unsigned char *)(p))[0] ) \
+ )
+
+#define put_byte(p, v) { ((unsigned char *)(p))[0] = ((unsigned long)(v)); }
+
+#define put_short(p, v) { ((unsigned char *)(p))[1] = \
+ ((((unsigned long)(v)) >> 8) & 0xff); \
+ ((unsigned char *)(p))[0] = \
+ ((((unsigned long)(v)) ) & 0xff); }
+
+#define put_long(p, v) { ((unsigned char *)(p))[3] = \
+ ((((unsigned long)(v)) >> 24) & 0xff); \
+ ((unsigned char *)(p))[2] = \
+ ((((unsigned long)(v)) >> 16) & 0xff); \
+ ((unsigned char *)(p))[1] = \
+ ((((unsigned long)(v)) >> 8) & 0xff); \
+ ((unsigned char *)(p))[0] = \
+ ((((unsigned long)(v)) ) & 0xff); }
+
+#ifdef NEED_SWAP
+
+/* Define IO byte swapping routines */
+
+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)
+#define md_swapout_symbols(s,n) swap_symbols(s,n)
+#define md_swapin_zsymbols(s,n) swap_zsymbols(s,n)
+#define md_swapout_zsymbols(s,n) swap_zsymbols(s,n)
+#define md_swapin__dynamic(l) swap__dynamic(l)
+#define md_swapout__dynamic(l) swap__dynamic(l)
+#define md_swapin_section_dispatch_table(l) swap_section_dispatch_table(l)
+#define md_swapout_section_dispatch_table(l) swap_section_dispatch_table(l)
+#define md_swapin_so_debug(d) swap_so_debug(d)
+#define md_swapout_so_debug(d) swap_so_debug(d)
+#define md_swapin_rrs_hash(f,n) swap_rrs_hash(f,n)
+#define md_swapout_rrs_hash(f,n) swap_rrs_hash(f,n)
+#define md_swapin_sod(l,n) swapin_sod(l,n)
+#define md_swapout_sod(l,n) swapout_sod(l,n)
+#define md_swapout_got(g,n) swap_longs((long*)(g),n)
+#define md_swapin_ranlib_hdr(h,n) swap_ranlib_hdr(h,n)
+#define md_swapout_ranlib_hdr(h,n) swap_ranlib_hdr(h,n)
+
+#define md_swap_short(x) ( (((x) >> 8) & 0xff) | (((x) & 0xff) << 8) )
+
+#define md_swap_long(x) ( (((x) >> 24) & 0xff ) | (((x) >> 8 ) & 0xff00 ) | \
+ (((x) << 8 ) & 0xff0000) | (((x) << 24) & 0xff000000))
+
+#else /* We need not swap, but must pay attention to alignment: */
+
+#define md_swap_short(x) (x)
+#define md_swap_long(x) (x)
+
+#endif /* NEED_SWAP */
+
+#else /* Not a cross linker: use native */
+
+#define md_swap_short(x) (x)
+#define md_swap_long(x) (x)
+
+#define get_byte(where) (*(char *)(where))
+#define get_short(where) (*(short *)(where))
+#define get_long(where) (*(long *)(where))
+
+#define put_byte(where,what) (*(char *)(where) = (what))
+#define put_short(where,what) (*(short *)(where) = (what))
+#define put_long(where,what) (*(long *)(where) = (what))
+
+#endif /* CROSS_LINKER */
+
+/*
+ * Define all the RELOC_ macros
+ */
+#define RELOC_ADDRESS(r) ((r)->r_address)
+#define RELOC_EXTERN_P(r) ((r)->r_extern)
+#define RELOC_TYPE(r) ((r)->r_symbolnum)
+#define RELOC_SYMBOL(r) ((r)->r_symbolnum)
+/* #define RELOC_MEMORY_SUB_P(r) ((r)->r_neg) not used */
+#define RELOC_MEMORY_ADD_P(r) 1
+#undef RELOC_ADD_EXTRA
+#define RELOC_PCREL_P(r) (((r)->r_pcrel == 1) ^ ((r)->r_length == 3))
+#define RELOC_VALUE_RIGHTSHIFT(r) 0
+/*#define RELOC_TARGET_SIZE(r) ((r)->r_length) not used */
+/*#define RELOC_TARGET_BITPOS(r) 0 not used */
+/*#define RELOC_TARGET_BITSIZE(r) 32 not used */
+
+#define RELOC_JMPTAB_P(r) ((r)->r_jmptable)
+#define RELOC_BASEREL_P(r) ((r)->r_baserel)
+#define RELOC_RELATIVE_P(r) ((r)->r_relative)
+#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 RELOC_INIT_SEGMENT_RELOC(r)