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>