summaryrefslogtreecommitdiffstats
path: root/libexec/rtld-elf/ia64
diff options
context:
space:
mode:
authordillon <dillon@FreeBSD.org>2002-06-22 18:36:21 +0000
committerdillon <dillon@FreeBSD.org>2002-06-22 18:36:21 +0000
commit7b9815cfbebc18bbc15daea92d4f6bfe511fa38b (patch)
tree458b0224bcffec8a0352f8cfc61a391b53c71cba /libexec/rtld-elf/ia64
parente904c7f5434bb9ebfeb97d1f2a5c31d76781e853 (diff)
downloadFreeBSD-src-7b9815cfbebc18bbc15daea92d4f6bfe511fa38b.zip
FreeBSD-src-7b9815cfbebc18bbc15daea92d4f6bfe511fa38b.tar.gz
The last bits of the alloca -> mmap fix. IA64 and SPARC64 (current only).
Untested (testing request went unanswered), but sparc64 is not expected to cause problems. IA64 is not expected to cause problems but the patch was slightly more complex so the possibility exists. Approved by: jdp
Diffstat (limited to 'libexec/rtld-elf/ia64')
-rw-r--r--libexec/rtld-elf/ia64/reloc.c60
1 files changed, 43 insertions, 17 deletions
diff --git a/libexec/rtld-elf/ia64/reloc.c b/libexec/rtld-elf/ia64/reloc.c
index 581f4be..5a054c8 100644
--- a/libexec/rtld-elf/ia64/reloc.c
+++ b/libexec/rtld-elf/ia64/reloc.c
@@ -190,24 +190,35 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld)
const Elf_Rela *rela;
SymCache *cache;
struct fptr **fptrs;
+ int bytes = obj->nchains * sizeof(SymCache);
+ int fbytes = obj->nchains * sizeof(struct fptr *);
+ int r = -1;
- cache = (SymCache *)alloca(obj->nchains * sizeof(SymCache));
+ /*
+ * The dynamic loader may be called from a thread, we have
+ * limited amounts of stack available so we cannot use alloca().
+ */
+ cache = mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0);
+ if (cache == MAP_FAILED)
+ cache = NULL;
if (cache != NULL)
- memset(cache, 0, obj->nchains * sizeof(SymCache));
+ memset(cache, 0, bytes);
/*
* When relocating rtld itself, we need to avoid using malloc.
*/
- if (obj == obj_rtld)
- fptrs = (struct fptr **)
- alloca(obj->nchains * sizeof(struct fptr *));
- else
+ 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)
- return -1;
- memset(fptrs, 0, obj->nchains * sizeof(struct fptr *));
+ goto done;
+ memset(fptrs, 0, fbytes);
/* Perform relocations without addend if there are any: */
rellim = (const Elf_Rel *) ((caddr_t) obj->rel + obj->relsize);
@@ -218,28 +229,43 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld)
locrela.r_offset = rel->r_offset;
locrela.r_addend = 0;
if (reloc_non_plt_obj(obj_rtld, obj, &locrela, cache, fptrs))
- return -1;
+ 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))
- return -1;
+ goto done;
}
/*
* Remember the fptrs in case of later calls to dlsym(). Don't
* bother for rtld - we will lazily create a table in
- * make_function_pointer(). At this point we still can't risk
- * calling malloc().
+ * make_function_pointer(). We still can't risk calling malloc()
+ * in the rtld case.
+ *
+ * When remembering fptrs, NULL out our local fptrs variable so we
+ * do not free it.
*/
- if (obj != obj_rtld)
- obj->priv = fptrs;
- else
+ if (obj == obj_rtld) {
obj->priv = NULL;
+ } else {
+ obj->priv = fptrs;
+ fptrs = NULL;
+ }
- return 0;
+ r = 0;
+done:
+ if (cache)
+ munmap(cache, bytes);
+ if (fptrs) {
+ if (obj == obj_rtld)
+ munmap(fptrs, fbytes);
+ else
+ free(fptrs);
+ }
+ return (r);
}
/* Process the PLT relocations. */
OpenPOWER on IntegriCloud