diff options
author | Carmelo Amoroso <carmelo.amoroso@st.com> | 2011-05-04 08:31:16 +0200 |
---|---|---|
committer | Carmelo Amoroso <carmelo.amoroso@st.com> | 2011-05-04 08:31:16 +0200 |
commit | 3004ce0c9619f89bf8e64931edd696bf4df8d2e1 (patch) | |
tree | f03f898fa5c2506c4e30f5f89ce097acf01bc016 | |
parent | 3b3285b1b7c02d36c74a6ae265fdb02ca991c96b (diff) | |
parent | 4916fd889ec1c60710faa528a3ccdb50973198e2 (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>
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 @@ -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), |