summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarmelo Amoroso <carmelo.amoroso@st.com>2011-05-04 08:31:16 +0200
committerCarmelo Amoroso <carmelo.amoroso@st.com>2011-05-04 08:31:16 +0200
commit3004ce0c9619f89bf8e64931edd696bf4df8d2e1 (patch)
treef03f898fa5c2506c4e30f5f89ce097acf01bc016
parent3b3285b1b7c02d36c74a6ae265fdb02ca991c96b (diff)
parent4916fd889ec1c60710faa528a3ccdb50973198e2 (diff)
Merge remote-tracking branch 'origin/master' into prelink
* origin/master: (32 commits) libubacktrace: fix backtrace support on arm-eabi, which needs libgcc_eh linked too getaddrinfo.c: fix incorrect check for ERANGE from gethostbyaddr_r getaddrinfo.c: improve code readability. No functional changes string: remove unused variable x86_64: silence warning if !TLS buildsys: prettify ssp.c handling madvise is LINUX_SPECIFIC test_nptl: fix expected result for tst-cputimer[123] test_nptl: fix expected result for tst-clock2 test buildsys: make $(LOCAL_INSTALL_PATH) phony ether_aton: reject invalid input tests: disable ether tests if !HAS_SOCKET inet: add ether_aton testcase sysconf: clock_getres depends on HAS_REALTIME __rt_sigwaitinfo: depends on HAS_REALTIME buildsys: minor fixes in Makefile.arch for C6X buildsys: minor fixes in Makefile.arch for microblaze libubacktrace: enabled for all archs indeed. sparc: don't access fp registers when configured for no fpu libubacktrace: generic implementation based dwarf ... Conflicts: ldso/ldso/dl-elf.c ldso/ldso/mips/elfinterp.c ldso/ldso/x86_64/elfinterp.c Signed-off-by: Carmelo Amoroso <carmelo.amoroso@st.com>
-rw-r--r--Makefile.in2
-rw-r--r--Rules.mak2
-rw-r--r--extra/Configs/Config.in14
-rw-r--r--include/fts.h131
-rw-r--r--ldso/include/dl-elf.h2
-rw-r--r--ldso/include/ldso.h2
-rw-r--r--ldso/ldso/bfin/dl-inlines.h41
-rw-r--r--ldso/ldso/bfin/dl-sysdep.h2
-rw-r--r--ldso/ldso/c6x/dl-inlines.h29
-rw-r--r--ldso/ldso/c6x/dl-sysdep.h3
-rw-r--r--ldso/ldso/c6x/elfinterp.c6
-rw-r--r--ldso/ldso/dl-elf.c318
-rw-r--r--ldso/ldso/dl-startup.c16
-rw-r--r--ldso/ldso/frv/dl-inlines.h41
-rw-r--r--ldso/ldso/frv/dl-sysdep.h2
-rw-r--r--ldso/ldso/mips/elfinterp.c5
-rw-r--r--ldso/ldso/x86_64/elfinterp.c8
-rw-r--r--libc/inet/ether_addr.c6
-rw-r--r--libc/inet/getaddrinfo.c60
-rw-r--r--libc/inet/resolv.c2
-rw-r--r--libc/misc/Makefile.in1
-rw-r--r--libc/misc/fts/Makefile14
-rw-r--r--libc/misc/fts/Makefile.in23
-rw-r--r--libc/misc/fts/fts.c1145
-rw-r--r--libc/stdlib/malloc/heap.h6
-rw-r--r--libc/stdlib/malloc/malloc.h2
-rw-r--r--libc/string/generic/strnlen.c4
-rw-r--r--libc/sysdeps/linux/Makefile.commonarch2
-rw-r--r--libc/sysdeps/linux/c6x/Makefile.arch5
-rw-r--r--libc/sysdeps/linux/common/Makefile.in11
-rw-r--r--libc/sysdeps/linux/microblaze/Makefile.arch2
-rw-r--r--libc/sysdeps/linux/sparc/soft-fp/sfp-machine.h2
-rw-r--r--libc/unistd/sysconf.c5
-rw-r--r--libubacktrace/Makefile.in25
-rw-r--r--libubacktrace/backtrace.c75
-rw-r--r--libubacktrace/sysdeps/sh/Makefile.arch12
-rw-r--r--libubacktrace/sysdeps/sh/backtrace.c84
-rw-r--r--test/inet/Makefile.in6
-rw-r--r--test/inet/tst-ether_aton.c46
-rw-r--r--test/nptl/Makefile.in5
-rw-r--r--test/nptl/tst-clock2.c2
-rw-r--r--test/tls/Makefile.in1
-rw-r--r--test/tls/tst-tls13.c2
43 files changed, 1816 insertions, 356 deletions
diff --git a/Makefile.in b/Makefile.in
index 0c1f414ec..2f8370b0f 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -185,6 +185,7 @@ $(top_builddir)include/bits/sysnum.h: $(top_srcdir)extra/scripts/gen_bits_syscal
exit 1; \
fi
+.PHONY: $(LOCAL_INSTALL_PATH)
$(LOCAL_INSTALL_PATH):
$(Q)$(MAKE) PREFIX=$(shell pwd)/$(LOCAL_INSTALL_PATH) RUNTIME_PREFIX=/ \
DEVEL_PREFIX=/usr/ \
@@ -239,6 +240,7 @@ HEADERS_RM-$(UCLIBC_HAS_FLOATS) += complex.h fpu_control.h ieee754.
tgmath.h \
bits/math*.h
HEADERS_RM-$(findstring y,$(UCLIBC_HAS_FTW)$(UCLIBC_HAS_NFTW)) += ftw.h
+HEADERS_RM-$(UCLIBC_HAS_FTS) += fts.h
HEADERS_RM-$(UCLIBC_HAS_GETTEXT_AWARENESS) += libintl.h
HEADERS_RM-$(UCLIBC_HAS_GLIBC_CUSTOM_PRINTF) += printf.h
HEADERS_RM-$(UCLIBC_HAS_GLOB) += glob.h
diff --git a/Rules.mak b/Rules.mak
index 0aa684342..49ca2072a 100644
--- a/Rules.mak
+++ b/Rules.mak
@@ -531,7 +531,7 @@ ifdef LD_FLAG_NO_ASNEEDED
export CC_FLAG_NO_ASNEEDED:=-Wl,$(LD_FLAG_NO_ASNEEDED)
endif
endif
-link.asneeded = $(if $(and $(CC_FLAG_ASNEEDED),$(CC_FLAG_NO_ASNEEDED)),$(CC_FLAG_ASNEEDED) $(1) $(CC_FLAG_NO_ASNEEDED))
+link.asneeded = $(if $(findstring yy,$(CC_FLAG_ASNEEDED)$(CC_FLAG_NO_ASNEEDED)),$(CC_FLAG_ASNEEDED) $(1) $(CC_FLAG_NO_ASNEEDED))
# Check for AS_NEEDED support in linker script (binutils>=2.16.1 has it)
ifndef ASNEEDED
diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in
index 8cbe31847..843988959 100644
--- a/extra/Configs/Config.in
+++ b/extra/Configs/Config.in
@@ -1926,6 +1926,18 @@ config UCLIBC_HAS_FTW
This interface is rarely used, and adds around 4.5k. Unless you have
a pressing need for ftw(), you should probably answer N.
+config UCLIBC_HAS_FTS
+ bool "Support the fts() interface (bsd-compat)"
+ default n
+ help
+ The fts functions are provided for traversing UNIX file hierarchies.
+
+ This interface is currently used by the elfutils and adds
+ around 7.5k.
+ You should port your application to use the POSIX nftw()
+ interface.
+
+ Unless you need to build/use elfutils, you should prolly answer N.
config UCLIBC_HAS_GLOB
bool "Support the glob() interface"
@@ -2350,7 +2362,7 @@ config UCLIBC_MALLOC_DEBUGGING
config UCLIBC_HAS_BACKTRACE
bool "Add support for application self-debugging"
- depends on HAVE_SHARED && TARGET_sh
+ depends on HAVE_SHARED
default n
help
Answer Y here to compile support for application self-debugging, by adding
diff --git a/include/fts.h b/include/fts.h
new file mode 100644
index 000000000..0a070ba8d
--- /dev/null
+++ b/include/fts.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ * @(#)fts.h 8.3 (Berkeley) 8/14/94
+ */
+
+#ifndef _FTS_H
+#define _FTS_H 1
+
+#include <features.h>
+#include <sys/types.h>
+
+/* The fts interface is incompatible with the LFS interface which
+ transparently uses the 64-bit file access functions. */
+#ifdef __USE_FILE_OFFSET64
+# error "<fts.h> cannot be used with -D_FILE_OFFSET_BITS==64"
+#endif
+
+
+typedef struct {
+ struct _ftsent *fts_cur; /* current node */
+ struct _ftsent *fts_child; /* linked list of children */
+ struct _ftsent **fts_array; /* sort array */
+ dev_t fts_dev; /* starting device # */
+ char *fts_path; /* path for this descent */
+ int fts_rfd; /* fd for root */
+ int fts_pathlen; /* sizeof(path) */
+ int fts_nitems; /* elements in the sort array */
+ int (*fts_compar) (const void *, const void *); /* compare fn */
+
+#define FTS_COMFOLLOW 0x0001 /* follow command line symlinks */
+#define FTS_LOGICAL 0x0002 /* logical walk */
+#define FTS_NOCHDIR 0x0004 /* don't change directories */
+#define FTS_NOSTAT 0x0008 /* don't get stat info */
+#define FTS_PHYSICAL 0x0010 /* physical walk */
+#define FTS_SEEDOT 0x0020 /* return dot and dot-dot */
+#define FTS_XDEV 0x0040 /* don't cross devices */
+#define FTS_WHITEOUT 0x0080 /* return whiteout information */
+#define FTS_OPTIONMASK 0x00ff /* valid user option mask */
+
+#define FTS_NAMEONLY 0x0100 /* (private) child names only */
+#define FTS_STOP 0x0200 /* (private) unrecoverable error */
+ int fts_options; /* fts_open options, global flags */
+} FTS;
+
+typedef struct _ftsent {
+ struct _ftsent *fts_cycle; /* cycle node */
+ struct _ftsent *fts_parent; /* parent directory */
+ struct _ftsent *fts_link; /* next file in directory */
+ long fts_number; /* local numeric value */
+ void *fts_pointer; /* local address value */
+ char *fts_accpath; /* access path */
+ char *fts_path; /* root path */
+ int fts_errno; /* errno for this node */
+ int fts_symfd; /* fd for symlink */
+ u_short fts_pathlen; /* strlen(fts_path) */
+ u_short fts_namelen; /* strlen(fts_name) */
+
+ ino_t fts_ino; /* inode */
+ dev_t fts_dev; /* device */
+ nlink_t fts_nlink; /* link count */
+
+#define FTS_ROOTPARENTLEVEL -1
+#define FTS_ROOTLEVEL 0
+ short fts_level; /* depth (-1 to N) */
+
+#define FTS_D 1 /* preorder directory */
+#define FTS_DC 2 /* directory that causes cycles */
+#define FTS_DEFAULT 3 /* none of the above */
+#define FTS_DNR 4 /* unreadable directory */
+#define FTS_DOT 5 /* dot or dot-dot */
+#define FTS_DP 6 /* postorder directory */
+#define FTS_ERR 7 /* error; errno is set */
+#define FTS_F 8 /* regular file */
+#define FTS_INIT 9 /* initialized only */
+#define FTS_NS 10 /* stat(2) failed */
+#define FTS_NSOK 11 /* no stat(2) requested */
+#define FTS_SL 12 /* symbolic link */
+#define FTS_SLNONE 13 /* symbolic link without target */
+#define FTS_W 14 /* whiteout object */
+ u_short fts_info; /* user flags for FTSENT structure */
+
+#define FTS_DONTCHDIR 0x01 /* don't chdir .. to the parent */
+#define FTS_SYMFOLLOW 0x02 /* followed a symlink to get here */
+ u_short fts_flags; /* private flags for FTSENT structure */
+
+#define FTS_AGAIN 1 /* read node again */
+#define FTS_FOLLOW 2 /* follow symbolic link */
+#define FTS_NOINSTR 3 /* no instructions */
+#define FTS_SKIP 4 /* discard node */
+ u_short fts_instr; /* fts_set() instructions */
+
+ struct stat *fts_statp; /* stat(2) information */
+ char fts_name[1]; /* file name */
+} FTSENT;
+
+__BEGIN_DECLS
+FTSENT *fts_children (FTS *, int);
+int fts_close (FTS *);
+FTS *fts_open (char * const *, int,
+ int (*)(const FTSENT **, const FTSENT **));
+FTSENT *fts_read (FTS *);
+int fts_set (FTS *, FTSENT *, int) __THROW;
+__END_DECLS
+
+#endif /* fts.h */
diff --git a/ldso/include/dl-elf.h b/ldso/include/dl-elf.h
index 908cb63ce..495bd2bca 100644
--- a/ldso/include/dl-elf.h
+++ b/ldso/include/dl-elf.h
@@ -222,7 +222,7 @@ unsigned int __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info
ADJUST_DYN_INFO(DT_DSBT_BASE_IDX, load_off);
/* Initialize loadmap dsbt info. */
- load_off.map->dsbt_table = dynamic_info[DT_DSBT_BASE_IDX];
+ load_off.map->dsbt_table = (void *)dynamic_info[DT_DSBT_BASE_IDX];
load_off.map->dsbt_size = dynamic_info[DT_DSBT_SIZE_IDX];
load_off.map->dsbt_index = dynamic_info[DT_DSBT_INDEX_IDX];
#endif
diff --git a/ldso/include/ldso.h b/ldso/include/ldso.h
index 9aa610e7b..3152b744a 100644
--- a/ldso/include/ldso.h
+++ b/ldso/include/ldso.h
@@ -35,6 +35,8 @@
#include <sys/types.h>
/* Pull in the arch specific page size */
#include <bits/uClibc_page.h>
+/* Pull in the MIN macro */
+#include <sys/param.h>
/* Pull in the ldso syscalls and string functions */
#ifndef __ARCH_HAS_NO_SHARED__
#include <dl-syscall.h>
diff --git a/ldso/ldso/bfin/dl-inlines.h b/ldso/ldso/bfin/dl-inlines.h
index 6524f5edc..969986218 100644
--- a/ldso/ldso/bfin/dl-inlines.h
+++ b/ldso/ldso/bfin/dl-inlines.h
@@ -88,14 +88,39 @@ __dl_init_loadaddr_hdr (struct elf32_fdpic_loadaddr loadaddr, void *addr,
segdata->p_memsz = phdr->p_memsz;
#if defined (__SUPPORT_LD_DEBUG__)
- {
- extern char *_dl_debug;
- extern int _dl_debug_file;
- if (_dl_debug)
- _dl_dprintf(_dl_debug_file, "%i: mapped %x at %x, size %x\n",
- loadaddr.map->nsegs-1,
- segdata->p_vaddr, segdata->addr, segdata->p_memsz);
- }
+ if (_dl_debug)
+ _dl_dprintf(_dl_debug_file, "%i: mapped %x at %x, size %x\n",
+ loadaddr.map->nsegs-1,
+ segdata->p_vaddr, segdata->addr, segdata->p_memsz);
+#endif
+}
+
+/* Replace an existing entry in the load map. */
+static __always_inline void
+__dl_update_loadaddr_hdr (struct elf32_fdpic_loadaddr loadaddr, void *addr,
+ Elf32_Phdr *phdr)
+{
+ struct elf32_fdpic_loadseg *segdata;
+ void *oldaddr;
+ int i;
+
+ for (i = 0; i < loadaddr.map->nsegs; i++)
+ if (loadaddr.map->segs[i].p_vaddr == phdr->p_vaddr
+ && loadaddr.map->segs[i].p_memsz == phdr->p_memsz)
+ break;
+ if (i == loadaddr.map->nsegs)
+ _dl_exit (-1);
+
+ segdata = loadaddr.map->segs + i;
+ oldaddr = (void *)segdata->addr;
+ _dl_munmap (oldaddr, segdata->p_memsz);
+ segdata->addr = (Elf32_Addr) addr;
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug)
+ _dl_dprintf(_dl_debug_file, "%i: changed mapping %x at %x (old %x), size %x\n",
+ loadaddr.map->nsegs-1,
+ segdata->p_vaddr, segdata->addr, oldaddr, segdata->p_memsz);
#endif
}
diff --git a/ldso/ldso/bfin/dl-sysdep.h b/ldso/ldso/bfin/dl-sysdep.h
index 50c750990..168e5c89a 100644
--- a/ldso/ldso/bfin/dl-sysdep.h
+++ b/ldso/ldso/bfin/dl-sysdep.h
@@ -120,6 +120,8 @@ struct funcdesc_ht;
#define DL_INIT_LOADADDR_HDR(LOADADDR, ADDR, PHDR) \
(__dl_init_loadaddr_hdr ((LOADADDR), (ADDR), (PHDR), \
dl_init_loadaddr_load_count))
+#define DL_UPDATE_LOADADDR_HDR(LOADADDR, ADDR, PHDR) \
+ (__dl_update_loadaddr_hdr ((LOADADDR), (ADDR), (PHDR)))
#define DL_LOADADDR_UNMAP(LOADADDR, LEN) \
(__dl_loadaddr_unmap ((LOADADDR), (NULL)))
#define DL_LIB_UNMAP(LIB, LEN) \
diff --git a/ldso/ldso/c6x/dl-inlines.h b/ldso/ldso/c6x/dl-inlines.h
index d8fb42c55..62e1cc9ca 100644
--- a/ldso/ldso/c6x/dl-inlines.h
+++ b/ldso/ldso/c6x/dl-inlines.h
@@ -74,6 +74,35 @@ __dl_init_loadaddr_hdr (struct elf32_dsbt_loadaddr loadaddr, void *addr,
#endif
}
+/* Replace an existing entry in the load map. */
+static __always_inline void
+__dl_update_loadaddr_hdr (struct elf32_dsbt_loadaddr loadaddr, void *addr,
+ Elf32_Phdr *phdr)
+{
+ struct elf32_dsbt_loadseg *segdata;
+ void *oldaddr;
+ int i;
+
+ for (i = 0; i < loadaddr.map->nsegs; i++)
+ if (loadaddr.map->segs[i].p_vaddr == phdr->p_vaddr
+ && loadaddr.map->segs[i].p_memsz == phdr->p_memsz)
+ break;
+ if (i == loadaddr.map->nsegs)
+ _dl_exit (-1);
+
+ segdata = loadaddr.map->segs + i;
+ oldaddr = (void *)segdata->addr;
+ _dl_munmap (oldaddr, segdata->p_memsz);
+ segdata->addr = (Elf32_Addr) addr;
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug)
+ _dl_dprintf(_dl_debug_file, "%i: changed mapping %x at %x (old %x), size %x\n",
+ loadaddr.map->nsegs-1,
+ segdata->p_vaddr, segdata->addr, oldaddr, segdata->p_memsz);
+#endif
+}
+
static __always_inline void
__dl_loadaddr_unmap (struct elf32_dsbt_loadaddr loadaddr)
{
diff --git a/ldso/ldso/c6x/dl-sysdep.h b/ldso/ldso/c6x/dl-sysdep.h
index 8f1b122d3..ff7accdf1 100644
--- a/ldso/ldso/c6x/dl-sysdep.h
+++ b/ldso/ldso/c6x/dl-sysdep.h
@@ -104,6 +104,9 @@ struct elf32_dsbt_loadaddr;
(__dl_init_loadaddr_hdr ((LOADADDR), (ADDR), (PHDR), \
dl_init_loadaddr_load_count))
+#define DL_UPDATE_LOADADDR_HDR(LOADADDR, ADDR, PHDR) \
+ (__dl_update_loadaddr_hdr ((LOADADDR), (ADDR), (PHDR)))
+
#define DL_LOADADDR_UNMAP(LOADADDR, LEN) \
(__dl_loadaddr_unmap ((LOADADDR)))
diff --git a/ldso/ldso/c6x/elfinterp.c b/ldso/ldso/c6x/elfinterp.c
index 7c79171ce..f5d3ad41e 100644
--- a/ldso/ldso/c6x/elfinterp.c
+++ b/ldso/ldso/c6x/elfinterp.c
@@ -198,6 +198,10 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
new_val = sym_val;
*reloc_addr = sym_val;
break;
+ case R_C6000_DSBT_INDEX:
+ new_val = (old_val & ~0x007fff00) | ((tpnt->loadaddr.map->dsbt_index & 0x7fff) << 8);
+ *reloc_addr = new_val;
+ break;
case R_C6000_ABS_L16:
new_val = (old_val & ~0x007fff80) | ((sym_val & 0xffff) << 7);
*reloc_addr = new_val;
@@ -224,7 +228,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
(char *)symbol_addr,
symtab[symtab_index].st_size);
}
- break;
+ return 0;
default:
return -1; /*call _dl_exit(1) */
}
diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c
index a881b7df7..9e1415b83 100644
--- a/ldso/ldso/dl-elf.c
+++ b/ldso/ldso/dl-elf.c
@@ -314,6 +314,121 @@ goof:
return NULL;
}
+/*
+ * Make a writeable mapping of a segment, regardless of whether PF_W is
+ * set or not.
+ */
+static void *
+map_writeable (int infile, ElfW(Phdr) *ppnt, int piclib, int flags,
+ unsigned long libaddr)
+{
+ int prot_flags = ppnt->p_flags | PF_W;
+ char *status, *retval;
+ char *tryaddr;
+ ssize_t size;
+ unsigned long map_size;
+ char *cpnt;
+ char *piclib2map = NULL;
+
+ if (piclib == 2 &&
+ /* We might be able to avoid this call if memsz doesn't
+ require an additional page, but this would require mmap
+ to always return page-aligned addresses and a whole
+ number of pages allocated. Unfortunately on uClinux
+ may return misaligned addresses and may allocate
+ partial pages, so we may end up doing unnecessary mmap
+ calls.
+
+ This is what we could do if we knew mmap would always
+ return aligned pages:
+
+ ((ppnt->p_vaddr + ppnt->p_filesz + ADDR_ALIGN) &
+ PAGE_ALIGN) < ppnt->p_vaddr + ppnt->p_memsz)
+
+ Instead, we have to do this: */
+ ppnt->p_filesz < ppnt->p_memsz)
+ {
+ piclib2map = (char *)
+ _dl_mmap(0, (ppnt->p_vaddr & ADDR_ALIGN) + ppnt->p_memsz,
+ LXFLAGS(prot_flags), flags | MAP_ANONYMOUS, -1, 0);
+ if (_dl_mmap_check_error(piclib2map))
+ return 0;
+ }
+
+ tryaddr = piclib == 2 ? piclib2map
+ : ((char*) (piclib ? libaddr : 0) +
+ (ppnt->p_vaddr & PAGE_ALIGN));
+
+ size = (ppnt->p_vaddr & ADDR_ALIGN) + ppnt->p_filesz;
+
+ /* For !MMU, mmap to fixed address will fail.
+ So instead of desperately call mmap and fail,
+ we set status to MAP_FAILED to save a call
+ to mmap (). */
+#ifndef __ARCH_USE_MMU__
+ if (piclib2map == 0)
+#endif
+ status = (char *) _dl_mmap
+ (tryaddr, size, LXFLAGS(prot_flags),
+ flags | (piclib2map ? MAP_FIXED : 0),
+ infile, ppnt->p_offset & OFFS_ALIGN);
+#ifndef __ARCH_USE_MMU__
+ else
+ status = MAP_FAILED;
+#endif
+#ifdef _DL_PREAD
+ if (_dl_mmap_check_error(status) && piclib2map
+ && (_DL_PREAD (infile, tryaddr, size,
+ ppnt->p_offset & OFFS_ALIGN) == size))
+ status = tryaddr;
+#endif
+ if (_dl_mmap_check_error(status) || (tryaddr && tryaddr != status))
+ return 0;
+
+ if (piclib2map)
+ retval = piclib2map;
+ else
+ retval = status;
+
+ /* Now we want to allocate and zero-out any data from the end
+ of the region we mapped in from the file (filesz) to the
+ end of the loadable segment (memsz). We may need
+ additional pages for memsz, that we map in below, and we
+ can count on the kernel to zero them out, but we have to
+ zero out stuff in the last page that we mapped in from the
+ file. However, we can't assume to have actually obtained
+ full pages from the kernel, since we didn't ask for them,
+ and uClibc may not give us full pages for small
+ allocations. So only zero out up to memsz or the end of
+ the page, whichever comes first. */
+
+ /* CPNT is the beginning of the memsz portion not backed by
+ filesz. */
+ cpnt = (char *) (status + size);
+
+ /* MAP_SIZE is the address of the
+ beginning of the next page. */
+ map_size = (ppnt->p_vaddr + ppnt->p_filesz
+ + ADDR_ALIGN) & PAGE_ALIGN;
+
+ _dl_memset (cpnt, 0,
+ MIN (map_size
+ - (ppnt->p_vaddr
+ + ppnt->p_filesz),
+ ppnt->p_memsz
+ - ppnt->p_filesz));
+
+ if (map_size < ppnt->p_vaddr + ppnt->p_memsz && !piclib2map) {
+ tryaddr = map_size + (char*)(piclib ? libaddr : 0);
+ status = (char *) _dl_mmap(tryaddr,
+ ppnt->p_vaddr + ppnt->p_memsz - map_size,
+ LXFLAGS(prot_flags),
+ flags | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
+ if (_dl_mmap_check_error(status) || tryaddr != status)
+ return NULL;
+ }
+ return retval;
+}
/*
* Read one ELF library into memory, mmap it into the correct locations and
@@ -482,6 +597,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
status = (char *) _dl_mmap((char *) (piclib ? 0 : minvma),
maxvma - minvma, PROT_NONE, flags | MAP_ANONYMOUS, -1, 0);
if (_dl_mmap_check_error(status)) {
+ cant_map:
_dl_dprintf(2, "%s:%i: can't map '%s'\n", _dl_progname, __LINE__, libname);
_dl_internal_error_number = LD_ERROR_MMAP_FAILED;
_dl_close(infile);
@@ -502,8 +618,11 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
char *addr;
addr = DL_MAP_SEGMENT (epnt, ppnt, infile, flags);
- if (addr == NULL)
+ if (addr == NULL) {
+ cant_map1:
+ DL_LOADADDR_UNMAP (lib_loadaddr, maxvma - minvma);
goto cant_map;
+ }
DL_INIT_LOADADDR_HDR (lib_loadaddr, addr, ppnt);
ppnt++;
@@ -518,141 +637,9 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
ssize_t size;
if (ppnt->p_flags & PF_W) {
- unsigned long map_size;
- char *cpnt;
- char *piclib2map = 0;
-
- if (piclib == 2 &&
- /* We might be able to avoid this
- call if memsz doesn't require
- an additional page, but this
- would require mmap to always
- return page-aligned addresses
- and a whole number of pages
- allocated. Unfortunately on
- uClinux may return misaligned
- addresses and may allocate
- partial pages, so we may end up
- doing unnecessary mmap calls.
-
- This is what we could do if we
- knew mmap would always return
- aligned pages:
-
- ((ppnt->p_vaddr + ppnt->p_filesz
- + ADDR_ALIGN)
- & PAGE_ALIGN)
- < ppnt->p_vaddr + ppnt->p_memsz)
-
- Instead, we have to do this: */
- ppnt->p_filesz < ppnt->p_memsz)
- {
- piclib2map = (char *)
- _dl_mmap(0, (ppnt->p_vaddr & ADDR_ALIGN)
- + ppnt->p_memsz,
- LXFLAGS(ppnt->p_flags),
- flags | MAP_ANONYMOUS, -1, 0);
- if (_dl_mmap_check_error(piclib2map))
- goto cant_map;
- DL_INIT_LOADADDR_HDR
- (lib_loadaddr, piclib2map
- + (ppnt->p_vaddr & ADDR_ALIGN), ppnt);
- }
-
- tryaddr = piclib == 2 ? piclib2map
- : ((char*) (piclib ? libaddr : lib_loadaddr) +
- (ppnt->p_vaddr & PAGE_ALIGN));
-
- size = (ppnt->p_vaddr & ADDR_ALIGN)
- + ppnt->p_filesz;
-
- /* For !MMU, mmap to fixed address will fail.
- So instead of desperately call mmap and fail,
- we set status to MAP_FAILED to save a call
- to mmap (). */
-#ifndef __ARCH_USE_MMU__
- if (piclib2map == 0)
-#endif
- status = (char *) _dl_mmap
- (tryaddr, size, LXFLAGS(ppnt->p_flags),
- flags | (piclib2map ? MAP_FIXED : 0),
- infile, ppnt->p_offset & OFFS_ALIGN);
-#ifndef __ARCH_USE_MMU__
- else
- status = MAP_FAILED;
-#endif
-#ifdef _DL_PREAD
- if (_dl_mmap_check_error(status) && piclib2map
- && (_DL_PREAD (infile, tryaddr, size,
- ppnt->p_offset & OFFS_ALIGN)
- == size))
- status = tryaddr;
-#endif
- if (_dl_mmap_check_error(status)
- || (tryaddr && tryaddr != status)) {
- cant_map:
- _dl_dprintf(2, "%s:%i: can't map '%s'\n",
- _dl_progname, __LINE__, libname);
- _dl_internal_error_number = LD_ERROR_MMAP_FAILED;
- DL_LOADADDR_UNMAP (lib_loadaddr, maxvma - minvma);
- _dl_close(infile);
- _dl_munmap(header, _dl_pagesize);
- return NULL;
- }
-
- if (! piclib2map) {
- DL_INIT_LOADADDR_HDR
- (lib_loadaddr, status
- + (ppnt->p_vaddr & ADDR_ALIGN), ppnt);
- }
- /* Now we want to allocate and
- zero-out any data from the end of
- the region we mapped in from the
- file (filesz) to the end of the
- loadable segment (memsz). We may
- need additional pages for memsz,
- that we map in below, and we can
- count on the kernel to zero them
- out, but we have to zero out stuff
- in the last page that we mapped in
- from the file. However, we can't
- assume to have actually obtained
- full pages from the kernel, since
- we didn't ask for them, and uClibc
- may not give us full pages for
- small allocations. So only zero
- out up to memsz or the end of the
- page, whichever comes first. */
-
- /* CPNT is the beginning of the memsz
- portion not backed by filesz. */
- cpnt = (char *) (status + size);
-
- /* MAP_SIZE is the address of the
- beginning of the next page. */
- map_size = (ppnt->p_vaddr + ppnt->p_filesz
- + ADDR_ALIGN) & PAGE_ALIGN;
-
-#ifndef MIN
-# define MIN(a,b) ((a) < (b) ? (a) : (b))
-#endif
- _dl_memset (cpnt, 0,
- MIN (map_size
- - (ppnt->p_vaddr
- + ppnt->p_filesz),