Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 6 Mar 2003 18:16:40 -0800
From:      Arun Sharma <arun.sharma@intel.com>
To:        freebsd-ia64@freebsd.org
Cc:        jdp@freebsd.org
Subject:   Review fix for ia64/48024 
Message-ID:  <200303070216.h272Gev29185@unix-os.sc.intel.com>

next in thread | raw e-mail | index | archive | help

The following changes are proposed to: rtld-elf 

- factor out alloc_fptrs into a function of its own
- update the fptrs array of the defining object rather than the
  referencing object
- We use the same algorithm to index fptrs array now in
  make_function_pointer and reloc_non_plt_obj.

Issues:

- Is it possible to make an out of bounds access to the fptr array ?

	-Arun

--- ia64/reloc.c-	Fri Mar  7 02:06:30 2003
+++ ia64/reloc.c	Fri Mar  7 02:06:16 2003
@@ -77,6 +77,31 @@
 static struct fptr *next_fptr = &first_chunk.fptrs[0];
 static struct fptr *last_fptr = &first_chunk.fptrs[FPTR_CHUNK_SIZE];
 
+static struct fptr **
+alloc_fptrs(const Obj_Entry *obj, Obj_Entry *obj_rtld)
+{
+	struct fptr **fptrs;
+	int fbytes = obj->nchains * sizeof(struct fptr *);
+
+        /*
+         * When relocating rtld itself, we need to avoid using malloc.
+         */
+        if (obj == obj_rtld) {
+                fptrs = mmap(NULL, fbytes, PROT_READ|PROT_WRITE,
+                            MAP_ANON, -1, 0);
+                if (fptrs == MAP_FAILED)
+                        fptrs = NULL;
+        } else {
+                fptrs = (struct fptr **)
+                        malloc(obj->nchains * sizeof(struct fptr *));
+        }
+
+	if (fptrs != NULL)
+		memset(fptrs, 0, fbytes);
+
+	return fptrs;
+}
+
 /*
  * We use static storage initially so that we don't have to call
  * malloc during init_rtld().
@@ -101,8 +126,9 @@
 /* Relocate a non-PLT object with addend. */
 static int
 reloc_non_plt_obj(Obj_Entry *obj_rtld, Obj_Entry *obj, const Elf_Rela *rela,
-		  SymCache *cache, struct fptr **fptrs)
+		  SymCache *cache)
 {
+	struct fptr **fptrs;
 	Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rela->r_offset);
 
 	switch (ELF_R_TYPE(rela->r_info)) {
@@ -135,9 +161,7 @@
 		/*
 		 * We have to make sure that all @fptr references to
 		 * the same function are identical so that code can
-		 * compare function pointers. We actually only bother
-		 * to ensure this within a single object. If the
-		 * caller's alloca failed, we don't even ensure that.
+		 * compare function pointers. 
 		 */
 		const Elf_Sym *def;
 		const Obj_Entry *defobj;
@@ -150,18 +174,28 @@
 			return -1;
 
 		if (def->st_shndx != SHN_UNDEF) {
+			int index;
 			target = (Elf_Addr)(defobj->relocbase + def->st_value);
 			gp = (Elf_Addr)defobj->pltgot;
+			fptrs = defobj->priv;
+			index = def - defobj->symtab;
+
+			if (!fptrs) {
+				/* Need to allocate one */
+				fptrs = alloc_fptrs(defobj, obj_rtld);
+				if (fptrs)
+					((Obj_Entry*) defobj)->priv = fptrs;
+			}
 
 			/*
 			 * Find the @fptr, using fptrs as a helper.
 			 */
 			if (fptrs)
-				fptr = fptrs[ELF_R_SYM(rela->r_info)];
+				fptr = fptrs[index];
 			if (!fptr) {
 				fptr = alloc_fptr(target, gp);
 				if (fptrs)
-					fptrs[ELF_R_SYM(rela->r_info)] = fptr;
+					fptrs[index] = fptr;
 			}
 		} else
 			fptr = NULL;
@@ -221,7 +255,6 @@
 	SymCache *cache;
 	struct fptr **fptrs;
 	int bytes = obj->nchains * sizeof(SymCache);
-	int fbytes = obj->nchains * sizeof(struct fptr *);
 	int r = -1;
 
 	/*
@@ -234,21 +267,9 @@
 	if (cache != NULL)
 		memset(cache, 0, bytes);
 
-	/*
-	 * When relocating rtld itself, we need to avoid using malloc.
-	 */
-        if (obj == obj_rtld) {
-		fptrs = mmap(NULL, fbytes, PROT_READ|PROT_WRITE, 
-			    MAP_ANON, -1, 0);
-		if (fptrs == MAP_FAILED)
-			fptrs = NULL;
-	} else {
-		fptrs = (struct fptr **)
-			malloc(obj->nchains * sizeof(struct fptr *));
-	}
+	fptrs = alloc_fptrs(obj, obj_rtld);
 	if (fptrs == NULL)
 		goto done;
-	memset(fptrs, 0, fbytes);
 
 	/* Perform relocations without addend if there are any: */
 	rellim = (const Elf_Rel *) ((caddr_t) obj->rel + obj->relsize);
@@ -258,14 +279,14 @@
 		locrela.r_info = rel->r_info;
 		locrela.r_offset = rel->r_offset;
 		locrela.r_addend = 0;
-		if (reloc_non_plt_obj(obj_rtld, obj, &locrela, cache, fptrs))
+		if (reloc_non_plt_obj(obj_rtld, obj, &locrela, cache))
 			goto done;
 	}
 
 	/* Perform relocations with addend if there are any: */
 	relalim = (const Elf_Rela *) ((caddr_t) obj->rela + obj->relasize);
 	for (rela = obj->rela;  obj->rela != NULL && rela < relalim;  rela++) {
-		if (reloc_non_plt_obj(obj_rtld, obj, rela, cache, fptrs))
+		if (reloc_non_plt_obj(obj_rtld, obj, rela, cache))
 			goto done;
 	}
 
@@ -290,10 +311,12 @@
 	if (cache)
 		munmap(cache, bytes);
 	if (fptrs) {
-		if (obj == obj_rtld)
+		if (obj == obj_rtld) {
+			int fbytes = obj->nchains * sizeof(struct fptr *);
 			munmap(fptrs, fbytes);
-		else
+		} else {
 			free(fptrs);
+		}
 	}
 	return (r);
 }
@@ -449,9 +472,9 @@
 		 * dlsym("dlopen"). Actually, I'm not sure it can ever 
 		 * happen.
 		 */
-		fptrs = (struct fptr **)
-			malloc(obj->nchains * sizeof(struct fptr *));
-		memset(fptrs, 0, obj->nchains * sizeof(struct fptr *));
+
+		/* assume obj != obj_rtld */
+		fptrs = alloc_fptrs((Obj_Entry *) obj, NULL);   
 		((Obj_Entry*) obj)->priv = fptrs;
 	}
 	if (!fptrs[index]) {


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-ia64" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200303070216.h272Gev29185>