rtld: Implement ELF filters (DT_FILTER and DT_AUXILIARY)
[dragonfly.git] / libexec / rtld-elf / i386 / reloc.c
index f1292d3..5b0c68a 100644 (file)
@@ -22,7 +22,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD: src/libexec/rtld-elf/i386/reloc.c,v 1.22 2010/12/25 08:51:20 kib Exp $
+ * $FreeBSD$
  */
 
 /*
@@ -65,29 +65,34 @@ do_copy_relocations(Obj_Entry *dstobj)
 
     assert(dstobj->mainprog);  /* COPY relocations are invalid elsewhere */
 
-    rellim = (const Elf_Rel *) ((c_caddr_t) dstobj->rel + dstobj->relsize);
+    rellim = (const Elf_Rel *) ((caddr_t) dstobj->rel + dstobj->relsize);
     for (rel = dstobj->rel;  rel < rellim;  rel++) {
        if (ELF_R_TYPE(rel->r_info) == R_386_COPY) {
            void *dstaddr;
            const Elf_Sym *dstsym;
            const char *name;
-           unsigned long hash;
            size_t size;
            const void *srcaddr;
            const Elf_Sym *srcsym;
-           const Ver_Entry *ve;
-           Obj_Entry *srcobj;
+           const Obj_Entry *srcobj, *defobj;
+           SymLook req;
+           int res;
 
            dstaddr = (void *) (dstobj->relocbase + rel->r_offset);
            dstsym = dstobj->symtab + ELF_R_SYM(rel->r_info);
            name = dstobj->strtab + dstsym->st_name;
-           hash = elf_hash(name);
            size = dstsym->st_size;
-           ve = fetch_ventry(dstobj, ELF_R_SYM(rel->r_info));
-
-           for (srcobj = dstobj->next;  srcobj != NULL;  srcobj = srcobj->next)
-               if ((srcsym = symlook_obj(name, hash, srcobj, ve, 0)) != NULL)
+           symlook_init(&req, name);
+           req.ventry = fetch_ventry(dstobj, ELF_R_SYM(rel->r_info));
+
+           for (srcobj = dstobj->next;  srcobj != NULL;  srcobj = srcobj->next) {
+               res = symlook_obj(&req, srcobj);
+               if (res == 0) {
+                   srcsym = req.sym_out;
+                   defobj = req.defobj_out;
                    break;
+               }
+           }
 
            if (srcobj == NULL) {
                _rtld_error("Undefined symbol \"%s\" referenced from COPY"
@@ -95,7 +100,7 @@ do_copy_relocations(Obj_Entry *dstobj)
                return -1;
            }
 
-           srcaddr = (const void *) (srcobj->relocbase + srcsym->st_value);
+           srcaddr = (const void *) (defobj->relocbase + srcsym->st_value);
            memcpy(dstaddr, srcaddr, size);
        }
     }
@@ -115,7 +120,7 @@ init_pltgot(Obj_Entry *obj)
 
 /* Process the non-PLT relocations. */
 int
-reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld)
+reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, RtldLockState *lockstate)
 {
        const Elf_Rel *rellim;
        const Elf_Rel *rel;
@@ -132,7 +137,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld)
        } else
            cache = NULL;
 
-       rellim = (const Elf_Rel *) ((c_caddr_t) obj->rel + obj->relsize);
+       rellim = (const Elf_Rel *) ((caddr_t) obj->rel + obj->relsize);
        for (rel = obj->rel;  rel < rellim;  rel++) {
            Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rel->r_offset);
 
@@ -147,7 +152,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld)
                    const Obj_Entry *defobj;
 
                    def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
-                     false, cache);
+                     false, cache, lockstate);
                    if (def == NULL)
                        goto done;
 
@@ -166,7 +171,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld)
                    const Obj_Entry *defobj;
 
                    def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
-                     false, cache);
+                     false, cache, lockstate);
                    if (def == NULL)
                        goto done;
 
@@ -196,7 +201,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld)
                    const Obj_Entry *defobj;
 
                    def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
-                     false, cache);
+                     false, cache, lockstate);
                    if (def == NULL)
                        goto done;
 
@@ -214,7 +219,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld)
                    const Obj_Entry *defobj;
 
                    def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
-                     false, cache);
+                     false, cache, lockstate);
                    if (def == NULL)
                        goto done;
 
@@ -274,7 +279,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld)
                    const Obj_Entry *defobj;
 
                    def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
-                     false, cache);
+                     false, cache, lockstate);
                    if (def == NULL)
                        goto done;
 
@@ -288,7 +293,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld)
                    const Obj_Entry *defobj;
 
                    def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
-                     false, cache);
+                     false, cache, lockstate);
                    if (def == NULL)
                        goto done;
 
@@ -339,14 +344,14 @@ reloc_plt(Obj_Entry *obj)
 
 /* Relocate the jump slots in an object. */
 int
-reloc_jmpslots(Obj_Entry *obj)
+reloc_jmpslots(Obj_Entry *obj, RtldLockState *lockstate)
 {
     const Elf_Rel *rellim;
     const Elf_Rel *rel;
 
     if (obj->jmpslots_done)
        return 0;
-    rellim = (const Elf_Rel *)((const char *)obj->pltrel + obj->pltrelsize);
+    rellim = (const Elf_Rel *)((char *)obj->pltrel + obj->pltrelsize);
     for (rel = obj->pltrel;  rel < rellim;  rel++) {
        Elf_Addr *where, target;
        const Elf_Sym *def;
@@ -355,7 +360,8 @@ reloc_jmpslots(Obj_Entry *obj)
        switch (ELF_R_TYPE(rel->r_info)) {
        case R_386_JMP_SLOT:
          where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
-         def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true, NULL);
+         def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true, NULL,
+             lockstate);
          if (def == NULL)
              return (-1);
          target = (Elf_Addr)(defobj->relocbase + def->st_value);