Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/libexec/ld.elf_so Add support for dynamic linking on HP PA-R...



details:   https://anonhg.NetBSD.org/src/rev/1158c6ce5911
branches:  trunk
changeset: 533881:1158c6ce5911
user:      fredette <fredette%NetBSD.org@localhost>
date:      Wed Jul 10 15:12:33 2002 +0000

description:
Add support for dynamic linking on HP PA-RISC.

diffstat:

 libexec/ld.elf_so/Makefile               |    3 +-
 libexec/ld.elf_so/README                 |    9 +-
 libexec/ld.elf_so/arch/hppa/Makefile.inc |   17 +
 libexec/ld.elf_so/arch/hppa/hppa_reloc.c |  337 +++++++++++++++++++++++++++++++
 libexec/ld.elf_so/arch/hppa/ld.so.script |  190 +++++++++++++++++
 libexec/ld.elf_so/arch/hppa/rtld_start.S |  269 ++++++++++++++++++++++++
 libexec/ld.elf_so/headers.c              |   25 +-
 libexec/ld.elf_so/reloc.c                |  120 ++++++++++-
 libexec/ld.elf_so/rtld.c                 |   25 ++-
 libexec/ld.elf_so/rtld.h                 |   18 +-
 10 files changed, 991 insertions(+), 22 deletions(-)

diffs (truncated from 1214 to 300 lines):

diff -r 37186e76ee93 -r 1158c6ce5911 libexec/ld.elf_so/Makefile
--- a/libexec/ld.elf_so/Makefile        Wed Jul 10 15:00:35 2002 +0000
+++ b/libexec/ld.elf_so/Makefile        Wed Jul 10 15:12:33 2002 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: Makefile,v 1.48 2002/03/01 20:15:16 tv Exp $
+#      $NetBSD: Makefile,v 1.49 2002/07/10 15:12:33 fredette Exp $
 
 .include <bsd.own.mk>                  # for OBJECT_FMT definition
 
@@ -7,6 +7,7 @@
 
 .if ((${MACHINE_ARCH} == "alpha") ||                                   \
      (${MACHINE_ARCH} == "arm") ||                                     \
+     (${MACHINE_ARCH} == "hppa") ||                                    \
      (${MACHINE_ARCH} == "i386") ||                                    \
      (${MACHINE_ARCH} == "m68k") ||                                    \
      (${MACHINE_ARCH} == "mipsel") || (${MACHINE_ARCH} == "mipseb") || \
diff -r 37186e76ee93 -r 1158c6ce5911 libexec/ld.elf_so/README
--- a/libexec/ld.elf_so/README  Wed Jul 10 15:00:35 2002 +0000
+++ b/libexec/ld.elf_so/README  Wed Jul 10 15:12:33 2002 +0000
@@ -1,4 +1,4 @@
-$NetBSD: README,v 1.8 2001/12/20 06:49:03 thorpej Exp $
+$NetBSD: README,v 1.9 2002/07/10 15:12:34 fredette Exp $
 
 BUGS/PROBLEMS:
 
@@ -15,13 +15,14 @@
 * The method used to relocate ld.so is shoddy and fragile.  Currently it's
   something like:
 
-  alpha, powerpc:
+  alpha, hppa, powerpc:
        (1) assembly code relocates RELATIVE relocations in the GOT
            (on some ports, all relative relocations; this will probably
            have to be #ifdef'd in reloc.c), assuming that everything
-           in the GOT is a RELATIVE relocation.
+           in the GOT is a RELATIVE relocation.  On the hppa, this
+           is actually done in C code.
 
-       (2) alpha only: C code relocates the rest of the loader,
+       (2) alpha, hppa only: C code relocates the rest of the loader,
            excluding those RELATIVE relocations already done (via an ...
            iffy heuristic).
 
diff -r 37186e76ee93 -r 1158c6ce5911 libexec/ld.elf_so/arch/hppa/Makefile.inc
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/libexec/ld.elf_so/arch/hppa/Makefile.inc  Wed Jul 10 15:12:33 2002 +0000
@@ -0,0 +1,17 @@
+#      $NetBSD: Makefile.inc,v 1.1 2002/07/10 15:12:37 fredette Exp $
+
+SRCS+= rtld_start.S hppa_reloc.c
+
+# XXX Should not be in CPPFLAGS!
+CPPFLAGS+= -fpic
+
+CPPFLAGS+= -DELFSIZE=32 #-DVARPSZ
+#CPPFLAGS+= -DRTLD_DEBUG
+#CPPFLAGS+= -DRTLD_DEBUG_RELOC
+#CPPFLAGS+= -DRTLD_DEBUG_HPPA
+
+LDFLAGS+= -Bshareable -Bsymbolic -e '$$rtld_start'
+LDFLAGS+= --script ${.CURDIR}/arch/hppa/ld.so.script
+
+# XXX fredette - the libgcc millicode is needed here:
+LDADD=`$(CC) -print-libgcc-file-name`
diff -r 37186e76ee93 -r 1158c6ce5911 libexec/ld.elf_so/arch/hppa/hppa_reloc.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/libexec/ld.elf_so/arch/hppa/hppa_reloc.c  Wed Jul 10 15:12:33 2002 +0000
@@ -0,0 +1,337 @@
+/*     $NetBSD: hppa_reloc.c,v 1.1 2002/07/10 15:12:38 fredette Exp $  */
+
+/*-
+ * Copyright (c) 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Fredette.
+ *
+ * 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 the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 FOUNDATION OR CONTRIBUTORS
+ * 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.
+ */
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/queue.h>
+
+#include "rtld.h"
+#include "debug.h"
+
+#ifdef RTLD_DEBUG_HPPA
+#define        hdbg(x)         if (dodebug) xprintf x
+#else
+#define        hdbg(x)         /* nothing */
+#endif
+
+/*
+ * In the runtime architecture (ABI), PLABEL function 
+ * pointers are distinguished from normal function 
+ * pointers by having the next-least-significant bit
+ * set.  (This bit is referred to as the L field in
+ * HP documentation).  The $$dyncall millicode is
+ * aware of this.
+ */
+#define        RTLD_MAKE_PLABEL(plabel)        (((Elf_Addr)(plabel)) | (1 << 1))
+#define RTLD_IS_PLABEL(addr)           (((Elf_Addr)(addr)) & (1 << 1))
+#define        RTLD_GET_PLABEL(addr)   ((hppa_plabel *) (((Elf_Addr)addr) & ~3))
+
+/*
+ * This is the PLABEL structure.  The function PC and
+ * shared linkage members must come first, as they are
+ * the actual PLABEL.
+ */
+typedef struct _hppa_plabel {
+       Elf_Addr        hppa_plabel_pc;
+       Elf_Addr        hppa_plabel_sl;
+       SLIST_ENTRY(_hppa_plabel)       hppa_plabel_next;
+} hppa_plabel;
+
+/*
+ * For now allocated PLABEL structures are tracked on a 
+ * singly linked list.  This maybe should be revisited.
+ */
+static SLIST_HEAD(hppa_plabel_head, _hppa_plabel) hppa_plabel_list
+    = SLIST_HEAD_INITIALIZER(hppa_plabel_list);
+
+/*
+ * Because I'm hesitant to use NEW while relocating self,
+ * this is a small pool of preallocated PLABELs.
+ */
+#define        HPPA_PLABEL_PRE (10)
+static hppa_plabel hppa_plabel_pre[HPPA_PLABEL_PRE];
+static int hppa_plabel_pre_next = 0;
+
+/*
+ * The DT_PLTGOT _DYNAMIC entry always gives the linkage table 
+ * pointer for an object.  This is often, but not always, the
+ * same as the object's value for _GLOBAL_OFFSET_TABLE_.  We
+ * cache one object's GOT value, otherwise we look it up.
+ * XXX it would be nice to be able to keep this in the Obj_Entry.
+ */
+static const Obj_Entry *hppa_got_cache_obj = NULL;
+static Elf_Addr *hppa_got_cache_got;
+#define HPPA_OBJ_SL(obj)       ((obj)->pltgot)
+#define        HPPA_OBJ_GOT(obj)       ((obj) == hppa_got_cache_obj ?          \
+                                 hppa_got_cache_got :                  \
+                                 _rtld_fill_hppa_got_cache(obj))
+static Elf_Addr *_rtld_fill_hppa_got_cache __P((const Obj_Entry *));
+
+/*
+ * This bootstraps the dynamic linker by relocating its GOT.
+ * On the hppa, unlike on other architectures, static strings
+ * are found through the GOT.  Static strings are essential
+ * for RTLD_DEBUG, and I suspect they're used early even when 
+ * !defined(RTLD_DEBUG), making relocating the GOT essential.
+ *
+ * It gets worse.  Relocating the GOT doesn't mean just walking
+ * it and adding the relocbase to all of the entries.  You must
+ * find and use the GOT relocations, since those RELA relocations 
+ * have the necessary addends - the GOT comes initialized as 
+ * zeroes.
+ */
+void
+_rtld_bootstrap_hppa_got(Elf_Dyn *dynp, Elf_Addr relocbase,
+    Elf_Addr got_begin, Elf_Addr got_end)
+{
+       const Elf_Rela  *relafirst, *rela, *relalim;
+       Elf_Addr        relasz = 0;
+       Elf_Addr        where;
+
+       /* 
+        * Process the DYNAMIC section, looking for the non-PLT
+        * relocations.
+        */ 
+       relafirst = NULL;
+       for (; dynp->d_tag != DT_NULL; ++dynp) {
+               switch (dynp->d_tag) {
+
+               case DT_RELA:
+                       relafirst = (const Elf_Rela *)
+                           (relocbase + dynp->d_un.d_ptr);
+                       break;
+
+               case DT_RELASZ:
+                       relasz = dynp->d_un.d_val;
+                       break;
+               }
+       }
+       relalim = (const Elf_Rela *)((caddr_t)relafirst + relasz);
+
+       /* 
+        * Process all relocations that look like they're in 
+        * the GOT.
+        */
+       for(rela = relafirst; rela < relalim; rela++) {
+               where = (Elf_Addr)(relocbase + rela->r_offset);
+               if (where >= got_begin && where < got_end)
+                       *((Elf_Addr *)where) = relocbase + rela->r_addend;
+       }
+
+#if defined(RTLD_DEBUG_HPPA)
+       for(rela = relafirst; rela < relalim; rela++) {
+               where = (Elf_Addr)(relocbase + rela->r_offset);
+               if (where >= got_begin && where < got_end)
+                       xprintf("GOT rela @%p(%p) -> %p(%p)\n",
+                           (void *)rela->r_offset,
+                           (void *)where,
+                           (void *)rela->r_addend,
+                           (void *)*((Elf_Addr *)where));
+       }
+#endif /* RTLD_DEBUG_HPPA */
+}
+
+/*
+ * This looks up the object's _GLOBAL_OFFSET_TABLE_
+ * and caches the result.
+ */
+static Elf_Addr *
+_rtld_fill_hppa_got_cache(const Obj_Entry *obj)
+{
+       const char *name = "_GLOBAL_OFFSET_TABLE_";
+       unsigned long hash;
+       const Elf_Sym *def;
+
+       hash = _rtld_elf_hash(name);
+       def = _rtld_symlook_obj(name, hash, obj, true);
+       assert(def != NULL);
+       hppa_got_cache_obj = obj;
+       return hppa_got_cache_got = 
+           (Elf_Addr *)(obj->relocbase + def->st_value);
+}
+
+/* This sets up an object's GOT. */
+void
+_rtld_setup_hppa_pltgot(const Obj_Entry *obj)
+{
+       __rtld_setup_hppa_pltgot(obj, HPPA_OBJ_GOT(obj));
+}
+
+/*
+ * This allocates a PLABEL.  If called with a non-NULL def, the 
+ * plabel is for the function associated with that definition
+ * in the defining object defobj, plus the given addend.  If 
+ * called with a NULL def, the plabel is for the function at
+ * the (unrelocated) address in addend in the object defobj.
+ */
+Elf_Addr
+_rtld_function_descriptor_alloc(const Obj_Entry *defobj, const Elf_Sym *def,
+    Elf_Addr addend)
+{
+       Elf_Addr        func_pc, func_sl;
+       hppa_plabel     *plabel;
+
+       if (def != NULL) {
+       
+               /*
+                * We assume that symbols of type STT_NOTYPE
+                * are undefined.  Return NULL for these.
+                */
+               if (ELF_ST_TYPE(def->st_info) == STT_NOTYPE)
+                       return (Elf_Addr)NULL;
+
+               /* Otherwise assert that this symbol must be a function. */
+               assert(ELF_ST_TYPE(def->st_info) == STT_FUNC);
+
+               func_pc = (Elf_Addr)(defobj->relocbase + def->st_value + 
+                   addend);
+       } else
+               func_pc = (Elf_Addr)(defobj->relocbase + addend);
+
+       /*
+        * Search the existing PLABELs for one matching
+        * this function.  If there is one, return it.
+        */
+       func_sl = (Elf_Addr)HPPA_OBJ_SL(defobj);



Home | Main Index | Thread Index | Old Index