diff options
-rw-r--r-- | toolchain/uClibc/uClibc-0.9.28-host-ldconfig.patch | 635 | ||||
-rw-r--r-- | toolchain/uClibc/uClibc-0.9.28-ldso.patch | 5190 | ||||
-rw-r--r-- | toolchain/uClibc/uClibc-0.9.28-math-endianness.patch | 247 | ||||
-rw-r--r-- | toolchain/uClibc/uClibc-0.9.28-mutex-cancel.patch | 8631 | ||||
-rw-r--r-- | toolchain/uClibc/uClibc-0.9.28-new_dst_rules.patch | 99 |
5 files changed, 14802 insertions, 0 deletions
diff --git a/toolchain/uClibc/uClibc-0.9.28-host-ldconfig.patch b/toolchain/uClibc/uClibc-0.9.28-host-ldconfig.patch new file mode 100644 index 000000000..f55c3498a --- /dev/null +++ b/toolchain/uClibc/uClibc-0.9.28-host-ldconfig.patch @@ -0,0 +1,635 @@ +This patch supports cross-development for embedded systems by allowing the +host version of ldconfig (ldconfig.host) to build ld.so.cache for the target. +Changes include: + 1) LDSO_CACHE_SUPPORT is defined for the host build. + 2) A little-endian host can create a big-endian ld.so.cache, and vice versa. + 3) Can use -r option without chroot(), so no need to run as superuser. + +Dan Howell <dahowell@directv.com> + +diff -urN uClibc-orig/utils/chroot_realpath.c uClibc-20050502/utils/chroot_realpath.c +--- uClibc-orig/utils/chroot_realpath.c 1969-12-31 16:00:00.000000000 -0800 ++++ uClibc-20050502/utils/chroot_realpath.c 2005-09-12 18:30:29.000000000 -0700 +@@ -0,0 +1,163 @@ ++/* ++ * chroot_realpath.c -- reslove pathname as if inside chroot ++ * Based on realpath.c Copyright (C) 1993 Rick Sladkey <jrs@world.std.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Library Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU Library Public License for more details. ++ * ++ * 2005/09/12: Dan Howell (modified from realpath.c to emulate chroot) ++ */ ++ ++#ifdef HAVE_CONFIG_H ++#include <config.h> ++#endif ++ ++#include <sys/types.h> ++#include <unistd.h> ++#include <stdio.h> ++#include <string.h> ++#include <strings.h> ++#include <limits.h> /* for PATH_MAX */ ++#include <sys/param.h> /* for MAXPATHLEN */ ++#include <errno.h> ++#ifndef __set_errno ++#define __set_errno(val) ((errno) = (val)) ++#endif ++ ++#include <sys/stat.h> /* for S_IFLNK */ ++ ++#ifndef PATH_MAX ++#define PATH_MAX _POSIX_PATH_MAX ++#endif ++ ++#define MAX_READLINKS 32 ++ ++char *chroot_realpath(const char *chroot, const char *path, char resolved_path[]) ++{ ++ char copy_path[PATH_MAX]; ++ char link_path[PATH_MAX]; ++ char got_path[PATH_MAX]; ++ char *got_path_root = got_path; ++ char *new_path = got_path; ++ char *max_path; ++ int readlinks = 0; ++ int n; ++ int chroot_len; ++ ++ /* Trivial case. */ ++ if (chroot == NULL || *chroot == '\0' || ++ (*chroot == '/' && chroot[1] == '\0')) { ++ strcpy(resolved_path, path); ++ return resolved_path; ++ } ++ ++ chroot_len = strlen(chroot); ++ ++ if (chroot_len + strlen(path) >= PATH_MAX - 3) { ++ __set_errno(ENAMETOOLONG); ++ return NULL; ++ } ++ ++ /* Make a copy of the source path since we may need to modify it. */ ++ strcpy(copy_path, path); ++ path = copy_path; ++ max_path = copy_path + PATH_MAX - chroot_len - 3; ++ ++ /* Start with the chroot path. */ ++ strcpy(new_path, chroot); ++ new_path += chroot_len; ++ while (*new_path == '/' && new_path > got_path) ++ new_path--; ++ got_path_root = new_path; ++ *new_path++ = '/'; ++ ++ /* Expand each slash-separated pathname component. */ ++ while (*path != '\0') { ++ /* Ignore stray "/". */ ++ if (*path == '/') { ++ path++; ++ continue; ++ } ++ if (*path == '.') { ++ /* Ignore ".". */ ++ if (path[1] == '\0' || path[1] == '/') { ++ path++; ++ continue; ++ } ++ if (path[1] == '.') { ++ if (path[2] == '\0' || path[2] == '/') { ++ path += 2; ++ /* Ignore ".." at root. */ ++ if (new_path == got_path_root + 1) ++ continue; ++ /* Handle ".." by backing up. */ ++ while ((--new_path)[-1] != '/'); ++ continue; ++ } ++ } ++ } ++ /* Safely copy the next pathname component. */ ++ while (*path != '\0' && *path != '/') { ++ if (path > max_path) { ++ __set_errno(ENAMETOOLONG); ++ return NULL; ++ } ++ *new_path++ = *path++; ++ } ++ if (*path == '\0') ++ /* Don't follow symlink for last pathname component. */ ++ break; ++#ifdef S_IFLNK ++ /* Protect against infinite loops. */ ++ if (readlinks++ > MAX_READLINKS) { ++ __set_errno(ELOOP); ++ return NULL; ++ } ++ /* See if latest pathname component is a symlink. */ ++ *new_path = '\0'; ++ n = readlink(got_path, link_path, PATH_MAX - 1); ++ if (n < 0) { ++ /* EINVAL means the file exists but isn't a symlink. */ ++ if (errno != EINVAL) { ++ /* Make sure it's null terminated. */ ++ *new_path = '\0'; ++ strcpy(resolved_path, got_path); ++ return NULL; ++ } ++ } else { ++ /* Note: readlink doesn't add the null byte. */ ++ link_path[n] = '\0'; ++ if (*link_path == '/') ++ /* Start over for an absolute symlink. */ ++ new_path = got_path_root; ++ else ++ /* Otherwise back up over this component. */ ++ while (*(--new_path) != '/'); ++ /* Safe sex check. */ ++ if (strlen(path) + n >= PATH_MAX - 2) { ++ __set_errno(ENAMETOOLONG); ++ return NULL; ++ } ++ /* Insert symlink contents into path. */ ++ strcat(link_path, path); ++ strcpy(copy_path, link_path); ++ path = copy_path; ++ } ++#endif /* S_IFLNK */ ++ *new_path++ = '/'; ++ } ++ /* Delete trailing slash but don't whomp a lone slash. */ ++ if (new_path != got_path + 1 && new_path[-1] == '/') ++ new_path--; ++ /* Make sure it's null terminated. */ ++ *new_path = '\0'; ++ strcpy(resolved_path, got_path); ++ return resolved_path; ++} +diff -urN uClibc-orig/utils/ldconfig.c uClibc-20050502/utils/ldconfig.c +--- uClibc-orig/utils/ldconfig.c 2005-05-01 23:10:12.000000000 -0700 ++++ uClibc-20050502/utils/ldconfig.c 2005-09-16 19:26:33.000000000 -0700 +@@ -22,6 +22,8 @@ + * + * This program may be used for any purpose as long as this + * copyright notice is kept. ++ * ++ * 2005/09/16: Dan Howell (modified for cross-development) + */ + + #include <stdio.h> +@@ -37,6 +39,7 @@ + #include <errno.h> + #include <sys/stat.h> + #include <sys/mman.h> ++#include "bswap.h" + #include "dl-defs.h" + + #define BUFFER_SIZE 4096 +@@ -56,6 +59,7 @@ + #if !defined (N_MAGIC) + #define N_MAGIC(exec) ((exec).a_info & 0xffff) + #endif ++#define N_MAGIC_SWAP(exec) (bswap_32((exec).a_info) & 0xffff) + /* Code indicating object file or impure executable. */ + #define OMAGIC 0407 + /* Code indicating pure executable. */ +@@ -97,6 +101,8 @@ + char *conffile = LDSO_CONF; /* default conf file */ + char *cachefile = LDSO_CACHE; /* default cache file */ + #endif ++char *chroot_dir = NULL; ++int byteswap = 0; + + struct needed_tab + { +@@ -117,6 +123,8 @@ + { NULL, LIB_ELF } + }; + ++extern char *chroot_realpath(const char *chroot, const char *path, char resolved_path[]); ++ + + /* These two are used internally -- you shouldn't need to use them */ + static void verror_msg(const char *s, va_list p) +@@ -242,6 +250,8 @@ + ElfW(Ehdr) *elf_hdr; + struct stat statbuf; + char buff[BUFFER_SIZE]; ++ char real[BUFFER_SIZE]; ++ static int byteswapflag = -1; /* start with byte-order unknown */ + + /* see if name is of the form *.so* */ + if (name[strlen(name)-1] != '~' && (cp = strstr(name, ".so"))) +@@ -256,8 +266,12 @@ + sprintf(buff, "%s%s%s", dir, (*dir && strcmp(dir, "/")) ? + "/" : "", name); + ++ /* get real path in case of chroot */ ++ if (!chroot_realpath(chroot_dir, buff, real)) ++ warn("can't resolve %s in chroot %s", buff, chroot_dir); ++ + /* first, make sure it's a regular file */ +- if (lstat(buff, &statbuf)) ++ if (lstat(real, &statbuf)) + warn("skipping %s", buff); + else if (!S_ISREG(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode)) + warnx("%s is not a regular file or symlink, skipping", buff); +@@ -267,14 +281,15 @@ + *islink = S_ISLNK(statbuf.st_mode); + + /* then try opening it */ +- if (!(file = fopen(buff, "rb"))) ++ if (!(file = fopen(real, "rb"))) + warn("skipping %s", buff); + else + { + /* now make sure it's a shared library */ + if (fread(&exec, sizeof exec, 1, file) < 1) + warnx("can't read header from %s, skipping", buff); +- else if (N_MAGIC(exec) != ZMAGIC && N_MAGIC(exec) != QMAGIC) ++ else if (N_MAGIC(exec) != ZMAGIC && N_MAGIC(exec) != QMAGIC && ++ N_MAGIC_SWAP(exec) != ZMAGIC && N_MAGIC_SWAP(exec) != QMAGIC) + { + elf_hdr = (ElfW(Ehdr) *) &exec; + if (elf_hdr->e_ident[0] != 0x7f || +@@ -294,6 +309,9 @@ + *type = LIB_ELF; + good = readsoname(buff, file, expected_type, type, + elf_hdr->e_ident[EI_CLASS]); ++ if (byteswapflag == -1) ++ /* byte-order detected */ ++ byteswapflag = byteswap; + if (good == NULL || *islink) + { + if (good != NULL) +@@ -313,6 +331,12 @@ + } + else + { ++ /* Determine byte-order */ ++ byteswap = (N_MAGIC(exec) == ZMAGIC || N_MAGIC(exec) == QMAGIC) ? 0 : 1; ++ if (byteswapflag == -1) ++ /* byte-order detected */ ++ byteswapflag = byteswap; ++ + if (*islink) + good = xstrdup(name); + else +@@ -330,6 +354,14 @@ + *type = LIB_DLL; + } + fclose(file); ++ ++ if (byteswapflag >= 0 && byteswap != byteswapflag) ++ { ++ byteswapflag = -2; ++ warnx("mixed byte-order detected, using host byte-order..."); ++ } ++ if (byteswapflag == -2) ++ byteswap = 0; + } + } + } +@@ -343,18 +375,24 @@ + int change = 1; + char libname[BUFFER_SIZE]; + char linkname[BUFFER_SIZE]; ++ char reallibname[BUFFER_SIZE]; ++ char reallinkname[BUFFER_SIZE]; + struct stat libstat; + struct stat linkstat; + + /* construct the full path names */ + sprintf(libname, "%s/%s", dir, file); + sprintf(linkname, "%s/%s", dir, so); ++ if (!chroot_realpath(chroot_dir, libname, reallibname)) ++ warn("can't resolve %s in chroot %s", libname, chroot_dir); ++ if (!chroot_realpath(chroot_dir, linkname, reallinkname)) ++ warn("can't resolve %s in chroot %s", linkname, chroot_dir); + + /* see if a link already exists */ +- if (!stat(linkname, &linkstat)) ++ if (!stat(reallinkname, &linkstat)) + { + /* now see if it's the one we want */ +- if (stat(libname, &libstat)) ++ if (stat(reallibname, &libstat)) + warn("can't stat %s", libname); + else if (libstat.st_dev == linkstat.st_dev && + libstat.st_ino == linkstat.st_ino) +@@ -364,14 +402,14 @@ + /* then update the link, if required */ + if (change > 0 && !nolinks) + { +- if (!lstat(linkname, &linkstat)) ++ if (!lstat(reallinkname, &linkstat)) + { + if (!S_ISLNK(linkstat.st_mode)) + { + warnx("%s is not a symlink", linkname); + change = -1; + } +- else if (remove(linkname)) ++ else if (remove(reallinkname)) + { + warn("can't unlink %s", linkname); + change = -1; +@@ -379,7 +417,7 @@ + } + if (change > 0) + { +- if (symlink(file, linkname)) ++ if (symlink(file, reallinkname)) + { + warn("can't link %s to %s", linkname, file); + change = -1; +@@ -441,6 +479,7 @@ + char *so, *path, *path_n; + struct lib *lp, *libs = NULL; + int i, libtype, islink, expected_type = LIB_ANY; ++ char realname[BUFFER_SIZE]; + + /* We need a writable copy of this string */ + path = strdup(rawname); +@@ -500,8 +539,12 @@ + if (verbose > 0) + printf("%s:\n", name); + ++ /* get real path in case of chroot */ ++ if (!chroot_realpath(chroot_dir, name, realname)) ++ warn("can't resolve %s in chroot %s", name, chroot_dir); ++ + /* if we can't open it, we can't do anything */ +- if ((dir = opendir(name)) == NULL) ++ if ((dir = opendir(realname)) == NULL) + { + warn("skipping %s", name); + free(path); +@@ -596,8 +639,12 @@ + char *res = NULL, *cp; + FILE *file; + struct stat stat; ++ char realconffile[BUFFER_SIZE]; ++ ++ if (!chroot_realpath(chroot_dir, conffile, realconffile)) ++ return NULL; + +- if ((file = fopen(conffile, "r")) != NULL) ++ if ((file = fopen(realconffile, "r")) != NULL) + { + fstat(fileno(file), &stat); + res = xmalloc(stat.st_size + 1); +@@ -678,22 +725,38 @@ + { + int cachefd; + int stroffset = 0; ++ char realcachefile[BUFFER_SIZE]; + char tempfile[BUFFER_SIZE]; ++ header_t swap_magic; ++ header_t *magic_ptr; ++ libentry_t swap_lib; ++ libentry_t *lib_ptr; + liblist_t *cur_lib; + + if (!magic.nlibs) + return; + +- sprintf(tempfile, "%s~", cachefile); ++ if (!chroot_realpath(chroot_dir, cachefile, realcachefile)) ++ err(EXIT_FATAL,"can't resolve %s in chroot %s (%s)", ++ cachefile, chroot_dir, strerror(errno)); ++ ++ sprintf(tempfile, "%s~", realcachefile); + + if (unlink(tempfile) && errno != ENOENT) +- err(EXIT_FATAL,"can't unlink %s (%s)", tempfile, strerror(errno)); ++ err(EXIT_FATAL,"can't unlink %s~ (%s)", cachefile, strerror(errno)); + + if ((cachefd = creat(tempfile, 0644)) < 0) +- err(EXIT_FATAL,"can't create %s (%s)", tempfile, strerror(errno)); ++ err(EXIT_FATAL,"can't create %s~ (%s)", cachefile, strerror(errno)); + +- if (write(cachefd, &magic, sizeof (header_t)) != sizeof (header_t)) +- err(EXIT_FATAL,"can't write %s (%s)", tempfile, strerror(errno)); ++ if (byteswap) { ++ swap_magic = magic; ++ swap_magic.nlibs = bswap_32(swap_magic.nlibs); ++ magic_ptr = &swap_magic; ++ } else { ++ magic_ptr = &magic; ++ } ++ if (write(cachefd, magic_ptr, sizeof (header_t)) != sizeof (header_t)) ++ err(EXIT_FATAL,"can't write %s~ (%s)", cachefile, strerror(errno)); + + for (cur_lib = lib_head; cur_lib != NULL; cur_lib = cur_lib->next) + { +@@ -701,29 +764,37 @@ + stroffset += strlen(cur_lib->soname) + 1; + cur_lib->liboffset = stroffset; + stroffset += strlen(cur_lib->libname) + 1; +- if (write(cachefd, cur_lib, sizeof (libentry_t)) != +- sizeof (libentry_t)) +- err(EXIT_FATAL,"can't write %s (%s)", tempfile, strerror(errno)); ++ if (byteswap) { ++ swap_lib.flags = bswap_32(cur_lib->flags); ++ swap_lib.sooffset = bswap_32(cur_lib->sooffset); ++ swap_lib.liboffset = bswap_32(cur_lib->liboffset); ++ lib_ptr = &swap_lib; ++ } else { ++ lib_ptr = (libentry_t *)cur_lib; ++ } ++ if (write(cachefd, lib_ptr, sizeof (libentry_t)) != ++ sizeof (libentry_t)) ++ err(EXIT_FATAL,"can't write %s~ (%s)", cachefile, strerror(errno)); + } + + for (cur_lib = lib_head; cur_lib != NULL; cur_lib = cur_lib->next) + { + if (write(cachefd, cur_lib->soname, strlen(cur_lib->soname) + 1) + != strlen(cur_lib->soname) + 1) +- err(EXIT_FATAL,"can't write %s (%s)", tempfile, strerror(errno)); ++ err(EXIT_FATAL,"can't write %s~ (%s)", cachefile, strerror(errno)); + if (write(cachefd, cur_lib->libname, strlen(cur_lib->libname) + 1) + != strlen(cur_lib->libname) + 1) +- err(EXIT_FATAL,"can't write %s (%s)", tempfile, strerror(errno)); ++ err(EXIT_FATAL,"can't write %s~ (%s)", cachefile, strerror(errno)); + } + + if (close(cachefd)) +- err(EXIT_FATAL,"can't close %s (%s)", tempfile, strerror(errno)); ++ err(EXIT_FATAL,"can't close %s~ (%s)", cachefile, strerror(errno)); + + if (chmod(tempfile, 0644)) +- err(EXIT_FATAL,"can't chmod %s (%s)", tempfile, strerror(errno)); ++ err(EXIT_FATAL,"can't chmod %s~ (%s)", cachefile, strerror(errno)); + +- if (rename(tempfile, cachefile)) +- err(EXIT_FATAL,"can't rename %s (%s)", tempfile, strerror(errno)); ++ if (rename(tempfile, realcachefile)) ++ err(EXIT_FATAL,"can't rename %s~ (%s)", cachefile, strerror(errno)); + } + + void cache_print(void) +@@ -734,8 +805,13 @@ + char *strs; + header_t *header; + libentry_t *libent; ++ char realcachefile[BUFFER_SIZE]; ++ ++ if (!chroot_realpath(chroot_dir, cachefile, realcachefile)) ++ err(EXIT_FATAL,"can't resolve %s in chroot %s (%s)", ++ cachefile, chroot_dir, strerror(errno)); + +- if (stat(cachefile, &st) || (fd = open(cachefile, O_RDONLY))<0) ++ if (stat(realcachefile, &st) || (fd = open(realcachefile, O_RDONLY))<0) + err(EXIT_FATAL,"can't read %s (%s)", cachefile, strerror(errno)); + if ((c = mmap(0,st.st_size, PROT_READ, MAP_SHARED ,fd, 0)) == (caddr_t)-1) + err(EXIT_FATAL,"can't map %s (%s)", cachefile, strerror(errno)); +@@ -828,7 +904,6 @@ + int nodefault = 0; + char *cp, *dir, *so; + int libtype, islink; +- char *chroot_dir = NULL; + int printcache = 0; + #ifdef __LDSO_CACHE_SUPPORT__ + char *extpath; +@@ -891,10 +966,16 @@ + } + + if (chroot_dir && *chroot_dir) { +- if (chroot(chroot_dir) < 0) +- err(EXIT_FATAL,"couldn't chroot to %s (%s)", chroot_dir, strerror(errno)); +- if (chdir("/") < 0) +- err(EXIT_FATAL,"couldn't chdir to / (%s)", strerror(errno)); ++ if (chroot(chroot_dir) < 0) { ++ if (chdir(chroot_dir) < 0) ++ err(EXIT_FATAL,"couldn't chroot to %s (%s)", chroot_dir, strerror(errno)); ++ } ++ else ++ { ++ if (chdir("/") < 0) ++ err(EXIT_FATAL,"couldn't chdir to / (%s)", strerror(errno)); ++ chroot_dir = NULL; ++ } + } + + /* allow me to introduce myself, hi, my name is ... */ +diff -urN uClibc-orig/utils/Makefile uClibc-20050502/utils/Makefile +--- uClibc-orig/utils/Makefile 2005-05-01 23:10:12.000000000 -0700 ++++ uClibc-20050502/utils/Makefile 2005-09-16 19:28:55.000000000 -0700 +@@ -29,6 +29,12 @@ + TARGET_ICONV = + endif + ++ifeq ($(strip $(LDSO_CACHE_SUPPORT)),y) ++HOST_LDSO_CACHE_FLAG = -D__LDSO_CACHE_SUPPORT__=1 ++else ++HOST_LDSO_CACHE_FLAG = ++endif ++ + # NOTE: We build the utils AFTER we have a uClibc-targeted toolchain. + + ifeq ($(strip $(HAVE_SHARED)),y) +@@ -51,7 +57,7 @@ + else + LDCONFIG_CFLAGS := $(PIEFLAG) $(LDPIEFLAG) + endif +-ldconfig: ldconfig.c ++ldconfig: ldconfig.c chroot_realpath.c + $(CC) $(CFLAGS) $(LDCONFIG_CFLAGS) \ + -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" \ + -DUCLIBC_LDSO=$(UCLIBC_LDSO) -I. -I../ldso/include \ +@@ -79,13 +85,13 @@ + + ldd.host: ldd.c + $(HOSTCC) $(HOSTCFLAGS) -Wl,-s \ +- -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" \ ++ -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" $(HOST_LDSO_CACHE_FLAG) \ + -DUCLIBC_LDSO=$(UCLIBC_LDSO) -I. -I../ldso/include \ + $^ -o $@ + +-ldconfig.host: ldconfig.c ++ldconfig.host: ldconfig.c chroot_realpath.c + $(HOSTCC) $(HOSTCFLAGS) -Wl,-s \ +- -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" \ ++ -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" $(HOST_LDSO_CACHE_FLAG) \ + -DUCLIBC_LDSO=$(UCLIBC_LDSO) -I. -I../ldso/include \ + $^ -o $@ + +diff -urN uClibc-orig/utils/readsoname2.c uClibc-20050502/utils/readsoname2.c +--- uClibc-orig/utils/readsoname2.c 2005-05-01 23:10:12.000000000 -0700 ++++ uClibc-20050502/utils/readsoname2.c 2005-09-16 17:48:59.000000000 -0700 +@@ -26,7 +26,7 @@ + + if (fstat(fileno(infile), &st)) + return NULL; +- header = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fileno(infile), 0); ++ header = mmap(0, st.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(infile), 0); + if (header == (caddr_t)-1) + return NULL; + +@@ -34,6 +34,19 @@ + if ((char *)(epnt+1) > (char *)(header + st.st_size)) + goto skip; + ++#if __BYTE_ORDER == __LITTLE_ENDIAN ++ byteswap = (epnt->e_ident[5] == ELFDATA2MSB) ? 1 : 0; ++#elif __BYTE_ORDER == __BIG_ENDIAN ++ byteswap = (epnt->e_ident[5] == ELFDATA2LSB) ? 1 : 0; ++#else ++#error Unknown host byte order! ++#endif ++ /* Be very lazy, and only byteswap the stuff we use */ ++ if (byteswap==1) { ++ epnt->e_phoff=bswap_32(epnt->e_phoff); ++ epnt->e_phnum=bswap_16(epnt->e_phnum); ++ } ++ + ppnt = (ElfW(Phdr) *)&header[epnt->e_phoff]; + if ((char *)ppnt < (char *)header || + (char *)(ppnt+epnt->e_phnum) > (char *)(header + st.st_size)) +@@ -41,6 +54,14 @@ + + for(i = 0; i < epnt->e_phnum; i++) + { ++ /* Be very lazy, and only byteswap the stuff we use */ ++ if (byteswap==1) { ++ ppnt->p_type=bswap_32(ppnt->p_type); ++ ppnt->p_vaddr=bswap_32(ppnt->p_vaddr); ++ ppnt->p_offset=bswap_32(ppnt->p_offset); ++ ppnt->p_filesz=bswap_32(ppnt->p_filesz); ++ } ++ + if (loadaddr == -1 && ppnt->p_type == PT_LOAD) + loadaddr = (ppnt->p_vaddr & ~(page_size-1)) - + (ppnt->p_offset & ~(page_size-1)); +@@ -58,11 +79,20 @@ + (char *)(dpnt+dynamic_size) > (char *)(header + st.st_size)) + goto skip; + ++ if (byteswap==1) { ++ dpnt->d_tag=bswap_32(dpnt->d_tag); ++ dpnt->d_un.d_val=bswap_32(dpnt->d_un.d_val); ++ } ++ + while (dpnt->d_tag != DT_NULL) + { + if (dpnt->d_tag == DT_STRTAB) + strtab_val = dpnt->d_un.d_val; + dpnt++; ++ if (byteswap==1) { ++ dpnt->d_tag=bswap_32(dpnt->d_tag); ++ dpnt->d_un.d_val=bswap_32(dpnt->d_un.d_val); ++ } + }; + + if (!strtab_val) diff --git a/toolchain/uClibc/uClibc-0.9.28-ldso.patch b/toolchain/uClibc/uClibc-0.9.28-ldso.patch new file mode 100644 index 000000000..4081fc7d1 --- /dev/null +++ b/toolchain/uClibc/uClibc-0.9.28-ldso.patch @@ -0,0 +1,5190 @@ +diff -urN uClibc-0.9.28.orig/include/elf.h uClibc-0.9.28/include/elf.h +--- uClibc-0.9.28.orig/include/elf.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/include/elf.h 2006-04-28 00:14:35.000000000 -0600 +@@ -142,6 +142,7 @@ + #define ELFOSABI_HPUX 1 /* HP-UX */ + #define ELFOSABI_NETBSD 2 /* NetBSD. */ + #define ELFOSABI_LINUX 3 /* Linux. */ ++#define ELFOSABI_HURD 4 /* GNU/Hurd */ + #define ELFOSABI_SOLARIS 6 /* Sun Solaris. */ + #define ELFOSABI_AIX 7 /* IBM AIX. */ + #define ELFOSABI_IRIX 8 /* SGI Irix. */ +@@ -149,6 +150,9 @@ + #define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */ + #define ELFOSABI_MODESTO 11 /* Novell Modesto. */ + #define ELFOSABI_OPENBSD 12 /* OpenBSD. */ ++#define ELFOSABI_OPENVMS 13 /* OpenVMS */ ++#define ELFOSABI_NSK 14 /* Hewlett-Packard Non-Stop Kernel */ ++#define ELFOSABI_AROS 15 /* Amiga Research OS */ + #define ELFOSABI_ARM 97 /* ARM */ + #define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ + +@@ -177,6 +181,7 @@ + #define EM_386 3 /* Intel 80386 */ + #define EM_68K 4 /* Motorola m68k family */ + #define EM_88K 5 /* Motorola m88k family */ ++#define EM_486 6 /* Intel 80486 *//* Reserved for future use */ + #define EM_860 7 /* Intel 80860 */ + #define EM_MIPS 8 /* MIPS R3000 big-endian */ + #define EM_S370 9 /* IBM System/370 */ +@@ -193,7 +198,8 @@ + #define EM_V800 36 /* NEC V800 series */ + #define EM_FR20 37 /* Fujitsu FR20 */ + #define EM_RH32 38 /* TRW RH-32 */ +-#define EM_RCE 39 /* Motorola RCE */ ++#define EM_MCORE 39 /* Motorola M*Core */ /* May also be taken by Fujitsu MMA */ ++#define EM_RCE 39 /* Old name for MCore */ + #define EM_ARM 40 /* ARM */ + #define EM_FAKE_ALPHA 41 /* Digital Alpha */ + #define EM_SH 42 /* Renesas SH */ +@@ -248,18 +254,105 @@ + #define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ + #define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */ + #define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ ++#define EM_IP2K 101 /* Ubicom IP2022 micro controller */ ++#define EM_CR 103 /* National Semiconductor CompactRISC */ ++#define EM_MSP430 105 /* TI msp430 micro controller */ ++#define EM_BLACKFIN 106 /* Analog Devices Blackfin */ ++#define EM_ALTERA_NIOS2 113 /* Altera Nios II soft-core processor */ ++#define EM_CRX 114 /* National Semiconductor CRX */ + #define EM_NUM 95 + +-/* If it is necessary to assign new unofficial EM_* values, please +- pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the +- chances of collision with official or non-GNU unofficial values. */ ++/* If it is necessary to assign new unofficial EM_* values, please pick large ++ random numbers (0x8523, 0xa7f2, etc.) to minimize the chances of collision ++ with official or non-GNU unofficial values. + +-/* Fujitsu FR-V. */ ++ NOTE: Do not just increment the most recent number by one. ++ Somebody else somewhere will do exactly the same thing, and you ++ will have a collision. Instead, pick a random number. ++ ++ Normally, each entity or maintainer responsible for a machine with an ++ unofficial e_machine number should eventually ask registry@caldera.com for ++ an officially blessed number to be added to the list above. */ ++ ++/* picoJava */ ++#define EM_PJ_OLD 99 ++ ++/* Cygnus PowerPC ELF backend. Written in the absence of an ABI. */ ++#define EM_CYGNUS_POWERPC 0x9025 ++ ++/* Old version of Sparc v9, from before the ABI; this should be ++ removed shortly. */ ++#define EM_OLD_SPARCV9 11 ++ ++/* Old version of PowerPC, this should be removed shortly. */ ++#define EM_PPC_OLD 17 ++ ++/* (Deprecated) Temporary number for the OpenRISC processor. */ ++#define EM_OR32 0x8472 ++ ++/* Renesas M32C and M16C. */ ++#define EM_M32C 0xFEB0 ++ ++/* Cygnus M32R ELF backend. Written in the absence of an ABI. */ ++#define EM_CYGNUS_M32R 0x9041 ++ ++/* old S/390 backend magic number. Written in the absence of an ABI. */ ++#define EM_S390_OLD 0xa390 ++ ++/* D10V backend magic number. Written in the absence of an ABI. */ ++#define EM_CYGNUS_D10V 0x7650 ++ ++/* D30V backend magic number. Written in the absence of an ABI. */ ++#define EM_CYGNUS_D30V 0x7676 ++ ++/* V850 backend magic number. Written in the absense of an ABI. */ ++#define EM_CYGNUS_V850 0x9080 ++ ++/* mn10200 and mn10300 backend magic numbers. ++ Written in the absense of an ABI. */ ++#define EM_CYGNUS_MN10200 0xdead ++#define EM_CYGNUS_MN10300 0xbeef ++ ++/* FR30 magic number - no EABI available. */ ++#define EM_CYGNUS_FR30 0x3330 ++ ++/* AVR magic number ++ Written in the absense of an ABI. */ ++#define EM_AVR_OLD 0x1057 ++ ++/* OpenRISC magic number ++ Written in the absense of an ABI. */ ++#define EM_OPENRISC_OLD 0x3426 ++ ++/* DLX magic number ++ Written in the absense of an ABI. */ ++#define EM_DLX 0x5aa5 ++ ++#define EM_XSTORMY16 0xad45 ++ ++/* FRV magic number - no EABI available??. */ + #define EM_CYGNUS_FRV 0x5441 + ++/* Ubicom IP2xxx; no ABI */ ++#define EM_IP2K_OLD 0x8217 ++ ++#define EM_MT 0x2530 /* Morpho MT; no ABI */ ++ ++/* MSP430 magic number ++ Written in the absense everything. */ ++#define EM_MSP430_OLD 0x1059 ++ ++/* Vitesse IQ2000. */ ++#define EM_IQ2000 0xFEBA ++ ++/* Old, unofficial value for Xtensa. */ ++#define EM_XTENSA_OLD 0xabc7 ++ ++/* Alpha backend magic number. Written in the absence of an ABI. */ + #define EM_ALPHA 0x9026 +-#define EM_NIOS32 0xfebb /* Altera Nios 32 */ +-#define EM_ALTERA_NIOS2 0x9ee5 /* Altera Nios II */ ++ ++/* NIOS magic number - no EABI available. */ ++#define EM_NIOS32 0xFEBB + + /* V850 backend magic number. Written in the absense of an ABI. */ + #define EM_CYGNUS_V850 0x9080 +@@ -2498,6 +2591,12 @@ + #define R_390_NUM 61 + + ++/* CRIS flags. */ ++#define EF_CRIS_VARIANT_MASK 0x0000000e ++#define EF_CRIS_VARIANT_ANY_V0_V10 0x00000000 ++#define EF_CRIS_VARIANT_V32 0x00000002 ++#define EF_CRIS_VARIANT_COMMON_V10_V32 0x00000004 ++ + /* CRIS relocations. */ + #define R_CRIS_NONE 0 + #define R_CRIS_8 1 +@@ -2688,6 +2787,7 @@ + #define R_V850_NUM 25 + + ++/* Renesas H8/300 Relocations */ + #define R_H8_NONE 0 + #define R_H8_DIR32 1 + #define R_H8_DIR32_28 2 +@@ -2731,8 +2831,7 @@ + #define R_H8_DIR32A16 63 + #define R_H8_ABS32 65 + #define R_H8_ABS32A16 127 +- +-/* Altera NIOS specific definitions. */ ++#define R_H8_NUM 128 + + /* NIOS relocations. */ + #define R_NIOS_NONE 0 +diff -urN uClibc-0.9.28.orig/include/errno.h uClibc-0.9.28/include/errno.h +--- uClibc-0.9.28.orig/include/errno.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/include/errno.h 2006-04-28 00:14:35.000000000 -0600 +@@ -43,9 +43,11 @@ + variable. This redeclaration using the macro still works, but it + will be a function declaration without a prototype and may trigger + a -Wstrict-prototypes warning. */ ++#ifndef __ASSEMBLER__ + #ifndef errno + extern int errno; + #endif ++#endif + + #if 0 /*def __USE_GNU uClibc note: not supported */ + +diff -urN uClibc-0.9.28.orig/ldso/Makefile uClibc-0.9.28/ldso/Makefile +--- uClibc-0.9.28.orig/ldso/Makefile 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/Makefile 2006-04-28 00:14:35.000000000 -0600 +@@ -37,15 +37,12 @@ + + LN_HEADERS := $(patsubst %, include/%, elf.h) + LN_ARCH_HEADERS := $(patsubst %, include/%, dl-startup.h dl-syscalls.h dl-sysdep.h dl-debug.h) +-HEADERS := $(LN_HEADERS) $(LN_ARCH_HEADERS) include/dl-progname.h ++HEADERS := $(LN_HEADERS) $(LN_ARCH_HEADERS) + headers: $(HEADERS) + $(LN_HEADERS): + $(LN) -fs $(TOPDIR)../$@ $@ + $(LN_ARCH_HEADERS): + $(LN) -fs ../ldso/$(TARGET_ARCH)/$(patsubst include/%,%,$@) $@ +-include/dl-progname.h: +- echo '#include "$(TARGET_ARCH)/elfinterp.c"' \ +- > include/dl-progname.h + + clean: + set -e ; for d in $(DIRS) ; do $(MAKE) -C $$d $@ ; done +diff -urN uClibc-0.9.28.orig/ldso/include/dl-defs.h uClibc-0.9.28/ldso/include/dl-defs.h +--- uClibc-0.9.28.orig/ldso/include/dl-defs.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/include/dl-defs.h 2006-04-28 00:14:35.000000000 -0600 +@@ -1,6 +1,29 @@ ++/* vi: set sw=4 ts=4: */ ++/* ++ * Copyright (C) 2000-2005 by Erik Andersen <andersen@codepoet.org> ++ * ++ * GNU Lesser General Public License version 2.1 or later. ++ */ ++ + #ifndef _LD_DEFS_H + #define _LD_DEFS_H + ++#define FLAG_ANY -1 ++#define FLAG_TYPE_MASK 0x00ff ++#define FLAG_LIBC4 0x0000 ++#define FLAG_ELF 0x0001 ++#define FLAG_ELF_LIBC5 0x0002 ++#define FLAG_ELF_LIBC6 0x0003 ++#define FLAG_ELF_UCLIBC 0x0004 ++#define FLAG_REQUIRED_MASK 0xff00 ++#define FLAG_SPARC_LIB64 0x0100 ++#define FLAG_IA64_LIB64 0x0200 ++#define FLAG_X8664_LIB64 0x0300 ++#define FLAG_S390_LIB64 0x0400 ++#define FLAG_POWERPC_LIB64 0x0500 ++#define FLAG_MIPS64_LIBN32 0x0600 ++#define FLAG_MIPS64_LIBN64 0x0700 ++ + #define LIB_ANY -1 + #define LIB_DLL 0 + #define LIB_ELF 1 +diff -urN uClibc-0.9.28.orig/ldso/include/dl-elf.h uClibc-0.9.28/ldso/include/dl-elf.h +--- uClibc-0.9.28.orig/ldso/include/dl-elf.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/include/dl-elf.h 2006-04-28 00:14:35.000000000 -0600 +@@ -1,3 +1,10 @@ ++/* vi: set sw=4 ts=4: */ ++/* ++ * Copyright (C) 2000-2005 by Erik Andersen <andersen@codepoet.org> ++ * ++ * GNU Lesser General Public License version 2.1 or later. ++ */ ++ + #ifndef LINUXELF_H + #define LINUXELF_H + +diff -urN uClibc-0.9.28.orig/ldso/include/dl-hash.h uClibc-0.9.28/ldso/include/dl-hash.h +--- uClibc-0.9.28.orig/ldso/include/dl-hash.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/include/dl-hash.h 2006-04-28 00:14:35.000000000 -0600 +@@ -1,3 +1,10 @@ ++/* vi: set sw=4 ts=4: */ ++/* ++ * Copyright (C) 2000-2005 by Erik Andersen <andersen@codepoet.org> ++ * ++ * GNU Lesser General Public License version 2.1 or later. ++ */ ++ + #ifndef _LD_HASH_H_ + #define _LD_HASH_H_ + +@@ -32,15 +39,15 @@ + unsigned short usage_count; + unsigned short int init_flag; + unsigned long rtld_flags; /* RTLD_GLOBAL, RTLD_NOW etc. */ +- Elf32_Word nbucket; +- Elf32_Word *elf_buckets; ++ Elf_Symndx nbucket; ++ Elf_Symndx *elf_buckets; + struct init_fini_list *init_fini; + struct init_fini_list *rtld_local; /* keep tack of RTLD_LOCAL libs in same group */ + /* + * These are only used with ELF style shared libraries + */ +- Elf32_Word nchain; +- Elf32_Word *chains; ++ Elf_Symndx nchain; ++ Elf_Symndx *chains; + unsigned long dynamic_info[DYNAMIC_SIZE]; + + unsigned long n_phent; +@@ -49,6 +56,9 @@ + ElfW(Addr) relro_addr; + size_t relro_size; + ++ dev_t st_dev; /* device */ ++ ino_t st_ino; /* inode */ ++ + #ifdef __powerpc__ + /* this is used to store the address of relocation data words, so + * we don't have to calculate it every time, which requires a divide */ +@@ -66,7 +76,6 @@ + extern struct elf_resolve * _dl_loaded_modules; + extern struct dyn_elf * _dl_handles; + +-extern struct elf_resolve * _dl_check_hashed_files(const char * libname); + extern struct elf_resolve * _dl_add_elf_hash_table(const char * libname, + char * loadaddr, unsigned long * dynamic_info, + unsigned long dynamic_addr, unsigned long dynamic_size); +diff -urN uClibc-0.9.28.orig/ldso/include/dl-string.h uClibc-0.9.28/ldso/include/dl-string.h +--- uClibc-0.9.28.orig/ldso/include/dl-string.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/include/dl-string.h 2006-04-28 00:14:35.000000000 -0600 +@@ -1,9 +1,24 @@ ++/* vi: set sw=4 ts=4: */ ++/* ++ * Copyright (C) 2000-2005 by Erik Andersen <andersen@codepoet.org> ++ * ++ * GNU Lesser General Public License version 2.1 or later. ++ */ ++ + #ifndef _LINUX_STRING_H_ + #define _LINUX_STRING_H_ + +-#include <dl-sysdep.h> // for do_rem ++#include <dl-sysdep.h> /* for do_rem */ + #include <features.h> + ++/* provide some sane defaults */ ++#ifndef do_rem ++# define do_rem(result, n, base) ((result) = (n) % (base)) ++#endif ++#ifndef do_div_10 ++# define do_div_10(result, remain) ((result) /= 10) ++#endif ++ + static size_t _dl_strlen(const char * str); + static char *_dl_strcat(char *dst, const char *src); + static char * _dl_strcpy(char * dst,const char *src); +@@ -26,8 +41,8 @@ + static __always_inline size_t _dl_strlen(const char * str) + { + register const char *ptr = (char *) str-1; +- +- while (*++ptr); ++ while (*++ptr) ++ ;/* empty */ + return (ptr - str); + } + +@@ -49,7 +64,8 @@ + register char *ptr = dst; + + dst--;src--; +- while ((*++dst = *++src) != 0); ++ while ((*++dst = *++src) != 0) ++ ;/* empty */ + + return ptr; + } +@@ -63,8 +79,7 @@ + c2 = (unsigned char) *++s2; + if (c1 == '\0') + return c1 - c2; +- } +- while (c1 == c2); ++ } while (c1 == c2); + + return c1 - c2; + } +@@ -98,43 +113,41 @@ + return 0; + } + +-static inline char * _dl_strrchr(const char *str, int c) ++static __always_inline char * _dl_strrchr(const char *str, int c) + { +- register char *prev = 0; +- register char *ptr = (char *) str-1; ++ register char *prev = 0; ++ register char *ptr = (char *) str-1; + +- while (*++ptr != '\0') { +- if (*ptr == c) +- prev = ptr; +- } +- if (c == '\0') +- return(ptr); +- return(prev); ++ while (*++ptr != '\0') { ++ if (*ptr == c) ++ prev = ptr; ++ } ++ if (c == '\0') ++ return(ptr); ++ return(prev); + } + +-static inline char * _dl_strstr(const char *s1, const char *s2) ++static __always_inline char * _dl_strstr(const char *s1, const char *s2) + { +- register const char *s = s1; +- register const char *p = s2; ++ register const char *s = s1; ++ register const char *p = s2; + +- do { +- if (!*p) { +- return (char *) s1;; +- } +- if (*p == *s) { +- ++p; +- ++s; +- } else { +- p = s2; +- if (!*s) { +- return NULL; +- } +- s = ++s1; +- } +- } while (1); ++ do { ++ if (!*p) ++ return (char *) s1;; ++ if (*p == *s) { ++ ++p; ++ ++s; ++ } else { ++ p = s2; ++ if (!*s) ++ return NULL; ++ s = ++s1; ++ } ++ } while (1); + } + +-static inline void * _dl_memcpy(void * dst, const void * src, size_t len) ++static __always_inline void * _dl_memcpy(void * dst, const void * src, size_t len) + { + register char *a = dst-1; + register const char *b = src-1; +@@ -163,27 +176,28 @@ + /* Will generate smaller and faster code due to loop unrolling.*/ + static __always_inline void * _dl_memset(void *to, int c, size_t n) + { +- unsigned long chunks; +- unsigned long *tmp_to; ++ unsigned long chunks; ++ unsigned long *tmp_to; + unsigned char *tmp_char; + +- chunks = n / 4; +- tmp_to = to + n; +- c = c << 8 | c; +- c = c << 16 | c; +- if (!chunks) +- goto lessthan4; +- do { +- *--tmp_to = c; +- } while (--chunks); +- lessthan4: +- n = n % 4; +- if (!n ) return to; +- tmp_char = (unsigned char *)tmp_to; +- do { +- *--tmp_char = c; +- } while (--n); +- return to; ++ chunks = n / 4; ++ tmp_to = to + n; ++ c = c << 8 | c; ++ c = c << 16 | c; ++ if (!chunks) ++ goto lessthan4; ++ do { ++ *--tmp_to = c; ++ } while (--chunks); ++lessthan4: ++ n = n % 4; ++ if (!n) ++ return to; ++ tmp_char = (unsigned char *)tmp_to; ++ do { ++ *--tmp_char = c; ++ } while (--n); ++ return to; + } + #else + static __always_inline void * _dl_memset(void * str,int c,size_t len) +@@ -225,10 +239,10 @@ + char *p = &local[22]; + *--p = '\0'; + do { +- char temp; +- do_rem(temp, i, 10); +- *--p = '0' + temp; +- i /= 10; ++ char temp; ++ do_rem(temp, i, 10); ++ *--p = '0' + temp; ++ do_div_10(i, temp); + } while (i > 0); + return p; + } +@@ -242,9 +256,9 @@ + do { + char temp = i & 0xf; + if (temp <= 0x09) +- *--p = '0' + temp; ++ *--p = '0' + temp; + else +- *--p = 'a' - 0x0a + temp; ++ *--p = 'a' - 0x0a + temp; + i >>= 4; + } while (i > 0); + *--p = 'x'; +@@ -270,8 +284,8 @@ + + /* On some arches constant strings are referenced through the GOT. + * This requires that load_addr must already be defined... */ +-#if defined(mc68000) || defined(__arm__) || defined(__mips__) \ +- || defined(__sh__) || defined(__powerpc__) ++#if defined(mc68000) || defined(__arm__) || defined(__thumb__) || \ ++ defined(__mips__) || defined(__sh__) || defined(__powerpc__) + # define CONSTANT_STRING_GOT_FIXUP(X) \ + if ((X) < (const char *) load_addr) (X) += load_addr + # define NO_EARLY_SEND_STDERR +@@ -318,7 +332,7 @@ + do { \ + do_rem(v, (X), 10); \ + *--tmp2 = '0' + v; \ +- (X) /= 10; \ ++ do_div_10((X), v); \ + } while ((X) > 0); \ + _dl_write(2, tmp2, tmp1 - tmp2 + sizeof(tmp) - 1); \ + } +diff -urN uClibc-0.9.28.orig/ldso/include/dl-syscall.h uClibc-0.9.28/ldso/include/dl-syscall.h +--- uClibc-0.9.28.orig/ldso/include/dl-syscall.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/include/dl-syscall.h 2006-04-28 00:14:35.000000000 -0600 +@@ -1,3 +1,10 @@ ++/* vi: set sw=4 ts=4: */ ++/* ++ * Copyright (C) 2000-2005 by Erik Andersen <andersen@codepoet.org> ++ * ++ * GNU Lesser General Public License version 2.1 or later. ++ */ ++ + #ifndef _LD_SYSCALL_H_ + #define _LD_SYSCALL_H_ + +@@ -12,9 +19,8 @@ + #include <bits/kernel_stat.h> + #include <bits/kernel_types.h> + +- + /* _dl_open() parameters */ +-#define O_RDONLY 0x0000 ++#define O_RDONLY 00 + #define O_WRONLY 01 + #define O_RDWR 02 + #define O_CREAT 0100 +@@ -39,18 +45,6 @@ + #define S_IWRITE 0200 /* Write by owner. */ + #define S_IEXEC 0100 /* Execute by owner. */ + +-/* Stuff for _dl_mmap */ +-#if 0 +-#define MAP_FAILED ((void *) -1) +-#define _dl_mmap_check_error(X) (((void *)X) == MAP_FAILED) +-#else +-#ifndef _dl_MAX_ERRNO +-#define _dl_MAX_ERRNO 4096 +-#endif +-#define _dl_mmap_check_error(__res) \ +- (((long)__res) < 0 && ((long)__res) >= -_dl_MAX_ERRNO) +-#endif +- + + + /* Here are the definitions for some syscalls that are used +@@ -66,54 +60,125 @@ + static inline _syscall1(int, _dl_close, int, fd); + + #define __NR__dl_open __NR_open +-static inline _syscall3(int, _dl_open, const char *, fn, int, flags, __kernel_mode_t, mode); ++static inline _syscall3(int, _dl_open, const char *, fn, int, flags, ++ __kernel_mode_t, mode); + + #define __NR__dl_write __NR_write + static inline _syscall3(unsigned long, _dl_write, int, fd, +- const void *, buf, unsigned long, count); ++ const void *, buf, unsigned long, count); + + #define __NR__dl_read __NR_read + static inline _syscall3(unsigned long, _dl_read, int, fd, +- const void *, buf, unsigned long, count); ++ const void *, buf, unsigned long, count); + + #define __NR__dl_mprotect __NR_mprotect +-static inline _syscall3(int, _dl_mprotect, const void *, addr, unsigned long, len, int, prot); ++static inline _syscall3(int, _dl_mprotect, const void *, addr, ++ unsigned long, len, int, prot); + + #define __NR__dl_stat __NR_stat +-static inline _syscall2(int, _dl_stat, const char *, file_name, struct stat *, buf); ++static inline _syscall2(int, _dl_stat, const char *, file_name, ++ struct stat *, buf); ++ ++#define __NR__dl_fstat __NR_fstat ++static inline _syscall2(int, _dl_fstat, int, fd, struct stat *, buf); + + #define __NR__dl_munmap __NR_munmap + static inline _syscall2(int, _dl_munmap, void *, start, unsigned long, length); + ++#ifdef __NR_getxuid ++# define __NR_getuid __NR_getxuid ++#endif + #define __NR__dl_getuid __NR_getuid + static inline _syscall0(uid_t, _dl_getuid); + ++#ifndef __NR_geteuid ++# define __NR_geteuid __NR_getuid ++#endif + #define __NR__dl_geteuid __NR_geteuid + static inline _syscall0(uid_t, _dl_geteuid); + ++#ifdef __NR_getxgid ++# define __NR_getgid __NR_getxgid ++#endif + #define __NR__dl_getgid __NR_getgid + static inline _syscall0(gid_t, _dl_getgid); + ++#ifndef __NR_getegid ++# define __NR_getegid __NR_getgid ++#endif + #define __NR__dl_getegid __NR_getegid + static inline _syscall0(gid_t, _dl_getegid); + ++#ifdef __NR_getxpid ++# define __NR_getpid __NR_getxpid ++#endif + #define __NR__dl_getpid __NR_getpid + static inline _syscall0(gid_t, _dl_getpid); + + #define __NR__dl_readlink __NR_readlink +-static inline _syscall3(int, _dl_readlink, const char *, path, char *, buf, size_t, bufsiz); ++static inline _syscall3(int, _dl_readlink, const char *, path, char *, buf, ++ size_t, bufsiz); + +-#ifdef __NR_mmap +-#ifdef MMAP_HAS_6_ARGS +-#define __NR__dl_mmap __NR_mmap +-static inline _syscall6(void *, _dl_mmap, void *, start, size_t, length, +- int, prot, int, flags, int, fd, off_t, offset); ++#ifdef __UCLIBC_HAS_SSP__ ++# include <sys/time.h> ++# define __NR__dl_gettimeofday __NR_gettimeofday ++static inline _syscall2(int, _dl_gettimeofday, struct timeval *, tv, ++# ifdef __USE_BSD ++ struct timezone *, tz); ++# else ++ void *, tz); ++# endif ++#endif ++ ++ ++/* handle all the fun mmap intricacies */ ++#if (defined(__UCLIBC_MMAP_HAS_6_ARGS__) && defined(__NR_mmap)) || !defined(__NR_mmap2) ++# define _dl_MAX_ERRNO 4096 ++# define _dl_mmap_check_error(__res) \ ++ (((long)__res) < 0 && ((long)__res) >= -_dl_MAX_ERRNO) + #else +-#define __NR__dl_mmap_real __NR_mmap +-static inline _syscall1(void *, _dl_mmap_real, unsigned long *, buffer); ++# define MAP_FAILED ((void *) -1) ++# define _dl_mmap_check_error(X) (((void *)X) == MAP_FAILED) ++#endif ++ ++/* first try mmap(), syscall6() style */ ++#if defined(__UCLIBC_MMAP_HAS_6_ARGS__) && defined(__NR_mmap) ++ ++# define __NR__dl_mmap __NR_mmap ++static inline _syscall6(void *, _dl_mmap, void *, start, size_t, length, ++ int, prot, int, flags, int, fd, off_t, offset); ++ ++/* then try mmap2() */ ++#elif defined(__NR_mmap2) ++ ++# define __NR___syscall_mmap2 __NR_mmap2 ++static inline _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr, size_t, len, ++ int, prot, int, flags, int, fd, off_t, offset); ++ ++/* Some architectures always use 12 as page shift for mmap2() eventhough the ++ * real PAGE_SHIFT != 12. Other architectures use the same value as ++ * PAGE_SHIFT... ++ */ ++#ifndef MMAP2_PAGE_SHIFT ++# define MMAP2_PAGE_SHIFT 12 ++#endif + + static inline void * _dl_mmap(void * addr, unsigned long size, int prot, +- int flags, int fd, unsigned long offset) ++ int flags, int fd, unsigned long offset) ++{ ++ if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1)) ++ return MAP_FAILED; ++ return __syscall_mmap2(addr, size, prot, flags, ++ fd, (off_t) (offset >> MMAP2_PAGE_SHIFT)); ++} ++ ++/* finally, fall back to mmap(), syscall1() style */ ++#elif defined(__NR_mmap) ++ ++# define __NR__dl_mmap_real __NR_mmap ++static inline _syscall1(void *, _dl_mmap_real, unsigned long *, buffer); ++static inline void * _dl_mmap(void * addr, unsigned long size, int prot, ++ int flags, int fd, unsigned long offset) + { + unsigned long buffer[6]; + +@@ -125,24 +190,9 @@ + buffer[5] = (unsigned long) offset; + return (void *) _dl_mmap_real(buffer); + } +-#endif +-#elif defined __NR_mmap2 +-#define __NR___syscall_mmap2 __NR_mmap2 +-static inline _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr, +- size_t, len, int, prot, int, flags, int, fd, off_t, offset); +-/*always 12, even on architectures where PAGE_SHIFT != 12 */ +-#define MMAP2_PAGE_SHIFT 12 +-static inline void * _dl_mmap(void * addr, unsigned long size, int prot, +- int flags, int fd, unsigned long offset) +-{ +- if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1)) +- return MAP_FAILED; +- return(__syscall_mmap2(addr, size, prot, flags, +- fd, (off_t) (offset >> MMAP2_PAGE_SHIFT))); +-} ++ + #else +-#error "Your architecture doesn't seem to provide mmap() !?" ++# error "Your architecture doesn't seem to provide mmap() !?" + #endif + + #endif /* _LD_SYSCALL_H_ */ +- +diff -urN uClibc-0.9.28.orig/ldso/include/dlfcn.h uClibc-0.9.28/ldso/include/dlfcn.h +--- uClibc-0.9.28.orig/ldso/include/dlfcn.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/include/dlfcn.h 2006-04-28 00:14:35.000000000 -0600 +@@ -1,3 +1,10 @@ ++/* vi: set sw=4 ts=4: */ ++/* ++ * Copyright (C) 2000-2005 by Erik Andersen <andersen@codepoet.org> ++ * ++ * GNU Lesser General Public License version 2.1 or later. ++ */ ++ + /* User functions for run-time dynamic loading. libdl version */ + #ifndef _DLFCN_H + #define _DLFCN_H 1 +diff -urN uClibc-0.9.28.orig/ldso/include/ldso.h uClibc-0.9.28/ldso/include/ldso.h +--- uClibc-0.9.28.orig/ldso/include/ldso.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/include/ldso.h 2006-04-28 00:14:35.000000000 -0600 +@@ -1,3 +1,10 @@ ++/* vi: set sw=4 ts=4: */ ++/* ++ * Copyright (C) 2000-2005 by Erik Andersen <andersen@codepoet.org> ++ * ++ * GNU Lesser General Public License version 2.1 or later. ++ */ ++ + #ifndef _LDSO_H_ + #define _LDSO_H_ + +@@ -20,13 +27,15 @@ + /* Pull in compiler and arch stuff */ + #include <stdlib.h> + #include <stdarg.h> ++#include <bits/wordsize.h> + /* Pull in the arch specific type information */ + #include <sys/types.h> ++/* Pull in the arch specific page size */ ++#include <bits/uClibc_page.h> ++#define attribute_unused __attribute__ ((unused)) + /* Pull in the ldso syscalls and string functions */ + #include <dl-syscall.h> + #include <dl-string.h> +-/* Pull in the arch specific page size */ +-#include <bits/uClibc_page.h> + /* Now the ldso specific headers */ + #include <dl-elf.h> + #include <dl-hash.h> +diff -urN uClibc-0.9.28.orig/ldso/include/unsecvars.h uClibc-0.9.28/ldso/include/unsecvars.h +--- uClibc-0.9.28.orig/ldso/include/unsecvars.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/include/unsecvars.h 2006-04-28 00:14:35.000000000 -0600 +@@ -1,3 +1,10 @@ ++/* vi: set sw=4 ts=4: */ ++/* ++ * Copyright (C) 2000-2005 by Erik Andersen <andersen@codepoet.org> ++ * ++ * GNU Lesser General Public License version 2.1 or later. ++ */ ++ + /* + * Environment variable to be removed for SUID programs. The names are all + * stuffed in a single string which means they have to be terminated with a +@@ -5,22 +12,21 @@ + */ + + #define UNSECURE_ENVVARS \ +- "LD_AOUT_PRELOAD\0" \ +- "LD_AOUT_LIBRARY_PATH\0" \ + "LD_PRELOAD\0" \ + "LD_LIBRARY_PATH\0" \ + "LD_DEBUG\0" \ + "LD_DEBUG_OUTPUT\0" \ + "LD_TRACE_LOADED_OBJECTS\0" \ +- "HOSTALIASES\0" \ +- "LOCALDOMAIN\0" \ +- "RES_OPTIONS\0" \ + "TMPDIR\0" + + /* ++ * LD_TRACE_LOADED_OBJECTS is not in glibc-2.3.5's unsecvars.h ++ * though used by ldd ++ * + * These environment variables are defined by glibc but ignored in + * uClibc, but may very well have an equivalent in uClibc. + * +- * MALLOC_TRACE, RESOLV_HOST_CONF, TZDIR, GCONV_PATH, LD_USE_LOAD_BIAS, +- * LD_PROFILE, LD_ORIGIN_PATH, LOCPATH, NLSPATH ++ * LD_ORIGIN_PATH, LD_PROFILE, LD_USE_LOAD_BIAS, LD_DYNAMIC_WEAK, LD_SHOW_AUXV, ++ * GCONV_PATH, GETCONF_DIR, HOSTALIASES, LOCALDOMAIN, LOCPATH, MALLOC_TRACE, ++ * NLSPATH, RESOLV_HOST_CONF, RES_OPTIONS, TZDIR + */ +diff -urN uClibc-0.9.28.orig/ldso/ldso/Makefile uClibc-0.9.28/ldso/ldso/Makefile +--- uClibc-0.9.28.orig/ldso/ldso/Makefile 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/Makefile 2006-04-28 00:14:35.000000000 -0600 +@@ -42,7 +42,9 @@ + endif + XXFLAGS+= -DUCLIBC_LDSO=\"$(UCLIBC_LDSO)\" $(XARCH_CFLAGS) $(CPU_CFLAGS) $(PICFLAG) \ + -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" \ +- -fno-builtin -nostdinc -D_LIBC -I$(TOPDIR)ldso/include -I. -I$(TOPDIR)include ++ -fno-builtin -nostdinc -D_LIBC \ ++ -DLDSO_ELFINTERP=\"$(TARGET_ARCH)/elfinterp.c\" \ ++ -I$(TOPDIR)ldso/ldso/$(TARGET_ARCH) -I$(TOPDIR)ldso/include -I$(TOPDIR)ldso/ldso -I$(TOPDIR)include + + # BEWARE!!! At least mips* will die if -O0 is used!!! + XXFLAGS:=$(XXFLAGS:-O0=-O1) +diff -urN uClibc-0.9.28.orig/ldso/ldso/arm/dl-startup.h uClibc-0.9.28/ldso/ldso/arm/dl-startup.h +--- uClibc-0.9.28.orig/ldso/ldso/arm/dl-startup.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/arm/dl-startup.h 2006-04-28 00:14:35.000000000 -0600 +@@ -1,10 +1,15 @@ + /* vi: set sw=4 ts=4: */ + /* + * Architecture specific code used by dl-startup.c +- * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org> ++ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> ++ * ++ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +-asm( ++#include <features.h> ++ ++#if !defined(__thumb__) ++__asm__( + " .text\n" + " .globl _start\n" + " .type _start,%function\n" +@@ -40,7 +45,78 @@ + " ldr r0, .L_FINI_PROC\n" + " ldr r0, [sl, r0]\n" + " @ jump to the user_s entry point\n" ++#if defined(__USE_BX__) ++ " bx r6\n" ++#else ++ " mov pc, r6\n" ++#endif ++ ".L_GET_GOT:\n" ++ " .word _GLOBAL_OFFSET_TABLE_ - .L_GOT_GOT - 4\n" ++ ".L_SKIP_ARGS:\n" ++ " .word _dl_skip_args(GOTOFF)\n" ++ ".L_FINI_PROC:\n" ++ " .word _dl_fini(GOT)\n" ++ "\n\n" ++ " .size _start,.-_start\n" ++ ".previous\n" ++); ++#else ++__asm__( ++ " .text\n" ++ " .arm\n" ++ " .globl _start\n" ++ " .type _start,%function\n" ++ "_start:\n" ++ " @ dumb: can't persuade the linker to make the start address\n" ++ " @ odd, so use an arm function and change to thumb (_dl_start\n" ++ " @ is thumb)\n" ++ " adr r0, __dl_thumb_start+1\n" ++ " bx r0\n" ++ "\n\n" ++ " .thumb\n" ++ " .globl __dl_thumb_start\n" ++ " .thumb_func\n" ++ " .type __dl_thumb_start,%function\n" ++ "__dl_thumb_start:\n" ++ " @ at start time, all the args are on the stack\n" ++ " mov r0, sp\n" ++ " bl _dl_start\n" ++ " @ returns user entry point in r0\n" ++ " mov r6, r0\n" ++ " @ we are PIC code, so get global offset table\n" ++ " ldr r7, .L_GET_GOT\n" ++ ".L_GOT_GOT:\n" ++ " add r7, pc\n" ++ " @ See if we were run as a command with the executable file\n" ++ " @ name as an extra leading argument.\n" ++ " ldr r4, .L_SKIP_ARGS\n" ++ " ldr r4, [r7, r4]\n" ++ " @ get the original arg count\n" ++ " ldr r1, [sp]\n" ++ " @ subtract _dl_skip_args from it\n" ++ " sub r1, r1, r4\n" ++ " @ adjust the stack pointer to skip them\n" ++ " lsl r4, r4, #2\n" ++ " add sp, r4\n" ++ " @ get the argv address\n" ++ " add r2, sp, #4\n" ++ " @ store the new argc in the new stack location\n" ++ " str r1, [sp]\n" ++ " @ compute envp\n" ++ " lsl r3, r1, #2\n" ++ " add r3, r3, r2\n" ++ " add r3, #4\n" ++ "\n\n" ++ " @ load the finalizer function\n" ++ " ldr r0, .L_FINI_PROC\n" ++ " ldr r0, [r7, r0]\n" ++ " @ jump to the user_s entry point\n" ++#if defined(__USE_BX__) ++ " bx r6\n" ++#else + " mov pc, r6\n" ++#endif ++ "\n\n" + ".L_GET_GOT:\n" + " .word _GLOBAL_OFFSET_TABLE_ - .L_GOT_GOT - 4\n" + ".L_SKIP_ARGS:\n" +@@ -51,6 +127,7 @@ + " .size _start,.-_start\n" + ".previous\n" + ); ++#endif + + + /* Get a pointer to the argv array. On many platforms this can be just +@@ -115,9 +192,3 @@ + _dl_exit(1); + } + } +- +- +-/* Transfer control to the user's application, once the dynamic loader is +- * done. This routine has to exit the current function, then call the +- * _dl_elf_main function. */ +-#define START() return _dl_elf_main; +diff -urN uClibc-0.9.28.orig/ldso/ldso/arm/dl-syscalls.h uClibc-0.9.28/ldso/ldso/arm/dl-syscalls.h +--- uClibc-0.9.28.orig/ldso/ldso/arm/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/arm/dl-syscalls.h 2006-04-28 00:14:35.000000000 -0600 +@@ -1,6 +1,7 @@ + /* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ ++#include "sys/syscall.h" + extern int _dl_errno; ++#undef __set_errno + #define __set_errno(X) {(_dl_errno) = (X);} +-#include "sys/syscall.h" + +diff -urN uClibc-0.9.28.orig/ldso/ldso/arm/dl-sysdep.h uClibc-0.9.28/ldso/ldso/arm/dl-sysdep.h +--- uClibc-0.9.28.orig/ldso/ldso/arm/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/arm/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600 +@@ -43,6 +43,7 @@ + return m; + } + #define do_rem(result, n, base) ((result) = arm_modulus(n, base)) ++#define do_div_10(result, remain) ((result) = (((result) - (remain)) / 2) * -(-1ul / 5ul)) + + /* Here we define the magic numbers that this dynamic loader should accept */ + #define MAGIC1 EM_ARM +@@ -85,7 +86,25 @@ + extern void __dl_start asm ("_dl_start"); + Elf32_Addr got_addr = (Elf32_Addr) &__dl_start; + Elf32_Addr pcrel_addr; ++#if !defined __thumb__ + asm ("adr %0, _dl_start" : "=r" (pcrel_addr)); ++#else ++ int tmp; ++ /* The above adr will not work on thumb because it ++ * is negative. The only safe way is to temporarily ++ * swap to arm. ++ */ ++ asm( ".align 2\n" ++ " bx pc\n" ++ " nop \n" ++ " .arm \n" ++ " adr %0, _dl_start\n" ++ " .align 2\n" ++ " orr %1, pc, #1\n" ++ " bx %1\n" ++ " .force_thumb\n" ++ : "=r" (pcrel_addr), "=&r" (tmp)); ++#endif + return pcrel_addr - got_addr; + } + +diff -urN uClibc-0.9.28.orig/ldso/ldso/arm/elfinterp.c uClibc-0.9.28/ldso/ldso/arm/elfinterp.c +--- uClibc-0.9.28.orig/ldso/ldso/arm/elfinterp.c 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/arm/elfinterp.c 2006-04-28 00:14:35.000000000 -0600 +@@ -38,6 +38,8 @@ + a more than adequate job of explaining everything required to get this + working. */ + ++#include "ldso.h" ++ + extern int _dl_linux_resolve(void); + + unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) +@@ -63,7 +65,6 @@ + strtab = (char *) tpnt->dynamic_info[DT_STRTAB]; + symname = strtab + symtab[symtab_index].st_name; + +- + if (unlikely(reloc_type != R_ARM_JUMP_SLOT)) { + _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n", + _dl_progname); +diff -urN uClibc-0.9.28.orig/ldso/ldso/cris/dl-startup.h uClibc-0.9.28/ldso/ldso/cris/dl-startup.h +--- uClibc-0.9.28.orig/ldso/ldso/cris/dl-startup.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/cris/dl-startup.h 2006-04-28 00:14:35.000000000 -0600 +@@ -4,22 +4,43 @@ + + /* This code fixes the stack pointer so that the dynamic linker + * can find argc, argv and auxvt (Auxillary Vector Table). */ ++#ifdef __arch_v32 ++ ++asm("" \ ++" .text\n" \ ++" .globl _start\n" \ ++" .type _start,@function\n" \ ++"_start:\n" \ ++" move.d $sp,$r10\n" \ ++" lapc _dl_start,$r9\n" \ ++" jsr $r9\n" \ ++" nop\n" \ ++" moveq 0,$r8\n" \ ++" jump $r10\n" \ ++" move $r8,$srp\n" \ ++" .size _start,.-_start\n" \ ++" .previous\n" \ ++); ++ ++#else ++ + asm("" \ + " .text\n" \ + " .globl _start\n" \ + " .type _start,@function\n" \ + "_start:\n" \ +-" move.d $sp,$r10\n" \ +-" move.d $pc,$r9\n" \ +-" add.d _dl_start - ., $r9\n" \ +-" jsr $r9\n" \ +-" moveq 0,$r8\n" \ +-" move $r8,$srp\n" \ +-" jump $r10\n" \ ++" move.d $sp,$r10\n" \ ++" move.d $pc,$r9\n" \ ++" add.d _dl_start - ., $r9\n" \ ++" jsr $r9\n" \ ++" moveq 0,$r8\n" \ ++" move $r8,$srp\n" \ ++" jump $r10\n" \ + " .size _start,.-_start\n" \ + " .previous\n" \ + ); + ++#endif /* __arch_v32 */ + + /* Get a pointer to the argv array. On many platforms this can be just + * the address if the first argument, on other platforms we need to +@@ -58,8 +79,3 @@ + break; + } + } +- +-/* Transfer control to the user's application, once the dynamic loader is +- * done. This routine has to exit the current function, then call the +- * _dl_elf_main function. */ +-#define START() return _dl_elf_main +diff -urN uClibc-0.9.28.orig/ldso/ldso/cris/dl-syscalls.h uClibc-0.9.28/ldso/ldso/cris/dl-syscalls.h +--- uClibc-0.9.28.orig/ldso/ldso/cris/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/cris/dl-syscalls.h 2006-04-28 00:14:35.000000000 -0600 +@@ -1,5 +1,6 @@ + /* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ ++#include "sys/syscall.h" + extern int _dl_errno; ++#undef __set_errno + #define __set_errno(X) {(_dl_errno) = (X);} +-#include "sys/syscall.h" +diff -urN uClibc-0.9.28.orig/ldso/ldso/cris/dl-sysdep.h uClibc-0.9.28/ldso/ldso/cris/dl-sysdep.h +--- uClibc-0.9.28.orig/ldso/ldso/cris/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/cris/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600 +@@ -18,8 +18,6 @@ + struct elf_resolve; + extern unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry); + +-#define do_rem(result, n, base) ((result) = (n) % (base)) +- + /* 8192 bytes alignment */ + #define PAGE_ALIGN 0xffffe000 + #define ADDR_ALIGN 0x1fff +@@ -68,8 +66,32 @@ + { + Elf32_Addr gotaddr_diff; + ++#ifdef __arch_v32 ++ extern char ___CRISv32_dummy[] __asm__ ("_dl_start"); ++ ++ __asm__ ("addo.w _dl_start:GOT16,$r0,$acr\n\t" ++ "lapc _dl_start,%0\n\t" ++ "sub.d [$acr],%0" ++ /* For v32, we need to force GCC to have R0 loaded with ++ _GLOBAL_OFFSET_TABLE_ at this point, which might not ++ otherwise have happened in the caller. (For v10, it's ++ loaded for non-global variables too, so we don't need ++ anything special there.) We accomplish this by faking the ++ address of a global variable (as seen by GCC) as input to ++ the asm; that address calculation goes through the GOT. ++ Use of this function happens before we've filled in the ++ GOT, so the address itself will not be correctly ++ calculated, therefore we don't use any symbol whose ++ address may be re-used later on. Let's just reuse the ++ _dl_start symbol, faking it as a global by renaming it as ++ another variable through an asm. */ ++ : "=r" (gotaddr_diff) ++ : "g" (___CRISv32_dummy) ++ : "acr"); ++#else + __asm__ ("sub.d [$r0+_dl_start:GOT16],$r0,%0\n\t" + "add.d _dl_start:GOTOFF,%0" : "=r" (gotaddr_diff)); ++#endif + return gotaddr_diff; + } + +diff -urN uClibc-0.9.28.orig/ldso/ldso/cris/resolve.S uClibc-0.9.28/ldso/ldso/cris/resolve.S +--- uClibc-0.9.28.orig/ldso/ldso/cris/resolve.S 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/cris/resolve.S 2006-04-28 00:14:35.000000000 -0600 +@@ -17,33 +17,73 @@ + .globl _dl_linux_resolve + .type _dl_linux_resolve,@function + ++#ifdef __arch_v32 ++ ++_dl_linux_resolve: ++ subq 4,$sp ++ move.d $r0,[$sp] ++ subq 4,$sp ++ move.d $r13,[$sp] ++ subq 4,$sp ++ move.d $r12,[$sp] ++ subq 4,$sp ++ move.d $r11,[$sp] ++ subq 4,$sp ++ addoq 5*4,$sp,$acr ++ move.d $r10,[$sp] ++ subq 4,$sp ++ move $mof,$r10 ++ move.d $r9,[$sp] ++ subq 4,$sp ++ move.d [$acr],$r11 ++ move $srp,[$sp] ++ lapc _GLOBAL_OFFSET_TABLE_,$r0 ++ move.d _dl_linux_resolver:PLTG,$r9 ++ add.d $r0,$r9 ++ jsr $r9 ++ nop ++ move.d $r10,$acr ++ move [$sp+],$srp ++ move.d [$sp+],$r9 ++ move.d [$sp+],$r10 ++ move.d [$sp+],$r11 ++ move.d [$sp+],$r12 ++ move.d [$sp+],$r13 ++ move.d [$sp+],$r0 ++ jump $acr ++ addq 4,$sp ++ ++#else ++ + _dl_linux_resolve: +- push $r13 +- push $r12 +- push $r11 +- push $r10 +- push $r9 +- push $r0 +- push $srp +- move.d [$sp+7*4],$r11 +- move $mof,$r10 ++ push $r13 ++ push $r12 ++ push $r11 ++ push $r10 ++ push $r9 ++ push $r0 ++ push $srp ++ move.d [$sp+7*4],$r11 ++ move $mof,$r10 + #ifdef __PIC__ +- move.d $pc,$r0 +- sub.d .:GOTOFF,$r0 +- move.d _dl_linux_resolver:PLTG,$r9 +- add.d $r0,$r9 +- jsr $r9 ++ move.d $pc,$r0 ++ sub.d .:GOTOFF,$r0 ++ move.d _dl_linux_resolver:PLTG,$r9 ++ add.d $r0,$r9 ++ jsr $r9 + #else +- jsr _dl_linux_resolver ++ jsr _dl_linux_resolver + #endif +- move.d $r10,[$sp+7*4] +- pop $srp +- pop $r0 +- pop $r9 +- pop $r10 +- pop $r11 +- pop $r12 +- pop $r13 +- jump [$sp+] ++ move.d $r10,[$sp+7*4] ++ pop $srp ++ pop $r0 ++ pop $r9 ++ pop $r10 ++ pop $r11 ++ pop $r12 ++ pop $r13 ++ jump [$sp+] ++ ++#endif /* __arch_v32 */ + + .size _dl_linux_resolve, . - _dl_linux_resolve +diff -urN uClibc-0.9.28.orig/ldso/ldso/dl-elf.c uClibc-0.9.28/ldso/ldso/dl-elf.c +--- uClibc-0.9.28.orig/ldso/ldso/dl-elf.c 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/dl-elf.c 2006-05-02 13:50:58.000000000 -0600 +@@ -3,7 +3,7 @@ + * This file contains the helper routines to load an ELF shared + * library into memory and add the symbol table info to the chain. + * +- * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org> ++ * Copyright (C) 2000-2006 by Erik Andersen <andersen@codepoet.org> + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * +@@ -60,8 +60,8 @@ + _dl_cache_addr = (caddr_t) _dl_mmap(0, _dl_cache_size, PROT_READ, MAP_SHARED, fd, 0); + _dl_close(fd); + if (_dl_mmap_check_error(_dl_cache_addr)) { +- _dl_dprintf(2, "%s: can't map cache '%s'\n", +- _dl_progname, LDSO_CACHE); ++ _dl_dprintf(2, "%s:%i: can't map '%s'\n", ++ _dl_progname, __LINE__, LDSO_CACHE); + return -1; + } + +@@ -115,7 +115,7 @@ + #endif + + +-void ++void + _dl_protect_relro (struct elf_resolve *l) + { + ElfW(Addr) start = ((l->loadaddr + l->relro_addr) +@@ -136,27 +136,41 @@ + search_for_named_library(const char *name, int secure, const char *path_list, + struct dyn_elf **rpnt) + { +- char *path, *path_n; +- char mylibname[2050]; ++ char *path, *path_n, *mylibname; + struct elf_resolve *tpnt; +- int done = 0; ++ int done; + + if (path_list==NULL) + return NULL; + +- /* We need a writable copy of this string */ +- path = _dl_strdup(path_list); +- if (!path) { ++ /* We need a writable copy of this string, but we don't ++ * need this allocated permanently since we don't want ++ * to leak memory, so use alloca to put path on the stack */ ++ done = _dl_strlen(path_list); ++ path = alloca(done + 1); ++ ++ /* another bit of local storage */ ++ mylibname = alloca(2050); ++ ++ /* gcc inlines alloca using a single instruction adjusting ++ * the stack pointer and no stack overflow check and thus ++ * no NULL error return. No point leaving in dead code... */ ++#if 0 ++ if (!path || !mylibname) { + _dl_dprintf(2, "Out of memory!\n"); + _dl_exit(0); + } ++#endif ++ ++ _dl_memcpy(path, path_list, done+1); + + /* Unlike ldd.c, don't bother to eliminate double //s */ + + /* Replace colons with zeros in path_list */ + /* : at the beginning or end of path maps to CWD */ + /* :: anywhere maps CWD */ +- /* "" maps to CWD */ ++ /* "" maps to CWD */ ++ done = 0; + path_n = path; + do { + if (*path == 0) { +@@ -180,71 +194,6 @@ + return NULL; + } + +-/* Check if the named library is already loaded... */ +-struct elf_resolve *_dl_check_if_named_library_is_loaded(const char *full_libname, +- int trace_loaded_objects) +-{ +- const char *pnt, *pnt1; +- struct elf_resolve *tpnt1; +- const char *libname, *libname2; +- static const char libc[] = "libc.so."; +- static const char aborted_wrong_lib[] = "%s: aborted attempt to load %s!\n"; +- +- pnt = libname = full_libname; +- +- _dl_if_debug_dprint("Checking if '%s' is already loaded\n", full_libname); +- /* quick hack to ensure mylibname buffer doesn't overflow. don't +- allow full_libname or any directory to be longer than 1024. */ +- if (_dl_strlen(full_libname) > 1024) +- return NULL; +- +- /* Skip over any initial initial './' and '/' stuff to +- * get the short form libname with no path garbage */ +- pnt1 = _dl_strrchr(pnt, '/'); +- if (pnt1) { +- libname = pnt1 + 1; +- } +- +- /* Make sure they are not trying to load the wrong C library! +- * This sometimes happens esp with shared libraries when the +- * library path is somehow wrong! */ +-#define isdigit(c) (c >= '0' && c <= '9') +- if ((_dl_strncmp(libname, libc, 8) == 0) && _dl_strlen(libname) >=8 && +- isdigit(libname[8])) +- { +- /* Abort attempts to load glibc, libc5, etc */ +- if ( libname[8]!='0') { +- if (!trace_loaded_objects) { +- _dl_dprintf(2, aborted_wrong_lib, libname, _dl_progname); +- _dl_exit(1); +- } +- return NULL; +- } +- } +- +- /* Critical step! Weed out duplicates early to avoid +- * function aliasing, which wastes memory, and causes +- * really bad things to happen with weaks and globals. */ +- for (tpnt1 = _dl_loaded_modules; tpnt1; tpnt1 = tpnt1->next) { +- +- /* Skip over any initial initial './' and '/' stuff to +- * get the short form libname with no path garbage */ +- libname2 = tpnt1->libname; +- pnt1 = _dl_strrchr(libname2, '/'); +- if (pnt1) { +- libname2 = pnt1 + 1; +- } +- +- if (_dl_strcmp(libname2, libname) == 0) { +- /* Well, that was certainly easy */ +- return tpnt1; +- } +- } +- +- return NULL; +-} +- +- + /* Used to return error codes back to dlopen et. al. */ + unsigned long _dl_error_number; + unsigned long _dl_internal_error_number; +@@ -271,14 +220,6 @@ + libname = pnt + 1; + } + +- /* Critical step! Weed out duplicates early to avoid +- * function aliasing, which wastes memory, and causes +- * really bad things to happen with weaks and globals. */ +- if ((tpnt1=_dl_check_if_named_library_is_loaded(libname, trace_loaded_objects))!=NULL) { +- tpnt1->usage_count++; +- return tpnt1; +- } +- + _dl_if_debug_dprint("\tfind library='%s'; searching\n", libname); + /* If the filename has any '/', try it straight and leave it at that. + For IBCS2 compatibility under linux, we substitute the string +@@ -290,7 +231,6 @@ + if (tpnt1) { + return tpnt1; + } +- //goto goof; + } + + /* +@@ -411,56 +351,45 @@ + int i, flags, piclib, infile; + ElfW(Addr) relro_addr = 0; + size_t relro_size = 0; +- +- /* If this file is already loaded, skip this step */ +- tpnt = _dl_check_hashed_files(libname); +- if (tpnt) { +- if (*rpnt) { +- (*rpnt)->next = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf)); +- _dl_memset((*rpnt)->next, 0, sizeof(struct dyn_elf)); +- (*rpnt)->next->prev = (*rpnt); +- *rpnt = (*rpnt)->next; +- (*rpnt)->dyn = tpnt; +- tpnt->symbol_scope = _dl_symbol_tables; +- } +- tpnt->usage_count++; +- tpnt->libtype = elf_lib; +- _dl_if_debug_dprint("file='%s'; already loaded\n", libname); +- return tpnt; +- } +- +- /* If we are in secure mode (i.e. a setu/gid binary using LD_PRELOAD), +- we don't load the library if it isn't setuid. */ +- +- if (secure) { +- struct stat st; +- +- if (_dl_stat(libname, &st) || !(st.st_mode & S_ISUID)) +- return NULL; +- } ++ struct stat st; + + libaddr = 0; + infile = _dl_open(libname, O_RDONLY, 0); + if (infile < 0) { +-#if 0 +- /* +- * NO! When we open shared libraries we may search several paths. +- * it is inappropriate to generate an error here. +- */ +- _dl_dprintf(2, "%s: can't open '%s'\n", _dl_progname, libname); +-#endif + _dl_internal_error_number = LD_ERROR_NOFILE; + return NULL; + } + ++ if (_dl_fstat(infile, &st) < 0) { ++ _dl_internal_error_number = LD_ERROR_NOFILE; ++ _dl_close(infile); ++ return NULL; ++ } ++ /* If we are in secure mode (i.e. a setu/gid binary using LD_PRELOAD), ++ we don't load the library if it isn't setuid. */ ++ if (secure) ++ if (!(st.st_mode & S_ISUID)) { ++ _dl_close(infile); ++ return NULL; ++ } ++ ++ /* Check if file is already loaded */ ++ for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) { ++ if(tpnt->st_dev == st.st_dev && tpnt->st_ino == st.st_ino) { ++ /* Already loaded */ ++ tpnt->usage_count++; ++ _dl_close(infile); ++ return tpnt; ++ } ++ } + header = _dl_mmap((void *) 0, _dl_pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (_dl_mmap_check_error(header)) { +- _dl_dprintf(2, "%s: can't map '%s'\n", _dl_progname, libname); ++ _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); + return NULL; +- }; ++ } + + _dl_read(infile, header, _dl_pagesize); + epnt = (ElfW(Ehdr) *) (intptr_t) header; +@@ -475,7 +404,7 @@ + _dl_close(infile); + _dl_munmap(header, _dl_pagesize); + return NULL; +- }; ++ } + + if ((epnt->e_type != ET_DYN) || (epnt->e_machine != MAGIC1 + #ifdef MAGIC2 +@@ -490,7 +419,7 @@ + _dl_close(infile); + _dl_munmap(header, _dl_pagesize); + return NULL; +- }; ++ } + + ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff]; + +@@ -502,7 +431,7 @@ + _dl_dprintf(2, "%s: '%s' has more than one dynamic section\n", + _dl_progname, libname); + dynamic_addr = ppnt->p_vaddr; +- }; ++ } + + if (ppnt->p_type == PT_LOAD) { + /* See if this is a PIC library. */ +@@ -518,7 +447,7 @@ + } + } + ppnt++; +- }; ++ } + + maxvma = (maxvma + ADDR_ALIGN) & ~ADDR_ALIGN; + minvma = minvma & ~0xffffU; +@@ -530,12 +459,12 @@ + status = (char *) _dl_mmap((char *) (piclib ? 0 : minvma), + maxvma - minvma, PROT_NONE, flags | MAP_ANONYMOUS, -1, 0); + if (_dl_mmap_check_error(status)) { +- _dl_dprintf(2, "%s: can't map %s\n", _dl_progname, libname); ++ _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); + _dl_munmap(header, _dl_pagesize); + return NULL; +- }; ++ } + libaddr = (unsigned long) status; + flags |= MAP_FIXED; + +@@ -567,14 +496,14 @@ + ppnt->p_offset & OFFS_ALIGN); + + if (_dl_mmap_check_error(status)) { +- _dl_dprintf(2, "%s: can't map '%s'\n", +- _dl_progname, libname); ++ _dl_dprintf(2, "%s:%i: can't map '%s'\n", ++ _dl_progname, __LINE__, libname); + _dl_internal_error_number = LD_ERROR_MMAP_FAILED; + _dl_munmap((char *) libaddr, maxvma - minvma); + _dl_close(infile); + _dl_munmap(header, _dl_pagesize); + return NULL; +- }; ++ } + + /* Pad the last page with zeroes. */ + cpnt = (char *) (status + (ppnt->p_vaddr & ADDR_ALIGN) + +@@ -601,21 +530,21 @@ + ppnt->p_filesz, LXFLAGS(ppnt->p_flags), flags, + infile, ppnt->p_offset & OFFS_ALIGN); + if (_dl_mmap_check_error(status)) { +- _dl_dprintf(2, "%s: can't map '%s'\n", _dl_progname, libname); ++ _dl_dprintf(2, "%s:%i: can't map '%s'\n", _dl_progname, __LINE__, libname); + _dl_internal_error_number = LD_ERROR_MMAP_FAILED; + _dl_munmap((char *) libaddr, maxvma - minvma); + _dl_close(infile); + _dl_munmap(header, _dl_pagesize); + return NULL; +- }; ++ } + + /* if(libaddr == 0 && piclib) { + libaddr = (unsigned long) status; + flags |= MAP_FIXED; +- }; */ +- }; ++ } */ ++ } + ppnt++; +- }; ++ } + _dl_close(infile); + + /* For a non-PIC library, the addresses are all absolute */ +@@ -665,6 +594,8 @@ + dynamic_addr, 0); + tpnt->relro_addr = relro_addr; + tpnt->relro_size = relro_size; ++ tpnt->st_dev = st.st_dev; ++ tpnt->st_ino = st.st_ino; + tpnt->ppnt = (ElfW(Phdr) *)(intptr_t) (tpnt->loadaddr + epnt->e_phoff); + tpnt->n_phent = epnt->e_phnum; + +@@ -693,7 +624,7 @@ + if (lpnt) { + lpnt = (unsigned long *) (dynamic_info[DT_PLTGOT]); + INIT_GOT(lpnt, tpnt); +- }; ++ } + + _dl_if_debug_dprint("\n\tfile='%s'; generating link map\n", libname); + _dl_if_debug_dprint("\t\tdynamic: %x base: %x\n", dynamic_addr, libaddr); +@@ -714,10 +645,12 @@ + ElfW(Addr) reloc_addr; + + if (rpnt->next) +- goof += _dl_fixup(rpnt->next, now_flag); ++ goof = _dl_fixup(rpnt->next, now_flag); ++ if (goof) ++ return goof; + tpnt = rpnt->dyn; + +- if(!(tpnt->init_flag & RELOCS_DONE)) ++ if(!(tpnt->init_flag & RELOCS_DONE)) + _dl_if_debug_dprint("relocation processing: %s\n", tpnt->libname); + + if (unlikely(tpnt->dynamic_info[UNSUPPORTED_RELOC_TYPE])) { +@@ -735,7 +668,6 @@ + #endif + if (tpnt->dynamic_info[DT_RELOC_TABLE_ADDR] && + !(tpnt->init_flag & RELOCS_DONE)) { +- tpnt->init_flag |= RELOCS_DONE; + reloc_addr = tpnt->dynamic_info[DT_RELOC_TABLE_ADDR]; + relative_count = tpnt->dynamic_info[DT_RELCONT_IDX]; + if (relative_count) { /* Optimize the XX_RELATIVE relocations if possible */ +@@ -746,14 +678,14 @@ + goof += _dl_parse_relocation_information(rpnt, + reloc_addr, + reloc_size); ++ tpnt->init_flag |= RELOCS_DONE; + } + if (tpnt->dynamic_info[DT_BIND_NOW]) + now_flag = RTLD_NOW; + if (tpnt->dynamic_info[DT_JMPREL] && + (!(tpnt->init_flag & JMP_RELOCS_DONE) || + (now_flag && !(tpnt->rtld_flags & now_flag)))) { +- tpnt->rtld_flags |= now_flag; +- tpnt->init_flag |= JMP_RELOCS_DONE; ++ tpnt->rtld_flags |= now_flag; + if (!(tpnt->rtld_flags & RTLD_NOW)) { + _dl_parse_lazy_relocation_information(rpnt, + tpnt->dynamic_info[DT_JMPREL], +@@ -763,6 +695,7 @@ + tpnt->dynamic_info[DT_JMPREL], + tpnt->dynamic_info[DT_PLTRELSZ]); + } ++ tpnt->init_flag |= JMP_RELOCS_DONE; + } + return goof; + } +@@ -770,11 +703,18 @@ + /* Minimal printf which handles only %s, %d, and %x */ + void _dl_dprintf(int fd, const char *fmt, ...) + { +- long num; ++#if __WORDSIZE > 32 ++ long int num; ++#else ++ int num; ++#endif + va_list args; + char *start, *ptr, *string; + static char *buf; + ++ if (!fmt) ++ return; ++ + buf = _dl_mmap((void *) 0, _dl_pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (_dl_mmap_check_error(buf)) { +@@ -784,9 +724,6 @@ + + start = ptr = buf; + +- if (!fmt) +- return; +- + if (_dl_strlen(fmt) >= (_dl_pagesize - 1)) { + _dl_write(fd, "overflow\n", 11); + _dl_exit(20); +@@ -818,8 +755,11 @@ + case 'd': + { + char tmp[22]; +- num = va_arg(args, long); +- ++#if __WORDSIZE > 32 ++ num = va_arg(args, long int); ++#else ++ num = va_arg(args, int); ++#endif + string = _dl_simple_ltoa(tmp, num); + _dl_write(fd, string, _dl_strlen(string)); + break; +@@ -828,8 +768,11 @@ + case 'X': + { + char tmp[22]; +- num = va_arg(args, long); +- ++#if __WORDSIZE > 32 ++ num = va_arg(args, long int); ++#else ++ num = va_arg(args, int); ++#endif + string = _dl_simple_ltoahex(tmp, num); + _dl_write(fd, string, _dl_strlen(string)); + break; +@@ -864,8 +807,10 @@ + { + __dl_parse_dynamic_info(dpnt, dynamic_info, debug_addr, load_off); + } ++ ++/* we want this in ldso.so and libdl.a but nowhere else */ + #ifdef __USE_GNU +-#if ! defined LIBDL || (! defined PIC && ! defined __PIC__) ++#if ! defined SHARED || (! defined PIC && ! defined __PIC__) + int + __dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info, size_t size, void *data), void *data) + { +@@ -884,6 +829,6 @@ + } + return ret; + } +-strong_alias(__dl_iterate_phdr, dl_iterate_phdr); ++strong_alias(__dl_iterate_phdr, dl_iterate_phdr) + #endif + #endif +diff -urN uClibc-0.9.28.orig/ldso/ldso/dl-hash.c uClibc-0.9.28/ldso/ldso/dl-hash.c +--- uClibc-0.9.28.orig/ldso/ldso/dl-hash.c 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/dl-hash.c 2006-04-28 00:14:35.000000000 -0600 +@@ -57,7 +57,7 @@ + /* This is the hash function that is used by the ELF linker to generate the + * hash table that each executable and library is required to have. We need + * it to decode the hash table. */ +-static inline Elf32_Word _dl_elf_hash(const char *name) ++static inline Elf_Symndx _dl_elf_hash(const char *name) + { + unsigned long hash=0; + unsigned long tmp; +@@ -77,21 +77,6 @@ + return hash; + } + +-/* Check to see if a library has already been added to the hash chain. */ +-struct elf_resolve *_dl_check_hashed_files(const char *libname) +-{ +- struct elf_resolve *tpnt; +- int len = _dl_strlen(libname); +- +- for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) { +- if (_dl_strncmp(tpnt->libname, libname, len) == 0 && +- (tpnt->libname[len] == '\0' || tpnt->libname[len] == '.')) +- return tpnt; +- } +- +- return NULL; +-} +- + /* + * We call this function when we have just read an ELF library or executable. + * We add the relevant info to the symbol chain, so that we can resolve all +@@ -99,9 +84,10 @@ + */ + struct elf_resolve *_dl_add_elf_hash_table(const char *libname, + char *loadaddr, unsigned long *dynamic_info, unsigned long dynamic_addr, ++ //attribute_unused + unsigned long dynamic_size) + { +- Elf32_Word *hash_addr; ++ Elf_Symndx *hash_addr; + struct elf_resolve *tpnt; + int i; + +@@ -125,7 +111,7 @@ + tpnt->libtype = loaded_file; + + if (dynamic_info[DT_HASH] != 0) { +- hash_addr = (Elf32_Word*)dynamic_info[DT_HASH]; ++ hash_addr = (Elf_Symndx*)dynamic_info[DT_HASH]; + tpnt->nbucket = *hash_addr++; + tpnt->nchain = *hash_addr++; + tpnt->elf_buckets = hash_addr; +diff -urN uClibc-0.9.28.orig/ldso/ldso/dl-startup.c uClibc-0.9.28/ldso/ldso/dl-startup.c +--- uClibc-0.9.28.orig/ldso/ldso/dl-startup.c 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/dl-startup.c 2006-04-28 00:14:35.000000000 -0600 +@@ -98,7 +98,7 @@ + int (*_dl_elf_main) (int, char **, char **); + + static void* __rtld_stack_end; /* Points to argc on stack, e.g *((long *)__rtld_stackend) == argc */ +-strong_alias(__rtld_stack_end, __libc_stack_end); /* Exported version of __rtld_stack_end */ ++strong_alias(__rtld_stack_end, __libc_stack_end) /* Exported version of __rtld_stack_end */ + + /* When we enter this piece of code, the program stack looks like this: + argc argument counter (integer) +@@ -307,5 +307,11 @@ + SEND_STDERR_DEBUG("transfering control to application @ "); + _dl_elf_main = (int (*)(int, char **, char **)) auxvt[AT_ENTRY].a_un.a_val; + SEND_ADDRESS_STDERR_DEBUG(_dl_elf_main, 1); ++ ++#ifndef START ++ return _dl_elf_main; ++#else ++#warning You need to update your arch ldso code + START(); ++#endif + } +diff -urN uClibc-0.9.28.orig/ldso/ldso/frv/dl-syscalls.h uClibc-0.9.28/ldso/ldso/frv/dl-syscalls.h +--- uClibc-0.9.28.orig/ldso/ldso/frv/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/frv/dl-syscalls.h 2006-04-28 00:14:35.000000000 -0600 +@@ -20,9 +20,10 @@ + + /* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ ++#include "sys/syscall.h" + extern int _dl_errno; ++#undef __set_errno + #define __set_errno(X) {(_dl_errno) = (X);} +-#include "sys/syscall.h" + #include <sys/mman.h> + + /* The code below is extracted from libc/sysdeps/linux/frv/_mmap.c */ +diff -urN uClibc-0.9.28.orig/ldso/ldso/frv/dl-sysdep.h uClibc-0.9.28/ldso/ldso/frv/dl-sysdep.h +--- uClibc-0.9.28.orig/ldso/ldso/frv/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/frv/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600 +@@ -65,8 +65,6 @@ + + extern int _dl_linux_resolve(void) __attribute__((__visibility__("hidden"))); + +-#define do_rem(result, n, base) ((result) = (n) % (base)) +- + /* 16KiB page alignment. Should perhaps be made dynamic using + getpagesize(), based on AT_PAGESZ from auxvt? */ + #define PAGE_ALIGN 0xffffc000 +diff -urN uClibc-0.9.28.orig/ldso/ldso/frv/elfinterp.c uClibc-0.9.28/ldso/ldso/frv/elfinterp.c +--- uClibc-0.9.28.orig/ldso/ldso/frv/elfinterp.c 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/frv/elfinterp.c 2006-04-28 00:14:35.000000000 -0600 +@@ -24,7 +24,7 @@ + the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, + USA. */ + +-#include <sys/cdefs.h> /* __attribute_used__ */ ++#include <features.h> + + /* Program to load an ELF binary on a linux system, and run it. + References to symbols in sharable libraries can be resolved by either +@@ -37,7 +37,7 @@ + a more than adequate job of explaining everything required to get this + working. */ + +-struct funcdesc_value volatile *__attribute__((__visibility__("hidden"))) ++struct funcdesc_value volatile attribute_hidden * + _dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry) + { + int reloc_type; +diff -urN uClibc-0.9.28.orig/ldso/ldso/i386/dl-startup.h uClibc-0.9.28/ldso/ldso/i386/dl-startup.h +--- uClibc-0.9.28.orig/ldso/ldso/i386/dl-startup.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/i386/dl-startup.h 2006-04-28 00:14:35.000000000 -0600 +@@ -3,7 +3,7 @@ + * Architecture specific code used by dl-startup.c + * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org> + */ +-asm( ++__asm__ ( + " .text\n" + " .align 16\n" + " .globl _start\n" +@@ -41,9 +41,9 @@ + #define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*) & ARGS)+1) + + /* Handle relocation of the symbols in the dynamic loader. */ +-static inline ++static __always_inline + void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr, +- unsigned long symbol_addr, unsigned long load_addr, Elf32_Sym *symtab) ++ unsigned long symbol_addr, unsigned long load_addr, attribute_unused Elf32_Sym *symtab) + { + switch (ELF32_R_TYPE(rpnt->r_info)) + { +@@ -64,8 +64,3 @@ + _dl_exit(1); + } + } +- +-/* Transfer control to the user's application, once the dynamic loader is +- * done. This routine has to exit the current function, then call the +- * _dl_elf_main function. */ +-#define START() return _dl_elf_main +diff -urN uClibc-0.9.28.orig/ldso/ldso/i386/dl-syscalls.h uClibc-0.9.28/ldso/ldso/i386/dl-syscalls.h +--- uClibc-0.9.28.orig/ldso/ldso/i386/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/i386/dl-syscalls.h 2006-04-28 00:14:35.000000000 -0600 +@@ -1,5 +1,6 @@ + /* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ ++#include "sys/syscall.h" + extern int _dl_errno; ++#undef __set_errno + #define __set_errno(X) {(_dl_errno) = (X);} +-#include "sys/syscall.h" +diff -urN uClibc-0.9.28.orig/ldso/ldso/i386/dl-sysdep.h uClibc-0.9.28/ldso/ldso/i386/dl-sysdep.h +--- uClibc-0.9.28.orig/ldso/ldso/i386/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/i386/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600 +@@ -25,8 +25,6 @@ + struct elf_resolve; + extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); + +-#define do_rem(result, n, base) ((result) = (n) % (base)) +- + /* 4096 bytes alignment */ + #define PAGE_ALIGN 0xfffff000 + #define ADDR_ALIGN 0xfff +@@ -44,16 +42,18 @@ + /* Return the link-time address of _DYNAMIC. Conveniently, this is the + first element of the GOT. This must be inlined in a function which + uses global data. */ +-static inline Elf32_Addr __attribute__ ((unused)) ++static inline Elf32_Addr elf_machine_dynamic (void) attribute_unused; ++static inline Elf32_Addr + elf_machine_dynamic (void) + { +- register Elf32_Addr *got asm ("%ebx"); ++ register Elf32_Addr *got __asm__ ("%ebx"); + return *got; + } + + + /* Return the run-time load address of the shared object. */ +-static inline Elf32_Addr __attribute__ ((unused)) ++static inline Elf32_Addr elf_machine_load_address (void) attribute_unused; ++static inline Elf32_Addr + elf_machine_load_address (void) + { + /* It doesn't matter what variable this is, the reference never makes +@@ -61,7 +61,7 @@ + via the GOT to make sure the compiler initialized %ebx in time. */ + extern int _dl_errno; + Elf32_Addr addr; +- asm ("leal _dl_start@GOTOFF(%%ebx), %0\n" ++ __asm__ ("leal _dl_start@GOTOFF(%%ebx), %0\n" + "subl _dl_start@GOT(%%ebx), %0" + : "=r" (addr) : "m" (_dl_errno) : "cc"); + return addr; +diff -urN uClibc-0.9.28.orig/ldso/ldso/i386/elfinterp.c uClibc-0.9.28/ldso/ldso/i386/elfinterp.c +--- uClibc-0.9.28.orig/ldso/ldso/i386/elfinterp.c 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/i386/elfinterp.c 2006-04-28 00:14:35.000000000 -0600 +@@ -67,12 +67,6 @@ + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + symname = strtab + symtab[symtab_index].st_name; + +- if (unlikely(reloc_type != R_386_JMP_SLOT)) { +- _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n", +- _dl_progname); +- _dl_exit(1); +- } +- + /* Address of the jump instruction to fix up. */ + instr_addr = ((unsigned long)this_reloc->r_offset + + (unsigned long)tpnt->loadaddr); +@@ -81,7 +75,7 @@ + /* Get the address of the GOT entry. */ + new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); + if (unlikely(!new_addr)) { +- _dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname); ++ _dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname); + _dl_exit(1); + } + +@@ -147,15 +141,15 @@ + int reloc_type = ELF32_R_TYPE(rpnt->r_info); + + #if defined (__SUPPORT_LD_DEBUG__) +- _dl_dprintf(2, "can't handle reloc type %s\n", +- _dl_reltypes(reloc_type)); ++ _dl_dprintf(2, "can't handle reloc type '%s' in lib '%s'\n", ++ _dl_reltypes(reloc_type), tpnt->libname); + #else +- _dl_dprintf(2, "can't handle reloc type %x\n", +- reloc_type); ++ _dl_dprintf(2, "can't handle reloc type %x in lib '%s'\n", ++ reloc_type, tpnt->libname); + #endif +- _dl_exit(-res); ++ return res; + } else if (unlikely(res > 0)) { +- _dl_dprintf(2, "can't resolve symbol\n"); ++ _dl_dprintf(2, "can't resolve symbol in lib '%s'.\n", tpnt->libname); + return res; + } + } +@@ -191,10 +185,8 @@ + * might have been intentional. We should not be linking local + * symbols here, so all bases should be covered. + */ +- if (unlikely(!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) { +- _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); +- _dl_exit(1); +- }; ++ if (unlikely(!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) ++ return 1; + } + + #if defined (__SUPPORT_LD_DEBUG__) +@@ -233,7 +225,7 @@ + } + break; + default: +- return -1; /* Calls _dl_exit(1). */ ++ return -1; + } + + #if defined (__SUPPORT_LD_DEBUG__) +@@ -273,7 +265,7 @@ + *reloc_addr += (unsigned long)tpnt->loadaddr; + break; + default: +- return -1; /* Calls _dl_exit(1). */ ++ return -1; + } + + #if defined (__SUPPORT_LD_DEBUG__) +diff -urN uClibc-0.9.28.orig/ldso/ldso/ldso.c uClibc-0.9.28/ldso/ldso/ldso.c +--- uClibc-0.9.28.orig/ldso/ldso/ldso.c 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/ldso.c 2006-05-02 13:55:54.000000000 -0600 +@@ -39,7 +39,7 @@ + #define ALLOW_ZERO_PLTGOT + + /* Pull in the value of _dl_progname */ +-#include "dl-progname.h" ++#include LDSO_ELFINTERP + + /* Global variables used within the shared library loader */ + char *_dl_library_path = 0; /* Where we look for libraries */ +@@ -74,7 +74,8 @@ + * can set an internal breakpoint on it, so that we are notified when the + * address mapping is changed in some way. + */ +-void _dl_debug_state(void) ++void _dl_debug_state(void); ++void _dl_debug_state() + { + } + +@@ -82,9 +83,78 @@ + static unsigned char *_dl_mmap_zero = 0; /* Also used by _dl_malloc */ + + static struct elf_resolve **init_fini_list; +-static int nlist; /* # items in init_fini_list */ ++static unsigned int nlist; /* # items in init_fini_list */ + extern void _start(void); + ++#ifdef __UCLIBC_HAS_SSP__ ++#ifndef __UCLIBC_HAS_SSP_COMPAT__ ++#define __UCLIBC_HAS_SSP_COMPAT__ 1 ++#endif ++# include <dl-osinfo.h> ++uintptr_t stack_chk_guard; ++# ifndef THREAD_SET_STACK_GUARD ++/* Only exported for architectures that don't store the stack guard canary ++ * in local thread area. */ ++uintptr_t __stack_chk_guard attribute_relro; ++# ifdef __UCLIBC_HAS_SSP_COMPAT__ ++strong_alias(__stack_chk_guard,__guard) ++# endif ++# elif __UCLIBC_HAS_SSP_COMPAT__ ++uintptr_t __guard attribute_relro; ++# endif ++#endif ++ ++static void _dl_run_array_forward(unsigned long array, unsigned long size, ++ ElfW(Addr) loadaddr) ++{ ++ if (array != 0) { ++ unsigned int j; ++ unsigned int jm; ++ ElfW(Addr) *addrs; ++ jm = size / sizeof (ElfW(Addr)); ++ addrs = (ElfW(Addr) *) (array + loadaddr); ++ for (j = 0; j < jm; ++j) { ++ void (*dl_elf_func) (void); ++ dl_elf_func = (void (*)(void)) (intptr_t) addrs[j]; ++ (*dl_elf_func) (); ++ } ++ } ++} ++ ++void _dl_run_init_array(struct elf_resolve *tpnt); ++void _dl_run_init_array(struct elf_resolve *tpnt) ++{ ++ _dl_run_array_forward(tpnt->dynamic_info[DT_INIT_ARRAY], ++ tpnt->dynamic_info[DT_INIT_ARRAYSZ], ++ tpnt->loadaddr); ++} ++ ++void _dl_app_init_array(void); ++void _dl_app_init_array(void) ++{ ++ _dl_run_init_array(_dl_loaded_modules); ++} ++ ++void _dl_run_fini_array(struct elf_resolve *tpnt); ++void _dl_run_fini_array(struct elf_resolve *tpnt) ++{ ++ if (tpnt->dynamic_info[DT_FINI_ARRAY]) { ++ ElfW(Addr) *array = (ElfW(Addr) *) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI_ARRAY]); ++ unsigned int i = (tpnt->dynamic_info[DT_FINI_ARRAYSZ] / sizeof(ElfW(Addr))); ++ while (i-- > 0) { ++ void (*dl_elf_func) (void); ++ dl_elf_func = (void (*)(void)) (intptr_t) array[i]; ++ (*dl_elf_func) (); ++ } ++ } ++} ++ ++void _dl_app_fini_array(void); ++void _dl_app_fini_array(void) ++{ ++ _dl_run_fini_array(_dl_loaded_modules); ++} ++ + static void __attribute__ ((destructor)) __attribute_used__ _dl_fini(void) + { + int i; +@@ -95,6 +165,7 @@ + if (tpnt->init_flag & FINI_FUNCS_CALLED) + continue; + tpnt->init_flag |= FINI_FUNCS_CALLED; ++ _dl_run_fini_array(tpnt); + if (tpnt->dynamic_info[DT_FINI]) { + void (*dl_elf_func) (void); + +@@ -112,7 +183,8 @@ + ElfW(Phdr) *ppnt; + ElfW(Dyn) *dpnt; + char *lpntstr; +- int i, goof = 0, unlazy = 0, trace_loaded_objects = 0; ++ unsigned int i; ++ int unlazy = 0, trace_loaded_objects = 0; + struct dyn_elf *rpnt; + struct elf_resolve *tcurr; + struct elf_resolve *tpnt1; +@@ -128,6 +200,7 @@ + * setup so we can use _dl_dprintf() to print debug noise + * instead of the SEND_STDERR macros used in dl-startup.c */ + ++ _dl_memset(app_tpnt, 0x00, sizeof(*app_tpnt)); + + /* Store the page size for later use */ + _dl_pagesize = (auxvt[AT_PAGESZ].a_un.a_val) ? (size_t) auxvt[AT_PAGESZ].a_un.a_val : PAGE_SIZE; +@@ -168,8 +241,8 @@ + * Note that for SUID programs we ignore the settings in + * LD_LIBRARY_PATH. + */ +- if ((auxvt[AT_UID].a_un.a_val == -1 && _dl_suid_ok()) || +- (auxvt[AT_UID].a_un.a_val != -1 && ++ if ((auxvt[AT_UID].a_un.a_val == (size_t)-1 && _dl_suid_ok()) || ++ (auxvt[AT_UID].a_un.a_val != (size_t)-1 && + auxvt[AT_UID].a_un.a_val == auxvt[AT_EUID].a_un.a_val && + auxvt[AT_GID].a_un.a_val == auxvt[AT_EGID].a_un.a_val)) { + _dl_secure = 0; +@@ -196,6 +269,20 @@ + unlazy = RTLD_NOW; + } + ++ /* sjhill: your TLS init should go before this */ ++#ifdef __UCLIBC_HAS_SSP__ ++ /* Set up the stack checker's canary. */ ++ stack_chk_guard = _dl_setup_stack_chk_guard (); ++# ifdef THREAD_SET_STACK_GUARD ++ THREAD_SET_STACK_GUARD (stack_chk_guard); ++# ifdef __UCLIBC_HAS_SSP_COMPAT__ ++ __guard = stack_chk_guard; ++# endif ++# else ++ __stack_chk_guard = stack_chk_guard; ++# endif ++#endif ++ + /* At this point we are now free to examine the user application, + * and figure out which libraries are supposed to be called. Until + * we have this list, we will not be completely ready for dynamic +@@ -206,12 +293,12 @@ + * different from what the ELF header says for ET_DYN/PIE executables. + */ + { +- int i; +- ElfW(Phdr) *ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val; ++ unsigned int idx; ++ ElfW(Phdr) *phdr = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val; + +- for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) +- if (ppnt->p_type == PT_PHDR) { +- app_tpnt->loadaddr = (ElfW(Addr)) (auxvt[AT_PHDR].a_un.a_val - ppnt->p_vaddr); ++ for (idx = 0; idx < auxvt[AT_PHNUM].a_un.a_val; idx++, phdr++) ++ if (phdr->p_type == PT_PHDR) { ++ app_tpnt->loadaddr = (ElfW(Addr)) (auxvt[AT_PHDR].a_un.a_val - phdr->p_vaddr); + break; + } + +@@ -459,8 +546,8 @@ + PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + _dl_close(fd); + if (preload == (caddr_t) -1) { +- _dl_dprintf(_dl_debug_file, "%s: can't map file '%s'\n", +- _dl_progname, LDSO_PRELOAD); ++ _dl_dprintf(_dl_debug_file, "%s:%i: can't map '%s'\n", ++ _dl_progname, __LINE__, LDSO_PRELOAD); + break; + } + +@@ -528,15 +615,15 @@ + + nlist = 0; + for (tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next) { +- ElfW(Dyn) *dpnt; ++ ElfW(Dyn) *this_dpnt; + + nlist++; +- for (dpnt = (ElfW(Dyn) *) tcurr->dynamic_addr; dpnt->d_tag; dpnt++) { +- if (dpnt->d_tag == DT_NEEDED) { ++ for (this_dpnt = (ElfW(Dyn) *) tcurr->dynamic_addr; this_dpnt->d_tag; this_dpnt++) { ++ if (this_dpnt->d_tag == DT_NEEDED) { + char *name; + struct init_fini_list *tmp; + +- lpntstr = (char*) (tcurr->dynamic_info[DT_STRTAB] + dpnt->d_un.d_val); ++ lpntstr = (char*) (tcurr->dynamic_info[DT_STRTAB] + this_dpnt->d_un.d_val); + name = _dl_get_last_path_component(lpntstr); + if (_dl_strcmp(name, UCLIBC_LDSO) == 0) + continue; +@@ -633,7 +720,7 @@ + ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val; + ElfW(Phdr) *myppnt = (ElfW(Phdr) *) (load_addr + epnt->e_phoff); + int j; +- ++ + tpnt = _dl_add_elf_hash_table(tpnt->libname, (char *)load_addr, + tpnt->dynamic_info, + (unsigned long)tpnt->dynamic_addr, +@@ -703,16 +790,14 @@ + * order so that COPY directives work correctly. + */ + if (_dl_symbol_tables) +- goof += _dl_fixup(_dl_symbol_tables, unlazy); ++ if (_dl_fixup(_dl_symbol_tables, unlazy)) ++ _dl_exit(-1); + + for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) { + if (tpnt->relro_size) + _dl_protect_relro (tpnt); + } + +- +- +- + /* OK, at this point things are pretty much ready to run. Now we need + * to touch up a few items that are required, and then we can let the + * user application have at it. Note that the dynamic linker itself +@@ -746,6 +831,14 @@ + /* Notify the debugger we have added some objects. */ + _dl_debug_addr->r_state = RT_ADD; + _dl_debug_state(); ++ ++ /* Run pre-initialization functions for the executable. */ ++ _dl_run_array_forward(_dl_loaded_modules->dynamic_info[DT_PREINIT_ARRAY], ++ _dl_loaded_modules->dynamic_info[DT_PREINIT_ARRAYSZ], ++ _dl_loaded_modules->loadaddr); ++ ++ /* Run initialization functions for loaded objects. For the ++ main executable, they will be run from __uClibc_main. */ + for (i = nlist; i; --i) { + tpnt = init_fini_list[i-1]; + tpnt->init_fini = NULL; /* Clear, since alloca was used */ +@@ -762,17 +855,9 @@ + + (*dl_elf_func) (); + } +- } +-#ifdef _DL_FINI_CRT_COMPAT +- /* arches that have moved their ldso FINI handling should skip this part */ +- { +- int (*_dl_atexit) (void *) = (int (*)(void *)) (intptr_t) _dl_find_hash("atexit", +- _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT); + +- if (_dl_atexit) +- (*_dl_atexit) (_dl_fini); ++ _dl_run_init_array(tpnt); + } +-#endif + + /* Find the real malloc function and make ldso functions use that from now on */ + _dl_malloc_function = (void* (*)(size_t)) (intptr_t) _dl_find_hash("malloc", +diff -urN uClibc-0.9.28.orig/ldso/ldso/m68k/dl-startup.h uClibc-0.9.28/ldso/ldso/m68k/dl-startup.h +--- uClibc-0.9.28.orig/ldso/ldso/m68k/dl-startup.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/m68k/dl-startup.h 2006-04-28 00:14:35.000000000 -0600 +@@ -4,23 +4,48 @@ + * Copyright (C) 2005 by Erik Andersen <andersen@codepoet.org> + */ + +-asm( +- " .text\n" +- " .globl _start\n" +- " .type _start,@function\n" +- "_start:\n" +- " .set _start,_dl_start\n" +- " .size _start,.-_start\n" +- " .previous\n" +-); ++asm ("\ ++ .text\n\ ++ .globl _start\n\ ++ .type _start,@function\n\ ++_start:\n\ ++ move.l %sp, -(%sp)\n\ ++ jbsr _dl_start\n\ ++ addq.l #4, %sp\n\ ++ /* FALLTHRU */\n\ ++\n\ ++ .globl _dl_start_user\n\ ++.type _dl_start_user,@function\n\ ++_dl_start_user:\n\ ++ # Save the user entry point address in %a4.\n\ ++ move.l %d0, %a4\n\ ++ # See if we were run as a command with the executable file\n\ ++ # name as an extra leading argument.\n\ ++ move.l _dl_skip_args(%pc), %d0\n\ ++ # Pop the original argument count\n\ ++ move.l (%sp)+, %d1\n\ ++ # Subtract _dl_skip_args from it.\n\ ++ sub.l %d0, %d1\n\ ++ # Adjust the stack pointer to skip _dl_skip_args words.\n\ ++ lea (%sp, %d0*4), %sp\n\ ++ # Push back the modified argument count.\n\ ++ move.l %d1, -(%sp)\n\ ++ # Pass our finalizer function to the user in %a1.\n\ ++ lea _dl_fini(%pc), %a1\n\ ++ # Initialize %fp with the stack pointer.\n\ ++ move.l %sp, %fp\n\ ++ # Jump to the user's entry point.\n\ ++ jmp (%a4)\n\ ++ .size _dl_start_user, . - _dl_start_user\n\ ++ .previous"); + + /* Get a pointer to the argv array. On many platforms this can be just + * the address if the first argument, on other platforms we need to + * do something a little more subtle here. */ +-#define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned int *) & ARGS) ++#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS) + 1) + + /* Handle relocation of the symbols in the dynamic loader. */ +-static inline ++static __always_inline + void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr, + unsigned long symbol_addr, unsigned long load_addr, Elf32_Sym *symtab) + { +@@ -59,12 +84,3 @@ + _dl_exit (1); + } + } +- +-/* Transfer control to the user's application, once the dynamic loader is +- * done. This routine has to exit the current function, then call the +- * _dl_elf_main function. */ +-#define START() \ +- __asm__ volatile ( \ +- "unlk %%a6\n\t" \ +- "jmp %0@" \ +- : : "a" (_dl_elf_main)); +diff -urN uClibc-0.9.28.orig/ldso/ldso/m68k/dl-syscalls.h uClibc-0.9.28/ldso/ldso/m68k/dl-syscalls.h +--- uClibc-0.9.28.orig/ldso/ldso/m68k/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/m68k/dl-syscalls.h 2006-04-28 00:14:35.000000000 -0600 +@@ -1,5 +1,6 @@ + /* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ ++#include "sys/syscall.h" + extern int _dl_errno; ++#undef __set_errno + #define __set_errno(X) {(_dl_errno) = (X);} +-#include "sys/syscall.h" +diff -urN uClibc-0.9.28.orig/ldso/ldso/m68k/dl-sysdep.h uClibc-0.9.28/ldso/ldso/m68k/dl-sysdep.h +--- uClibc-0.9.28.orig/ldso/ldso/m68k/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/m68k/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600 +@@ -25,10 +25,6 @@ + struct elf_resolve; + extern unsigned int _dl_linux_resolver (struct elf_resolve *, int); + +-/* Define this because we do not want to call .udiv in the library. +- Not needed for m68k. */ +-#define do_rem(result, n, base) ((result) = (n) % (base)) +- + /* 4096 bytes alignment */ + #define PAGE_ALIGN 0xfffff000 + #define ADDR_ALIGN 0xfff +diff -urN uClibc-0.9.28.orig/ldso/ldso/m68k/elfinterp.c uClibc-0.9.28/ldso/ldso/m68k/elfinterp.c +--- uClibc-0.9.28.orig/ldso/ldso/m68k/elfinterp.c 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/m68k/elfinterp.c 2006-04-28 00:14:35.000000000 -0600 +@@ -40,6 +40,8 @@ + a more than adequate job of explaining everything required to get this + working. */ + ++#include "ldso.h" ++ + extern int _dl_linux_resolve(void); + + unsigned int +@@ -48,20 +50,20 @@ + int reloc_type; + ELF_RELOC *this_reloc; + char *strtab; +- Elf32_Sym *symtab; ++ ElfW(Sym) *symtab; + int symtab_index; +- ELF_RELOC *rel_addr; ++ char *rel_addr; + char *new_addr; + char **got_addr; +- unsigned int instr_addr; ++ ElfW(Addr) instr_addr; + char *symname; + +- rel_addr = (ELF_RELOC *)tpnt->dynamic_info[DT_JMPREL]; +- this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry); +- reloc_type = ELF32_R_TYPE(this_reloc->r_info); +- symtab_index = ELF32_R_SYM(this_reloc->r_info); ++ rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL]; ++ this_reloc = (ELF_RELOC *)(rel_addr + reloc_entry); ++ reloc_type = ELF_R_TYPE(this_reloc->r_info); ++ symtab_index = ELF_R_SYM(this_reloc->r_info); + +- symtab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB]; ++ symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + symname = strtab + symtab[symtab_index].st_name; + +@@ -72,7 +74,7 @@ + } + + /* Address of the jump instruction to fix up. */ +- instr_addr = ((int)this_reloc->r_offset + (int)tpnt->loadaddr); ++ instr_addr = (this_reloc->r_offset + tpnt->loadaddr); + got_addr = (char **)instr_addr; + + /* Get the address of the GOT entry. */ +@@ -88,159 +90,237 @@ + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); + if (_dl_debug_detail) + _dl_dprintf(_dl_debug_file, +- "\n\tpatched: %x ==> %x @ %x", ++ "\tpatched: %x ==> %x @ %x\n", + *got_addr, new_addr, got_addr); + } + } +- if (!_dl_debug_nofixups) { +- *got_addr = new_addr; +- } +-#else +- *got_addr = new_addr; ++ if (!_dl_debug_nofixups) + #endif ++ *got_addr = new_addr; + +- return (unsigned int)new_addr; ++ return (unsigned int)new_addr; + } + +-void +-_dl_parse_lazy_relocation_information(struct dyn_elf *arg_rpnt, +- unsigned long rel_addr, unsigned long rel_size) ++static int ++_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, ++ unsigned long rel_addr, unsigned long rel_size, ++ int (*reloc_fnc)(struct elf_resolve *tpnt, struct dyn_elf *scope, ++ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)) + { +- int i; ++ unsigned int i; + char *strtab; +- int reloc_type; ++ ElfW(Sym) *symtab; ++ ELF_RELOC *rpnt; + int symtab_index; +- Elf32_Sym *symtab; +- Elf32_Rela *rpnt; +- unsigned int *reloc_addr; +- struct elf_resolve *tpnt = arg_rpnt->dyn; +- +- /* Now parse the relocation information. */ +- rpnt = (Elf32_Rela *)rel_addr; +- rel_size = rel_size / sizeof (Elf32_Rela); + +- symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB]; ++ /* Parse the relocation information. */ ++ rpnt = (ELF_RELOC *)rel_addr; ++ rel_size /= sizeof(ELF_RELOC); ++ ++ symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + + for (i = 0; i < rel_size; i++, rpnt++) { +- reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset); +- reloc_type = ELF32_R_TYPE (rpnt->r_info); +- symtab_index = ELF32_R_SYM (rpnt->r_info); ++ int res; + +- switch (reloc_type) +- { +- case R_68K_NONE: +- break; +- case R_68K_JMP_SLOT: +- *reloc_addr += (unsigned int) tpnt->loadaddr; +- break; +- default: +- _dl_dprintf (2, "%s: (LAZY) can't handle reloc type ", _dl_progname); ++ symtab_index = ELF_R_SYM(rpnt->r_info); ++ ++ debug_sym(symtab, strtab, symtab_index); ++ debug_reloc(symtab, strtab, rpnt); ++ ++ res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab); ++ ++ if (res == 0) ++ continue; ++ ++ _dl_dprintf(2, "\n%s: ", _dl_progname); ++ ++ if (symtab_index) ++ _dl_dprintf(2, "symbol '%s': ", ++ strtab + symtab[symtab_index].st_name); ++ ++ if (unlikely(res < 0)) { ++ int reloc_type = ELF_R_TYPE(rpnt->r_info); ++ ++ _dl_dprintf(2, "can't handle reloc type " + #if defined (__SUPPORT_LD_DEBUG__) +- _dl_dprintf (2, "%s ", _dl_reltypes_tab[reloc_type]); ++ "%s\n", _dl_reltypes(reloc_type)); ++#else ++ "%x\n", reloc_type); + #endif +- if (symtab_index) +- _dl_dprintf (2, "'%s'", strtab + symtab[symtab_index].st_name); +- _dl_dprintf (2, "\n"); +- _dl_exit (1); ++ _dl_exit(-res); ++ } else if (unlikely(res > 0)) { ++ _dl_dprintf(2, "can't resolve symbol\n"); ++ return res; + } + } ++ ++ return 0; + } + +-int +-_dl_parse_relocation_information(struct dyn_elf *arg_rpnt, +- unsigned long rel_addr, unsigned long rel_size) ++static int ++_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, ++ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) + { +- int i; +- char *strtab; + int reloc_type; +- int goof = 0; +- Elf32_Sym *symtab; +- Elf32_Rela *rpnt; +- unsigned int *reloc_addr; +- unsigned int symbol_addr; + int symtab_index; +- struct elf_resolve *tpnt = arg_rpnt->dyn; +- /* Now parse the relocation information */ ++ char *symname; ++ ElfW(Sym) *sym; ++ ElfW(Addr) *reloc_addr; ++ ElfW(Addr) symbol_addr; ++#if defined (__SUPPORT_LD_DEBUG__) ++ ElfW(Addr) old_val; ++#endif + +- rpnt = (Elf32_Rela *)rel_addr; +- rel_size = rel_size / sizeof (Elf32_Rela); ++ reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); ++ reloc_type = ELF_R_TYPE(rpnt->r_info); ++ symtab_index = ELF_R_SYM(rpnt->r_info); ++ sym = &symtab[symtab_index]; ++ symbol_addr = 0; ++ symname = strtab + sym->st_name; ++ ++ if (symtab_index) { ++ symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt, ++ elf_machine_type_class(reloc_type)); ++ /* ++ * We want to allow undefined references to weak symbols - this ++ * might have been intentional. We should not be linking local ++ * symbols here, so all bases should be covered. ++ */ ++ if (unlikely(!symbol_addr && ELF_ST_BIND(sym->st_info) != STB_WEAK)) { ++ _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); ++ _dl_exit(1); ++ }; ++ } + +- symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB]; +- strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; ++#if defined (__SUPPORT_LD_DEBUG__) ++ old_val = *reloc_addr; ++#endif + +- for (i = 0; i < rel_size; i++, rpnt++) { +- reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset); +- reloc_type = ELF32_R_TYPE (rpnt->r_info); +- symtab_index = ELF32_R_SYM (rpnt->r_info); +- symbol_addr = 0; +- if (symtab_index) { +- symbol_addr = (unsigned int) +- _dl_find_hash (strtab + symtab[symtab_index].st_name, +- tpnt->symbol_scope, tpnt, +- elf_machine_type_class(reloc_type)); +- +- /* We want to allow undefined references to weak symbols - +- this might have been intentional. We should not be +- linking local symbols here, so all bases should be +- covered. */ +- if (!symbol_addr +- && ELF32_ST_BIND (symtab[symtab_index].st_info) != STB_WEAK) +- { +- _dl_dprintf (2, "%s: can't resolve symbol '%s'\n", +- _dl_progname, strtab + symtab[symtab_index].st_name); +- _dl_exit (1); +- } +- } +- switch (reloc_type) +- { +- case R_68K_NONE: +- break; +- case R_68K_8: +- *(char *) reloc_addr = symbol_addr + rpnt->r_addend; +- break; +- case R_68K_16: +- *(short *) reloc_addr = symbol_addr + rpnt->r_addend; +- break; +- case R_68K_32: +- *reloc_addr = symbol_addr + rpnt->r_addend; +- break; +- case R_68K_PC8: +- *(char *) reloc_addr = (symbol_addr + rpnt->r_addend +- - (unsigned int) reloc_addr); +- break; +- case R_68K_PC16: +- *(short *) reloc_addr = (symbol_addr + rpnt->r_addend +- - (unsigned int) reloc_addr); +- break; +- case R_68K_PC32: +- *reloc_addr = (symbol_addr + rpnt->r_addend +- - (unsigned int) reloc_addr); +- break; +- case R_68K_GLOB_DAT: +- case R_68K_JMP_SLOT: +- *reloc_addr = symbol_addr; +- break; +- case R_68K_RELATIVE: +- *reloc_addr = ((unsigned int) tpnt->loadaddr +- /* Compatibility kludge. */ +- + (rpnt->r_addend ? : *reloc_addr)); +- break; +- case R_68K_COPY: ++ switch (reloc_type) { ++ case R_68K_NONE: ++ break; ++ case R_68K_8: ++ *(char *) reloc_addr = symbol_addr + rpnt->r_addend; ++ break; ++ case R_68K_16: ++ *(short *) reloc_addr = symbol_addr + rpnt->r_addend; ++ break; ++ case R_68K_32: ++ *reloc_addr = symbol_addr + rpnt->r_addend; ++ break; ++ case R_68K_PC8: ++ *(char *) reloc_addr = (symbol_addr + rpnt->r_addend ++ - (unsigned int) reloc_addr); ++ break; ++ case R_68K_PC16: ++ *(short *) reloc_addr = (symbol_addr + rpnt->r_addend ++ - (unsigned int) reloc_addr); ++ break; ++ case R_68K_PC32: ++ *reloc_addr = (symbol_addr + rpnt->r_addend ++ - (unsigned int) reloc_addr); ++ break; ++ case R_68K_GLOB_DAT: ++ case R_68K_JMP_SLOT: ++ *reloc_addr = symbol_addr + rpnt->r_addend; ++ break; ++ /* handled by elf_machine_relative() ++ case R_68K_RELATIVE: ++ *reloc_addr = ((unsigned int) tpnt->loadaddr ++ / * Compatibility kludge. * / ++ + (rpnt->r_addend ? : *reloc_addr)); ++ */ ++ break; ++ case R_68K_COPY: ++ if (symbol_addr) { ++#if defined (__SUPPORT_LD_DEBUG__) ++ if (_dl_debug_move) ++ _dl_dprintf(_dl_debug_file, ++ "\t%s move %d bytes from %x to %x\n", ++ symname, sym->st_size, ++ symbol_addr, reloc_addr); ++#endif + _dl_memcpy ((void *) reloc_addr, + (void *) symbol_addr, +- symtab[symtab_index].st_size); +- break; +- default: +- _dl_dprintf (2, "%s: can't handle reloc type ", _dl_progname); +-#if defined (__SUPPORT_LD_DEBUG__) +- _dl_dprintf (2, "%s ", _dl_reltypes_tab[reloc_type]); +-#endif +- if (symtab_index) +- _dl_dprintf (2, "'%s'", strtab + symtab[symtab_index].st_name); +- _dl_dprintf (2, "\n"); +- _dl_exit (1); +- } ++ sym->st_size); ++ } else ++ _dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n"); ++ break; ++ ++ default: ++ return -1; /* Calls _dl_exit(1). */ ++ } ++ ++#if defined (__SUPPORT_LD_DEBUG__) ++ if (_dl_debug_reloc && _dl_debug_detail) ++ _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", ++ old_val, *reloc_addr, reloc_addr); ++#endif ++ ++ return 0; ++} ++ ++#undef LAZY_RELOC_WORKS ++#ifdef LAZY_RELOC_WORKS ++static int ++_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, ++ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) ++{ ++ int reloc_type; ++ int symtab_index; ++ ElfW(Addr) *reloc_addr; ++#if defined (__SUPPORT_LD_DEBUG__) ++ ElfW(Addr) old_val; ++#endif ++ ++ (void)scope; ++ symtab_index = ELF_R_SYM(rpnt->r_info); ++ (void)strtab; ++ ++ reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + rpnt->r_offset); ++ reloc_type = ELF_R_TYPE(rpnt->r_info); ++ ++#if defined (__SUPPORT_LD_DEBUG__) ++ old_val = *reloc_addr; ++#endif ++ ++ switch (reloc_type) { ++ case R_68K_NONE: ++ break; ++ case R_68K_JMP_SLOT: ++ *reloc_addr += (unsigned int) tpnt->loadaddr; ++ break; ++ default: ++ _dl_exit(1); + } +- return goof; ++ ++#if defined (__SUPPORT_LD_DEBUG__) ++ if (_dl_debug_reloc && _dl_debug_detail) ++ _dl_dprintf(_dl_debug_file, "\tpatched_lazy: %x ==> %x @ %x\n", ++ old_val, *reloc_addr, reloc_addr); ++#endif ++ ++ return 0; ++} ++#endif ++ ++void ++_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, ++ unsigned long rel_addr, ++ unsigned long rel_size) ++{ ++#ifdef LAZY_RELOC_WORKS ++ (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); ++#else ++ _dl_parse_relocation_information(rpnt, rel_addr, rel_size); ++#endif ++} ++ ++int ++_dl_parse_relocation_information(struct dyn_elf *rpnt, ++ unsigned long rel_addr, ++ unsigned long rel_size) ++{ ++ return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); + } +diff -urN uClibc-0.9.28.orig/ldso/ldso/m68k/resolve.S uClibc-0.9.28/ldso/ldso/m68k/resolve.S +--- uClibc-0.9.28.orig/ldso/ldso/m68k/resolve.S 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/m68k/resolve.S 2006-04-28 00:14:35.000000000 -0600 +@@ -8,14 +8,16 @@ + .globl _dl_linux_resolve + .type _dl_linux_resolve,@function + _dl_linux_resolve: +- moveml %a0/%a1,%sp@- +-#ifdef __PIC__ +- bsrl _dl_linux_resolver@PLTPC +-#else +- jbsr _dl_linux_resolver +-#endif +- moveml %sp@+,%a0/%a1 +- addql #8,%sp +- jmp @(%d0) +-.LFE2: +- .size _dl_linux_resolve,.LFE2-_dl_linux_resolve ++ # Save %a0 (struct return address) and %a1. ++ move.l %a0, -(%sp) ++ move.l %a1, -(%sp) ++ # Call the real address resolver. ++ jbsr _dl_linux_resolver ++ # Restore register %a0 and %a1. ++ move.l (%sp)+, %a1 ++ move.l (%sp)+, %a0 ++ # Pop parameters ++ addq.l #8, %sp ++ # Call real function. ++ jmp (%d0) ++.size _dl_linux_resolve,.-_dl_linux_resolve +diff -urN uClibc-0.9.28.orig/ldso/ldso/mips/dl-startup.h uClibc-0.9.28/ldso/ldso/mips/dl-startup.h +--- uClibc-0.9.28.orig/ldso/ldso/mips/dl-startup.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/mips/dl-startup.h 2006-04-28 00:14:35.000000000 -0600 +@@ -136,13 +136,3 @@ + SEND_STDERR("Aiieeee!"); \ + _dl_exit(1); \ + } +- +- +-/* +- * Transfer control to the user's application, once the dynamic loader +- * is done. This routine has to exit the current function, then +- * call the _dl_elf_main function. For MIPS, we do it in assembly +- * because the stack doesn't get properly restored otherwise. Got look +- * at boot1_arch.h +- */ +-#define START() return _dl_elf_main +diff -urN uClibc-0.9.28.orig/ldso/ldso/mips/dl-syscalls.h uClibc-0.9.28/ldso/ldso/mips/dl-syscalls.h +--- uClibc-0.9.28.orig/ldso/ldso/mips/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/mips/dl-syscalls.h 2006-05-02 13:39:25.000000000 -0600 +@@ -1,7 +1,8 @@ + /* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ ++#define __UCLIBC_MMAP_HAS_6_ARGS__ ++ ++#include "sys/syscall.h" + extern int _dl_errno; ++#undef __set_errno + #define __set_errno(X) {(_dl_errno) = (X);} +-#include "sys/syscall.h" +- +-#define MMAP_HAS_6_ARGS +diff -urN uClibc-0.9.28.orig/ldso/ldso/mips/dl-sysdep.h uClibc-0.9.28/ldso/ldso/mips/dl-sysdep.h +--- uClibc-0.9.28.orig/ldso/ldso/mips/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/mips/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600 +@@ -30,7 +30,7 @@ + /* Initialization sequence for the application/library GOT. */ + #define INIT_GOT(GOT_BASE,MODULE) \ + do { \ +- unsigned long i; \ ++ unsigned long idx; \ + \ + /* Check if this is the dynamic linker itself */ \ + if (MODULE->libtype == program_interpreter) \ +@@ -41,9 +41,9 @@ + GOT_BASE[1] = (unsigned long) MODULE; \ + \ + /* Add load address displacement to all local GOT entries */ \ +- i = 2; \ +- while (i < MODULE->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]) \ +- GOT_BASE[i++] += (unsigned long) MODULE->loadaddr; \ ++ idx = 2; \ ++ while (idx < MODULE->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]) \ ++ GOT_BASE[idx++] += (unsigned long) MODULE->loadaddr; \ + \ + } while (0) + +@@ -63,8 +63,6 @@ + struct elf_resolve; + void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy); + +-#define do_rem(result, n, base) ((result) = (n) % (base)) +- + /* 4096 bytes alignment */ + #define PAGE_ALIGN 0xfffff000 + #define ADDR_ALIGN 0xfff +diff -urN uClibc-0.9.28.orig/ldso/ldso/mips/elfinterp.c uClibc-0.9.28/ldso/ldso/mips/elfinterp.c +--- uClibc-0.9.28.orig/ldso/ldso/mips/elfinterp.c 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/mips/elfinterp.c 2006-04-28 00:14:35.000000000 -0600 +@@ -27,6 +27,8 @@ + * SUCH DAMAGE. + */ + ++#include "ldso.h" ++ + extern int _dl_runtime_resolve(void); + + #define OFFSET_GP_GOT 0x7ff0 +@@ -146,7 +148,6 @@ + break; + default: + { +- int reloc_type = ELF32_R_TYPE(rpnt->r_info); + _dl_dprintf(2, "\n%s: ",_dl_progname); + + if (symtab_index) +diff -urN uClibc-0.9.28.orig/ldso/ldso/powerpc/dl-startup.h uClibc-0.9.28/ldso/ldso/powerpc/dl-startup.h +--- uClibc-0.9.28.orig/ldso/ldso/powerpc/dl-startup.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/powerpc/dl-startup.h 2006-04-28 00:14:35.000000000 -0600 +@@ -42,8 +42,10 @@ + " bne 2b\n" + " addi 6,6,4\n" + #endif +- /* Pass a termination function pointer (in this case _dl_fini) in r7. */ +- " lwz 7,_dl_fini@got(31)\n" ++ /* Pass a termination function pointer (in this case _dl_fini) in r3. */ ++ /* Paulus promized he would keep r3 zero in the exec ABI. */ ++ " lwz 3,_dl_fini@got(31)\n" ++ " mr 7,3\n" /* Pass _dl_fini in r7 to maintain compat */ + " bctr\n" /* Jump to entry point */ + " .size _start,.-_start\n" + " .previous\n" +@@ -78,9 +80,3 @@ + _dl_exit(100+ELF32_R_TYPE((RELP)->r_info));\ + } \ + } +-/* +- * Transfer control to the user's application, once the dynamic loader +- * is done. This routine has to exit the current function, then +- * call the _dl_elf_main function. +- */ +-#define START() return _dl_elf_main +diff -urN uClibc-0.9.28.orig/ldso/ldso/powerpc/dl-syscalls.h uClibc-0.9.28/ldso/ldso/powerpc/dl-syscalls.h +--- uClibc-0.9.28.orig/ldso/ldso/powerpc/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/powerpc/dl-syscalls.h 2006-05-02 13:39:14.000000000 -0600 +@@ -1,251 +1,8 @@ +-/* +- * This file contains the system call macros and syscall +- * numbers used by the shared library loader. +- */ +- +-#define MMAP_HAS_6_ARGS +- +-#define __NR_exit 1 +-#define __NR_read 3 +-#define __NR_write 4 +-#define __NR_open 5 +-#define __NR_close 6 +-#define __NR_getpid 20 +-#define __NR_getuid 24 +-#define __NR_geteuid 49 +-#define __NR_getgid 47 +-#define __NR_getegid 50 +-#define __NR_readlink 85 +-#define __NR_mmap 90 +-#define __NR_munmap 91 +-#define __NR_stat 106 +-#define __NR_mprotect 125 +- +- + /* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ +-extern int _dl_errno; +- +-/* Here are the macros which define how this platform makes +- * system calls. This particular variant does _not_ set +- * errno (note how it is disabled in __syscall_return) since +- * these will get called before the errno symbol is dynamicly +- * linked. */ +- +-#undef __syscall_return +-#define __syscall_return(type) \ +- return (__sc_err & 0x10000000 ? _dl_errno = __sc_ret, __sc_ret = -1 : 0), \ +- (type) __sc_ret +- +-#undef __syscall_clobbers +-#define __syscall_clobbers \ +- "r9", "r10", "r11", "r12" +- //"r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" +- +-#undef _syscall0 +-#define _syscall0(type,name) \ +-type name(void) \ +-{ \ +- unsigned long __sc_ret, __sc_err; \ +- { \ +- register unsigned long __sc_0 __asm__ ("r0"); \ +- register unsigned long __sc_3 __asm__ ("r3"); \ +- \ +- __sc_0 = __NR_##name; \ +- __asm__ __volatile__ \ +- ("sc \n\t" \ +- "mfcr %1 " \ +- : "=&r" (__sc_3), "=&r" (__sc_0) \ +- : "0" (__sc_3), "1" (__sc_0) \ +- : "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" ); \ +- __sc_ret = __sc_3; \ +- __sc_err = __sc_0; \ +- } \ +- __syscall_return (type); \ +-} +- +-#undef _syscall1 +-#define _syscall1(type,name,type1,arg1) \ +-type name(type1 arg1) \ +-{ \ +- unsigned long __sc_ret, __sc_err; \ +- { \ +- register unsigned long __sc_0 __asm__ ("r0"); \ +- register unsigned long __sc_3 __asm__ ("r3"); \ +- \ +- __sc_3 = (unsigned long) (arg1); \ +- __sc_0 = __NR_##name; \ +- __asm__ __volatile__ \ +- ("sc \n\t" \ +- "mfcr %1 " \ +- : "=&r" (__sc_3), "=&r" (__sc_0) \ +- : "0" (__sc_3), "1" (__sc_0) \ +- : "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" ); \ +- __sc_ret = __sc_3; \ +- __sc_err = __sc_0; \ +- } \ +- __syscall_return (type); \ +-} +- +-#undef _syscall2 +-#define _syscall2(type,name,type1,arg1,type2,arg2) \ +-type name(type1 arg1, type2 arg2) \ +-{ \ +- unsigned long __sc_ret, __sc_err; \ +- { \ +- register unsigned long __sc_0 __asm__ ("r0"); \ +- register unsigned long __sc_3 __asm__ ("r3"); \ +- register unsigned long __sc_4 __asm__ ("r4"); \ +- \ +- __sc_3 = (unsigned long) (arg1); \ +- __sc_4 = (unsigned long) (arg2); \ +- __sc_0 = __NR_##name; \ +- __asm__ __volatile__ \ +- ("sc \n\t" \ +- "mfcr %1 " \ +- : "=&r" (__sc_3), "=&r" (__sc_0) \ +- : "0" (__sc_3), "1" (__sc_0), \ +- "r" (__sc_4) \ +- : "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" ); \ +- __sc_ret = __sc_3; \ +- __sc_err = __sc_0; \ +- } \ +- __syscall_return (type); \ +-} +- +-#undef _syscall3 +-#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +-type name(type1 arg1, type2 arg2, type3 arg3) \ +-{ \ +- unsigned long __sc_ret, __sc_err; \ +- { \ +- register unsigned long __sc_0 __asm__ ("r0"); \ +- register unsigned long __sc_3 __asm__ ("r3"); \ +- register unsigned long __sc_4 __asm__ ("r4"); \ +- register unsigned long __sc_5 __asm__ ("r5"); \ +- \ +- __sc_3 = (unsigned long) (arg1); \ +- __sc_4 = (unsigned long) (arg2); \ +- __sc_5 = (unsigned long) (arg3); \ +- __sc_0 = __NR_##name; \ +- __asm__ __volatile__ \ +- ("sc \n\t" \ +- "mfcr %1 " \ +- : "=&r" (__sc_3), "=&r" (__sc_0) \ +- : "0" (__sc_3), "1" (__sc_0), \ +- "r" (__sc_4), \ +- "r" (__sc_5) \ +- : "r6", "r7", "r8", "r9", "r10", "r11", "r12" ); \ +- __sc_ret = __sc_3; \ +- __sc_err = __sc_0; \ +- } \ +- __syscall_return (type); \ +-} +- +-#undef _syscall4 +-#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ +-{ \ +- unsigned long __sc_ret, __sc_err; \ +- { \ +- register unsigned long __sc_0 __asm__ ("r0"); \ +- register unsigned long __sc_3 __asm__ ("r3"); \ +- register unsigned long __sc_4 __asm__ ("r4"); \ +- register unsigned long __sc_5 __asm__ ("r5"); \ +- register unsigned long __sc_6 __asm__ ("r6"); \ +- \ +- __sc_3 = (unsigned long) (arg1); \ +- __sc_4 = (unsigned long) (arg2); \ +- __sc_5 = (unsigned long) (arg3); \ +- __sc_6 = (unsigned long) (arg4); \ +- __sc_0 = __NR_##name; \ +- __asm__ __volatile__ \ +- ("sc \n\t" \ +- "mfcr %1 " \ +- : "=&r" (__sc_3), "=&r" (__sc_0) \ +- : "0" (__sc_3), "1" (__sc_0), \ +- "r" (__sc_4), \ +- "r" (__sc_5), \ +- "r" (__sc_6) \ +- : "r7", "r8", "r9", "r10", "r11", "r12" ); \ +- __sc_ret = __sc_3; \ +- __sc_err = __sc_0; \ +- } \ +- __syscall_return (type); \ +-} +- +-#undef _syscall5 +-#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ +-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ +-{ \ +- unsigned long __sc_ret, __sc_err; \ +- { \ +- register unsigned long __sc_0 __asm__ ("r0"); \ +- register unsigned long __sc_3 __asm__ ("r3"); \ +- register unsigned long __sc_4 __asm__ ("r4"); \ +- register unsigned long __sc_5 __asm__ ("r5"); \ +- register unsigned long __sc_6 __asm__ ("r6"); \ +- register unsigned long __sc_7 __asm__ ("r7"); \ +- \ +- __sc_3 = (unsigned long) (arg1); \ +- __sc_4 = (unsigned long) (arg2); \ +- __sc_5 = (unsigned long) (arg3); \ +- __sc_6 = (unsigned long) (arg4); \ +- __sc_7 = (unsigned long) (arg5); \ +- __sc_0 = __NR_##name; \ +- __asm__ __volatile__ \ +- ("sc \n\t" \ +- "mfcr %1 " \ +- : "=&r" (__sc_3), "=&r" (__sc_0) \ +- : "0" (__sc_3), "1" (__sc_0), \ +- "r" (__sc_4), \ +- "r" (__sc_5), \ +- "r" (__sc_6), \ +- "r" (__sc_7) \ +- : "r8", "r9", "r10", "r11", "r12" ); \ +- __sc_ret = __sc_3; \ +- __sc_err = __sc_0; \ +- } \ +- __syscall_return (type); \ +-} +- +- +-#undef _syscall6 +-#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \ +-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) \ +-{ \ +- unsigned long __sc_ret, __sc_err; \ +- { \ +- register unsigned long __sc_0 __asm__ ("r0"); \ +- register unsigned long __sc_3 __asm__ ("r3"); \ +- register unsigned long __sc_4 __asm__ ("r4"); \ +- register unsigned long __sc_5 __asm__ ("r5"); \ +- register unsigned long __sc_6 __asm__ ("r6"); \ +- register unsigned long __sc_7 __asm__ ("r7"); \ +- register unsigned long __sc_8 __asm__ ("r8"); \ +- \ +- __sc_3 = (unsigned long) (arg1); \ +- __sc_4 = (unsigned long) (arg2); \ +- __sc_5 = (unsigned long) (arg3); \ +- __sc_6 = (unsigned long) (arg4); \ +- __sc_7 = (unsigned long) (arg5); \ +- __sc_8 = (unsigned long) (arg6); \ +- __sc_0 = __NR_##name; \ +- __asm__ __volatile__ \ +- ("sc \n\t" \ +- "mfcr %1 " \ +- : "=&r" (__sc_3), "=&r" (__sc_0) \ +- : "0" (__sc_3), "1" (__sc_0), \ +- "r" (__sc_4), \ +- "r" (__sc_5), \ +- "r" (__sc_6), \ +- "r" (__sc_7), \ +- "r" (__sc_8) \ +- : "r9", "r10", "r11", "r12" ); \ +- __sc_ret = __sc_3; \ +- __sc_err = __sc_0; \ +- } \ +- __syscall_return (type); \ +-} +- ++#define __UCLIBC_MMAP_HAS_6_ARGS__ + ++#include "sys/syscall.h" ++extern int _dl_errno; ++#undef __set_errno ++#define __set_errno(X) {(_dl_errno) = (X);} +diff -urN uClibc-0.9.28.orig/ldso/ldso/powerpc/dl-sysdep.h uClibc-0.9.28/ldso/ldso/powerpc/dl-sysdep.h +--- uClibc-0.9.28.orig/ldso/ldso/powerpc/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/powerpc/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600 +@@ -67,9 +67,6 @@ + extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); + void _dl_init_got(unsigned long *lpnt,struct elf_resolve *tpnt); + +- +-#define do_rem(result, n, base) ((result) = (n) % (base)) +- + /* 4096 bytes alignment */ + #define PAGE_ALIGN 0xfffff000 + #define ADDR_ALIGN 0xfff +diff -urN uClibc-0.9.28.orig/ldso/ldso/powerpc/elfinterp.c uClibc-0.9.28/ldso/ldso/powerpc/elfinterp.c +--- uClibc-0.9.28.orig/ldso/ldso/powerpc/elfinterp.c 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/powerpc/elfinterp.c 2006-04-28 00:14:35.000000000 -0600 +@@ -29,6 +29,8 @@ + * SUCH DAMAGE. + */ + ++#include "ldso.h" ++ + extern int _dl_linux_resolve(void); + + void _dl_init_got(unsigned long *plt,struct elf_resolve *tpnt) +@@ -138,7 +140,7 @@ + finaladdr = (Elf32_Addr) _dl_find_hash(symname, + tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); + if (unlikely(!finaladdr)) { +- _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); ++ _dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname); + _dl_exit(1); + }; + finaladdr += this_reloc->r_addend; +@@ -379,15 +381,15 @@ + { + int reloc_type = ELF32_R_TYPE(rpnt->r_info); + #if defined (__SUPPORT_LD_DEBUG__) +- _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type)); ++ _dl_dprintf(2, "can't handle reloc type '%s' in lib '%s'\n", _dl_reltypes(reloc_type), tpnt->libname); + #else +- _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type); ++ _dl_dprintf(2, "can't handle reloc type %x in lib '%s'\n", reloc_type, tpnt->libname); + #endif +- _dl_exit(-res); ++ return res; + } + if (unlikely(res >0)) + { +- _dl_dprintf(2, "can't resolve symbol\n"); ++ _dl_dprintf(2, "can't resolve symbol in lib '%s'.\n", tpnt->libname); + return res; + } + } +diff -urN uClibc-0.9.28.orig/ldso/ldso/sh/dl-startup.h uClibc-0.9.28/ldso/ldso/sh/dl-startup.h +--- uClibc-0.9.28.orig/ldso/ldso/sh/dl-startup.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/sh/dl-startup.h 2006-04-28 00:14:35.000000000 -0600 +@@ -55,11 +55,3 @@ + default: \ + _dl_exit(1); \ + } +- +- +-/* +- * Transfer control to the user's application, once the dynamic loader +- * is done. This routine has to exit the current function, then +- * call the _dl_elf_main function. +- */ +-#define START() return _dl_elf_main; +diff -urN uClibc-0.9.28.orig/ldso/ldso/sh/dl-syscalls.h uClibc-0.9.28/ldso/ldso/sh/dl-syscalls.h +--- uClibc-0.9.28.orig/ldso/ldso/sh/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/sh/dl-syscalls.h 2006-05-02 13:39:28.000000000 -0600 +@@ -1,7 +1,8 @@ + /* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ ++#define __UCLIBC_MMAP_HAS_6_ARGS__ ++ ++#include "sys/syscall.h" + extern int _dl_errno; ++#undef __set_errno + #define __set_errno(X) {(_dl_errno) = (X);} +-#include "sys/syscall.h" +- +-#define MMAP_HAS_6_ARGS +diff -urN uClibc-0.9.28.orig/ldso/ldso/sh/dl-sysdep.h uClibc-0.9.28/ldso/ldso/sh/dl-sysdep.h +--- uClibc-0.9.28.orig/ldso/ldso/sh/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/sh/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600 +@@ -25,7 +25,7 @@ + struct elf_resolve; + extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); + +-static __inline__ unsigned int ++static inline unsigned int + _dl_urem(unsigned int n, unsigned int base) + { + int res; +@@ -104,7 +104,7 @@ + elf_machine_dynamic (void) + { + register Elf32_Addr *got; +- asm ("mov r12,%0" :"=r" (got)); ++ __asm__ ("mov r12,%0" :"=r" (got)); + return *got; + } + +@@ -113,7 +113,7 @@ + elf_machine_load_address (void) + { + Elf32_Addr addr; +- asm ("mov.l 1f,r0\n\ ++ __asm__ ("mov.l 1f,r0\n\ + mov.l 3f,r2\n\ + add r12,r2\n\ + mov.l @(r0,r12),r0\n\ +diff -urN uClibc-0.9.28.orig/ldso/ldso/sh/elfinterp.c uClibc-0.9.28/ldso/ldso/sh/elfinterp.c +--- uClibc-0.9.28.orig/ldso/ldso/sh/elfinterp.c 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/sh/elfinterp.c 2006-04-28 00:14:35.000000000 -0600 +@@ -39,6 +39,8 @@ + a more than adequate job of explaining everything required to get this + working. */ + ++#include "ldso.h" ++ + extern int _dl_linux_resolve(void); + + unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) +diff -urN uClibc-0.9.28.orig/ldso/ldso/sh64/dl-startup.h uClibc-0.9.28/ldso/ldso/sh64/dl-startup.h +--- uClibc-0.9.28.orig/ldso/ldso/sh64/dl-startup.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/sh64/dl-startup.h 2006-04-28 00:14:35.000000000 -0600 +@@ -115,12 +115,3 @@ + default: \ + _dl_exit(1); \ + } +- +-/* +- * Transfer control to the user's application, once the dynamic loader +- * is done. This routine has to exit the current function, then +- * call the _dl_elf_main function. +- */ +- +-#define START() return _dl_elf_main; +- +diff -urN uClibc-0.9.28.orig/ldso/ldso/sh64/dl-syscalls.h uClibc-0.9.28/ldso/ldso/sh64/dl-syscalls.h +--- uClibc-0.9.28.orig/ldso/ldso/sh64/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/sh64/dl-syscalls.h 2006-04-28 00:14:35.000000000 -0600 +@@ -1,8 +1,9 @@ + /* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ ++#include "sys/syscall.h" + extern int _dl_errno; ++#undef __set_errno + #define __set_errno(X) {(_dl_errno) = (X);} +-#include "sys/syscall.h" + + #undef __syscall_return + #define __syscall_return(type, res) \ +diff -urN uClibc-0.9.28.orig/ldso/ldso/sh64/dl-sysdep.h uClibc-0.9.28/ldso/ldso/sh64/dl-sysdep.h +--- uClibc-0.9.28.orig/ldso/ldso/sh64/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/sh64/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600 +@@ -25,8 +25,6 @@ + struct elf_resolve; + extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); + +-#define do_rem(result, n, base) ((result) = (n) % (base)) +- + /* 4096 bytes alignment */ + #define PAGE_ALIGN 0xfffff000 + #define ADDR_ALIGN 0xfff +diff -urN uClibc-0.9.28.orig/ldso/ldso/sh64/elfinterp.c uClibc-0.9.28/ldso/ldso/sh64/elfinterp.c +--- uClibc-0.9.28.orig/ldso/ldso/sh64/elfinterp.c 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/sh64/elfinterp.c 2006-04-28 00:14:35.000000000 -0600 +@@ -41,6 +41,8 @@ + a more than adequate job of explaining everything required to get this + working. */ + ++#include "ldso.h" ++ + extern int _dl_linux_resolve(void); + + unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) +diff -urN uClibc-0.9.28.orig/ldso/ldso/sparc/dl-startup.h uClibc-0.9.28/ldso/ldso/sparc/dl-startup.h +--- uClibc-0.9.28.orig/ldso/ldso/sparc/dl-startup.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/sparc/dl-startup.h 2006-04-28 00:14:35.000000000 -0600 +@@ -3,15 +3,46 @@ + * needed for this architecture. See arm/boot1_arch.h for an example of what + * can be done. + */ +-asm( +- " .text\n" +- " .global _start\n" +- " .type _start,%function\n" +- "_start:\n" +- " .set _start,_dl_start\n" +- " .size _start,.-_start\n" +- " .previous\n" +-); ++ ++asm ("\ ++ .text\n\ ++ .global _start\n\ ++ .type _start,%function\n\ ++ .align 32\n\ ++_start:\n\ ++ /* Allocate space for functions to drop their arguments. */\n\ ++ sub %sp, 6*4, %sp\n\ ++ /* Pass pointer to argument block to _dl_start. */\n\ ++ call _dl_start\n\ ++ add %sp, 22*4, %o0\n\ ++ /* FALTHRU */\n\ ++ .globl _dl_start_user\n\ ++ .type _dl_start_user, @function\n\ ++_dl_start_user:\n\ ++ /* Load the PIC register. */\n\ ++1: call 2f\n\ ++ sethi %hi(_GLOBAL_OFFSET_TABLE_-(1b-.)), %l7\n\ ++2: or %l7, %lo(_GLOBAL_OFFSET_TABLE_-(1b-.)), %l7\n\ ++ add %l7, %o7, %l7\n\ ++ /* Save the user entry point address in %l0 */\n\ ++ mov %o0, %l0\n\ ++ /* See if we were run as a command with the executable file name as an\n\ ++ extra leading argument. If so, adjust the contents of the stack. */\n\ ++ sethi %hi(_dl_skip_args), %g2\n\ ++ or %g2, %lo(_dl_skip_args), %g2\n\ ++ ld [%l7+%g2], %i0\n\ ++ ld [%i0], %i0\n\ ++ tst %i0\n\ ++ /* Pass our finalizer function to the user in %g1. */\n\ ++ sethi %hi(_dl_fini), %g1\n\ ++ or %g1, %lo(_dl_fini), %g1\n\ ++ ld [%l7+%g1], %g1\n\ ++ /* Jump to the user's entry point and deallocate the extra stack we got. */\n\ ++ jmp %l0\n\ ++ add %sp, 6*4, %sp\n\ ++ .size _dl_start_user, . - _dl_start_user\n\ ++ .previous\n\ ++"); + + /* + * Get a pointer to the argv array. On many platforms this can be just +@@ -19,17 +50,15 @@ + * do something a little more subtle here. We assume that argc is stored + * at the word just below the argvp that we return here. + */ +-#define GET_ARGV(ARGVP, ARGS) __asm__("\tadd %%fp,68,%0\n" : "=r" (ARGVP)); ++#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS) + 1) + + /* + * Here is a macro to perform a relocation. This is only used when + * bootstrapping the dynamic loader. + */ + #define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \ +- switch(ELF32_R_TYPE((RELP)->r_info)) { \ ++switch(ELF_R_TYPE((RELP)->r_info)) { \ + case R_SPARC_32: \ +- *REL = SYMBOL + (RELP)->r_addend; \ +- break; \ + case R_SPARC_GLOB_DAT: \ + *REL = SYMBOL + (RELP)->r_addend; \ + break; \ +@@ -38,7 +67,6 @@ + REL[2] = 0x81c06000 | (SYMBOL & 0x3ff); \ + break; \ + case R_SPARC_NONE: \ +- break; \ + case R_SPARC_WDISP30: \ + break; \ + case R_SPARC_RELATIVE: \ +@@ -46,18 +74,4 @@ + break; \ + default: \ + _dl_exit(1); \ +- } +- +-/* +- * Transfer control to the user's application, once the dynamic loader +- * is done. The crt calls atexit with $g1 if not null, so we need to +- * ensure that it contains NULL. +- */ +- +-#define START() \ +- __asm__ volatile ( \ +- "add %%g0,%%g0,%%g1\n\t" \ +- "jmpl %0, %%o7\n\t" \ +- "restore %%g0,%%g0,%%g0\n\t" \ +- : /*"=r" (status) */ : \ +- "r" (_dl_elf_main): "g1", "o0", "o1") ++} +diff -urN uClibc-0.9.28.orig/ldso/ldso/sparc/dl-syscalls.h uClibc-0.9.28/ldso/ldso/sparc/dl-syscalls.h +--- uClibc-0.9.28.orig/ldso/ldso/sparc/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/sparc/dl-syscalls.h 2006-05-02 13:39:21.000000000 -0600 +@@ -1,187 +1,8 @@ +-/* +- * This file contains the system call macros and syscall +- * numbers used by the shared library loader. +- * +- * NOTE: This should be integrated/moved to +- * sysdeps/linux/sparc/bits/syscalls.h at some point ... +- */ +- +-#define MMAP_HAS_6_ARGS +- +-#define __NR_exit 1 +-#define __NR_read 3 +-#define __NR_write 4 +-#define __NR_open 5 +-#define __NR_close 6 +-#define __NR_getpid 20 +-#define __NR_getuid 24 +-#define __NR_getgid 47 +-#define __NR_geteuid 49 +-#define __NR_getegid 50 +-#define __NR_readlink 58 +-#define __NR_mmap 71 +-#define __NR_munmap 73 +-#define __NR_stat 38 +-#define __NR_mprotect 74 +- + /* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ ++#define __UCLIBC_MMAP_HAS_6_ARGS__ ++ ++#include "sys/syscall.h" + extern int _dl_errno; ++#undef __set_errno + #define __set_errno(X) {(_dl_errno) = (X);} +- +-/* Here are the macros which define how this platform makes +- * system calls. This particular variant does _not_ set +- * errno (note how _dl_errno is used in __syscall_return) since +- * these will get called before the errno symbol is dynamicly +- * linked. */ +- +-#define __syscall_return(type, res) \ +-do { \ +- if (res < -255 || res >= 0) \ +- return (type) res; \ +- __set_errno(-res); \ +- res = -1; \ +- return (type) res; \ +-} while (0) +- +-#define _syscall0(type,name) \ +-type name(void) \ +-{ \ +- long __res; \ +- register long __g1 __asm__ ("g1") = __NR_##name; \ +- __asm__ __volatile__ ( \ +- "t 0x10\n\t" \ +- "bcc 1f\n\t" \ +- "mov %%o0, %0\n\t" \ +- "sub %%g0, %%o0, %0\n\t" \ +- "1:\n\t" \ +- : "=r" (__res)\ +- : "r" (__g1) \ +- : "o0", "cc"); \ +- __syscall_return(type, __res); \ +-} +- +-#define _syscall1(type,name,type1,arg1) \ +-type name(type1 arg1) \ +-{ \ +- long __res; \ +- register long __g1 __asm__ ("g1") = __NR_##name; \ +- register long __o0 __asm__ ("o0") = (long)(arg1); \ +- __asm__ __volatile__ ( \ +- "t 0x10\n\t" \ +- "bcc 1f\n\t" \ +- "mov %%o0, %0\n\t" \ +- "sub %%g0, %%o0, %0\n\t" \ +- "1:\n\t" \ +- : "=r" (__res), "=&r" (__o0) \ +- : "1" (__o0), "r" (__g1) \ +- : "cc"); \ +- __syscall_return(type, __res); \ +-} +- +-#define _syscall2(type,name,type1,arg1,type2,arg2) \ +-type name(type1 arg1,type2 arg2) \ +-{ \ +- long __res; \ +- register long __g1 __asm__ ("g1") = __NR_##name; \ +- register long __o0 __asm__ ("o0") = (long)(arg1); \ +- register long __o1 __asm__ ("o1") = (long)(arg2); \ +- __asm__ __volatile__ ( \ +- "t 0x10\n\t" \ +- "bcc 1f\n\t" \ +- "mov %%o0, %0\n\t" \ +- "sub %%g0, %%o0, %0\n\t" \ +- "1:\n\t" \ +- : "=r" (__res), "=&r" (__o0) \ +- : "1" (__o0), "r" (__o1), "r" (__g1) \ +- : "cc"); \ +- __syscall_return(type, __res); \ +-} +- +-#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +-type name(type1 arg1,type2 arg2,type3 arg3) \ +-{ \ +- long __res; \ +- register long __g1 __asm__ ("g1") = __NR_##name; \ +- register long __o0 __asm__ ("o0") = (long)(arg1); \ +- register long __o1 __asm__ ("o1") = (long)(arg2); \ +- register long __o2 __asm__ ("o2") = (long)(arg3); \ +- __asm__ __volatile__ ( \ +- "t 0x10\n\t" \ +- "bcc 1f\n\t" \ +- "mov %%o0, %0\n\t" \ +- "sub %%g0, %%o0, %0\n\t" \ +- "1:\n\t" \ +- : "=r" (__res), "=&r" (__o0) \ +- : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1) \ +- : "cc"); \ +- __syscall_return(type, __res); \ +-} +- +-#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +-type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ +-{ \ +- long __res; \ +- register long __g1 __asm__ ("g1") = __NR_##name; \ +- register long __o0 __asm__ ("o0") = (long)(arg1); \ +- register long __o1 __asm__ ("o1") = (long)(arg2); \ +- register long __o2 __asm__ ("o2") = (long)(arg3); \ +- register long __o3 __asm__ ("o3") = (long)(arg4); \ +- __asm__ __volatile__ ( \ +- "t 0x10\n\t" \ +- "bcc 1f\n\t" \ +- "mov %%o0, %0\n\t" \ +- "sub %%g0, %%o0, %0\n\t" \ +- "1:\n\t" \ +- : "=r" (__res), "=&r" (__o0) \ +- : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__g1) \ +- : "cc"); \ +- __syscall_return(type, __res); \ +-} +- +-#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ +- type5,arg5) \ +-type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ +-{ \ +- long __res; \ +- register long __g1 __asm__ ("g1") = __NR_##name; \ +- register long __o0 __asm__ ("o0") = (long)(arg1); \ +- register long __o1 __asm__ ("o1") = (long)(arg2); \ +- register long __o2 __asm__ ("o2") = (long)(arg3); \ +- register long __o3 __asm__ ("o3") = (long)(arg4); \ +- register long __o4 __asm__ ("o4") = (long)(arg5); \ +- __asm__ __volatile__ ( \ +- "t 0x10\n\t" \ +- "bcc 1f\n\t" \ +- "mov %%o0, %0\n\t" \ +- "sub %%g0, %%o0, %0\n\t" \ +- "1:\n\t" \ +- : "=r" (__res), "=&r" (__o0) \ +- : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__o4), "r" (__g1) \ +- : "cc"); \ +- __syscall_return(type, __res); \ +-} +- +-#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ +- type5,arg5,type6,arg6) \ +-type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \ +-{ \ +- long __res; \ +- register long __g1 __asm__ ("g1") = __NR_##name; \ +- register long __o0 __asm__ ("o0") = (long)(arg1); \ +- register long __o1 __asm__ ("o1") = (long)(arg2); \ +- register long __o2 __asm__ ("o2") = (long)(arg3); \ +- register long __o3 __asm__ ("o3") = (long)(arg4); \ +- register long __o4 __asm__ ("o4") = (long)(arg5); \ +- register long __o5 __asm__ ("o5") = (long)(arg6); \ +- __asm__ __volatile__ ( \ +- "t 0x10\n\t" \ +- "bcc 1f\n\t" \ +- "mov %%o0, %0\n\t" \ +- "sub %%g0, %%o0, %0\n\t" \ +- "1:\n\t" \ +- : "=r" (__res), "=&r" (__o0) \ +- : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__o4), "r" (__o5), "r" (__g1) \ +- : "cc"); \ +- __syscall_return(type, __res); \ +-} +diff -urN uClibc-0.9.28.orig/ldso/ldso/sparc/dl-sysdep.h uClibc-0.9.28/ldso/ldso/sparc/dl-sysdep.h +--- uClibc-0.9.28.orig/ldso/ldso/sparc/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/sparc/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600 +@@ -1,9 +1,9 @@ +- ++/* vi: set sw=4 ts=4: */ + /* + * Various assmbly language/system dependent hacks that are required + * so that we can minimize the amount of platform specific code. ++ * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org> + */ +-#define LINUXBIN + + /* Define this if the system uses RELOCA. */ + #define ELF_USES_RELOCA +@@ -31,19 +31,14 @@ + #undef MAGIC2 + + /* Used for error messages */ +-#define ELF_TARGET "Sparc" ++#define ELF_TARGET "sparc" + +-#ifndef COMPILE_ASM +-extern unsigned int _dl_linux_resolver(unsigned int reloc_entry, +- unsigned int * i); +-#endif ++struct elf_resolve; ++unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); + + /* + * Define this if you want a dynamic loader that works on Solaris. + */ +-#ifndef __linux__ +-#define SOLARIS_COMPATIBLE +-#endif + + #ifndef COMPILE_ASM + /* Cheap modulo implementation, taken from arm/ld_sysdep.h. */ +@@ -87,13 +82,6 @@ + #define do_rem(result, n, base) ((result) = sparc_mod(n, base)) + #endif + +-/* +- * dbx wants the binder to have a specific name. Mustn't disappoint it. +- */ +-#ifdef SOLARIS_COMPATIBLE +-#define _dl_linux_resolve _elf_rtbndr +-#endif +- + /* 4096 bytes alignment */ + /* ...but 8192 is required for mmap() on sparc64 kernel */ + #define PAGE_ALIGN 0xffffe000 +@@ -160,7 +148,7 @@ + elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr, + Elf32_Word relative_count) + { +- Elf32_Rela * rpnt = (void *)rel_addr; ++ Elf32_Rela * rpnt = (void *)rel_addr; + --rpnt; + do { + Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset); +diff -urN uClibc-0.9.28.orig/ldso/ldso/sparc/elfinterp.c uClibc-0.9.28/ldso/ldso/sparc/elfinterp.c +--- uClibc-0.9.28.orig/ldso/ldso/sparc/elfinterp.c 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/sparc/elfinterp.c 2006-04-28 00:14:35.000000000 -0600 +@@ -33,236 +33,340 @@ + an ELF sharable library or a linux style of shared library. */ + + /* Disclaimer: I have never seen any AT&T source code for SVr4, nor have +- I ever taken any courses on internals. This program was developed using +- information available through the book "UNIX SYSTEM V RELEASE 4, +- Programmers guide: Ansi C and Programming Support Tools", which did +- a more than adequate job of explaining everything required to get this +- working. */ ++ I ever taken any courses on internals. This program was developed using ++ information available through the book "UNIX SYSTEM V RELEASE 4, ++ Programmers guide: Ansi C and Programming Support Tools", which did ++ a more than adequate job of explaining everything required to get this ++ working. */ ++ ++/* Some SPARC opcodes we need to use for self-modifying code. */ ++#define OPCODE_NOP 0x01000000 /* nop */ ++#define OPCODE_CALL 0x40000000 /* call ?; add PC-rel word address */ ++#define OPCODE_SETHI_G1 0x03000000 /* sethi ?, %g1; add value>>10 */ ++#define OPCODE_JMP_G1 0x81c06000 /* jmp %g1+?; add lo 10 bits of value */ ++#define OPCODE_SAVE_SP 0x9de3bfa8 /* save %sp, -(16+6)*4, %sp */ ++#define OPCODE_BA 0x30800000 /* b,a ?; add PC-rel word address */ + + extern int _dl_linux_resolve(void); + +-unsigned int _dl_linux_resolver(unsigned int reloc_entry, unsigned int * plt) ++unsigned long ++_dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) + { +- int reloc_type; +- Elf32_Rela * this_reloc; +- char * strtab; +- Elf32_Sym * symtab; +- Elf32_Rela * rel_addr; +- struct elf_resolve * tpnt; +- int symtab_index; +- char * new_addr; +- char ** got_addr; +- unsigned int instr_addr; +- tpnt = (struct elf_resolve *) plt[2]; +- +- rel_addr = (Elf32_Rela *)tpnt->dynamic_info[DT_JMPREL]; +- +- /* +- * Generate the correct relocation index into the .rela.plt section. +- */ +- reloc_entry = (reloc_entry >> 10) - 0xc; +- +- this_reloc = (Elf32_Rela *) ((char *) rel_addr + reloc_entry); +- +- reloc_type = ELF32_R_TYPE(this_reloc->r_info); +- symtab_index = ELF32_R_SYM(this_reloc->r_info); +- +- symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB]; +- strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; +- +-#ifdef __SUPPORT_LD_DEBUG__ +- if (_dl_debug_symbols) { +- _dl_dprintf(2, "tpnt = %x\n", tpnt); +- _dl_dprintf(2, "reloc = %x\n", this_reloc); +- _dl_dprintf(2, "symtab = %x\n", symtab); +- _dl_dprintf(2, "strtab = %x\n", strtab); +- } +-#endif +- +- +- if (unlikely(reloc_type != R_SPARC_JMP_SLOT)) { +- _dl_dprintf(2, "%s: incorrect relocation type in jump relocations (%d)\n", +- _dl_progname, reloc_type); +- _dl_exit(30); +- }; +- +- /* Address of jump instruction to fix up */ +- instr_addr = ((int)this_reloc->r_offset + (int)tpnt->loadaddr); +- got_addr = (char **) instr_addr; +- +-#ifdef __SUPPORT_LD_DEBUG__ +- if (_dl_debug_symbols) { +- _dl_dprintf(2, "symtab_index %x\n", symtab_index); +- +- _dl_dprintf(2, "Resolving symbol %s\n", +- strtab + symtab[symtab_index].st_name); +- } +-#endif +- +- /* Get the address of the GOT entry */ +- new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name, +- tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); +- if(unlikely(!new_addr)) { +- _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", +- _dl_progname, strtab + symtab[symtab_index].st_name); +- _dl_exit(31); +- }; ++ int reloc_type; ++ ELF_RELOC *this_reloc; ++ char *strtab; ++ ElfW(Sym) *symtab; ++ int symtab_index; ++ char *rel_addr; ++ char *new_addr; ++ char **got_addr; ++ ElfW(Addr) instr_addr; ++ char *symname; ++ ++ rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL]; ++ /* ++ * Generate the correct relocation index into the .rela.plt section. ++ */ ++ reloc_entry = (reloc_entry >> 10) - 0xc; ++ ++ this_reloc = (ELF_RELOC *)(rel_addr + reloc_entry); ++ reloc_type = ELF_R_TYPE(this_reloc->r_info); ++ symtab_index = ELF_R_SYM(this_reloc->r_info); ++ ++ symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB]; ++ strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; ++ symname = strtab + symtab[symtab_index].st_name; ++ ++ if (unlikely(reloc_type != R_SPARC_JMP_SLOT)) { ++ _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n", ++ _dl_progname); ++ _dl_exit(1); ++ } ++ ++ /* Address of the jump instruction to fix up. */ ++ instr_addr = (this_reloc->r_offset + tpnt->loadaddr); ++ got_addr = (char **)instr_addr; ++ ++ /* Get the address of the GOT entry */ ++ new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); ++ if (unlikely(!new_addr)) { ++ _dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname); ++ _dl_exit(1); ++ } + + #if defined (__SUPPORT_LD_DEBUG__) +- if ((unsigned long) got_addr < 0x40000000) +- { +- if (_dl_debug_bindings) +- { +- _dl_dprintf(_dl_debug_file, "\nresolve function: %s", +- strtab + symtab[symtab_index].st_name); +- if(_dl_debug_detail) _dl_dprintf(_dl_debug_file, +- "\tpatch %x ==> %x @ %x", *got_addr, new_addr, got_addr); ++ if ((unsigned long)got_addr < 0x40000000) { ++ if (_dl_debug_bindings) { ++ _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); ++ if (_dl_debug_detail) ++ _dl_dprintf(_dl_debug_file, ++ "\tpatched: %x ==> %x @ %x\n", ++ *got_addr, new_addr, got_addr); + } + } +- if (!_dl_debug_nofixups) { ++ if (!_dl_debug_nofixups) ++#endif ++ { + got_addr[1] = (char *) (0x03000000 | (((unsigned int) new_addr >> 10) & 0x3fffff)); + got_addr[2] = (char *) (0x81c06000 | ((unsigned int) new_addr & 0x3ff)); + } ++ ++ return (unsigned long)new_addr; ++} ++ ++static int ++_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, ++ unsigned long rel_addr, unsigned long rel_size, ++ int (*reloc_fnc)(struct elf_resolve *tpnt, struct dyn_elf *scope, ++ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)) ++{ ++ unsigned int i; ++ char *strtab; ++ ElfW(Sym) *symtab; ++ ELF_RELOC *rpnt; ++ int symtab_index; ++ ++ /* Parse the relocation information. */ ++ rpnt = (ELF_RELOC *)rel_addr; ++ rel_size /= sizeof(ELF_RELOC); ++ ++ symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB]; ++ strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; ++ ++ for (i = 0; i < rel_size; i++, rpnt++) { ++ int res; ++ ++ symtab_index = ELF_R_SYM(rpnt->r_info); ++ ++ debug_sym(symtab, strtab, symtab_index); ++ debug_reloc(symtab, strtab, rpnt); ++ ++ res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab); ++ ++ if (res == 0) ++ continue; ++ ++ _dl_dprintf(2, "\n%s: ", _dl_progname); ++ ++ if (symtab_index) ++ _dl_dprintf(2, "symbol '%s': ", ++ strtab + symtab[symtab_index].st_name); ++ ++ if (unlikely(res < 0)) { ++ int reloc_type = ELF_R_TYPE(rpnt->r_info); ++ ++ _dl_dprintf(2, "can't handle reloc type " ++#if defined (__SUPPORT_LD_DEBUG__) ++ "%s\n", _dl_reltypes(reloc_type)); + #else +- got_addr[1] = (char *) (0x03000000 | (((unsigned int) new_addr >> 10) & 0x3fffff)); +- got_addr[2] = (char *) (0x81c06000 | ((unsigned int) new_addr & 0x3ff)); ++ "%x\n", reloc_type); + #endif ++ _dl_exit(-res); ++ } else if (unlikely(res > 0)) { ++ _dl_dprintf(2, "can't resolve symbol\n"); ++ return res; ++ } ++ } ++ ++ return 0; ++} + +- _dl_dprintf(2, "Address = %x\n",new_addr); +- _dl_exit(32); ++static int ++_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, ++ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) ++{ ++ int reloc_type; ++ int symtab_index; ++ char *symname; ++ ElfW(Sym) *sym; ++ ElfW(Addr) *reloc_addr; ++ ElfW(Addr) symbol_addr; ++#if defined (__SUPPORT_LD_DEBUG__) ++ ElfW(Addr) old_val; ++#endif ++ ++ reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); ++ reloc_type = ELF_R_TYPE(rpnt->r_info); ++ symtab_index = ELF_R_SYM(rpnt->r_info); ++ sym = &symtab[symtab_index]; ++ symbol_addr = 0; ++ symname = strtab + sym->st_name; ++ ++ if (symtab_index) { ++ symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt, ++ elf_machine_type_class(reloc_type)); ++ /* ++ * We want to allow undefined references to weak symbols - this ++ * might have been intentional. We should not be linking local ++ * symbols here, so all bases should be covered. ++ */ ++ if (unlikely(!symbol_addr && ELF_ST_BIND(sym->st_info) != STB_WEAK)) { ++ _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); ++ _dl_exit(1); ++ } ++ } ++ ++#if defined (__SUPPORT_LD_DEBUG__) ++ old_val = *reloc_addr; ++#endif + +- return (unsigned int) new_addr; ++ symbol_addr += rpnt->r_addend; /* Assume copy relocs have zero addend. */ ++ ++ switch (reloc_type) { ++ case R_SPARC_NONE: ++ break; ++ ++#if 0 /* these dont really seem to be useful */ ++ case R_SPARC_8: ++ *(char *) reloc_addr = symbol_addr; ++ break; ++ case R_SPARC_16: ++ *(short *) reloc_addr = symbol_addr; ++ break; ++ case R_SPARC_DISP8: ++ *(char *) reloc_addr = (symbol_addr) - (Elf32_Addr) reloc_addr; ++ break; ++ case R_SPARC_DISP16: ++ *(short *) reloc_addr = (symbol_addr) - (Elf32_Addr) reloc_addr; ++ break; ++#endif ++ ++ case R_SPARC_DISP32: ++ *reloc_addr = symbol_addr - (unsigned int) reloc_addr; ++ break; ++ ++ case R_SPARC_LO10: ++ if (!symbol_addr) ++ symbol_addr = tpnt->loadaddr + rpnt->r_addend; ++ else ++ symbol_addr += rpnt->r_addend; ++ *reloc_addr = (*reloc_addr & ~0x3ff)|(symbol_addr & 0x3ff); ++ break; ++ ++ case R_SPARC_GLOB_DAT: ++ case R_SPARC_32: ++ *reloc_addr = symbol_addr; ++ break; ++ ++ case R_SPARC_JMP_SLOT: ++/* ++value = symbol_addr; ++value += reloc->r_addend; ++disp = value - reloc_addr; ++reloc_addr[1] = OPCODE_JMP_G1 | (value & 0x3ff); ++reloc_addr[0] = OPCODE_SETHI_G1 | (value >> 10); ++ reloc_addr[1] = OPCODE_JMP_G1 | ((symbol_addr-(Elf32_Addr)reloc_addr) & 0x3ff); ++ reloc_addr[0] = OPCODE_SETHI_G1 | ((symbol_addr-(Elf32_Addr)reloc_addr) >> 10); ++*/ ++ reloc_addr[1] = 0x03000000 | ((symbol_addr >> 10) & 0x3fffff); ++ reloc_addr[2] = 0x81c06000 | (symbol_addr & 0x3ff); ++ break; ++ ++ case R_SPARC_RELATIVE: ++ *reloc_addr += tpnt->loadaddr + rpnt->r_addend; ++ break; ++ ++ case R_SPARC_WDISP30: ++ *reloc_addr = (*reloc_addr & 0xc0000000)| ++ ((symbol_addr - (unsigned int) reloc_addr) >> 2); ++ break; ++ ++ case R_SPARC_HI22: ++ if (!symbol_addr) ++ symbol_addr = tpnt->loadaddr + rpnt->r_addend; ++ else ++ symbol_addr += rpnt->r_addend; ++ *reloc_addr = (*reloc_addr & 0xffc00000) | (symbol_addr >> 10); ++ break; ++ ++ case R_SPARC_COPY: ++ if (symbol_addr) { ++#if defined (__SUPPORT_LD_DEBUG__) ++ if (_dl_debug_move) ++ _dl_dprintf(_dl_debug_file, ++ "\t%s move %d bytes from %x to %x\n", ++ symname, sym->st_size, ++ symbol_addr, reloc_addr); ++#endif ++ ++ _dl_memcpy((char *)reloc_addr, ++ (char *)symbol_addr, ++ sym->st_size); ++ } else ++ _dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n"); ++ break; ++ default: ++ return -1; /* Calls _dl_exit(1). */ ++ } ++ ++#if defined (__SUPPORT_LD_DEBUG__) ++ if (_dl_debug_reloc && _dl_debug_detail) ++ _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", ++ old_val, *reloc_addr, reloc_addr); ++#endif ++ ++ return 0; ++} ++ ++#undef __SPARC_LAZY_RELOC_WORKS ++#ifdef __SPARC_LAZY_RELOC_WORKS ++static int ++_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, ++ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) ++{ ++ int reloc_type; ++ int symtab_index; ++ ElfW(Addr) *reloc_addr; ++#if defined (__SUPPORT_LD_DEBUG__) ++ ElfW(Addr) old_val; ++#endif ++ ++ (void)scope; ++ symtab_index = ELF_R_SYM(rpnt->r_info); ++ (void)strtab; ++ ++ reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + rpnt->r_offset); ++ reloc_type = ELF_R_TYPE(rpnt->r_info); ++ ++#if defined (__SUPPORT_LD_DEBUG__) ++ old_val = *reloc_addr; ++#endif ++ ++ switch (reloc_type) { ++ case R_SPARC_NONE: ++ break; ++ case R_SPARC_JMP_SLOT: ++ break; ++ default: ++ _dl_exit(1); ++ } ++ ++#if defined (__SUPPORT_LD_DEBUG__) ++ if (_dl_debug_reloc && _dl_debug_detail) ++ _dl_dprintf(_dl_debug_file, "\tpatched_lazy: %x ==> %x @ %x\n", ++ old_val, *reloc_addr, reloc_addr); ++#endif ++ ++ return 0; + } ++#endif + +-void _dl_parse_lazy_relocation_information(struct dyn_elf *arg_rpnt, +- unsigned long rel_addr, unsigned long rel_size) +-{ +- int i; +- char * strtab; +- int reloc_type; +- int symtab_index; +- Elf32_Sym * symtab; +- Elf32_Rela * rpnt; +- unsigned int * reloc_addr; +- struct elf_resolve * tpnt = arg_rpnt->dyn; +- +- /* Now parse the relocation information */ +- rpnt = (Elf32_Rela *)rel_addr; +- +- symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB]; +- strtab = ( char *)tpnt->dynamic_info[DT_STRTAB]; +- +- for(i=0; i< rel_size; i += sizeof(Elf32_Rela), rpnt++){ +- reloc_addr = (int *) (tpnt->loadaddr + (int)rpnt->r_offset); +- reloc_type = ELF32_R_TYPE(rpnt->r_info); +- symtab_index = ELF32_R_SYM(rpnt->r_info); +- +- switch(reloc_type){ +- case R_SPARC_NONE: +- break; +- case R_SPARC_JMP_SLOT: +- break; +- default: +- _dl_dprintf(2, "%s: (LAZY) can't handle reloc type ", _dl_progname); +-#if defined (__SUPPORT_LD_DEBUG__) +- _dl_dprintf(2, "%s ", _dl_reltypes_tab[reloc_type]); +-#endif +- if(symtab_index) _dl_dprintf(2, "'%s'\n", +- strtab + symtab[symtab_index].st_name); +- _dl_exit(33); +- }; +- }; +-} +- +-int _dl_parse_relocation_information(struct dyn_elf *arg_rpnt, +- unsigned long rel_addr, unsigned long rel_size) +-{ +- int i; +- char * strtab; +- int reloc_type; +- int goof = 0; +- Elf32_Sym * symtab; +- Elf32_Rela * rpnt; +- unsigned int * reloc_addr; +- unsigned int symbol_addr; +- int symtab_index; +- struct elf_resolve * tpnt = arg_rpnt->dyn; +- /* Now parse the relocation information */ +- +- rpnt = (Elf32_Rela *)rel_addr; +- +- symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB]; +- strtab = ( char *)tpnt->dynamic_info[DT_STRTAB]; +- +- for(i=0; i< rel_size; i+= sizeof(Elf32_Rela), rpnt++){ +- reloc_addr = (int *) (tpnt->loadaddr + (int)rpnt->r_offset); +- reloc_type = ELF32_R_TYPE(rpnt->r_info); +- symtab_index = ELF32_R_SYM(rpnt->r_info); +- symbol_addr = 0; +- +- if(symtab_index) { +- +- symbol_addr = (unsigned int) +- _dl_find_hash(strtab + symtab[symtab_index].st_name, +- tpnt->symbol_scope, tpnt, elf_machine_type_class(reloc_type)); +- +- if(!symbol_addr && +- ELF32_ST_BIND(symtab [symtab_index].st_info) != STB_WEAK) { +- _dl_dprintf (2, "%s: can't resolve symbol '%s'\n", +- _dl_progname, strtab + symtab[symtab_index].st_name); +- _dl_exit (1); +- }; +- }; +- switch(reloc_type){ +- case R_SPARC_NONE: +- break; +- case R_SPARC_32: +- *reloc_addr = symbol_addr + rpnt->r_addend; +- break; +- case R_SPARC_DISP32: +- *reloc_addr = symbol_addr + rpnt->r_addend - (unsigned int) reloc_addr; +- break; +- case R_SPARC_GLOB_DAT: +- *reloc_addr = symbol_addr + rpnt->r_addend; +- break; +- case R_SPARC_JMP_SLOT: +- reloc_addr[1] = 0x03000000 | ((symbol_addr >> 10) & 0x3fffff); +- reloc_addr[2] = 0x81c06000 | (symbol_addr & 0x3ff); +- break; +- case R_SPARC_RELATIVE: +- *reloc_addr += (unsigned int) tpnt->loadaddr + rpnt->r_addend; +- break; +- case R_SPARC_HI22: +- if (!symbol_addr) +- symbol_addr = tpnt->loadaddr + rpnt->r_addend; +- else +- symbol_addr += rpnt->r_addend; +- *reloc_addr = (*reloc_addr & 0xffc00000)|(symbol_addr >> 10); +- break; +- case R_SPARC_LO10: +- if (!symbol_addr) +- symbol_addr = tpnt->loadaddr + rpnt->r_addend; +- else +- symbol_addr += rpnt->r_addend; +- *reloc_addr = (*reloc_addr & ~0x3ff)|(symbol_addr & 0x3ff); +- break; +- case R_SPARC_WDISP30: +- *reloc_addr = (*reloc_addr & 0xc0000000)| +- ((symbol_addr - (unsigned int) reloc_addr) >> 2); +- break; +- case R_SPARC_COPY: +- _dl_memcpy((void *) reloc_addr, (void *) symbol_addr, symtab[symtab_index].st_size); +- break; +- default: +- _dl_dprintf(2, "%s: can't handle reloc type ", _dl_progname); +-#if defined (__SUPPORT_LD_DEBUG__) +- _dl_dprintf(2, "%s ", _dl_reltypes_tab[reloc_type]); +-#endif +- if (symtab_index) +- _dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name); +- _dl_exit(34); +- }; ++void ++_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, ++ unsigned long rel_addr, ++ unsigned long rel_size) ++{ ++#ifdef __SPARC_LAZY_RELOC_WORKS ++ (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); ++#else ++ _dl_parse_relocation_information(rpnt, rel_addr, rel_size); ++#endif ++} + +- }; +- return goof; ++int ++_dl_parse_relocation_information(struct dyn_elf *rpnt, ++ unsigned long rel_addr, ++ unsigned long rel_size) ++{ ++ return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); + } +diff -urN uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-debug.h uClibc-0.9.28/ldso/ldso/x86_64/dl-debug.h +--- uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-debug.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/x86_64/dl-debug.h 2006-04-28 00:14:35.000000000 -0600 +@@ -30,7 +30,10 @@ + */ + + static const char *_dl_reltypes_tab[] = { +- [0] "R_X86_64_NONE", "R_X86_64_64", "R_X86_64_PC32", "R_X86_64_GOT32", +- [4] "R_X86_64_PLT32", "R_X86_64_COPY", "R_X86_64_GLOB_DAT", "R_X86_64_JUMP_SLOT", +- [8] "R_X86_64_RELATIVE", "R_X86_64_GOTPCREL", "R_X86_64_32" ++ [ 0] "R_X86_64_NONE", "R_X86_64_64", "R_X86_64_PC32", "R_X86_64_GOT32", ++ [ 4] "R_X86_64_PLT32", "R_X86_64_COPY", "R_X86_64_GLOB_DAT", "R_X86_64_JUMP_SLOT", ++ [ 8] "R_X86_64_RELATIVE", "R_X86_64_GOTPCREL", "R_X86_64_32", "R_X86_64_32S", ++ [12] "R_X86_64_16", "R_X86_64_PC16", "R_X86_64_8", "R_X86_64_PC8", ++ [16] "R_X86_64_DTPMOD64", "R_X86_64_DTPOFF64", "R_X86_64_TPOFF64", "R_X86_64_TLSGD", ++ [20] "R_X86_64_TLSLD", "R_X86_64_DTPOFF32", "R_X86_64_GOTTPOFF", "R_X86_64_TPOFF32" + }; +diff -urN uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-startup.h uClibc-0.9.28/ldso/ldso/x86_64/dl-startup.h +--- uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-startup.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/x86_64/dl-startup.h 2006-04-28 00:14:35.000000000 -0600 +@@ -6,7 +6,7 @@ + * + * Parts taken from glibc/sysdeps/x86_64/dl-machine.h + */ +-asm( ++__asm__ ( + " .text\n" + " .align 16\n" + " .global _start\n" +@@ -42,10 +42,10 @@ + + /* Handle relocation of the symbols in the dynamic loader. */ + static __always_inline +-void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr, +- unsigned long symbol_addr, unsigned long load_addr, Elf64_Sym *sym) ++void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, ElfW(Addr) *reloc_addr, ++ ElfW(Addr) symbol_addr, ElfW(Addr) load_addr, ElfW(Sym) *sym) + { +- switch (ELF64_R_TYPE(rpnt->r_info)) { ++ switch (ELF_R_TYPE(rpnt->r_info)) { + case R_X86_64_GLOB_DAT: + case R_X86_64_JUMP_SLOT: + *reloc_addr = symbol_addr + rpnt->r_addend; +@@ -63,8 +63,3 @@ + _dl_exit(1); + } + } +- +-/* Transfer control to the user's application, once the dynamic loader is +- * done. This routine has to exit the current function, then call the +- * _dl_elf_main function. */ +-#define START() return _dl_elf_main +diff -urN uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-syscalls.h uClibc-0.9.28/ldso/ldso/x86_64/dl-syscalls.h +--- uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/x86_64/dl-syscalls.h 2006-05-02 13:39:17.000000000 -0600 +@@ -1,7 +1,8 @@ + /* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ ++#define __UCLIBC_MMAP_HAS_6_ARGS__ ++ ++#include "sys/syscall.h" + extern int _dl_errno; ++#undef __set_errno + #define __set_errno(X) {(_dl_errno) = (X);} +-#include "sys/syscall.h" +- +-#define MMAP_HAS_6_ARGS +diff -urN uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-sysdep.h uClibc-0.9.28/ldso/ldso/x86_64/dl-sysdep.h +--- uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/x86_64/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600 +@@ -41,8 +41,6 @@ + struct elf_resolve; + extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); + +-#define do_rem(result, n, base) ((result) = (n) % (base)) +- + /* 4096 bytes alignment */ + #define PAGE_ALIGN 0xfffff000 + #define ADDR_ALIGN 0xfff +@@ -90,7 +88,7 @@ + and compare it with the current value that we can get via + an RIP relative addressing mode. */ + +- asm ("movq 1f(%%rip), %1\n" ++ __asm__ ("movq 1f(%%rip), %1\n" + "0:\tleaq _dl_start(%%rip), %0\n\t" + "subq %1, %0\n\t" + ".section\t.data\n" +diff -urN uClibc-0.9.28.orig/ldso/ldso/x86_64/elfinterp.c uClibc-0.9.28/ldso/ldso/x86_64/elfinterp.c +--- uClibc-0.9.28.orig/ldso/ldso/x86_64/elfinterp.c 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/ldso/x86_64/elfinterp.c 2006-04-28 00:14:35.000000000 -0600 +@@ -165,6 +165,7 @@ + int reloc_type; + int symtab_index; + char *symname; ++ ElfW(Sym) *sym; + ElfW(Addr) *reloc_addr; + ElfW(Addr) symbol_addr; + #if defined (__SUPPORT_LD_DEBUG__) +@@ -174,8 +175,9 @@ + reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); + reloc_type = ELF_R_TYPE(rpnt->r_info); + symtab_index = ELF_R_SYM(rpnt->r_info); ++ sym = &symtab[symtab_index]; + symbol_addr = 0; +- symname = strtab + symtab[symtab_index].st_name; ++ symname = strtab + sym->st_name; + + if (symtab_index) { + symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt, +@@ -185,7 +187,7 @@ + * might have been intentional. We should not be linking local + * symbols here, so all bases should be covered. + */ +- if (unlikely(!symbol_addr && ELF_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) { ++ if (unlikely(!symbol_addr && ELF_ST_BIND(sym->st_info) != STB_WEAK)) { + _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); + _dl_exit(1); + }; +@@ -209,7 +211,7 @@ + + case R_X86_64_GLOB_DAT: + case R_X86_64_JUMP_SLOT: +- *reloc_addr = symbol_addr; ++ *reloc_addr = symbol_addr + rpnt->r_addend; + break; + + /* handled by elf_machine_relative() +@@ -217,33 +219,33 @@ + *reloc_addr = map->l_addr + rpnt->r_addend; + break; + */ +-#if 0 + case R_X86_64_DTPMOD64: ++ *reloc_addr = 1; + break; + case R_X86_64_DTPOFF64: +- *reloc_addr = symbol_addr + rpnt->r_addend; ++ *reloc_addr = sym->st_value + rpnt->r_addend; + break; + case R_X86_64_TPOFF64: +- *reloc_addr = symbol_addr + rpnt->r_addend; ++ *reloc_addr = sym->st_value + rpnt->r_addend - symbol_addr; + break; + case R_X86_64_32: +- *reloc_addr = symbol_addr + rpnt->r_addend; ++ *(unsigned int *) reloc_addr = symbol_addr + rpnt->r_addend; ++ /* XXX: should check for overflow eh ? */ + break; + +-#endif + case R_X86_64_COPY: + if (symbol_addr) { + #if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_move) + _dl_dprintf(_dl_debug_file, + "\t%s move %d bytes from %x to %x\n", +- symname, symtab[symtab_index].st_size, ++ symname, sym->st_size, + symbol_addr, reloc_addr); + #endif + + _dl_memcpy((char *)reloc_addr, + (char *)symbol_addr, +- symtab[symtab_index].st_size); ++ sym->st_size); + } else + _dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n"); + break; +@@ -261,7 +263,6 @@ + return 0; + } + +-#if 0 + static int + _dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) +@@ -288,7 +289,7 @@ + case R_X86_64_NONE: + break; + case R_X86_64_JUMP_SLOT: +- *reloc_addr = tpnt->loadaddr + symtab[symtab_index].st_value; ++ *reloc_addr += (unsigned long)tpnt->loadaddr; + break; + default: + _dl_exit(1); +@@ -302,17 +303,13 @@ + + return 0; + } +-#endif + + void + _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) + { +- _dl_parse_relocation_information(rpnt, rel_addr, rel_size); +-/* jump slot isnt working + (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); +-*/ + } + + int +diff -urN uClibc-0.9.28.orig/ldso/ldso/x86_64/resolve.S uClibc-0.9.28/ldso/ldso/x86_64/resolve.S +--- uClibc-0.9.28.orig/ldso/ldso/x86_64/resolve.S 1969-12-31 17:00:00.000000000 -0700 ++++ uClibc-0.9.28/ldso/ldso/x86_64/resolve.S 2006-04-28 00:14:35.000000000 -0600 +@@ -0,0 +1,63 @@ ++/* ++ * This function is _not_ called directly. It is jumped to (so no return ++ * address is on the stack) when attempting to use a symbol that has not yet ++ * been resolved. The first time a jump symbol (such as a function call inside ++ * a shared library) is used (before it gets resolved) it will jump here to ++ * _dl_linux_resolve. When we get called the stack looks like this: ++ * reloc_entry ++ * tpnt ++ * ++ * This function saves all the registers, puts a copy of reloc_entry and tpnt ++ * on the stack (as function arguments) then make the function call ++ * _dl_linux_resolver(tpnt, reloc_entry). _dl_linux_resolver() figures out ++ * where the jump symbol is _really_ supposed to have jumped to and returns ++ * that to us. Once we have that, we overwrite tpnt with this fixed up ++ * address. We then clean up after ourselves, put all the registers back how we ++ * found them, then we jump to where the fixed up address, which is where the ++ * jump symbol that got us here really wanted to jump to in the first place. ++ * found them, then we jump to the fixed up address, which is where the jump ++ * symbol that got us here really wanted to jump to in the first place. ++ * -Erik Andersen ++ */ ++ ++/* more info taken from glibc/sysdeps/x86_64/dl-trampoline.S */ ++ ++.text ++ ++.global _dl_linux_resolve ++.type _dl_linux_resolve,%function ++.align 16 ++ ++_dl_linux_resolve: ++ subq $56,%rsp ++ /* Preserve registers otherwise clobbered. */ ++ movq %rax, (%rsp) ++ movq %rcx, 8(%rsp) ++ movq %rdx, 16(%rsp) ++ movq %rsi, 24(%rsp) ++ movq %rdi, 32(%rsp) ++ movq %r8, 40(%rsp) ++ movq %r9, 48(%rsp) ++ ++ movq 64(%rsp), %rsi /* Copy args pushed by PLT in register. */ ++ movq %rsi, %r11 /* Multiply by 24 */ ++ addq %r11, %rsi ++ addq %r11, %rsi ++ shlq $3, %rsi ++ movq 56(%rsp), %rdi /* %rdi: link_map, %rsi: reloc_offset */ ++ call _dl_linux_resolver /* Call resolver. */ ++ movq %rax, %r11 /* Save return value */ ++ ++ /* Get register content back. */ ++ movq 48(%rsp), %r9 ++ movq 40(%rsp), %r8 ++ movq 32(%rsp), %rdi ++ movq 24(%rsp), %rsi ++ movq 16(%rsp), %rdx ++ movq 8(%rsp), %rcx ++ movq (%rsp), %rax ++ ++ addq $72, %rsp /* Adjust stack(PLT did 2 pushes) */ ++ jmp *%r11 /* Jump to function address. */ ++ ++.size _dl_linux_resolve,.-_dl_linux_resolve +diff -urN uClibc-0.9.28.orig/ldso/libdl/Makefile uClibc-0.9.28/ldso/libdl/Makefile +--- uClibc-0.9.28.orig/ldso/libdl/Makefile 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/libdl/Makefile 2006-04-28 00:14:35.000000000 -0600 +@@ -29,12 +29,14 @@ + endif + XXFLAGS+= $(XARCH_CFLAGS) $(CPU_CFLAGS) \ + -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" \ +- -fno-builtin -nostdinc -D_LIBC -I$(TOPDIR)ldso/include -I$(TOPDIR)ldso/ldso -I. -I$(TOPDIR)include ++ -fno-builtin -nostdinc -D_LIBC \ ++ -DLDSO_ELFINTERP=\"$(TARGET_ARCH)/elfinterp.c\" \ ++ -I$(TOPDIR)ldso/ldso/$(TARGET_ARCH) -I$(TOPDIR)ldso/include -I$(TOPDIR)ldso/ldso -I$(TOPDIR)include + + XXFLAGS+=-isystem $(shell $(CC) -print-file-name=include) + XXFLAGS_NOPIC:=$(XXFLAGS) + ifeq ($(DOPIC),y) +- XXFLAGS += $(PICFLAG) -D__LIBDL_SHARED__ ++ XXFLAGS += $(PICFLAG) -DSHARED + endif + ifeq ($(strip $(SUPPORT_LD_DEBUG)),y) + XXFLAGS+=-D__SUPPORT_LD_DEBUG__ +diff -urN uClibc-0.9.28.orig/ldso/libdl/libdl.c uClibc-0.9.28/ldso/libdl/libdl.c +--- uClibc-0.9.28.orig/ldso/libdl/libdl.c 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/ldso/libdl/libdl.c 2006-04-28 00:14:35.000000000 -0600 +@@ -3,7 +3,7 @@ + * Program to load an ELF binary on a linux system, and run it + * after resolving ELF shared library symbols + * +- * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org> ++ * Copyright (C) 2000-2006 by Erik Andersen <andersen@uclibc.org> + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * +@@ -30,12 +30,12 @@ + */ + + +-#define _GNU_SOURCE ++#define _GNU_SOURCE + #include <ldso.h> + #include <stdio.h> + + +-#if defined (__LIBDL_SHARED__) ++#ifdef SHARED + + /* When libdl is loaded as a shared library, we need to load in + * and use a pile of symbols from ldso... */ +@@ -52,6 +51,8 @@ + extern struct r_debug *_dl_debug_addr; + extern unsigned long _dl_error_number; + extern void *(*_dl_malloc_function)(size_t); ++extern void _dl_run_init_array(struct elf_resolve *); ++extern void _dl_run_fini_array(struct elf_resolve *); + #ifdef __LDSO_CACHE_SUPPORT__ + int _dl_map_cache(void); + int _dl_unmap_cache(void); +@@ -64,7 +65,7 @@ + #endif + + +-#else /* __LIBDL_SHARED__ */ ++#else /* SHARED */ + + /* When libdl is linked as a static library, we need to replace all + * the symbols that otherwise would have been loaded in from ldso... */ +@@ -81,11 +82,11 @@ + struct r_debug *_dl_debug_addr = NULL; + #define _dl_malloc malloc + #include "../ldso/dl-debug.c" +-#include "dl-progname.h" ++#include LDSO_ELFINTERP + #include "../ldso/dl-hash.c" + #define _dl_trace_loaded_objects 0 + #include "../ldso/dl-elf.c" +-#endif /* __LIBDL_SHARED__ */ ++#endif /* SHARED */ + + #ifdef __SUPPORT_LD_DEBUG__ + # define _dl_if_debug_print(fmt, args...) \ +@@ -126,7 +127,8 @@ + "Unable to resolve symbol" + }; + +-void __attribute__ ((destructor)) dl_cleanup(void) ++void dl_cleanup(void) __attribute__ ((destructor)); ++void dl_cleanup(void) + { + struct dyn_elf *d; + for (d = _dl_handles; d; d = d->next_handle) { +@@ -138,13 +140,12 @@ + { + struct elf_resolve *tpnt, *tfrom; + struct dyn_elf *dyn_chain, *rpnt = NULL, *dyn_ptr, *relro_ptr, *handle; +- struct dyn_elf *dpnt; + ElfW(Addr) from; + struct elf_resolve *tpnt1; + void (*dl_brk) (void); + int now_flag; + struct init_fini_list *tmp, *runp, *runp2, *dep_list; +- int nlist, i; ++ unsigned int nlist, i; + struct elf_resolve **init_fini_list; + + /* A bit of sanity checking... */ +@@ -169,12 +170,15 @@ + * the application. Thus this may go away at some time + * in the future. + */ +- tfrom = NULL; +- for (dpnt = _dl_symbol_tables; dpnt; dpnt = dpnt->next) { +- tpnt = dpnt->dyn; +- if (tpnt->loadaddr < from +- && (tfrom == NULL || tfrom->loadaddr < tpnt->loadaddr)) +- tfrom = tpnt; ++ { ++ struct dyn_elf *dpnt; ++ tfrom = NULL; ++ for (dpnt = _dl_symbol_tables; dpnt; dpnt = dpnt->next) { ++ tpnt = dpnt->dyn; ++ if (tpnt->loadaddr < from ++ && (tfrom == NULL || tfrom->loadaddr < tpnt->loadaddr)) ++ tfrom = tpnt; ++ } + } + for(rpnt = _dl_symbol_tables; rpnt && rpnt->next; rpnt=rpnt->next); + +@@ -233,11 +237,8 @@ + runp->tpnt->init_fini = NULL; /* clear any previous dependcies */ + for (dpnt = (ElfW(Dyn) *) runp->tpnt->dynamic_addr; dpnt->d_tag; dpnt++) { + if (dpnt->d_tag == DT_NEEDED) { +- char *name; +- + lpntstr = (char*) (runp->tpnt->dynamic_info[DT_STRTAB] + + dpnt->d_un.d_val); +- name = _dl_get_last_path_component(lpntstr); + _dl_if_debug_print("Trying to load '%s', needed by '%s'\n", + lpntstr, runp->tpnt->libname); + tpnt1 = _dl_load_shared_library(0, &rpnt, runp->tpnt, lpntstr, 0); +@@ -297,14 +298,14 @@ + } + /* Sort the INIT/FINI list in dependency order. */ + for (runp2 = dep_list; runp2; runp2 = runp2->next) { +- int j, k; ++ unsigned int j, k; + for (j = 0; init_fini_list[j] != runp2->tpnt; ++j) + /* Empty */; + for (k = j + 1; k < nlist; ++k) { +- struct init_fini_list *runp = init_fini_list[k]->init_fini; ++ struct init_fini_list *ele = init_fini_list[k]->init_fini; + +- for (; runp; runp = runp->next) { +- if (runp->tpnt == runp2->tpnt) { ++ for (; ele; ele = ele->next) { ++ if (ele->tpnt == runp2->tpnt) { + struct elf_resolve *here = init_fini_list[k]; + _dl_if_debug_print("Move %s from pos %d to %d in INIT/FINI list.\n", here->libname, k, j); + for (i = (k - j); i; --i) +@@ -367,7 +368,7 @@ + } + } + +-#if defined (__LIBDL_SHARED__) ++#ifdef SHARED + /* Run the ctors and setup the dtors */ + for (i = nlist; i; --i) { + tpnt = init_fini_list[i-1]; +@@ -384,8 +385,11 @@ + (*dl_elf_func) (); + } + } ++ ++ _dl_run_init_array(tpnt); + } +-#endif ++#endif /* SHARED */ ++ + _dl_unmap_cache(); + return (void *) dyn_chain; + +@@ -450,9 +454,16 @@ + return ret; + } + ++#if 0 ++void *dlvsym(void *vhandle, const char *name, const char *version) ++{ ++ return dlsym(vhandle, name); ++} ++#endif ++ + static int do_dlclose(void *vhandle, int need_fini) + { +- struct dyn_elf *rpnt, *rpnt1; ++ struct dyn_elf *rpnt, *rpnt1, *rpnt1_tmp; + struct init_fini_list *runp, *tmp; + ElfW(Phdr) *ppnt; + struct elf_resolve *tpnt, *run_tpnt; +@@ -460,7 +471,7 @@ + void (*dl_brk) (void); + struct dyn_elf *handle; + unsigned int end; +- int i = 0, j; ++ unsigned int i, j; + + handle = (struct dyn_elf *) vhandle; + if (handle == _dl_symbol_tables) +@@ -491,13 +502,21 @@ + for (j = 0; j < handle->init_fini.nlist; ++j) { + tpnt = handle->init_fini.init_fini[j]; + if (--tpnt->usage_count == 0) { +- if (tpnt->dynamic_info[DT_FINI] && need_fini && ++ if ((tpnt->dynamic_info[DT_FINI] ++ || tpnt->dynamic_info[DT_FINI_ARRAY]) ++ && need_fini && + !(tpnt->init_flag & FINI_FUNCS_CALLED)) { + tpnt->init_flag |= FINI_FUNCS_CALLED; +- dl_elf_fini = (int (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]); +- _dl_if_debug_print("running dtors for library %s at '%p'\n", +- tpnt->libname, dl_elf_fini); +- (*dl_elf_fini) (); ++#ifdef SHARED ++ _dl_run_fini_array(tpnt); ++#endif ++ ++ if (tpnt->dynamic_info[DT_FINI]) { ++ dl_elf_fini = (int (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]); ++ _dl_if_debug_print("running dtors for library %s at '%p'\n", ++ tpnt->libname, dl_elf_fini); ++ (*dl_elf_fini) (); ++ } + } + + _dl_if_debug_print("unmapping: %s\n", tpnt->libname); +@@ -541,8 +560,9 @@ + for (rpnt1 = _dl_symbol_tables; rpnt1->next; rpnt1 = rpnt1->next) { + if (rpnt1->next->dyn == tpnt) { + _dl_if_debug_print("removing symbol_tables: %s\n", tpnt->libname); ++ rpnt1_tmp = rpnt1->next->next; + free(rpnt1->next); +- rpnt1->next = rpnt1->next->next; ++ rpnt1->next = rpnt1_tmp; + if (rpnt1->next) + rpnt1->next->prev = rpnt1; + break; +@@ -588,8 +608,9 @@ + } + + /* +- * Dump information to stderrr about the current loaded modules ++ * Dump information to stderr about the current loaded modules + */ ++#if 1 + static char *type[] = { "Lib", "Exe", "Int", "Mod" }; + + int dlinfo(void) +@@ -660,16 +681,14 @@ + { + char *strtab; + ElfW(Sym) *symtab; +- int hn, si; +- int sf; +- int sn = 0; ++ unsigned int hn, si, sn, sf; + ElfW(Addr) sa; + + sa = 0; + symtab = (ElfW(Sym) *) (pelf->dynamic_info[DT_SYMTAB]); + strtab = (char *) (pelf->dynamic_info[DT_STRTAB]); + +- sf = 0; ++ sf = sn = 0; + for (hn = 0; hn < pelf->nbucket; hn++) { + for (si = pelf->elf_buckets[hn]; si; si = pelf->chains[si]) { + ElfW(Addr) symbol_addr; +@@ -696,3 +715,4 @@ + return 1; + } + } ++#endif +diff -urN uClibc-0.9.28.orig/libc/sysdeps/linux/i386/bits/syscalls.h uClibc-0.9.28/libc/sysdeps/linux/i386/bits/syscalls.h +--- uClibc-0.9.28.orig/libc/sysdeps/linux/i386/bits/syscalls.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/libc/sysdeps/linux/i386/bits/syscalls.h 2006-04-28 00:14:35.000000000 -0600 +@@ -4,17 +4,15 @@ + # error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead." + #endif + ++#include <errno.h> ++ + /* This includes the `__NR_<name>' syscall numbers taken from the Linux kernel + * header files. It also defines the traditional `SYS_<name>' macros for older + * programs. */ + #include <bits/sysnum.h> + +-#ifndef __set_errno +-# define __set_errno(val) (*__errno_location ()) = (val) +-#endif +- + /* +- Some of the sneaky macros in the code were taken from ++ Some of the sneaky macros in the code were taken from + glibc-2.2.5/sysdeps/unix/sysv/linux/i386/sysdep.h + */ + +@@ -22,7 +20,8 @@ + + /* We need some help from the assembler to generate optimal code. We + define some macros here which later will be used. */ +-asm (".L__X'%ebx = 1\n\t" ++ ++__asm__ (".L__X'%ebx = 1\n\t" + ".L__X'%ecx = 2\n\t" + ".L__X'%edx = 2\n\t" + ".L__X'%eax = 3\n\t" +@@ -56,7 +55,6 @@ + ".endif\n\t" + ".endm\n\t"); + +- + #undef _syscall0 + #define _syscall0(type,name) \ + type name(void) \ +@@ -90,7 +88,7 @@ + type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ + { \ + return (type) (INLINE_SYSCALL(name, 4, arg1, arg2, arg3, arg4)); \ +-} ++} + + #undef _syscall5 + #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ +@@ -100,10 +98,18 @@ + return (type) (INLINE_SYSCALL(name, 5, arg1, arg2, arg3, arg4, arg5)); \ + } + ++#undef _syscall6 ++#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ ++ type5,arg5,type6,arg6) \ ++type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, type6 arg6) \ ++{ \ ++return (type) (INLINE_SYSCALL(name, 6, arg1, arg2, arg3, arg4, arg5, arg6)); \ ++} ++ + #define INLINE_SYSCALL(name, nr, args...) \ + ({ \ + unsigned int resultvar; \ +- asm volatile ( \ ++ __asm__ __volatile__ ( \ + LOADARGS_##nr \ + "movl %1, %%eax\n\t" \ + "int $0x80\n\t" \ +@@ -125,6 +131,7 @@ + #define LOADARGS_3 LOADARGS_1 + #define LOADARGS_4 LOADARGS_1 + #define LOADARGS_5 LOADARGS_1 ++#define LOADARGS_6 LOADARGS_1 "push %%ebp ; movl %7, %%ebp\n\t" + + #define RESTOREARGS_0 + #define RESTOREARGS_1 \ +@@ -133,6 +140,7 @@ + #define RESTOREARGS_3 RESTOREARGS_1 + #define RESTOREARGS_4 RESTOREARGS_1 + #define RESTOREARGS_5 RESTOREARGS_1 ++#define RESTOREARGS_6 "pop %%ebp\n\t" RESTOREARGS_1 + + #define ASMFMT_0() + #define ASMFMT_1(arg1) \ +@@ -145,7 +153,8 @@ + , "aD" (arg1), "c" (arg2), "d" (arg3), "S" (arg4) + #define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \ + , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5) +- ++#define ASMFMT_6(arg1, arg2, arg3, arg4, arg5, arg6) \ ++ , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5), "m" (arg6) + + #endif /* __ASSEMBLER__ */ + #endif /* _BITS_SYSCALLS_H */ +diff -urN uClibc-0.9.28.orig/libc/sysdeps/linux/powerpc/bits/syscalls.h uClibc-0.9.28/libc/sysdeps/linux/powerpc/bits/syscalls.h +--- uClibc-0.9.28.orig/libc/sysdeps/linux/powerpc/bits/syscalls.h 2006-05-02 10:47:27.000000000 -0600 ++++ uClibc-0.9.28/libc/sysdeps/linux/powerpc/bits/syscalls.h 2006-04-28 00:14:35.000000000 -0600 +@@ -5,67 +5,164 @@ + # error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead." + #endif + ++#include <errno.h> ++ + /* This includes the `__NR_<name>' syscall numbers taken from the Linux kernel + * header files. It also defines the traditional `SYS_<name>' macros for older + * programs. */ + #include <bits/sysnum.h> + +- +-#define __STRINGIFY(s) __STRINGIFY2 (s) +-#define __STRINGIFY2(s) #s +- +-#undef JUMPTARGET +-#ifdef __PIC__ +-#define __MAKE_SYSCALL __STRINGIFY(__uClibc_syscall@plt) ++/* Define a macro which expands inline into the wrapper code for a system ++ call. This use is for internal calls that do not need to handle errors ++ normally. It will never touch errno. ++ On powerpc a system call basically clobbers the same registers like a ++ function call, with the exception of LR (which is needed for the ++ "sc; bnslr+" sequence) and CR (where only CR0.SO is clobbered to signal ++ an error return status). */ ++ ++# undef INLINE_SYSCALL ++#if 1 ++# define INLINE_SYSCALL(name, nr, args...) \ ++ ({ \ ++ INTERNAL_SYSCALL_DECL (sc_err); \ ++ long int sc_ret = INTERNAL_SYSCALL (name, sc_err, nr, args); \ ++ if (INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err)) \ ++ { \ ++ __set_errno (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err)); \ ++ sc_ret = -1L; \ ++ } \ ++ sc_ret; \ ++ }) + #else +-#define __MAKE_SYSCALL __STRINGIFY(__uClibc_syscall) ++# define INLINE_SYSCALL(name, nr, args...) \ ++ ({ \ ++ INTERNAL_SYSCALL_DECL (sc_err); \ ++ long int sc_ret = INTERNAL_SYSCALL (name, sc_err, nr, args); \ ++ if (INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err)) \ ++ { \ ++ sc_ret = __syscall_error(INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err));\ ++ } \ ++ sc_ret; \ ++ }) + #endif + +-#define unified_syscall_body(name) \ +- __asm__ ( \ +- ".section \".text\"\n\t" \ +- ".align 2\n\t" \ +- ".globl " __STRINGIFY(name) "\n\t" \ +- ".type " __STRINGIFY(name) ",@function\n\t" \ +- #name":\tli 0," __STRINGIFY(__NR_##name) "\n\t" \ +- "b " __MAKE_SYSCALL "\n\t" \ +- ".size\t" __STRINGIFY(name) ",.""-" __STRINGIFY(name) "\n" \ +- ) ++/* Define a macro which expands inline into the wrapper code for a system ++ call. This use is for internal calls that do not need to handle errors ++ normally. It will never touch errno. ++ On powerpc a system call basically clobbers the same registers like a ++ function call, with the exception of LR (which is needed for the ++ "sc; bnslr+" sequence) and CR (where only CR0.SO is clobbered to signal ++ an error return status). */ ++ ++# undef INTERNAL_SYSCALL_DECL ++# define INTERNAL_SYSCALL_DECL(err) long int err ++ ++# undef INTERNAL_SYSCALL ++# define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ ++ ({ \ ++ register long int r0 __asm__ ("r0"); \ ++ register long int r3 __asm__ ("r3"); \ ++ register long int r4 __asm__ ("r4"); \ ++ register long int r5 __asm__ ("r5"); \ ++ register long int r6 __asm__ ("r6"); \ ++ register long int r7 __asm__ ("r7"); \ ++ register long int r8 __asm__ ("r8"); \ ++ register long int r9 __asm__ ("r9"); \ ++ register long int r10 __asm__ ("r10"); \ ++ register long int r11 __asm__ ("r11"); \ ++ register long int r12 __asm__ ("r12"); \ ++ LOADARGS_##nr(name, args); \ ++ __asm__ __volatile__ \ ++ ("sc \n\t" \ ++ "mfcr %0" \ ++ : "=&r" (r0), \ ++ "=&r" (r3), "=&r" (r4), "=&r" (r5), "=&r" (r6), "=&r" (r7), \ ++ "=&r" (r8), "=&r" (r9), "=&r" (r10), "=&r" (r11), "=&r" (r12) \ ++ : ASM_INPUT_##nr \ ++ : "cr0", "ctr", "memory"); \ ++ err = r0; \ ++ (int) r3; \ ++ }) ++# define INTERNAL_SYSCALL(name, err, nr, args...) \ ++ INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args) ++ ++# undef INTERNAL_SYSCALL_ERROR_P ++# define INTERNAL_SYSCALL_ERROR_P(val, err) \ ++ ((void) (val), __builtin_expect ((err) & (1 << 28), 0)) ++ ++# undef INTERNAL_SYSCALL_ERRNO ++# define INTERNAL_SYSCALL_ERRNO(val, err) (val) ++ ++# define LOADARGS_0(name, dummy) \ ++ r0 = (long int)name ++# define LOADARGS_1(name, __arg1) \ ++ LOADARGS_0(name, 0); \ ++ r3 = (long int)__arg1 ++# define LOADARGS_2(name, __arg1, __arg2) \ ++ LOADARGS_1(name, __arg1); \ ++ r4 = (long int)__arg2 ++# define LOADARGS_3(name, __arg1, __arg2, __arg3) \ ++ LOADARGS_2(name, __arg1, __arg2); \ ++ r5 = (long int)__arg3 ++# define LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4) \ ++ LOADARGS_3(name, __arg1, __arg2, __arg3); \ ++ r6 = (long int)__arg4 ++# define LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5) \ ++ LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4); \ ++ r7 = (long int)__arg5 ++# define LOADARGS_6(name, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6) \ ++ LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5); \ ++ r8 = (long int)__arg6 ++ ++# define ASM_INPUT_0 "0" (r0) ++# define ASM_INPUT_1 ASM_INPUT_0, "1" (r3) ++# define ASM_INPUT_2 ASM_INPUT_1, "2" (r4) ++# define ASM_INPUT_3 ASM_INPUT_2, "3" (r5) ++# define ASM_INPUT_4 ASM_INPUT_3, "4" (r6) ++# define ASM_INPUT_5 ASM_INPUT_4, "5" (r7) ++# define ASM_INPUT_6 ASM_INPUT_5, "6" (r8) + + #undef _syscall0 +-#define _syscall0(type,name) \ +-type name(void); \ +-unified_syscall_body(name) ++#define _syscall0(type,name) \ ++type name(void){ \ ++ return (type) INLINE_SYSCALL(name, 0); \ ++} + + #undef _syscall1 + #define _syscall1(type,name,type1,arg1) \ +-type name(type1 arg1); \ +-unified_syscall_body(name) ++type name(type1 arg1){ \ ++ return (type) INLINE_SYSCALL(name, 1, arg1); \ ++} + + #undef _syscall2 + #define _syscall2(type,name,type1,arg1,type2,arg2) \ +-type name(type1 arg1, type2 arg2); \ +-unified_syscall_body(name) ++type name(type1 arg1, type2 arg2){ \ ++ return (type) INLINE_SYSCALL(name, 2, arg1, arg2); \ ++} + + #undef _syscall3 + #define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +-type name(type1 arg1, type2 arg2, type3 arg3); \ +-unified_syscall_body(name) ++type name(type1 arg1, type2 arg2, type3 arg3){ \ ++ return (type) INLINE_SYSCALL(name, 3, arg1, arg2, arg3); \ ++} + + #undef _syscall4 + #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4); \ +-unified_syscall_body(name) ++type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4){ \ ++ return (type) INLINE_SYSCALL(name, 4, arg1, arg2, arg3, arg4); \ ++} + + #undef _syscall5 + #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ +-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5); \ +-unified_syscall_body(name) ++type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5){ \ ++ return (type) INLINE_SYSCALL(name, 5, arg1, arg2, arg3, arg4, arg5); \ ++} + + #undef _syscall6 + #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \ +-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6); \ +-unified_syscall_body(name) ++type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6){ \ ++ return (type) INLINE_SYSCALL(name, 6, arg1, arg2, arg3, arg4, arg5, arg6); \ ++} + + #endif /* _BITS_SYSCALLS_H */ + diff --git a/toolchain/uClibc/uClibc-0.9.28-math-endianness.patch b/toolchain/uClibc/uClibc-0.9.28-math-endianness.patch new file mode 100644 index 000000000..015f79568 --- /dev/null +++ b/toolchain/uClibc/uClibc-0.9.28-math-endianness.patch @@ -0,0 +1,247 @@ +Index: uclibc/libm/fp_private.h +=================================================================== +--- uclibc/libm/fp_private.h (revision 12879) ++++ uclibc/libm/fp_private.h (working copy) +@@ -70,10 +70,11 @@ + *******************************************************************************/ + + #include <stdint.h> ++#include <endian.h> + + typedef struct /* Hex representation of a double. */ + { +-#if defined(__BIG_ENDIAN__) ++#if (__BYTE_ORDER == __BIG_ENDIAN) + uint32_t high; + uint32_t low; + #else +Index: uclibc/libm/powerpc/s_ceil.c +=================================================================== +--- uclibc/libm/powerpc/s_ceil.c (revision 12879) ++++ uclibc/libm/powerpc/s_ceil.c (working copy) +@@ -21,13 +21,15 @@ + * * + *******************************************************************************/ + ++#include <endian.h> ++ + static const double twoTo52 = 4503599627370496.0; + static const unsigned long signMask = 0x80000000ul; + + typedef union + { + struct { +-#if defined(__BIG_ENDIAN__) ++#if (__BYTE_ORDER == __BIG_ENDIAN) + unsigned long int hi; + unsigned long int lo; + #else +Index: uclibc/libm/powerpc/s_ldexp.c +=================================================================== +--- uclibc/libm/powerpc/s_ldexp.c (revision 12879) ++++ uclibc/libm/powerpc/s_ldexp.c (working copy) +@@ -21,11 +21,12 @@ + + #include <limits.h> + #include <math.h> ++#include <endian.h> + + typedef union + { + struct { +-#if defined(__BIG_ENDIAN__) ++#if (__BYTE_ORDER == __BIG_ENDIAN) + unsigned long int hi; + unsigned long int lo; + #else +Index: uclibc/libm/powerpc/s_rint.c +=================================================================== +--- uclibc/libm/powerpc/s_rint.c (revision 12879) ++++ uclibc/libm/powerpc/s_rint.c (working copy) +@@ -46,13 +46,14 @@ + + #include <limits.h> + #include <math.h> ++#include <endian.h> + + #define SET_INVALID 0x01000000UL + + typedef union + { + struct { +-#if defined(__BIG_ENDIAN__) ++#if (__BYTE_ORDER == __BIG_ENDIAN) + unsigned long int hi; + unsigned long int lo; + #else +Index: uclibc/libm/powerpc/s_floor.c +=================================================================== +--- uclibc/libm/powerpc/s_floor.c (revision 12879) ++++ uclibc/libm/powerpc/s_floor.c (working copy) +@@ -21,13 +21,15 @@ + * * + *******************************************************************************/ + ++#include <endian.h> ++ + static const double twoTo52 = 4503599627370496.0; + static const unsigned long signMask = 0x80000000ul; + + typedef union + { + struct { +-#if defined(__BIG_ENDIAN__) ++#if (__BYTE_ORDER == __BIG_ENDIAN) + unsigned long int hi; + unsigned long int lo; + #else +Index: uclibc/libm/powerpc/s_logb.c +=================================================================== +--- uclibc/libm/powerpc/s_logb.c (revision 12879) ++++ uclibc/libm/powerpc/s_logb.c (working copy) +@@ -32,10 +32,12 @@ + * Standard 754. * + *******************************************************************************/ + ++#include <endian.h> ++ + typedef union + { + struct { +-#if defined(__BIG_ENDIAN__) ++#if (__BYTE_ORDER == __BIG_ENDIAN) + unsigned long int hi; + unsigned long int lo; + #else +Index: uclibc/libm/powerpc/s_frexp.c +=================================================================== +--- uclibc/libm/powerpc/s_frexp.c (revision 12879) ++++ uclibc/libm/powerpc/s_frexp.c (working copy) +@@ -21,13 +21,14 @@ + + #include <limits.h> + #include <math.h> ++#include <endian.h> + + static const double two54 = 1.80143985094819840000e+16; /* 0x43500000, 0x00000000 */ + + typedef union + { + struct { +-#if defined(__BIG_ENDIAN__) ++#if (__BYTE_ORDER == __BIG_ENDIAN) + unsigned long int hi; + unsigned long int lo; + #else +Index: uclibc/libm/powerpc/s_modf.c +=================================================================== +--- uclibc/libm/powerpc/s_modf.c (revision 12879) ++++ uclibc/libm/powerpc/s_modf.c (working copy) +@@ -45,13 +45,14 @@ + + #include <limits.h> + #include <math.h> ++#include <endian.h> + + #define SET_INVALID 0x01000000UL + + typedef union + { + struct { +-#if defined(__BIG_ENDIAN__) ++#if (__BYTE_ORDER == __BIG_ENDIAN) + unsigned long int hi; + unsigned long int lo; + #else +Index: uclibc/libm/powerpc/w_scalb.c +=================================================================== +--- uclibc/libm/powerpc/w_scalb.c (revision 12879) ++++ uclibc/libm/powerpc/w_scalb.c (working copy) +@@ -19,10 +19,12 @@ + ** + ***********************************************************************/ + ++#include <endian.h> ++ + typedef union + { + struct { +-#if defined(__BIG_ENDIAN__) ++#if (__BYTE_ORDER == __BIG_ENDIAN) + unsigned long int hi; + unsigned long int lo; + #else +Index: uclibc/libc/string/sh64/strcpy.S +=================================================================== +--- uclibc/libc/string/sh64/strcpy.S (revision 12879) ++++ uclibc/libc/string/sh64/strcpy.S (working copy) +@@ -6,7 +6,9 @@ + ! + ! SH5 code Copyright 2002 SuperH Ltd. + +-#ifdef __LITTLE_ENDIAN__ ++#include <endian.h> ++ ++#if __BYTE_ORDER == __LITTLE_ENDIAN + #define SHHI shlld + #define SHLO shlrd + #else +@@ -67,7 +69,7 @@ + add r5, r63, r4 + addi r0, 8, r0 + shortstring: +-#ifndef __LITTLE_ENDIAN__ ++#if __BYTE_ORDER != __LITTLE_ENDIAN + pta/l shortstring2,tr1 + byterev r4,r4 + #endif +Index: uclibc/libc/string/sh64/memset.S +=================================================================== +--- uclibc/libc/string/sh64/memset.S (revision 12879) ++++ uclibc/libc/string/sh64/memset.S (working copy) +@@ -9,7 +9,9 @@ + ! Copyright 2002 SuperH Ltd. + ! + +-#ifdef __LITTLE_ENDIAN__ ++#include <endian.h> ++ ++#if __BYTE_ORDER == __LITTLE_ENDIAN + #define SHHI shlld + #define SHLO shlrd + #else +Index: uclibc/libc/sysdeps/linux/sh/bits/kernel_stat.h +=================================================================== +--- uclibc/libc/sysdeps/linux/sh/bits/kernel_stat.h (revision 12879) ++++ uclibc/libc/sysdeps/linux/sh/bits/kernel_stat.h (working copy) +@@ -30,10 +30,10 @@ + }; + + struct kernel_stat64 { +-#if defined(__BIG_ENDIAN__) ++#if (__BYTE_ORDER == __BIG_ENDIAN) + unsigned char __pad0b[6]; + unsigned short st_dev; +-#elif defined(__LITTLE_ENDIAN__) ++#elif (__BYTE_ORDER == __LITTLE_ENDIAN) + unsigned short st_dev; + unsigned char __pad0b[6]; + #else +@@ -48,7 +48,7 @@ + unsigned long st_uid; + unsigned long st_gid; + +-#if defined(__BIG_ENDIAN__) ++#if (__BYTE_ORDER == __BIG_ENDIAN) + unsigned char __pad3b[6]; + unsigned short st_rdev; + #else /* Must be little */ +@@ -60,7 +60,7 @@ + long long st_size; + unsigned long st_blksize; + +-#if defined(__BIG_ENDIAN__) ++#if (__BYTE_ORDER == __BIG_ENDIAN) + unsigned long __pad4; /* Future possible st_blocks hi bits */ + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + #else /* Must be little */ diff --git a/toolchain/uClibc/uClibc-0.9.28-mutex-cancel.patch b/toolchain/uClibc/uClibc-0.9.28-mutex-cancel.patch new file mode 100644 index 000000000..5e56a7397 --- /dev/null +++ b/toolchain/uClibc/uClibc-0.9.28-mutex-cancel.patch @@ -0,0 +1,8631 @@ +diff --git a/include/printf.h b/include/printf.h +index 340b6cb..2dea58f 100644 +--- a/include/printf.h ++++ b/include/printf.h +@@ -75,6 +75,7 @@ struct printf_info + unsigned int is_short:1; /* h flag. */ + unsigned int is_long:1; /* l flag. */ + unsigned int is_long_double:1;/* L flag. */ ++ unsigned int __padding:20;/* non-gnu -- total of 32 bits on 32bit arch */ + + #elif __BYTE_ORDER == __BIG_ENDIAN + +diff --git a/include/pthread.h b/include/pthread.h +index 8c01172..cee112b 100644 +--- a/include/pthread.h ++++ b/include/pthread.h +@@ -644,7 +644,8 @@ extern void _pthread_cleanup_pop (struct + /* Install a cleanup handler as pthread_cleanup_push does, but also + saves the current cancellation type and set it to deferred cancellation. */ + +-#ifdef __USE_GNU ++/* #ifdef __USE_GNU */ ++#if defined(__USE_GNU) || defined(_LIBC) + # define pthread_cleanup_push_defer_np(routine,arg) \ + { struct _pthread_cleanup_buffer _buffer; \ + _pthread_cleanup_push_defer (&_buffer, (routine), (arg)); +diff --git a/libc/inet/getnetent.c b/libc/inet/getnetent.c +index 181c5ad..659bf5d 100644 +--- a/libc/inet/getnetent.c ++++ b/libc/inet/getnetent.c +@@ -22,18 +22,9 @@ + #include <netdb.h> + #include <arpa/inet.h> + ++#include <bits/uClibc_mutex.h> + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER; +-# define LOCK __pthread_mutex_lock(&mylock) +-# define UNLOCK __pthread_mutex_unlock(&mylock); +-#else +-# define LOCK +-# define UNLOCK +-#endif +- +- ++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + + #define MAXALIASES 35 + static const char NETDB[] = _PATH_NETWORKS; +@@ -46,25 +37,25 @@ int _net_stayopen; + + void setnetent(int f) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (netf == NULL) +- netf = fopen(NETDB, "r" ); ++ netf = fopen(NETDB, "r" ); + else +- rewind(netf); ++ rewind(netf); + _net_stayopen |= f; +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + return; + } + + void endnetent(void) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (netf) { +- fclose(netf); +- netf = NULL; ++ fclose(netf); ++ netf = NULL; + } + _net_stayopen = 0; +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + + static char * any(register char *cp, char *match) +@@ -72,10 +63,10 @@ static char * any(register char *cp, cha + register char *mp, c; + + while ((c = *cp)) { +- for (mp = match; *mp; mp++) +- if (*mp == c) +- return (cp); +- cp++; ++ for (mp = match; *mp; mp++) ++ if (*mp == c) ++ return (cp); ++ cp++; + } + return ((char *)0); + } +@@ -84,59 +75,62 @@ struct netent * getnetent(void) + { + char *p; + register char *cp, **q; ++ struct netent *rv = NULL; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (netf == NULL && (netf = fopen(NETDB, "r" )) == NULL) { +- UNLOCK; +- return (NULL); ++ goto DONE; + } +-again: ++ again: + + if (!line) { +- line = malloc(BUFSIZ + 1); +- if (!line) +- abort(); ++ line = malloc(BUFSIZ + 1); ++ if (!line) ++ abort(); + } + + p = fgets(line, BUFSIZ, netf); + if (p == NULL) { +- UNLOCK; +- return (NULL); ++ goto DONE; + } + if (*p == '#') +- goto again; ++ goto again; + cp = any(p, "#\n"); + if (cp == NULL) +- goto again; ++ goto again; + *cp = '\0'; + net.n_name = p; + cp = any(p, " \t"); + if (cp == NULL) +- goto again; ++ goto again; + *cp++ = '\0'; + while (*cp == ' ' || *cp == '\t') +- cp++; ++ cp++; + p = any(cp, " \t"); + if (p != NULL) +- *p++ = '\0'; ++ *p++ = '\0'; + net.n_net = inet_network(cp); + net.n_addrtype = AF_INET; + q = net.n_aliases = net_aliases; + if (p != NULL) +- cp = p; ++ cp = p; + while (cp && *cp) { +- if (*cp == ' ' || *cp == '\t') { +- cp++; +- continue; +- } +- if (q < &net_aliases[MAXALIASES - 1]) +- *q++ = cp; +- cp = any(cp, " \t"); +- if (cp != NULL) +- *cp++ = '\0'; ++ if (*cp == ' ' || *cp == '\t') { ++ cp++; ++ continue; ++ } ++ if (q < &net_aliases[MAXALIASES - 1]) ++ *q++ = cp; ++ cp = any(cp, " \t"); ++ if (cp != NULL) ++ *cp++ = '\0'; + } + *q = NULL; +- UNLOCK; +- return (&net); ++ ++ rv = &net; ++ ++ DONE: ++ __UCLIBC_MUTEX_UNLOCK(mylock); ++ return rv; + } + +diff --git a/libc/inet/getproto.c b/libc/inet/getproto.c +index c9f35f1..3665d89 100644 +--- a/libc/inet/getproto.c ++++ b/libc/inet/getproto.c +@@ -62,17 +62,9 @@ + #include <string.h> + #include <errno.h> + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-static pthread_mutex_t mylock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +-# define LOCK __pthread_mutex_lock(&mylock) +-# define UNLOCK __pthread_mutex_unlock(&mylock); +-#else +-# define LOCK +-# define UNLOCK +-#endif +- ++#include <bits/uClibc_mutex.h> + ++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + + #define MAXALIASES 35 + #define SBUFSIZE (BUFSIZ + 1 + (sizeof(char *) * MAXALIASES)) +@@ -85,109 +77,114 @@ static int proto_stayopen; + static void __initbuf(void) + { + if (!static_aliases) { +- static_aliases = malloc(SBUFSIZE); +- if (!static_aliases) +- abort(); ++ static_aliases = malloc(SBUFSIZE); ++ if (!static_aliases) ++ abort(); + } + } + + void setprotoent(int f) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (protof == NULL) +- protof = fopen(_PATH_PROTOCOLS, "r" ); ++ protof = fopen(_PATH_PROTOCOLS, "r" ); + else +- rewind(protof); ++ rewind(protof); + proto_stayopen |= f; +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + + void endprotoent(void) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (protof) { +- fclose(protof); +- protof = NULL; ++ fclose(protof); ++ protof = NULL; + } + proto_stayopen = 0; +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + + int getprotoent_r(struct protoent *result_buf, +- char *buf, size_t buflen, +- struct protoent **result) ++ char *buf, size_t buflen, ++ struct protoent **result) + { + char *p; + register char *cp, **q; + char **proto_aliases; + char *line; ++ int rv; + + *result = NULL; + + if (buflen < sizeof(*proto_aliases)*MAXALIASES) { +- errno=ERANGE; +- return errno; ++ errno=ERANGE; ++ return errno; + } +- LOCK; ++ ++ __UCLIBC_MUTEX_LOCK(mylock); + proto_aliases=(char **)buf; + buf+=sizeof(*proto_aliases)*MAXALIASES; + buflen-=sizeof(*proto_aliases)*MAXALIASES; + + if (buflen < BUFSIZ+1) { +- UNLOCK; +- errno=ERANGE; +- return errno; ++ errno=rv=ERANGE; ++ goto DONE; + } + line=buf; + buf+=BUFSIZ+1; + buflen-=BUFSIZ+1; + + if (protof == NULL && (protof = fopen(_PATH_PROTOCOLS, "r" )) == NULL) { +- UNLOCK; +- return errno; ++ rv=errno; ++ goto DONE; + } +-again: ++ again: + if ((p = fgets(line, BUFSIZ, protof)) == NULL) { +- UNLOCK; +- return TRY_AGAIN; ++ rv=TRY_AGAIN; ++ goto DONE; + } + + if (*p == '#') +- goto again; ++ goto again; + cp = strpbrk(p, "#\n"); + if (cp == NULL) +- goto again; ++ goto again; + *cp = '\0'; + result_buf->p_name = p; + cp = strpbrk(p, " \t"); + if (cp == NULL) +- goto again; ++ goto again; + *cp++ = '\0'; + while (*cp == ' ' || *cp == '\t') +- cp++; ++ cp++; + p = strpbrk(cp, " \t"); + if (p != NULL) +- *p++ = '\0'; ++ *p++ = '\0'; + result_buf->p_proto = atoi(cp); + q = result_buf->p_aliases = proto_aliases; + if (p != NULL) { +- cp = p; +- while (cp && *cp) { +- if (*cp == ' ' || *cp == '\t') { +- cp++; +- continue; +- } +- if (q < &proto_aliases[MAXALIASES - 1]) +- *q++ = cp; +- cp = strpbrk(cp, " \t"); +- if (cp != NULL) +- *cp++ = '\0'; +- } ++ cp = p; ++ while (cp && *cp) { ++ if (*cp == ' ' || *cp == '\t') { ++ cp++; ++ continue; ++ } ++ if (q < &proto_aliases[MAXALIASES - 1]) ++ *q++ = cp; ++ cp = strpbrk(cp, " \t"); ++ if (cp != NULL) ++ *cp++ = '\0'; ++ } + } + *q = NULL; + *result=result_buf; +- UNLOCK; +- return 0; ++ ++ rv = 0; ++ ++ DONE: ++ __UCLIBC_MUTEX_UNLOCK(mylock); ++ return rv; + } + + struct protoent * getprotoent(void) +@@ -201,26 +198,26 @@ struct protoent * getprotoent(void) + + + int getprotobyname_r(const char *name, +- struct protoent *result_buf, +- char *buf, size_t buflen, +- struct protoent **result) ++ struct protoent *result_buf, ++ char *buf, size_t buflen, ++ struct protoent **result) + { + register char **cp; + int ret; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + setprotoent(proto_stayopen); + while (!(ret=getprotoent_r(result_buf, buf, buflen, result))) { +- if (strcmp(result_buf->p_name, name) == 0) +- break; +- for (cp = result_buf->p_aliases; *cp != 0; cp++) +- if (strcmp(*cp, name) == 0) +- goto found; ++ if (strcmp(result_buf->p_name, name) == 0) ++ break; ++ for (cp = result_buf->p_aliases; *cp != 0; cp++) ++ if (strcmp(*cp, name) == 0) ++ goto found; + } +-found: ++ found: + if (!proto_stayopen) +- endprotoent(); +- UNLOCK; ++ endprotoent(); ++ __UCLIBC_MUTEX_UNLOCK(mylock); + return *result?0:ret; + } + +@@ -236,20 +233,20 @@ struct protoent * getprotobyname(const c + + + int getprotobynumber_r (int proto_num, +- struct protoent *result_buf, +- char *buf, size_t buflen, +- struct protoent **result) ++ struct protoent *result_buf, ++ char *buf, size_t buflen, ++ struct protoent **result) + { + int ret; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + setprotoent(proto_stayopen); + while (!(ret=getprotoent_r(result_buf, buf, buflen, result))) +- if (result_buf->p_proto == proto_num) +- break; ++ if (result_buf->p_proto == proto_num) ++ break; + if (!proto_stayopen) +- endprotoent(); +- UNLOCK; ++ endprotoent(); ++ __UCLIBC_MUTEX_UNLOCK(mylock); + return *result?0:ret; + } + +diff --git a/libc/inet/getservice.c b/libc/inet/getservice.c +index cbe5c50..b666057 100644 +--- a/libc/inet/getservice.c ++++ b/libc/inet/getservice.c +@@ -65,20 +65,9 @@ + #include <arpa/inet.h> + #include <errno.h> + ++#include <bits/uClibc_mutex.h> + +- +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-static pthread_mutex_t mylock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +-# define LOCK __pthread_mutex_lock(&mylock) +-# define UNLOCK __pthread_mutex_unlock(&mylock); +-#else +-# define LOCK +-# define UNLOCK +-#endif +- +- +- ++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + + #define MAXALIASES 35 + #define SBUFSIZE (BUFSIZ + 1 + (sizeof(char *) * MAXALIASES)) +@@ -91,32 +80,32 @@ static int serv_stayopen; + static void __initbuf(void) + { + if (!servbuf) { +- servbuf = malloc(SBUFSIZE); +- if (!servbuf) +- abort(); ++ servbuf = malloc(SBUFSIZE); ++ if (!servbuf) ++ abort(); + } + } + + void setservent(int f) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (servf == NULL) +- servf = fopen(_PATH_SERVICES, "r" ); ++ servf = fopen(_PATH_SERVICES, "r" ); + else +- rewind(servf); ++ rewind(servf); + serv_stayopen |= f; +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + + void endservent(void) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (servf) { +- fclose(servf); +- servf = NULL; ++ fclose(servf); ++ servf = NULL; + } + serv_stayopen = 0; +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + + struct servent * getservent(void) +@@ -149,127 +138,129 @@ struct servent * getservbyport(int port, + } + + int getservent_r(struct servent * result_buf, +- char * buf, size_t buflen, +- struct servent ** result) ++ char * buf, size_t buflen, ++ struct servent ** result) + { + char *p; + register char *cp, **q; + char **serv_aliases; + char *line; ++ int rv; + + *result=NULL; + + if (buflen < sizeof(*serv_aliases)*MAXALIASES) { +- errno=ERANGE; +- return errno; ++ errno=ERANGE; ++ return errno; + } +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + serv_aliases=(char **)buf; + buf+=sizeof(*serv_aliases)*MAXALIASES; + buflen-=sizeof(*serv_aliases)*MAXALIASES; + + if (buflen < BUFSIZ+1) { +- UNLOCK; +- errno=ERANGE; +- return errno; ++ errno=rv=ERANGE; ++ goto DONE; + } + line=buf; + buf+=BUFSIZ+1; + buflen-=BUFSIZ+1; + + if (servf == NULL && (servf = fopen(_PATH_SERVICES, "r" )) == NULL) { +- UNLOCK; +- errno=EIO; +- return errno; ++ errno=rv=EIO; ++ goto DONE; + } +-again: ++ again: + if ((p = fgets(line, BUFSIZ, servf)) == NULL) { +- UNLOCK; +- errno=EIO; +- return errno; ++ errno=rv=EIO; ++ goto DONE; + } + if (*p == '#') +- goto again; ++ goto again; + cp = strpbrk(p, "#\n"); + if (cp == NULL) +- goto again; ++ goto again; + *cp = '\0'; + result_buf->s_name = p; + p = strpbrk(p, " \t"); + if (p == NULL) +- goto again; ++ goto again; + *p++ = '\0'; + while (*p == ' ' || *p == '\t') +- p++; ++ p++; + cp = strpbrk(p, ",/"); + if (cp == NULL) +- goto again; ++ goto again; + *cp++ = '\0'; + result_buf->s_port = htons((u_short)atoi(p)); + result_buf->s_proto = cp; + q = result_buf->s_aliases = serv_aliases; + cp = strpbrk(cp, " \t"); + if (cp != NULL) +- *cp++ = '\0'; ++ *cp++ = '\0'; + while (cp && *cp) { +- if (*cp == ' ' || *cp == '\t') { +- cp++; +- continue; +- } +- if (q < &serv_aliases[MAXALIASES - 1]) +- *q++ = cp; +- cp = strpbrk(cp, " \t"); +- if (cp != NULL) +- *cp++ = '\0'; ++ if (*cp == ' ' || *cp == '\t') { ++ cp++; ++ continue; ++ } ++ if (q < &serv_aliases[MAXALIASES - 1]) ++ *q++ = cp; ++ cp = strpbrk(cp, " \t"); ++ if (cp != NULL) ++ *cp++ = '\0'; + } + *q = NULL; + *result=result_buf; +- UNLOCK; +- return 0; ++ ++ rv = 0; ++ ++ DONE: ++ __UCLIBC_MUTEX_UNLOCK(mylock); ++ return rv; + } + + int getservbyname_r(const char *name, const char *proto, +- struct servent * result_buf, char * buf, size_t buflen, +- struct servent ** result) ++ struct servent * result_buf, char * buf, size_t buflen, ++ struct servent ** result) + { + register char **cp; + int ret; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + setservent(serv_stayopen); + while (!(ret=getservent_r(result_buf, buf, buflen, result))) { +- if (strcmp(name, result_buf->s_name) == 0) +- goto gotname; +- for (cp = result_buf->s_aliases; *cp; cp++) +- if (strcmp(name, *cp) == 0) +- goto gotname; +- continue; +-gotname: +- if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0) +- break; ++ if (strcmp(name, result_buf->s_name) == 0) ++ goto gotname; ++ for (cp = result_buf->s_aliases; *cp; cp++) ++ if (strcmp(name, *cp) == 0) ++ goto gotname; ++ continue; ++ gotname: ++ if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0) ++ break; + } + if (!serv_stayopen) +- endservent(); +- UNLOCK; ++ endservent(); ++ __UCLIBC_MUTEX_UNLOCK(mylock); + return *result?0:ret; + } + + int getservbyport_r(int port, const char *proto, +- struct servent * result_buf, char * buf, +- size_t buflen, struct servent ** result) ++ struct servent * result_buf, char * buf, ++ size_t buflen, struct servent ** result) + { + int ret; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + setservent(serv_stayopen); + while (!(ret=getservent_r(result_buf, buf, buflen, result))) { +- if (result_buf->s_port != port) +- continue; +- if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0) +- break; ++ if (result_buf->s_port != port) ++ continue; ++ if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0) ++ break; + } + if (!serv_stayopen) +- endservent(); +- UNLOCK; ++ endservent(); ++ __UCLIBC_MUTEX_UNLOCK(mylock); + return *result?0:ret; + } +diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c +index 27b60ef..0f583ab 100644 +--- a/libc/inet/resolv.c ++++ b/libc/inet/resolv.c +@@ -7,7 +7,7 @@ + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. +-*/ ++ */ + + /* + * Portions Copyright (c) 1985, 1993 +@@ -153,6 +153,11 @@ + #include <sys/utsname.h> + #include <sys/un.h> + ++#include <bits/uClibc_mutex.h> ++ ++__UCLIBC_MUTEX_EXTERN(__resolv_lock); ++ ++ + #define MAX_RECURSE 5 + #define REPLY_TIMEOUT 10 + #define MAX_RETRIES 3 +@@ -180,18 +185,6 @@ extern char * __nameserver[MAX_SERVERS]; + extern int __searchdomains; + extern char * __searchdomain[MAX_SEARCH]; + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-extern pthread_mutex_t __resolv_lock; +-# define BIGLOCK __pthread_mutex_lock(&__resolv_lock) +-# define BIGUNLOCK __pthread_mutex_unlock(&__resolv_lock); +-#else +-# define BIGLOCK +-# define BIGUNLOCK +-#endif +- +- +- + /* Structs */ + struct resolv_header { + int id; +@@ -229,49 +222,49 @@ enum etc_hosts_action { + + /* function prototypes */ + extern int __get_hosts_byname_r(const char * name, int type, +- struct hostent * result_buf, +- char * buf, size_t buflen, +- struct hostent ** result, +- int * h_errnop); ++ struct hostent * result_buf, ++ char * buf, size_t buflen, ++ struct hostent ** result, ++ int * h_errnop); + extern int __get_hosts_byaddr_r(const char * addr, int len, int type, +- struct hostent * result_buf, +- char * buf, size_t buflen, +- struct hostent ** result, +- int * h_errnop); ++ struct hostent * result_buf, ++ char * buf, size_t buflen, ++ struct hostent ** result, ++ int * h_errnop); + extern void __open_etc_hosts(FILE **fp); + extern int __read_etc_hosts_r(FILE *fp, const char * name, int type, +- enum etc_hosts_action action, +- struct hostent * result_buf, +- char * buf, size_t buflen, +- struct hostent ** result, +- int * h_errnop); ++ enum etc_hosts_action action, ++ struct hostent * result_buf, ++ char * buf, size_t buflen, ++ struct hostent ** result, ++ int * h_errnop); + extern int __dns_lookup(const char * name, int type, int nscount, +- char ** nsip, unsigned char ** outpacket, struct resolv_answer * a); ++ char ** nsip, unsigned char ** outpacket, struct resolv_answer * a); + + extern int __encode_dotted(const char * dotted, unsigned char * dest, int maxlen); + extern int __decode_dotted(const unsigned char * message, int offset, +- char * dest, int maxlen); ++ char * dest, int maxlen); + extern int __length_dotted(const unsigned char * message, int offset); + extern int __encode_header(struct resolv_header * h, unsigned char * dest, int maxlen); + extern int __decode_header(unsigned char * data, struct resolv_header * h); + extern int __encode_question(struct resolv_question * q, +- unsigned char * dest, int maxlen); ++ unsigned char * dest, int maxlen); + extern int __decode_question(unsigned char * message, int offset, +- struct resolv_question * q); ++ struct resolv_question * q); + extern int __encode_answer(struct resolv_answer * a, +- unsigned char * dest, int maxlen); ++ unsigned char * dest, int maxlen); + extern int __decode_answer(unsigned char * message, int offset, +- struct resolv_answer * a); ++ struct resolv_answer * a); + extern int __length_question(unsigned char * message, int offset); + extern int __open_nameservers(void); + extern void __close_nameservers(void); + extern int __dn_expand(const u_char *, const u_char *, const u_char *, +- char *, int); ++ char *, int); + extern int __ns_name_uncompress(const u_char *, const u_char *, +- const u_char *, char *, size_t); ++ const u_char *, char *, size_t); + extern int __ns_name_ntop(const u_char *, char *, size_t); + extern int __ns_name_unpack(const u_char *, const u_char *, const u_char *, +- u_char *, size_t); ++ u_char *, size_t); + + + #ifdef L_encodeh +@@ -361,7 +354,7 @@ int __encode_dotted(const char *dotted, + This routine understands compressed data. */ + + int __decode_dotted(const unsigned char *data, int offset, +- char *dest, int maxlen) ++ char *dest, int maxlen) + { + int l; + int measure = 1; +@@ -435,7 +428,7 @@ int __length_dotted(const unsigned char + + #ifdef L_encodeq + int __encode_question(struct resolv_question *q, +- unsigned char *dest, int maxlen) ++ unsigned char *dest, int maxlen) + { + int i; + +@@ -460,7 +453,7 @@ int __encode_question(struct resolv_ques + + #ifdef L_decodeq + int __decode_question(unsigned char *message, int offset, +- struct resolv_question *q) ++ struct resolv_question *q) + { + char temp[256]; + int i; +@@ -525,7 +518,7 @@ int __encode_answer(struct resolv_answer + + #ifdef L_decodea + int __decode_answer(unsigned char *message, int offset, +- struct resolv_answer *a) ++ struct resolv_answer *a) + { + char temp[256]; + int i; +@@ -557,11 +550,11 @@ int __decode_answer(unsigned char *messa + + #ifdef L_encodep + int __encode_packet(struct resolv_header *h, +- struct resolv_question **q, +- struct resolv_answer **an, +- struct resolv_answer **ns, +- struct resolv_answer **ar, +- unsigned char *dest, int maxlen) ++ struct resolv_question **q, ++ struct resolv_answer **an, ++ struct resolv_answer **ns, ++ struct resolv_answer **ar, ++ unsigned char *dest, int maxlen) + { + int i, total = 0; + int j; +@@ -621,7 +614,7 @@ int __decode_packet(unsigned char *data, + + #ifdef L_formquery + int __form_query(int id, const char *name, int type, unsigned char *packet, +- int maxlen) ++ int maxlen) + { + struct resolv_header h; + struct resolv_question q; +@@ -649,14 +642,7 @@ int __form_query(int id, const char *nam + + #ifdef L_dnslookup + +-#ifdef __UCLIBC_HAS_THREADS__ +-static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER; +-# define LOCK __pthread_mutex_lock(&mylock) +-# define UNLOCK __pthread_mutex_unlock(&mylock); +-#else +-# define LOCK +-# define UNLOCK +-#endif ++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + + /* Just for the record, having to lock __dns_lookup() just for these two globals + * is pretty lame. I think these two variables can probably be de-global-ized, +@@ -665,7 +651,7 @@ static pthread_mutex_t mylock = PTHREAD_ + static int ns=0, id=1; + + int __dns_lookup(const char *name, int type, int nscount, char **nsip, +- unsigned char **outpacket, struct resolv_answer *a) ++ unsigned char **outpacket, struct resolv_answer *a) + { + int i, j, len, fd, pos, rc; + struct timeval tv; +@@ -693,10 +679,10 @@ int __dns_lookup(const char *name, int t + DPRINTF("Looking up type %d answer for '%s'\n", type, name); + + /* Mess with globals while under lock */ +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + local_ns = ns % nscount; + local_id = id; +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + + while (retries < MAX_RETRIES) { + if (fd != -1) +@@ -722,13 +708,13 @@ int __dns_lookup(const char *name, int t + + strncpy(lookup,name,MAXDNAME); + if (variant >= 0) { +- BIGLOCK; +- if (variant < __searchdomains) { +- strncat(lookup,".", MAXDNAME); +- strncat(lookup,__searchdomain[variant], MAXDNAME); +- } +- BIGUNLOCK; +- } ++ __UCLIBC_MUTEX_LOCK(__resolv_lock); ++ if (variant < __searchdomains) { ++ strncat(lookup,".", MAXDNAME); ++ strncat(lookup,__searchdomain[variant], MAXDNAME); ++ } ++ __UCLIBC_MUTEX_UNLOCK(__resolv_lock); ++ } + DPRINTF("lookup name: %s\n", lookup); + q.dotted = (char *)lookup; + q.qtype = type; +@@ -750,7 +736,7 @@ int __dns_lookup(const char *name, int t + fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + #endif + if (fd < 0) { +- retries++; ++ retries++; + continue; + } + +@@ -772,11 +758,11 @@ int __dns_lookup(const char *name, int t + #endif + if (rc < 0) { + if (errno == ENETUNREACH) { +- /* routing error, presume not transient */ +- goto tryall; ++ /* routing error, presume not transient */ ++ goto tryall; + } else +- /* retry */ +- retries++; ++ /* retry */ ++ retries++; + continue; + } + +@@ -838,55 +824,55 @@ int __dns_lookup(const char *name, int t + + first_answer = 1; + for (j=0;j<h.ancount;j++,pos += i) +- { +- i = __decode_answer(packet, pos, &ma); ++ { ++ i = __decode_answer(packet, pos, &ma); + +- if (i<0) { +- DPRINTF("failed decode %d\n", i); +- goto again; +- } ++ if (i<0) { ++ DPRINTF("failed decode %d\n", i); ++ goto again; ++ } + +- if ( first_answer ) +- { +- ma.buf = a->buf; +- ma.buflen = a->buflen; +- ma.add_count = a->add_count; +- memcpy(a, &ma, sizeof(ma)); +- if (a->atype != T_SIG && (0 == a->buf || (type != T_A && type != T_AAAA))) +- { +- break; +- } +- if (a->atype != type) +- { +- free(a->dotted); +- continue; +- } +- a->add_count = h.ancount - j - 1; +- if ((a->rdlength + sizeof(struct in_addr*)) * a->add_count > a->buflen) +- { +- break; +- } +- a->add_count = 0; +- first_answer = 0; +- } +- else +- { +- free(ma.dotted); +- if (ma.atype != type) +- { +- continue; +- } +- if (a->rdlength != ma.rdlength) +- { +- free(a->dotted); +- DPRINTF("Answer address len(%u) differs from original(%u)\n", +- ma.rdlength, a->rdlength); +- goto again; ++ if ( first_answer ) ++ { ++ ma.buf = a->buf; ++ ma.buflen = a->buflen; ++ ma.add_count = a->add_count; ++ memcpy(a, &ma, sizeof(ma)); ++ if (a->atype != T_SIG && (0 == a->buf || (type != T_A && type != T_AAAA))) ++ { ++ break; ++ } ++ if (a->atype != type) ++ { ++ free(a->dotted); ++ continue; ++ } ++ a->add_count = h.ancount - j - 1; ++ if ((a->rdlength + sizeof(struct in_addr*)) * a->add_count > a->buflen) ++ { ++ break; ++ } ++ a->add_count = 0; ++ first_answer = 0; ++ } ++ else ++ { ++ free(ma.dotted); ++ if (ma.atype != type) ++ { ++ continue; ++ } ++ if (a->rdlength != ma.rdlength) ++ { ++ free(a->dotted); ++ DPRINTF("Answer address len(%u) differs from original(%u)\n", ++ ma.rdlength, a->rdlength); ++ goto again; ++ } ++ memcpy(a->buf + (a->add_count * ma.rdlength), ma.rdata, ma.rdlength); ++ ++a->add_count; ++ } + } +- memcpy(a->buf + (a->add_count * ma.rdlength), ma.rdata, ma.rdlength); +- ++a->add_count; +- } +- } + + DPRINTF("Answer name = |%s|\n", a->dotted); + DPRINTF("Answer type = |%d|\n", a->atype); +@@ -900,48 +886,48 @@ int __dns_lookup(const char *name, int t + free(lookup); + + /* Mess with globals while under lock */ +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + ns = local_ns; + id = local_id; +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + + return (len); /* success! */ + +- tryall: ++ tryall: + /* if there are other nameservers, give them a go, + otherwise return with error */ + { + variant = -1; +- local_ns = (local_ns + 1) % nscount; +- if (local_ns == 0) +- retries++; ++ local_ns = (local_ns + 1) % nscount; ++ if (local_ns == 0) ++ retries++; + +- continue; ++ continue; + } + +- again: ++ again: + /* if there are searchdomains, try them or fallback as passed */ + { + int sdomains; +- BIGLOCK; ++ __UCLIBC_MUTEX_LOCK(__resolv_lock); + sdomains=__searchdomains; +- BIGUNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + + if (variant < sdomains - 1) { +- /* next search */ +- variant++; ++ /* next search */ ++ variant++; + } else { +- /* next server, first search */ +- local_ns = (local_ns + 1) % nscount; +- if (local_ns == 0) +- retries++; ++ /* next server, first search */ ++ local_ns = (local_ns + 1) % nscount; ++ if (local_ns == 0) ++ retries++; + +- variant = -1; ++ variant = -1; + } + } + } + +-fail: ++ fail: + if (fd != -1) + close(fd); + if (lookup) +@@ -951,10 +937,10 @@ fail: + h_errno = NETDB_INTERNAL; + /* Mess with globals while under lock */ + if (local_ns != -1) { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + ns = local_ns; + id = local_id; +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + return -1; + } +@@ -966,9 +952,8 @@ int __nameservers; + char * __nameserver[MAX_SERVERS]; + int __searchdomains; + char * __searchdomain[MAX_SEARCH]; +-#ifdef __UCLIBC_HAS_THREADS__ +-pthread_mutex_t __resolv_lock = PTHREAD_MUTEX_INITIALIZER; +-#endif ++ ++__UCLIBC_MUTEX_INIT(__resolv_lock, PTHREAD_MUTEX_INITIALIZER); + + /* + * we currently read formats not quite the same as that on normal +@@ -982,60 +967,63 @@ int __open_nameservers() + #define RESOLV_ARGS 5 + char szBuffer[128], *p, *argv[RESOLV_ARGS]; + int argc; ++ int rv = 0; + +- BIGLOCK; ++ __UCLIBC_MUTEX_LOCK(__resolv_lock); + if (__nameservers > 0) { +- BIGUNLOCK; +- return 0; ++ goto DONE; + } + + if ((fp = fopen("/etc/resolv.conf", "r")) || +- (fp = fopen("/etc/config/resolv.conf", "r"))) +- { +- +- while (fgets(szBuffer, sizeof(szBuffer), fp) != NULL) { ++ (fp = fopen("/etc/config/resolv.conf", "r"))) ++ { + +- for (p = szBuffer; *p && isspace(*p); p++) +- /* skip white space */; +- if (*p == '\0' || *p == '\n' || *p == '#') /* skip comments etc */ +- continue; +- argc = 0; +- while (*p && argc < RESOLV_ARGS) { +- argv[argc++] = p; +- while (*p && !isspace(*p) && *p != '\n') +- p++; +- while (*p && (isspace(*p) || *p == '\n')) /* remove spaces */ +- *p++ = '\0'; +- } ++ while (fgets(szBuffer, sizeof(szBuffer), fp) != NULL) { + +- if (strcmp(argv[0], "nameserver") == 0) { +- for (i = 1; i < argc && __nameservers < MAX_SERVERS; i++) { +- __nameserver[__nameservers++] = strdup(argv[i]); +- DPRINTF("adding nameserver %s\n", argv[i]); ++ for (p = szBuffer; *p && isspace(*p); p++) ++ /* skip white space */; ++ if (*p == '\0' || *p == '\n' || *p == '#') /* skip comments etc */ ++ continue; ++ argc = 0; ++ while (*p && argc < RESOLV_ARGS) { ++ argv[argc++] = p; ++ while (*p && !isspace(*p) && *p != '\n') ++ p++; ++ while (*p && (isspace(*p) || *p == '\n')) /* remove spaces */ ++ *p++ = '\0'; + } +- } + +- /* domain and search are mutually exclusive, the last one wins */ +- if (strcmp(argv[0],"domain")==0 || strcmp(argv[0],"search")==0) { +- while (__searchdomains > 0) { +- free(__searchdomain[--__searchdomains]); +- __searchdomain[__searchdomains] = NULL; ++ if (strcmp(argv[0], "nameserver") == 0) { ++ for (i = 1; i < argc && __nameservers < MAX_SERVERS; i++) { ++ __nameserver[__nameservers++] = strdup(argv[i]); ++ DPRINTF("adding nameserver %s\n", argv[i]); ++ } + } +- for (i=1; i < argc && __searchdomains < MAX_SEARCH; i++) { +- __searchdomain[__searchdomains++] = strdup(argv[i]); +- DPRINTF("adding search %s\n", argv[i]); ++ ++ /* domain and search are mutually exclusive, the last one wins */ ++ if (strcmp(argv[0],"domain")==0 || strcmp(argv[0],"search")==0) { ++ while (__searchdomains > 0) { ++ free(__searchdomain[--__searchdomains]); ++ __searchdomain[__searchdomains] = NULL; ++ } ++ for (i=1; i < argc && __searchdomains < MAX_SEARCH; i++) { ++ __searchdomain[__searchdomains++] = strdup(argv[i]); ++ DPRINTF("adding search %s\n", argv[i]); ++ } + } + } ++ fclose(fp); ++ DPRINTF("nameservers = %d\n", __nameservers); ++ goto DONE; + } +- fclose(fp); +- DPRINTF("nameservers = %d\n", __nameservers); +- BIGUNLOCK; +- return 0; +- } + DPRINTF("failed to open %s\n", "resolv.conf"); + h_errno = NO_RECOVERY; +- BIGUNLOCK; +- return -1; ++ ++ rv = -1; ++ ++ DONE: ++ __UCLIBC_MUTEX_UNLOCK(__resolv_lock); ++ return rv; + } + #endif + +@@ -1044,7 +1032,7 @@ int __open_nameservers() + + void __close_nameservers(void) + { +- BIGLOCK; ++ __UCLIBC_MUTEX_LOCK(__resolv_lock); + while (__nameservers > 0) { + free(__nameserver[--__nameservers]); + __nameserver[__nameservers] = NULL; +@@ -1053,7 +1041,7 @@ void __close_nameservers(void) + free(__searchdomain[--__searchdomains]); + __searchdomain[__searchdomains] = NULL; + } +- BIGUNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + } + #endif + +@@ -1063,8 +1051,8 @@ struct hostent *gethostbyname(const char + { + static struct hostent h; + static char buf[sizeof(struct in_addr) + +- sizeof(struct in_addr *)*2 + +- sizeof(char *)*(ALIAS_DIM) + 384/*namebuffer*/ + 32/* margin */]; ++ sizeof(struct in_addr *)*2 + ++ sizeof(char *)*(ALIAS_DIM) + 384/*namebuffer*/ + 32/* margin */]; + struct hostent *hp; + + gethostbyname_r(name, &h, buf, sizeof(buf), &hp, &h_errno); +@@ -1082,8 +1070,8 @@ struct hostent *gethostbyname2(const cha + #else /* __UCLIBC_HAS_IPV6__ */ + static struct hostent h; + static char buf[sizeof(struct in6_addr) + +- sizeof(struct in6_addr *)*2 + +- sizeof(char *)*(ALIAS_DIM) + 384/*namebuffer*/ + 32/* margin */]; ++ sizeof(struct in6_addr *)*2 + ++ sizeof(char *)*(ALIAS_DIM) + 384/*namebuffer*/ + 32/* margin */]; + struct hostent *hp; + + gethostbyname2_r(name, family, &h, buf, sizeof(buf), &hp, &h_errno); +@@ -1119,7 +1107,7 @@ int res_init(void) + /** rp->rhook = NULL; **/ + /** rp->_u._ext.nsinit = 0; **/ + +- BIGLOCK; ++ __UCLIBC_MUTEX_LOCK(__resolv_lock); + if(__searchdomains) { + int i; + for(i=0; i<__searchdomains; i++) { +@@ -1139,7 +1127,7 @@ int res_init(void) + } + } + rp->nscount = __nameservers; +- BIGUNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + + return(0); + } +@@ -1175,10 +1163,10 @@ int res_query(const char *dname, int cla + + memset((char *) &a, '\0', sizeof(a)); + +- BIGLOCK; ++ __UCLIBC_MUTEX_LOCK(__resolv_lock); + __nameserversXX=__nameservers; + __nameserverXX=__nameserver; +- BIGUNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + i = __dns_lookup(dname, type, __nameserversXX, __nameserverXX, &packet, &a); + + if (i < 0) { +@@ -1207,10 +1195,10 @@ int res_query(const char *dname, int cla + * is detected. Error code, if any, is left in h_errno. + */ + int res_search(name, class, type, answer, anslen) +- const char *name; /* domain name */ +- int class, type; /* class and type of query */ +- u_char *answer; /* buffer to put answer */ +- int anslen; /* size of answer */ ++ const char *name; /* domain name */ ++ int class, type; /* class and type of query */ ++ u_char *answer; /* buffer to put answer */ ++ int anslen; /* size of answer */ + { + const char *cp, * const *domain; + HEADER *hp = (HEADER *)(void *)answer; +@@ -1256,11 +1244,11 @@ int res_search(name, class, type, answer + int done = 0; + + for (domain = (const char * const *)_res.dnsrch; +- *domain && !done; +- domain++) { ++ *domain && !done; ++ domain++) { + + ret = res_querydomain(name, *domain, class, type, +- answer, anslen); ++ answer, anslen); + if (ret > 0) + return (ret); + +@@ -1283,22 +1271,22 @@ int res_search(name, class, type, answer + } + + switch (h_errno) { +- case NO_DATA: +- got_nodata++; +- /* FALLTHROUGH */ +- case HOST_NOT_FOUND: +- /* keep trying */ +- break; +- case TRY_AGAIN: +- if (hp->rcode == SERVFAIL) { +- /* try next search element, if any */ +- got_servfail++; ++ case NO_DATA: ++ got_nodata++; ++ /* FALLTHROUGH */ ++ case HOST_NOT_FOUND: ++ /* keep trying */ + break; +- } +- /* FALLTHROUGH */ +- default: +- /* anything else implies that we're done */ +- done++; ++ case TRY_AGAIN: ++ if (hp->rcode == SERVFAIL) { ++ /* try next search element, if any */ ++ got_servfail++; ++ break; ++ } ++ /* FALLTHROUGH */ ++ default: ++ /* anything else implies that we're done */ ++ done++; + } + /* + * if we got here for some reason other than DNSRCH, +@@ -1342,10 +1330,10 @@ int res_search(name, class, type, answer + * removing a trailing dot from name if domain is NULL. + */ + int res_querydomain(name, domain, class, type, answer, anslen) +- const char *name, *domain; +- int class, type; /* class and type of query */ +- u_char *answer; /* buffer to put answer */ +- int anslen; /* size of answer */ ++ const char *name, *domain; ++ int class, type; /* class and type of query */ ++ u_char *answer; /* buffer to put answer */ ++ int anslen; /* size of answer */ + { + char nbuf[MAXDNAME]; + const char *longname = nbuf; +@@ -1359,7 +1347,7 @@ int res_querydomain(name, domain, class, + #ifdef DEBUG + if (_res.options & RES_DEBUG) + printf(";; res_querydomain(%s, %s, %d, %d)\n", +- name, domain?domain:"<Nil>", class, type); ++ name, domain?domain:"<Nil>", class, type); + #endif + if (domain == NULL) { + /* +@@ -1400,11 +1388,11 @@ struct hostent *gethostbyaddr (const voi + static struct hostent h; + static char buf[ + #ifndef __UCLIBC_HAS_IPV6__ +- sizeof(struct in_addr) + sizeof(struct in_addr *)*2 + ++ sizeof(struct in_addr) + sizeof(struct in_addr *)*2 + + #else +- sizeof(struct in6_addr) + sizeof(struct in6_addr *)*2 + ++ sizeof(struct in6_addr) + sizeof(struct in6_addr *)*2 + + #endif /* __UCLIBC_HAS_IPV6__ */ +- sizeof(char *)*(ALIAS_DIM) + 384/*namebuffer*/ + 32/* margin */]; ++ sizeof(char *)*(ALIAS_DIM) + 384/*namebuffer*/ + 32/* margin */]; + struct hostent *hp; + + gethostbyaddr_r(addr, len, type, &h, buf, sizeof(buf), &hp, &h_errno); +@@ -1425,11 +1413,11 @@ void __open_etc_hosts(FILE **fp) + } + + int __read_etc_hosts_r(FILE * fp, const char * name, int type, +- enum etc_hosts_action action, +- struct hostent * result_buf, +- char * buf, size_t buflen, +- struct hostent ** result, +- int * h_errnop) ++ enum etc_hosts_action action, ++ struct hostent * result_buf, ++ char * buf, size_t buflen, ++ struct hostent ** result, ++ int * h_errnop) + { + struct in_addr *in=NULL; + struct in_addr **addr_list=NULL; +@@ -1576,56 +1564,49 @@ int __read_etc_hosts_r(FILE * fp, const + + #ifdef L_gethostent + +-#ifdef __UCLIBC_HAS_THREADS__ +-static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER; +-# define LOCK __pthread_mutex_lock(&mylock) +-# define UNLOCK __pthread_mutex_unlock(&mylock); +-#else +-# define LOCK +-# define UNLOCK +-#endif ++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + + static int __stay_open; + static FILE * __gethostent_fp; + + void endhostent (void) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + __stay_open = 0; + if (__gethostent_fp) { +- fclose(__gethostent_fp); ++ fclose(__gethostent_fp); + } +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + + void sethostent (int stay_open) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + __stay_open = stay_open; +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + + int gethostent_r(struct hostent *result_buf, char *buf, size_t buflen, +- struct hostent **result, int *h_errnop) ++ struct hostent **result, int *h_errnop) + { +- int ret; ++ int ret = 0; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (__gethostent_fp == NULL) { +- __open_etc_hosts(&__gethostent_fp); +- if (__gethostent_fp == NULL) { +- UNLOCK; +- *result=NULL; +- return 0; +- } ++ __open_etc_hosts(&__gethostent_fp); ++ if (__gethostent_fp == NULL) { ++ *result=NULL; ++ goto DONE; ++ } + } + + ret = __read_etc_hosts_r(__gethostent_fp, NULL, AF_INET, GETHOSTENT, +- result_buf, buf, buflen, result, h_errnop); ++ result_buf, buf, buflen, result, h_errnop); + if (__stay_open==0) { +- fclose(__gethostent_fp); ++ fclose(__gethostent_fp); + } +- UNLOCK; ++ DONE: ++ __UCLIBC_MUTEX_UNLOCK(mylock); + return(ret); + } + +@@ -1634,17 +1615,17 @@ struct hostent *gethostent (void) + static struct hostent h; + static char buf[ + #ifndef __UCLIBC_HAS_IPV6__ +- sizeof(struct in_addr) + sizeof(struct in_addr *)*2 + ++ sizeof(struct in_addr) + sizeof(struct in_addr *)*2 + + #else +- sizeof(struct in6_addr) + sizeof(struct in6_addr *)*2 + ++ sizeof(struct in6_addr) + sizeof(struct in6_addr *)*2 + + #endif /* __UCLIBC_HAS_IPV6__ */ +- sizeof(char *)*(ALIAS_DIM) + +- 80/*namebuffer*/ + 2/* margin */]; ++ sizeof(char *)*(ALIAS_DIM) + ++ 80/*namebuffer*/ + 2/* margin */]; + struct hostent *host; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + gethostent_r(&h, buf, sizeof(buf), &host, &h_errno); +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + return(host); + } + #endif +@@ -1652,23 +1633,23 @@ struct hostent *gethostent (void) + #ifdef L_get_hosts_byname_r + + int __get_hosts_byname_r(const char * name, int type, +- struct hostent * result_buf, +- char * buf, size_t buflen, +- struct hostent ** result, +- int * h_errnop) ++ struct hostent * result_buf, ++ char * buf, size_t buflen, ++ struct hostent ** result, ++ int * h_errnop) + { + return(__read_etc_hosts_r(NULL, name, type, GET_HOSTS_BYNAME, +- result_buf, buf, buflen, result, h_errnop)); ++ result_buf, buf, buflen, result, h_errnop)); + } + #endif + + #ifdef L_get_hosts_byaddr_r + + int __get_hosts_byaddr_r(const char * addr, int len, int type, +- struct hostent * result_buf, +- char * buf, size_t buflen, +- struct hostent ** result, +- int * h_errnop) ++ struct hostent * result_buf, ++ char * buf, size_t buflen, ++ struct hostent ** result, ++ int * h_errnop) + { + #ifndef __UCLIBC_HAS_IPV6__ + char ipaddr[INET_ADDRSTRLEN]; +@@ -1677,24 +1658,24 @@ int __get_hosts_byaddr_r(const char * ad + #endif /* __UCLIBC_HAS_IPV6__ */ + + switch (type) { +- case AF_INET: +- if (len != sizeof(struct in_addr)) +- return 0; +- break; ++ case AF_INET: ++ if (len != sizeof(struct in_addr)) ++ return 0; ++ break; + #ifdef __UCLIBC_HAS_IPV6__ +- case AF_INET6: +- if (len != sizeof(struct in6_addr)) +- return 0; +- break; ++ case AF_INET6: ++ if (len != sizeof(struct in6_addr)) ++ return 0; ++ break; + #endif /* __UCLIBC_HAS_IPV6__ */ +- default: +- return 0; ++ default: ++ return 0; + } + + inet_ntop(type, addr, ipaddr, sizeof(ipaddr)); + + return(__read_etc_hosts_r(NULL, ipaddr, type, GET_HOSTS_BYADDR, +- result_buf, buf, buflen, result, h_errnop)); ++ result_buf, buf, buflen, result, h_errnop)); + } + #endif + +@@ -1705,8 +1686,8 @@ int __get_hosts_byaddr_r(const char * ad + #endif /* min */ + + int getnameinfo (const struct sockaddr *sa, socklen_t addrlen, char *host, +- socklen_t hostlen, char *serv, socklen_t servlen, +- unsigned int flags) ++ socklen_t hostlen, char *serv, socklen_t servlen, ++ unsigned int flags) + { + int serrno = errno; + int ok = 0; +@@ -1720,167 +1701,167 @@ int getnameinfo (const struct sockaddr * + return EAI_FAMILY; + + switch (sa->sa_family) { +- case AF_LOCAL: +- break; +- case AF_INET: +- if (addrlen < sizeof (struct sockaddr_in)) +- return EAI_FAMILY; +- break; ++ case AF_LOCAL: ++ break; ++ case AF_INET: ++ if (addrlen < sizeof (struct sockaddr_in)) ++ return EAI_FAMILY; ++ break; + #ifdef __UCLIBC_HAS_IPV6__ +- case AF_INET6: +- if (addrlen < sizeof (struct sockaddr_in6)) +- return EAI_FAMILY; +- break; ++ case AF_INET6: ++ if (addrlen < sizeof (struct sockaddr_in6)) ++ return EAI_FAMILY; ++ break; + #endif /* __UCLIBC_HAS_IPV6__ */ +- default: +- return EAI_FAMILY; ++ default: ++ return EAI_FAMILY; + } + + if (host != NULL && hostlen > 0) + switch (sa->sa_family) { +- case AF_INET: ++ case AF_INET: + #ifdef __UCLIBC_HAS_IPV6__ +- case AF_INET6: ++ case AF_INET6: + #endif /* __UCLIBC_HAS_IPV6__ */ +- if (!(flags & NI_NUMERICHOST)) { ++ if (!(flags & NI_NUMERICHOST)) { + #ifdef __UCLIBC_HAS_IPV6__ +- if (sa->sa_family == AF_INET6) +- h = gethostbyaddr ((const void *) +- &(((const struct sockaddr_in6 *) sa)->sin6_addr), +- sizeof(struct in6_addr), AF_INET6); +- else +-#endif /* __UCLIBC_HAS_IPV6__ */ +- h = gethostbyaddr ((const void *) &(((const struct sockaddr_in *)sa)->sin_addr), +- sizeof(struct in_addr), AF_INET); +- +- if (h) { +- char *c; +- if ((flags & NI_NOFQDN) +- && (getdomainname (domain, sizeof(domain)) == 0) +- && (c = strstr (h->h_name, domain)) +- && (c != h->h_name) && (*(--c) == '.')) { +- strncpy (host, h->h_name, +- min(hostlen, (size_t) (c - h->h_name))); +- host[min(hostlen - 1, (size_t) (c - h->h_name))] = '\0'; +- ok = 1; +- } else { +- strncpy (host, h->h_name, hostlen); +- ok = 1; ++ if (sa->sa_family == AF_INET6) ++ h = gethostbyaddr ((const void *) ++ &(((const struct sockaddr_in6 *) sa)->sin6_addr), ++ sizeof(struct in6_addr), AF_INET6); ++ else ++#endif /* __UCLIBC_HAS_IPV6__ */ ++ h = gethostbyaddr ((const void *) &(((const struct sockaddr_in *)sa)->sin_addr), ++ sizeof(struct in_addr), AF_INET); ++ ++ if (h) { ++ char *c; ++ if ((flags & NI_NOFQDN) ++ && (getdomainname (domain, sizeof(domain)) == 0) ++ && (c = strstr (h->h_name, domain)) ++ && (c != h->h_name) && (*(--c) == '.')) { ++ strncpy (host, h->h_name, ++ min(hostlen, (size_t) (c - h->h_name))); ++ host[min(hostlen - 1, (size_t) (c - h->h_name))] = '\0'; ++ ok = 1; ++ } else { ++ strncpy (host, h->h_name, hostlen); ++ ok = 1; ++ } + } +- } +- } ++ } + +- if (!ok) { +- if (flags & NI_NAMEREQD) { +- errno = serrno; +- return EAI_NONAME; +- } else { +- const char *c; ++ if (!ok) { ++ if (flags & NI_NAMEREQD) { ++ errno = serrno; ++ return EAI_NONAME; ++ } else { ++ const char *c; + #ifdef __UCLIBC_HAS_IPV6__ +- if (sa->sa_family == AF_INET6) { +- const struct sockaddr_in6 *sin6p; ++ if (sa->sa_family == AF_INET6) { ++ const struct sockaddr_in6 *sin6p; + +- sin6p = (const struct sockaddr_in6 *) sa; ++ sin6p = (const struct sockaddr_in6 *) sa; + +- c = inet_ntop (AF_INET6, +- (const void *) &sin6p->sin6_addr, host, hostlen); ++ c = inet_ntop (AF_INET6, ++ (const void *) &sin6p->sin6_addr, host, hostlen); + #if 0 +- /* Does scope id need to be supported? */ +- uint32_t scopeid; +- scopeid = sin6p->sin6_scope_id; +- if (scopeid != 0) { +- /* Buffer is >= IFNAMSIZ+1. */ +- char scopebuf[IFNAMSIZ + 1]; +- char *scopeptr; +- int ni_numericscope = 0; +- size_t real_hostlen = __strnlen (host, hostlen); +- size_t scopelen = 0; +- +- scopebuf[0] = SCOPE_DELIMITER; +- scopebuf[1] = '\0'; +- scopeptr = &scopebuf[1]; +- +- if (IN6_IS_ADDR_LINKLOCAL (&sin6p->sin6_addr) +- || IN6_IS_ADDR_MC_LINKLOCAL (&sin6p->sin6_addr)) { +- if (if_indextoname (scopeid, scopeptr) == NULL) ++ /* Does scope id need to be supported? */ ++ uint32_t scopeid; ++ scopeid = sin6p->sin6_scope_id; ++ if (scopeid != 0) { ++ /* Buffer is >= IFNAMSIZ+1. */ ++ char scopebuf[IFNAMSIZ + 1]; ++ char *scopeptr; ++ int ni_numericscope = 0; ++ size_t real_hostlen = __strnlen (host, hostlen); ++ size_t scopelen = 0; ++ ++ scopebuf[0] = SCOPE_DELIMITER; ++ scopebuf[1] = '\0'; ++ scopeptr = &scopebuf[1]; ++ ++ if (IN6_IS_ADDR_LINKLOCAL (&sin6p->sin6_addr) ++ || IN6_IS_ADDR_MC_LINKLOCAL (&sin6p->sin6_addr)) { ++ if (if_indextoname (scopeid, scopeptr) == NULL) ++ ++ni_numericscope; ++ else ++ scopelen = strlen (scopebuf); ++ } else { + ++ni_numericscope; +- else +- scopelen = strlen (scopebuf); +- } else { +- ++ni_numericscope; +- } ++ } + +- if (ni_numericscope) +- scopelen = 1 + snprintf (scopeptr, +- (scopebuf +- + sizeof scopebuf +- - scopeptr), +- "%u", scopeid); +- +- if (real_hostlen + scopelen + 1 > hostlen) +- return EAI_SYSTEM; +- memcpy (host + real_hostlen, scopebuf, scopelen + 1); +- } ++ if (ni_numericscope) ++ scopelen = 1 + snprintf (scopeptr, ++ (scopebuf ++ + sizeof scopebuf ++ - scopeptr), ++ "%u", scopeid); ++ ++ if (real_hostlen + scopelen + 1 > hostlen) ++ return EAI_SYSTEM; ++ memcpy (host + real_hostlen, scopebuf, scopelen + 1); ++ } + #endif +- } else ++ } else + #endif /* __UCLIBC_HAS_IPV6__ */ +- c = inet_ntop (AF_INET, (const void *) +- &(((const struct sockaddr_in *) sa)->sin_addr), +- host, hostlen); +- +- if (c == NULL) { +- errno = serrno; +- return EAI_SYSTEM; ++ c = inet_ntop (AF_INET, (const void *) ++ &(((const struct sockaddr_in *) sa)->sin_addr), ++ host, hostlen); ++ ++ if (c == NULL) { ++ errno = serrno; ++ return EAI_SYSTEM; ++ } + } ++ ok = 1; + } +- ok = 1; +- } +- break; +- +- case AF_LOCAL: +- if (!(flags & NI_NUMERICHOST)) { +- struct utsname utsname; ++ break; + +- if (!uname (&utsname)) { +- strncpy (host, utsname.nodename, hostlen); +- break; ++ case AF_LOCAL: ++ if (!(flags & NI_NUMERICHOST)) { ++ struct utsname utsname; ++ ++ if (!uname (&utsname)) { ++ strncpy (host, utsname.nodename, hostlen); ++ break; ++ }; + }; +- }; + +- if (flags & NI_NAMEREQD) { +- errno = serrno; +- return EAI_NONAME; +- } ++ if (flags & NI_NAMEREQD) { ++ errno = serrno; ++ return EAI_NONAME; ++ } + +- strncpy (host, "localhost", hostlen); +- break; ++ strncpy (host, "localhost", hostlen); ++ break; + +- default: +- return EAI_FAMILY; +- } ++ default: ++ return EAI_FAMILY; ++ } + + if (serv && (servlen > 0)) { + switch (sa->sa_family) { +- case AF_INET: ++ case AF_INET: + #ifdef __UCLIBC_HAS_IPV6__ +- case AF_INET6: ++ case AF_INET6: + #endif /* __UCLIBC_HAS_IPV6__ */ +- if (!(flags & NI_NUMERICSERV)) { +- struct servent *s; +- s = getservbyport (((const struct sockaddr_in *) sa)->sin_port, +- ((flags & NI_DGRAM) ? "udp" : "tcp")); +- if (s) { +- strncpy (serv, s->s_name, servlen); +- break; ++ if (!(flags & NI_NUMERICSERV)) { ++ struct servent *s; ++ s = getservbyport (((const struct sockaddr_in *) sa)->sin_port, ++ ((flags & NI_DGRAM) ? "udp" : "tcp")); ++ if (s) { ++ strncpy (serv, s->s_name, servlen); ++ break; ++ } + } +- } +- snprintf (serv, servlen, "%d", +- ntohs (((const struct sockaddr_in *) sa)->sin_port)); +- break; ++ snprintf (serv, servlen, "%d", ++ ntohs (((const struct sockaddr_in *) sa)->sin_port)); ++ break; + +- case AF_LOCAL: +- strncpy (serv, ((const struct sockaddr_un *) sa)->sun_path, servlen); +- break; ++ case AF_LOCAL: ++ strncpy (serv, ((const struct sockaddr_un *) sa)->sun_path, servlen); ++ break; + } + } + if (host && (hostlen > 0)) +@@ -1896,10 +1877,10 @@ int getnameinfo (const struct sockaddr * + #ifdef L_gethostbyname_r + + int gethostbyname_r(const char * name, +- struct hostent * result_buf, +- char * buf, size_t buflen, +- struct hostent ** result, +- int * h_errnop) ++ struct hostent * result_buf, ++ char * buf, size_t buflen, ++ struct hostent ** result, ++ int * h_errnop) + { + struct in_addr *in; + struct in_addr **addr_list; +@@ -1921,7 +1902,7 @@ int gethostbyname_r(const char * name, + __set_errno(0); /* to check for missing /etc/hosts. */ + + if ((i=__get_hosts_byname_r(name, AF_INET, result_buf, +- buf, buflen, result, h_errnop))==0) ++ buf, buflen, result, h_errnop))==0) + return i; + switch (*h_errnop) { + case HOST_NOT_FOUND: +@@ -1983,60 +1964,60 @@ int gethostbyname_r(const char * name, + + for (;;) { + +- BIGLOCK; ++ __UCLIBC_MUTEX_LOCK(__resolv_lock); + __nameserversXX=__nameservers; + __nameserverXX=__nameserver; +- BIGUNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + a.buf = buf; + a.buflen = buflen; + a.add_count = 0; + i = __dns_lookup(name, T_A, __nameserversXX, __nameserverXX, &packet, &a); + + if (i < 0) { +- *h_errnop = HOST_NOT_FOUND; +- DPRINTF("__dns_lookup\n"); +- return TRY_AGAIN; ++ *h_errnop = HOST_NOT_FOUND; ++ DPRINTF("__dns_lookup\n"); ++ return TRY_AGAIN; + } + + if ((a.rdlength + sizeof(struct in_addr*)) * a.add_count + 256 > buflen) +- { +- free(a.dotted); +- free(packet); +- *h_errnop = NETDB_INTERNAL; +- DPRINTF("buffer too small for all addresses\n"); +- return ERANGE; +- } ++ { ++ free(a.dotted); ++ free(packet); ++ *h_errnop = NETDB_INTERNAL; ++ DPRINTF("buffer too small for all addresses\n"); ++ return ERANGE; ++ } + else if(a.add_count > 0) +- { +- memmove(buf - sizeof(struct in_addr*)*2, buf, a.add_count * a.rdlength); +- addr_list = (struct in_addr**)(buf + a.add_count * a.rdlength); +- addr_list[0] = in; +- for (i = a.add_count-1; i>=0; --i) +- addr_list[i+1] = (struct in_addr*)(buf - sizeof(struct in_addr*)*2 + a.rdlength * i); +- addr_list[a.add_count + 1] = 0; +- buflen -= (((char*)&(addr_list[a.add_count + 2])) - buf); +- buf = (char*)&addr_list[a.add_count + 2]; +- } ++ { ++ memmove(buf - sizeof(struct in_addr*)*2, buf, a.add_count * a.rdlength); ++ addr_list = (struct in_addr**)(buf + a.add_count * a.rdlength); ++ addr_list[0] = in; ++ for (i = a.add_count-1; i>=0; --i) ++ addr_list[i+1] = (struct in_addr*)(buf - sizeof(struct in_addr*)*2 + a.rdlength * i); ++ addr_list[a.add_count + 1] = 0; ++ buflen -= (((char*)&(addr_list[a.add_count + 2])) - buf); ++ buf = (char*)&addr_list[a.add_count + 2]; ++ } + + strncpy(buf, a.dotted, buflen); + free(a.dotted); + + if (a.atype == T_A) { /* ADDRESS */ +- memcpy(in, a.rdata, sizeof(*in)); +- result_buf->h_name = buf; +- result_buf->h_addrtype = AF_INET; +- result_buf->h_length = sizeof(*in); +- result_buf->h_addr_list = (char **) addr_list; ++ memcpy(in, a.rdata, sizeof(*in)); ++ result_buf->h_name = buf; ++ result_buf->h_addrtype = AF_INET; ++ result_buf->h_length = sizeof(*in); ++ result_buf->h_addr_list = (char **) addr_list; + #ifdef __UCLIBC_MJN3_ONLY__ + #warning TODO -- generate the full list + #endif +- result_buf->h_aliases = alias; /* TODO: generate the full list */ +- free(packet); +- break; ++ result_buf->h_aliases = alias; /* TODO: generate the full list */ ++ free(packet); ++ break; + } else { +- free(packet); +- *h_errnop=HOST_NOT_FOUND; +- return TRY_AGAIN; ++ free(packet); ++ *h_errnop=HOST_NOT_FOUND; ++ return TRY_AGAIN; + } + } + +@@ -2049,14 +2030,14 @@ int gethostbyname_r(const char * name, + #ifdef L_gethostbyname2_r + + int gethostbyname2_r(const char *name, int family, +- struct hostent * result_buf, +- char * buf, size_t buflen, +- struct hostent ** result, +- int * h_errnop) ++ struct hostent * result_buf, ++ char * buf, size_t buflen, ++ struct hostent ** result, ++ int * h_errnop) + { + #ifndef __UCLIBC_HAS_IPV6__ + return family == (AF_INET)? gethostbyname_r(name, result_buf, +- buf, buflen, result, h_errnop) : HOST_NOT_FOUND; ++ buf, buflen, result, h_errnop) : HOST_NOT_FOUND; + #else /* __UCLIBC_HAS_IPV6__ */ + struct in6_addr *in; + struct in6_addr **addr_list; +@@ -2084,7 +2065,7 @@ int gethostbyname2_r(const char *name, i + __set_errno(0); /* to check for missing /etc/hosts. */ + + if ((i=__get_hosts_byname_r(name, AF_INET, result_buf, +- buf, buflen, result, h_errnop))==0) ++ buf, buflen, result, h_errnop))==0) + return i; + switch (*h_errnop) { + case HOST_NOT_FOUND: +@@ -2137,10 +2118,10 @@ int gethostbyname2_r(const char *name, i + memset((char *) &a, '\0', sizeof(a)); + + for (;;) { +- BIGLOCK; +- __nameserversXX=__nameservers; +- __nameserverXX=__nameserver; +- BIGUNLOCK; ++ __UCLIBC_MUTEX_LOCK(__resolv_lock); ++ __nameserversXX=__nameservers; ++ __nameserverXX=__nameserver; ++ __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + + i = __dns_lookup(buf, T_AAAA, __nameserversXX, __nameserverXX, &packet, &a); + +@@ -2190,10 +2171,10 @@ int gethostbyname2_r(const char *name, i + + #ifdef L_gethostbyaddr_r + int gethostbyaddr_r (const void *addr, socklen_t len, int type, +- struct hostent * result_buf, +- char * buf, size_t buflen, +- struct hostent ** result, +- int * h_errnop) ++ struct hostent * result_buf, ++ char * buf, size_t buflen, ++ struct hostent ** result, ++ int * h_errnop) + + { + struct in_addr *in; +@@ -2234,7 +2215,7 @@ int gethostbyaddr_r (const void *addr, s + + /* do /etc/hosts first */ + if ((i=__get_hosts_byaddr_r(addr, len, type, result_buf, +- buf, buflen, result, h_errnop))==0) ++ buf, buflen, result, h_errnop))==0) + return i; + switch (*h_errnop) { + case HOST_NOT_FOUND: +@@ -2294,7 +2275,7 @@ int gethostbyaddr_r (const void *addr, s + addr_list[0] = in; + + sprintf(buf, "%u.%u.%u.%u.in-addr.arpa", +- tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0]); ++ tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0]); + #ifdef __UCLIBC_HAS_IPV6__ + } else { + memcpy(in6->s6_addr, addr, len); +@@ -2304,7 +2285,7 @@ int gethostbyaddr_r (const void *addr, s + + for (i = len - 1; i >= 0; i--) { + qp += sprintf(qp, "%x.%x.", in6->s6_addr[i] & 0xf, +- (in6->s6_addr[i] >> 4) & 0xf); ++ (in6->s6_addr[i] >> 4) & 0xf); + } + strcpy(qp, "ip6.int"); + #endif /* __UCLIBC_HAS_IPV6__ */ +@@ -2314,10 +2295,10 @@ int gethostbyaddr_r (const void *addr, s + + for (;;) { + +- BIGLOCK; +- __nameserversXX=__nameservers; +- __nameserverXX=__nameserver; +- BIGUNLOCK; ++ __UCLIBC_MUTEX_LOCK(__resolv_lock); ++ __nameserversXX=__nameservers; ++ __nameserverXX=__nameserver; ++ __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + i = __dns_lookup(buf, T_PTR, __nameserversXX, __nameserverXX, &packet, &a); + + if (i < 0) { +@@ -2381,7 +2362,7 @@ int gethostbyaddr_r (const void *addr, s + * Return size of compressed name or -1 if there was an error. + */ + int __dn_expand(const u_char *msg, const u_char *eom, const u_char *src, +- char *dst, int dstsiz) ++ char *dst, int dstsiz) + { + int n = ns_name_uncompress(msg, eom, src, dst, (size_t)dstsiz); + +@@ -2401,7 +2382,7 @@ int __dn_expand(const u_char *msg, const + */ + static int printable(int ch) + { +- return (ch > 0x20 && ch < 0x7f); ++ return (ch > 0x20 && ch < 0x7f); + } + + /* +@@ -2413,18 +2394,18 @@ static int printable(int ch) + */ + static int special(int ch) + { +- switch (ch) { ++ switch (ch) { + case 0x22: /* '"' */ + case 0x2E: /* '.' */ + case 0x3B: /* ';' */ + case 0x5C: /* '\\' */ +- /* Special modifiers in zone files. */ ++ /* Special modifiers in zone files. */ + case 0x40: /* '@' */ + case 0x24: /* '$' */ +- return (1); ++ return (1); + default: +- return (0); +- } ++ return (0); ++ } + } + + /* +@@ -2436,7 +2417,7 @@ static int special(int ch) + * Root domain returns as "." not "". + */ + int __ns_name_uncompress(const u_char *msg, const u_char *eom, +- const u_char *src, char *dst, size_t dstsiz) ++ const u_char *src, char *dst, size_t dstsiz) + { + u_char tmp[NS_MAXCDNAME]; + int n; +@@ -2525,7 +2506,7 @@ int __ns_name_ntop(const u_char *src, ch + return (-1); + } + *dn++ = '\0'; +- return (dn - dst); ++ return (dn - dst); + } + + /* +@@ -2535,7 +2516,7 @@ int __ns_name_ntop(const u_char *src, ch + * -1 if it fails, or consumed octets if it succeeds. + */ + int __ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src, +- u_char *dst, size_t dstsiz) ++ u_char *dst, size_t dstsiz) + { + const u_char *srcp, *dstlim; + u_char *dstp; +@@ -2554,46 +2535,46 @@ int __ns_name_unpack(const u_char *msg, + while ((n = *srcp++) != 0) { + /* Check for indirection. */ + switch (n & NS_CMPRSFLGS) { +- case 0: +- /* Limit checks. */ +- if (dstp + n + 1 >= dstlim || srcp + n >= eom) { +- __set_errno (EMSGSIZE); +- return (-1); +- } +- checked += n + 1; +- *dstp++ = n; +- memcpy(dstp, srcp, n); +- dstp += n; +- srcp += n; +- break; ++ case 0: ++ /* Limit checks. */ ++ if (dstp + n + 1 >= dstlim || srcp + n >= eom) { ++ __set_errno (EMSGSIZE); ++ return (-1); ++ } ++ checked += n + 1; ++ *dstp++ = n; ++ memcpy(dstp, srcp, n); ++ dstp += n; ++ srcp += n; ++ break; + +- case NS_CMPRSFLGS: +- if (srcp >= eom) { +- __set_errno (EMSGSIZE); +- return (-1); +- } +- if (len < 0) +- len = srcp - src + 1; +- srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff)); +- if (srcp < msg || srcp >= eom) { /* Out of range. */ +- __set_errno (EMSGSIZE); +- return (-1); +- } +- checked += 2; +- /* +- * Check for loops in the compressed name; +- * if we've looked at the whole message, +- * there must be a loop. +- */ +- if (checked >= eom - msg) { +- __set_errno (EMSGSIZE); +- return (-1); +- } +- break; ++ case NS_CMPRSFLGS: ++ if (srcp >= eom) { ++ __set_errno (EMSGSIZE); ++ return (-1); ++ } ++ if (len < 0) ++ len = srcp - src + 1; ++ srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff)); ++ if (srcp < msg || srcp >= eom) { /* Out of range. */ ++ __set_errno (EMSGSIZE); ++ return (-1); ++ } ++ checked += 2; ++ /* ++ * Check for loops in the compressed name; ++ * if we've looked at the whole message, ++ * there must be a loop. ++ */ ++ if (checked >= eom - msg) { ++ __set_errno (EMSGSIZE); ++ return (-1); ++ } ++ break; + +- default: +- __set_errno (EMSGSIZE); +- return (-1); /* flag error */ ++ default: ++ __set_errno (EMSGSIZE); ++ return (-1); /* flag error */ + } + } + *dstp = '\0'; +diff --git a/libc/inet/rpc/create_xid.c b/libc/inet/rpc/create_xid.c +index cbb961e..c86cbb4 100644 +--- a/libc/inet/rpc/create_xid.c ++++ b/libc/inet/rpc/create_xid.c +@@ -27,15 +27,7 @@ + + /* The RPC code is not threadsafe, but new code should be threadsafe. */ + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-static pthread_mutex_t createxid_lock = PTHREAD_MUTEX_INITIALIZER; +-# define LOCK __pthread_mutex_lock(&createxid_lock) +-# define UNLOCK __pthread_mutex_unlock(&createxid_lock); +-#else +-# define LOCK +-# define UNLOCK +-#endif ++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + + static int is_initialized; + static struct drand48_data __rpc_lrand48_data; +@@ -43,22 +35,22 @@ static struct drand48_data __rpc_lrand48 + unsigned long + _create_xid (void) + { +- unsigned long res; ++ unsigned long res; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + +- if (!is_initialized) +- { +- struct timeval now; ++ if (!is_initialized) ++ { ++ struct timeval now; + +- gettimeofday (&now, (struct timezone *) 0); +- srand48_r (now.tv_sec ^ now.tv_usec, &__rpc_lrand48_data); +- is_initialized = 1; +- } ++ gettimeofday (&now, (struct timezone *) 0); ++ srand48_r (now.tv_sec ^ now.tv_usec, &__rpc_lrand48_data); ++ is_initialized = 1; ++ } + +- lrand48_r (&__rpc_lrand48_data, &res); ++ lrand48_r (&__rpc_lrand48_data, &res); + +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + +- return res; ++ return res; + } +diff --git a/libc/misc/dirent/closedir.c b/libc/misc/dirent/closedir.c +index 068e2d3..56adb23 100644 +--- a/libc/misc/dirent/closedir.c ++++ b/libc/misc/dirent/closedir.c +@@ -4,7 +4,6 @@ + #include <unistd.h> + #include "dirstream.h" + +- + int closedir(DIR * dir) + { + int fd; +@@ -19,14 +18,10 @@ int closedir(DIR * dir) + __set_errno(EBADF); + return -1; + } +-#ifdef __UCLIBC_HAS_THREADS__ +- __pthread_mutex_lock(&(dir->dd_lock)); +-#endif ++ __UCLIBC_MUTEX_LOCK(dir->dd_lock); + fd = dir->dd_fd; + dir->dd_fd = -1; +-#ifdef __UCLIBC_HAS_THREADS__ +- __pthread_mutex_unlock(&(dir->dd_lock)); +-#endif ++ __UCLIBC_MUTEX_UNLOCK(dir->dd_lock); + free(dir->dd_buf); + free(dir); + return close(fd); +diff --git a/libc/misc/dirent/dirstream.h b/libc/misc/dirent/dirstream.h +index 2dd0264..bd721c5 100644 +--- a/libc/misc/dirent/dirstream.h ++++ b/libc/misc/dirent/dirstream.h +@@ -26,9 +26,8 @@ Cambridge, MA 02139, USA. */ + + #include <features.h> + #include <sys/types.h> +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-#endif ++ ++#include <bits/uClibc_mutex.h> + + /* For now, syscall readdir () only supports one entry at a time. It + * will be changed in the future. +@@ -63,11 +62,7 @@ struct __dirstream { + size_t dd_max; + + /* lock */ +-#ifdef __UCLIBC_HAS_THREADS__ +- pthread_mutex_t dd_lock; +-#else +- void *dd_lock; +-#endif ++ __UCLIBC_MUTEX(dd_lock); + }; /* stream data from opendir() */ + + +diff --git a/libc/misc/dirent/readdir.c b/libc/misc/dirent/readdir.c +index 1f196e1..c55317a 100644 +--- a/libc/misc/dirent/readdir.c ++++ b/libc/misc/dirent/readdir.c +@@ -5,7 +5,6 @@ + #include <dirent.h> + #include "dirstream.h" + +- + struct dirent *readdir(DIR * dir) + { + ssize_t bytes; +@@ -16,9 +15,7 @@ struct dirent *readdir(DIR * dir) + return NULL; + } + +-#ifdef __UCLIBC_HAS_THREADS__ +- __pthread_mutex_lock(&(dir->dd_lock)); +-#endif ++ __UCLIBC_MUTEX_LOCK(dir->dd_lock); + + do { + if (dir->dd_size <= dir->dd_nextloc) { +@@ -44,8 +41,6 @@ struct dirent *readdir(DIR * dir) + } while (de->d_ino == 0); + + all_done: +-#ifdef __UCLIBC_HAS_THREADS__ +- __pthread_mutex_unlock(&(dir->dd_lock)); +-#endif ++ __UCLIBC_MUTEX_UNLOCK(dir->dd_lock); + return de; + } +diff --git a/libc/misc/dirent/readdir64.c b/libc/misc/dirent/readdir64.c +index f798c6f..6da3b0d 100644 +--- a/libc/misc/dirent/readdir64.c ++++ b/libc/misc/dirent/readdir64.c +@@ -20,7 +20,6 @@ + #include <dirent.h> + #include "dirstream.h" + +- + struct dirent64 *readdir64(DIR * dir) + { + ssize_t bytes; +@@ -31,9 +30,7 @@ struct dirent64 *readdir64(DIR * dir) + return NULL; + } + +-#ifdef __UCLIBC_HAS_THREADS__ +- __pthread_mutex_lock(&(dir->dd_lock)); +-#endif ++ __UCLIBC_MUTEX_LOCK(dir->dd_lock); + + do { + if (dir->dd_size <= dir->dd_nextloc) { +@@ -59,9 +56,7 @@ struct dirent64 *readdir64(DIR * dir) + } while (de->d_ino == 0); + + all_done: +-#ifdef __UCLIBC_HAS_THREADS__ +- __pthread_mutex_unlock(&(dir->dd_lock)); +-#endif ++ __UCLIBC_MUTEX_UNLOCK(dir->dd_lock); + + return de; + } +diff --git a/libc/misc/dirent/readdir64_r.c b/libc/misc/dirent/readdir64_r.c +index da3564e..cc96eff 100644 +--- a/libc/misc/dirent/readdir64_r.c ++++ b/libc/misc/dirent/readdir64_r.c +@@ -19,7 +19,6 @@ + #include <dirent.h> + #include "dirstream.h" + +- + int readdir64_r(DIR *dir, struct dirent64 *entry, struct dirent64 **result) + { + int ret; +@@ -32,21 +31,19 @@ int readdir64_r(DIR *dir, struct dirent6 + } + de = NULL; + +-#ifdef __UCLIBC_HAS_THREADS__ +- __pthread_mutex_lock(&(dir->dd_lock)); +-#endif ++ __UCLIBC_MUTEX_LOCK(dir->dd_lock); + + do { + if (dir->dd_size <= dir->dd_nextloc) { +- /* read dir->dd_max bytes of directory entries. */ +- bytes = __getdents64(dir->dd_fd, dir->dd_buf, dir->dd_max); +- if (bytes <= 0) { +- *result = NULL; +- ret = errno; +- goto all_done; +- } +- dir->dd_size = bytes; +- dir->dd_nextloc = 0; ++ /* read dir->dd_max bytes of directory entries. */ ++ bytes = __getdents64(dir->dd_fd, dir->dd_buf, dir->dd_max); ++ if (bytes <= 0) { ++ *result = NULL; ++ ret = errno; ++ goto all_done; ++ } ++ dir->dd_size = bytes; ++ dir->dd_nextloc = 0; + } + + de = (struct dirent64 *) (((char *) dir->dd_buf) + dir->dd_nextloc); +@@ -66,12 +63,10 @@ int readdir64_r(DIR *dir, struct dirent6 + } + ret = 0; + +-all_done: ++ all_done: + +-#ifdef __UCLIBC_HAS_THREADS__ +- __pthread_mutex_unlock(&(dir->dd_lock)); +-#endif +- return((de != NULL)? 0 : ret); ++ __UCLIBC_MUTEX_UNLOCK(dir->dd_lock); ++ return((de != NULL)? 0 : ret); + } + #endif /* __UCLIBC_HAS_LFS__ */ + +diff --git a/libc/misc/dirent/readdir_r.c b/libc/misc/dirent/readdir_r.c +index 245dcbd..aeccdd8 100644 +--- a/libc/misc/dirent/readdir_r.c ++++ b/libc/misc/dirent/readdir_r.c +@@ -5,7 +5,6 @@ + #include <dirent.h> + #include "dirstream.h" + +- + int readdir_r(DIR *dir, struct dirent *entry, struct dirent **result) + { + int ret; +@@ -18,21 +17,19 @@ int readdir_r(DIR *dir, struct dirent *e + } + de = NULL; + +-#ifdef __UCLIBC_HAS_THREADS__ +- __pthread_mutex_lock(&(dir->dd_lock)); +-#endif ++ __UCLIBC_MUTEX_LOCK(dir->dd_lock); + + do { + if (dir->dd_size <= dir->dd_nextloc) { +- /* read dir->dd_max bytes of directory entries. */ +- bytes = __getdents(dir->dd_fd, dir->dd_buf, dir->dd_max); +- if (bytes <= 0) { +- *result = NULL; +- ret = errno; +- goto all_done; +- } +- dir->dd_size = bytes; +- dir->dd_nextloc = 0; ++ /* read dir->dd_max bytes of directory entries. */ ++ bytes = __getdents(dir->dd_fd, dir->dd_buf, dir->dd_max); ++ if (bytes <= 0) { ++ *result = NULL; ++ ret = errno; ++ goto all_done; ++ } ++ dir->dd_size = bytes; ++ dir->dd_nextloc = 0; + } + + de = (struct dirent *) (((char *) dir->dd_buf) + dir->dd_nextloc); +@@ -52,10 +49,8 @@ int readdir_r(DIR *dir, struct dirent *e + } + ret = 0; + +-all_done: ++ all_done: + +-#ifdef __UCLIBC_HAS_THREADS__ +- __pthread_mutex_unlock(&(dir->dd_lock)); +-#endif +- return((de != NULL)? 0 : ret); ++ __UCLIBC_MUTEX_UNLOCK(dir->dd_lock); ++ return((de != NULL)? 0 : ret); + } +diff --git a/libc/misc/dirent/rewinddir.c b/libc/misc/dirent/rewinddir.c +index 60ef71d..fe8fc2a 100644 +--- a/libc/misc/dirent/rewinddir.c ++++ b/libc/misc/dirent/rewinddir.c +@@ -3,7 +3,6 @@ + #include <unistd.h> + #include "dirstream.h" + +- + /* rewinddir() just does an lseek(fd,0,0) - see close for comments */ + void rewinddir(DIR * dir) + { +@@ -11,12 +10,8 @@ void rewinddir(DIR * dir) + __set_errno(EBADF); + return; + } +-#ifdef __UCLIBC_HAS_THREADS__ +- __pthread_mutex_lock(&(dir->dd_lock)); +-#endif ++ __UCLIBC_MUTEX_LOCK(dir->dd_lock); + lseek(dir->dd_fd, 0, SEEK_SET); + dir->dd_nextoff = dir->dd_nextloc = dir->dd_size = 0; +-#ifdef __UCLIBC_HAS_THREADS__ +- __pthread_mutex_unlock(&(dir->dd_lock)); +-#endif ++ __UCLIBC_MUTEX_UNLOCK(dir->dd_lock); + } +diff --git a/libc/misc/dirent/seekdir.c b/libc/misc/dirent/seekdir.c +index 139f1e1..6d6f5f0 100644 +--- a/libc/misc/dirent/seekdir.c ++++ b/libc/misc/dirent/seekdir.c +@@ -3,19 +3,14 @@ + #include <unistd.h> + #include "dirstream.h" + +- + void seekdir(DIR * dir, long int offset) + { + if (!dir) { + __set_errno(EBADF); + return; + } +-#ifdef __UCLIBC_HAS_THREADS__ +- __pthread_mutex_lock(&(dir->dd_lock)); +-#endif ++ __UCLIBC_MUTEX_LOCK(dir->dd_lock); + dir->dd_nextoff = lseek(dir->dd_fd, offset, SEEK_SET); + dir->dd_size = dir->dd_nextloc = 0; +-#ifdef __UCLIBC_HAS_THREADS__ +- __pthread_mutex_unlock(&(dir->dd_lock)); +-#endif ++ __UCLIBC_MUTEX_UNLOCK(dir->dd_lock); + } +diff --git a/libc/misc/mntent/mntent.c b/libc/misc/mntent/mntent.c +index d98a687..af6d848 100644 +--- a/libc/misc/mntent/mntent.c ++++ b/libc/misc/mntent/mntent.c +@@ -3,15 +3,9 @@ + #include <string.h> + #include <mntent.h> + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER; +-# define LOCK __pthread_mutex_lock(&mylock) +-# define UNLOCK __pthread_mutex_unlock(&mylock); +-#else +-# define LOCK +-# define UNLOCK +-#endif ++#include <bits/uClibc_mutex.h> ++ ++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + + /* Reentrant version of getmntent. */ + struct mntent *getmntent_r (FILE *filep, +@@ -67,7 +61,7 @@ struct mntent *getmntent(FILE * filep) + struct mntent *tmp; + static char *buff = NULL; + static struct mntent mnt; +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + + if (!buff) { + buff = malloc(BUFSIZ); +@@ -76,7 +70,7 @@ struct mntent *getmntent(FILE * filep) + } + + tmp = getmntent_r(filep, &mnt, buff, BUFSIZ); +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + return(tmp); + } + +diff --git a/libc/misc/pthread/weaks.c b/libc/misc/pthread/weaks.c +index 89c2611..c27bd10 100644 +--- a/libc/misc/pthread/weaks.c ++++ b/libc/misc/pthread/weaks.c +@@ -21,6 +21,7 @@ + #include <limits.h> + #include <stdlib.h> + ++static void __pthread_return_void __P ((void)); + static int __pthread_return_0 __P ((void)); + static int __pthread_return_1 __P ((void)); + +@@ -104,8 +105,17 @@ weak_alias (__pthread_return_0, __pthrea + weak_alias (__pthread_return_0, __pthread_mutex_trylock) + weak_alias (__pthread_return_0, __pthread_mutex_unlock) + ++weak_alias (__pthread_return_void, _pthread_cleanup_push_defer) ++weak_alias (__pthread_return_void, _pthread_cleanup_pop_restore) ++ + /**********************************************************************/ + ++static void ++__pthread_return_void (void) ++{ ++ return; ++} ++ + static int + __pthread_return_0 (void) + { +diff --git a/libc/misc/syslog/syslog.c b/libc/misc/syslog/syslog.c +index 2b478e1..9e9ddbf 100644 +--- a/libc/misc/syslog/syslog.c ++++ b/libc/misc/syslog/syslog.c +@@ -80,17 +80,9 @@ + #include <ctype.h> + #include <signal.h> + ++#include <bits/uClibc_mutex.h> + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-static pthread_mutex_t mylock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +-# define LOCK __pthread_mutex_lock(&mylock) +-# define UNLOCK __pthread_mutex_unlock(&mylock); +-#else +-# define LOCK +-# define UNLOCK +-#endif +- ++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + + static int LogFile = -1; /* fd for log */ + static int connected; /* have done connect */ +@@ -110,26 +102,26 @@ int setlogmask(int pmask); + static void + closelog_intern(int to_default) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (LogFile != -1) { + (void) close(LogFile); + } + LogFile = -1; + connected = 0; + if (to_default) +- { +- LogStat = 0; +- LogTag = "syslog"; +- LogFacility = LOG_USER; +- LogMask = 0xff; +- } +- UNLOCK; ++ { ++ LogStat = 0; ++ LogTag = "syslog"; ++ LogFacility = LOG_USER; ++ LogMask = 0xff; ++ } ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + + static void + sigpipe_handler (int sig) + { +- closelog_intern (0); ++ closelog_intern (0); + } + + /* +@@ -165,7 +157,7 @@ vsyslog( int pri, const char *fmt, va_li + + saved_errno = errno; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + + /* See if we should just throw out this message. */ + if (!(LogMask & LOG_MASK(LOG_PRI(pri))) || (pri &~ (LOG_PRIMASK|LOG_FACMASK))) +@@ -208,7 +200,7 @@ vsyslog( int pri, const char *fmt, va_li + if (p >= end || p < head_end) { /* Returned -1 in case of error... */ + static const char truncate_msg[12] = "[truncated] "; + memmove(head_end + sizeof(truncate_msg), head_end, +- end - head_end - sizeof(truncate_msg)); ++ end - head_end - sizeof(truncate_msg)); + memcpy(head_end, truncate_msg, sizeof(truncate_msg)); + if (p < head_end) { + while (p < end && *p) { +@@ -261,11 +253,11 @@ vsyslog( int pri, const char *fmt, va_li + (void)close(fd); + } + +-getout: +- UNLOCK; ++ getout: ++ __UCLIBC_MUTEX_UNLOCK(mylock); + if (sigpipe == 0) + sigaction (SIGPIPE, &oldaction, +- (struct sigaction *) NULL); ++ (struct sigaction *) NULL); + } + + /* +@@ -276,48 +268,48 @@ openlog( const char *ident, int logstat, + { + int logType = SOCK_DGRAM; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + + if (ident != NULL) +- LogTag = ident; ++ LogTag = ident; + LogStat = logstat; + if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0) +- LogFacility = logfac; ++ LogFacility = logfac; + if (LogFile == -1) { +- SyslogAddr.sa_family = AF_UNIX; +- (void)strncpy(SyslogAddr.sa_data, _PATH_LOG, +- sizeof(SyslogAddr.sa_data)); +-retry: +- if (LogStat & LOG_NDELAY) { +- if ((LogFile = socket(AF_UNIX, logType, 0)) == -1){ +- UNLOCK; +- return; +- } +- /* fcntl(LogFile, F_SETFD, 1); */ +- } ++ SyslogAddr.sa_family = AF_UNIX; ++ (void)strncpy(SyslogAddr.sa_data, _PATH_LOG, ++ sizeof(SyslogAddr.sa_data)); ++ retry: ++ if (LogStat & LOG_NDELAY) { ++ if ((LogFile = socket(AF_UNIX, logType, 0)) == -1){ ++ goto DONE; ++ } ++ /* fcntl(LogFile, F_SETFD, 1); */ ++ } + } + + if (LogFile != -1 && !connected) { +- if (connect(LogFile, &SyslogAddr, sizeof(SyslogAddr) - +- sizeof(SyslogAddr.sa_data) + strlen(SyslogAddr.sa_data)) != -1) +- { +- connected = 1; +- } else if (logType == SOCK_DGRAM) { +- logType = SOCK_STREAM; +- if (LogFile != -1) { +- close(LogFile); +- LogFile = -1; +- } +- goto retry; +- } else { +- if (LogFile != -1) { +- close(LogFile); +- LogFile = -1; +- } +- } ++ if (connect(LogFile, &SyslogAddr, sizeof(SyslogAddr) - ++ sizeof(SyslogAddr.sa_data) + strlen(SyslogAddr.sa_data)) != -1) ++ { ++ connected = 1; ++ } else if (logType == SOCK_DGRAM) { ++ logType = SOCK_STREAM; ++ if (LogFile != -1) { ++ close(LogFile); ++ LogFile = -1; ++ } ++ goto retry; ++ } else { ++ if (LogFile != -1) { ++ close(LogFile); ++ LogFile = -1; ++ } ++ } + } + +- UNLOCK; ++ DONE: ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + + /* +@@ -335,10 +327,10 @@ int setlogmask(int pmask) + int omask; + + omask = LogMask; +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (pmask != 0) +- LogMask = pmask; +- UNLOCK; ++ LogMask = pmask; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + return (omask); + } + +diff --git a/libc/misc/time/time.c b/libc/misc/time/time.c +index f43bb8a..6165a52 100644 +--- a/libc/misc/time/time.c ++++ b/libc/misc/time/time.c +@@ -143,6 +143,8 @@ + #include <locale.h> + #include <bits/uClibc_uintmaxtostr.h> + ++#include <bits/uClibc_mutex.h> ++ + #ifdef __UCLIBC_HAS_XLOCALE__ + #include <xlocale.h> + #endif +@@ -191,21 +193,7 @@ typedef struct { + char tzname[TZNAME_MAX+1]; + } rule_struct; + +-#ifdef __UCLIBC_HAS_THREADS__ +- +-#include <pthread.h> +- +-extern pthread_mutex_t _time_tzlock; +- +-#define TZLOCK __pthread_mutex_lock(&_time_tzlock) +-#define TZUNLOCK __pthread_mutex_unlock(&_time_tzlock) +- +-#else +- +-#define TZLOCK ((void) 0) +-#define TZUNLOCK ((void) 0) +- +-#endif ++__UCLIBC_MUTEX_EXTERN(_time_tzlock); + + extern rule_struct _time_tzinfo[2]; + +@@ -542,13 +530,13 @@ struct tm *localtime(const time_t *timer + struct tm *localtime_r(register const time_t *__restrict timer, + register struct tm *__restrict result) + { +- TZLOCK; ++ __UCLIBC_MUTEX_LOCK(_time_tzlock); + + tzset(); + + __time_localtime_tzi(timer, result, _time_tzinfo); + +- TZUNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(_time_tzlock); + + return result; + } +@@ -1037,7 +1025,7 @@ size_t __XL(strftime)(char *__restrict s + goto LOOP; + } + +- o = spec + 26; /* set to "????" */ ++ o = ((const char *) spec) + 26; /* set to "????" */ + if ((code & MASK_SPEC) == CALC_SPEC) { + + if (*p == 's') { +@@ -1073,17 +1061,15 @@ size_t __XL(strftime)(char *__restrict s + + #ifdef __UCLIBC_HAS_TM_EXTENSIONS__ + +-#define RSP_TZUNLOCK ((void) 0) + #define RSP_TZNAME timeptr->tm_zone + #define RSP_GMT_OFFSET (-timeptr->tm_gmtoff) + + #else + +-#define RSP_TZUNLOCK TZUNLOCK + #define RSP_TZNAME rsp->tzname + #define RSP_GMT_OFFSET rsp->gmt_offset + +- TZLOCK; ++ __UCLIBC_MUTEX_LOCK(_time_tzlock); + + rsp = _time_tzinfo; + if (timeptr->tm_isdst > 0) { +@@ -1114,15 +1100,17 @@ size_t __XL(strftime)(char *__restrict s + } + #endif + o_count = SIZE_MAX; +- RSP_TZUNLOCK; ++/* RSP_TZUNLOCK; */ ++#ifdef __UCLIBC_HAS_TM_EXTENSIONS__ + goto OUTPUT; ++#endif + } else { /* z */ + *s = '+'; + if ((tzo = -RSP_GMT_OFFSET) < 0) { + tzo = -tzo; + *s = '-'; + } +- RSP_TZUNLOCK; ++/* RSP_TZUNLOCK; */ + ++s; + --count; + +@@ -1131,7 +1119,13 @@ size_t __XL(strftime)(char *__restrict s + + i = 16 + 6; /* 0-fill, width = 4 */ + } +- ++#ifdef __UCLIBC_HAS_TM_EXTENSIONS__ ++#else ++ __UCLIBC_MUTEX_UNLOCK(_time_tzlock); ++ if (*p == 'Z') { ++ goto OUTPUT; ++ } ++#endif + } else { + /* TODO: don't need year for U, W */ + for (i=0 ; i < 3 ; i++) { +@@ -1664,9 +1658,7 @@ int daylight = 0; + long timezone = 0; + char *tzname[2] = { (char *) UTC, (char *) (UTC-1) }; + +-#ifdef __UCLIBC_HAS_THREADS__ +-pthread_mutex_t _time_tzlock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +-#endif ++__UCLIBC_MUTEX_INIT(_time_tzlock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + + rule_struct _time_tzinfo[2]; + +@@ -1796,7 +1788,7 @@ void tzset(void) + static char oldval[TZ_BUFLEN]; /* BSS-zero'd. */ + #endif /* __UCLIBC_HAS_TZ_CACHING__ */ + +- TZLOCK; ++ __UCLIBC_MUTEX_LOCK(_time_tzlock); + + e = getenv(TZ); /* TZ env var always takes precedence. */ + +@@ -1962,10 +1954,10 @@ void tzset(void) + daylight = !!_time_tzinfo[1].tzname[0]; + timezone = _time_tzinfo[0].gmt_offset; + +-#if defined(__UCLIBC_HAS_TZ_FILE__) ++#if defined(__UCLIBC_HAS_TZ_FILE__) || defined(__UCLIBC_HAS_TZ_CACHING__) + FAST_DONE: + #endif +- TZUNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(_time_tzlock); + } + + #endif +@@ -2167,13 +2159,13 @@ time_t _time_mktime(struct tm *timeptr, + { + time_t t; + +- TZLOCK; ++ __UCLIBC_MUTEX_LOCK(_time_tzlock); + + tzset(); + + t = _time_mktime_tzi(timeptr, store_on_success, _time_tzinfo); + +- TZUNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(_time_tzlock); + + return t; + } +diff --git a/libc/misc/ttyent/getttyent.c b/libc/misc/ttyent/getttyent.c +index 6e2fbd2..c85c73a 100644 +--- a/libc/misc/ttyent/getttyent.c ++++ b/libc/misc/ttyent/getttyent.c +@@ -35,9 +35,6 @@ + #include <ctype.h> + #include <string.h> + #include <stdlib.h> +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-#endif + + static char zapchar; + static FILE *tf; +@@ -50,8 +47,8 @@ struct ttyent * getttynam(const char *tt + + setttyent(); + while ((t = getttyent())) +- if (!strcmp(tty, t->ty_name)) +- break; ++ if (!strcmp(tty, t->ty_name)) ++ break; + endttyent(); + return (t); + } +@@ -67,27 +64,27 @@ static char * skip(register char *p) + register int c, q; + + for (q = 0, t = p; (c = *p) != '\0'; p++) { +- if (c == '"') { +- q ^= QUOTED; /* obscure, but nice */ +- continue; +- } +- if (q == QUOTED && *p == '\\' && *(p+1) == '"') +- p++; +- *t++ = *p; +- if (q == QUOTED) +- continue; +- if (c == '#') { +- zapchar = c; +- *p = 0; +- break; +- } +- if (c == '\t' || c == ' ' || c == '\n') { +- zapchar = c; +- *p++ = 0; +- while ((c = *p) == '\t' || c == ' ' || c == '\n') +- p++; +- break; +- } ++ if (c == '"') { ++ q ^= QUOTED; /* obscure, but nice */ ++ continue; ++ } ++ if (q == QUOTED && *p == '\\' && *(p+1) == '"') ++ p++; ++ *t++ = *p; ++ if (q == QUOTED) ++ continue; ++ if (c == '#') { ++ zapchar = c; ++ *p = 0; ++ break; ++ } ++ if (c == '\t' || c == ' ' || c == '\n') { ++ zapchar = c; ++ *p++ = 0; ++ while ((c = *p) == '\t' || c == ' ' || c == '\n') ++ p++; ++ break; ++ } + } + *--t = '\0'; + return (p); +@@ -104,46 +101,46 @@ struct ttyent * getttyent(void) + register int c; + register char *p; + static char *line = NULL; ++ struct ttyent *retval = NULL; + + if (!tf && !setttyent()) +- return (NULL); ++ return (NULL); + + if (!line) { +- line = malloc(BUFSIZ); ++ line = malloc(BUFSIZ); + if (!line) + abort(); + } + +- __STDIO_ALWAYS_THREADLOCK(tf); ++ __STDIO_ALWAYS_THREADLOCK(tf); + + for (;;) { +- if (!fgets_unlocked(p = line, BUFSIZ, tf)) { +- __STDIO_ALWAYS_THREADUNLOCK(tf); +- return (NULL); +- } +- /* skip lines that are too big */ +- if (!index(p, '\n')) { +- while ((c = getc_unlocked(tf)) != '\n' && c != EOF) +- ; +- continue; +- } +- while (isspace(*p)) +- ++p; +- if (*p && *p != '#') +- break; ++ if (!fgets_unlocked(p = line, BUFSIZ, tf)) { ++ goto DONE; ++ } ++ /* skip lines that are too big */ ++ if (!index(p, '\n')) { ++ while ((c = getc_unlocked(tf)) != '\n' && c != EOF) ++ ; ++ continue; ++ } ++ while (isspace(*p)) ++ ++p; ++ if (*p && *p != '#') ++ break; + } + + zapchar = 0; + tty.ty_name = p; + p = skip(p); + if (!*(tty.ty_getty = p)) +- tty.ty_getty = tty.ty_type = NULL; ++ tty.ty_getty = tty.ty_type = NULL; + else { +- p = skip(p); +- if (!*(tty.ty_type = p)) +- tty.ty_type = NULL; +- else +- p = skip(p); ++ p = skip(p); ++ if (!*(tty.ty_type = p)) ++ tty.ty_type = NULL; ++ else ++ p = skip(p); + } + tty.ty_status = 0; + tty.ty_window = NULL; +@@ -151,43 +148,45 @@ struct ttyent * getttyent(void) + #define scmp(e) !strncmp(p, e, sizeof(e) - 1) && isspace(p[sizeof(e) - 1]) + #define vcmp(e) !strncmp(p, e, sizeof(e) - 1) && p[sizeof(e) - 1] == '=' + for (; *p; p = skip(p)) { +- if (scmp(_TTYS_OFF)) +- tty.ty_status &= ~TTY_ON; +- else if (scmp(_TTYS_ON)) +- tty.ty_status |= TTY_ON; +- else if (scmp(_TTYS_SECURE)) +- tty.ty_status |= TTY_SECURE; +- else if (vcmp(_TTYS_WINDOW)) +- tty.ty_window = value(p); +- else +- break; ++ if (scmp(_TTYS_OFF)) ++ tty.ty_status &= ~TTY_ON; ++ else if (scmp(_TTYS_ON)) ++ tty.ty_status |= TTY_ON; ++ else if (scmp(_TTYS_SECURE)) ++ tty.ty_status |= TTY_SECURE; ++ else if (vcmp(_TTYS_WINDOW)) ++ tty.ty_window = value(p); ++ else ++ break; + } +- /* We can release the lock only here since `zapchar' is global. */ +- __STDIO_ALWAYS_THREADUNLOCK(tf); + + if (zapchar == '#' || *p == '#') +- while ((c = *++p) == ' ' || c == '\t') +- ; ++ while ((c = *++p) == ' ' || c == '\t') ++ ; + tty.ty_comment = p; + if (*p == 0) +- tty.ty_comment = 0; ++ tty.ty_comment = 0; + if ((p = index(p, '\n'))) +- *p = '\0'; +- return (&tty); ++ *p = '\0'; ++ retval = &tty; ++ ++ DONE: ++ __STDIO_ALWAYS_THREADUNLOCK(tf); ++ return retval; + } + + int setttyent(void) + { + + if (tf) { +- rewind(tf); +- return (1); ++ rewind(tf); ++ return (1); + } else if ((tf = fopen(_PATH_TTYS, "r"))) { +- /* We do the locking ourselves. */ ++ /* We do the locking ourselves. */ + #ifdef __UCLIBC_HAS_THREADS__ +- __fsetlocking (tf, FSETLOCKING_BYCALLER); ++ __fsetlocking (tf, FSETLOCKING_BYCALLER); + #endif +- return (1); ++ return (1); + } + return (0); + } +@@ -197,9 +196,9 @@ int endttyent(void) + int rval; + + if (tf) { +- rval = !(fclose(tf) == EOF); +- tf = NULL; +- return (rval); ++ rval = !(fclose(tf) == EOF); ++ tf = NULL; ++ return (rval); + } + return (1); + } +diff --git a/libc/misc/utmp/utent.c b/libc/misc/utmp/utent.c +index c1d8d6f..0fc6df4 100644 +--- a/libc/misc/utmp/utent.c ++++ b/libc/misc/utmp/utent.c +@@ -20,19 +20,9 @@ + #include <string.h> + #include <utmp.h> + ++#include <bits/uClibc_mutex.h> + +- +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-static pthread_mutex_t utmplock = PTHREAD_MUTEX_INITIALIZER; +-# define LOCK __pthread_mutex_lock(&utmplock) +-# define UNLOCK __pthread_mutex_unlock(&utmplock) +-#else +-# define LOCK +-# define UNLOCK +-#endif +- +- ++__UCLIBC_MUTEX_STATIC(utmplock, PTHREAD_MUTEX_INITIALIZER); + + /* Some global crap */ + static int static_fd = -1; +@@ -46,19 +36,19 @@ static struct utmp *__getutent(int utmp_ + + { + if (utmp_fd == -1) { +- setutent(); ++ setutent(); + } + if (utmp_fd == -1) { +- return NULL; ++ return NULL; + } + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(utmplock); + if (read(utmp_fd, (char *) &static_utmp, sizeof(struct utmp)) != sizeof(struct utmp)) +- { +- return NULL; +- } ++ { ++ return NULL; ++ } + +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(utmplock); + return &static_utmp; + } + +@@ -66,39 +56,39 @@ void setutent(void) + { + int ret; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(utmplock); + if (static_fd == -1) { +- if ((static_fd = open(static_ut_name, O_RDWR)) < 0) { +- if ((static_fd = open(static_ut_name, O_RDONLY)) < 0) { +- goto bummer; +- } +- } +- /* Make sure the file will be closed on exec() */ +- ret = fcntl(static_fd, F_GETFD, 0); +- if (ret >= 0) { +- ret = fcntl(static_fd, F_GETFD, 0); +- } +- if (ret < 0) { +-bummer: +- UNLOCK; +- static_fd = -1; +- close(static_fd); +- return; +- } ++ if ((static_fd = open(static_ut_name, O_RDWR)) < 0) { ++ if ((static_fd = open(static_ut_name, O_RDONLY)) < 0) { ++ goto bummer; ++ } ++ } ++ /* Make sure the file will be closed on exec() */ ++ ret = fcntl(static_fd, F_GETFD, 0); ++ if (ret >= 0) { ++ ret = fcntl(static_fd, F_GETFD, 0); ++ } ++ if (ret < 0) { ++ bummer: ++ close(static_fd); ++ static_fd = -1; ++ goto DONE; ++ } + } + lseek(static_fd, 0, SEEK_SET); +- UNLOCK; ++ DONE: ++ __UCLIBC_MUTEX_UNLOCK(utmplock); + return; + } + + void endutent(void) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(utmplock); + if (static_fd != -1) { +- close(static_fd); ++ close(static_fd); + } + static_fd = -1; +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(utmplock); + } + + /* Locking is done in __getutent */ +@@ -113,22 +103,22 @@ struct utmp *getutid (const struct utmp + struct utmp *lutmp; + + while ((lutmp = __getutent(static_fd)) != NULL) { +- if ( (utmp_entry->ut_type == RUN_LVL || +- utmp_entry->ut_type == BOOT_TIME || +- utmp_entry->ut_type == NEW_TIME || +- utmp_entry->ut_type == OLD_TIME) && +- lutmp->ut_type == utmp_entry->ut_type) +- { +- return lutmp; +- } +- if ( (utmp_entry->ut_type == INIT_PROCESS || +- utmp_entry->ut_type == DEAD_PROCESS || +- utmp_entry->ut_type == LOGIN_PROCESS || +- utmp_entry->ut_type == USER_PROCESS) && +- !strncmp(lutmp->ut_id, utmp_entry->ut_id, sizeof(lutmp->ut_id))) +- { +- return lutmp; +- } ++ if ( (utmp_entry->ut_type == RUN_LVL || ++ utmp_entry->ut_type == BOOT_TIME || ++ utmp_entry->ut_type == NEW_TIME || ++ utmp_entry->ut_type == OLD_TIME) && ++ lutmp->ut_type == utmp_entry->ut_type) ++ { ++ return lutmp; ++ } ++ if ( (utmp_entry->ut_type == INIT_PROCESS || ++ utmp_entry->ut_type == DEAD_PROCESS || ++ utmp_entry->ut_type == LOGIN_PROCESS || ++ utmp_entry->ut_type == USER_PROCESS) && ++ !strncmp(lutmp->ut_id, utmp_entry->ut_id, sizeof(lutmp->ut_id))) ++ { ++ return lutmp; ++ } + } + + return NULL; +@@ -140,11 +130,11 @@ struct utmp *getutline(const struct utmp + struct utmp *lutmp; + + while ((lutmp = __getutent(static_fd)) != NULL) { +- if ((lutmp->ut_type == USER_PROCESS || lutmp->ut_type == LOGIN_PROCESS) && +- !strcmp(lutmp->ut_line, utmp_entry->ut_line)) +- { +- return lutmp; +- } ++ if ((lutmp->ut_type == USER_PROCESS || lutmp->ut_type == LOGIN_PROCESS) && ++ !strcmp(lutmp->ut_line, utmp_entry->ut_line)) ++ { ++ return lutmp; ++ } + } + + return NULL; +@@ -152,42 +142,42 @@ struct utmp *getutline(const struct utmp + + struct utmp *pututline (const struct utmp *utmp_entry) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(utmplock); + /* Ignore the return value. That way, if they've already positioned + the file pointer where they want it, everything will work out. */ + lseek(static_fd, (off_t) - sizeof(struct utmp), SEEK_CUR); + + if (getutid(utmp_entry) != NULL) { +- lseek(static_fd, (off_t) - sizeof(struct utmp), SEEK_CUR); +- if (write(static_fd, utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp)) +- return NULL; ++ lseek(static_fd, (off_t) - sizeof(struct utmp), SEEK_CUR); ++ if (write(static_fd, utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp)) ++ return NULL; + } else { +- lseek(static_fd, (off_t) 0, SEEK_END); +- if (write(static_fd, utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp)) +- return NULL; ++ lseek(static_fd, (off_t) 0, SEEK_END); ++ if (write(static_fd, utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp)) ++ return NULL; + } + +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(utmplock); + return (struct utmp *)utmp_entry; + } + + int utmpname (const char *new_ut_name) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(utmplock); + if (new_ut_name != NULL) { +- if (static_ut_name != default_file_name) +- free((char *)static_ut_name); +- static_ut_name = strdup(new_ut_name); +- if (static_ut_name == NULL) { +- /* We should probably whine about out-of-memory +- * errors here... Instead just reset to the default */ +- static_ut_name = default_file_name; +- } ++ if (static_ut_name != default_file_name) ++ free((char *)static_ut_name); ++ static_ut_name = strdup(new_ut_name); ++ if (static_ut_name == NULL) { ++ /* We should probably whine about out-of-memory ++ * errors here... Instead just reset to the default */ ++ static_ut_name = default_file_name; ++ } + } + + if (static_fd != -1) +- close(static_fd); +- UNLOCK; ++ close(static_fd); ++ __UCLIBC_MUTEX_UNLOCK(utmplock); + return 0; + } + +diff --git a/libc/misc/wchar/wstdio.c b/libc/misc/wchar/wstdio.c +index b49494f..408c57a 100644 +--- a/libc/misc/wchar/wstdio.c ++++ b/libc/misc/wchar/wstdio.c +@@ -82,9 +82,6 @@ strong_alias(NAME,NAME##_unlocked) \ + void NAME PARAMS + #endif + +-#define __STDIO_THREADLOCK_OPENLIST +-#define __STDIO_THREADUNLOCK_OPENLIST +- + #else /* __UCLIBC_HAS_THREADS__ */ + + #include <pthread.h> +@@ -112,15 +109,6 @@ void NAME PARAMS \ + } \ + void NAME##_unlocked PARAMS + +-#define __STDIO_THREADLOCK_OPENLIST \ +- __pthread_mutex_lock(&_stdio_openlist_lock) +- +-#define __STDIO_THREADUNLOCK_OPENLIST \ +- __pthread_mutex_unlock(&_stdio_openlist_lock) +- +-#define __STDIO_THREADTRYLOCK_OPENLIST \ +- __pthread_mutex_trylock(&_stdio_openlist_lock) +- + #endif /* __UCLIBC_HAS_THREADS__ */ + + #ifndef __STDIO_BUFFERS +diff --git a/libc/pwd_grp/lckpwdf.c b/libc/pwd_grp/lckpwdf.c +index 6b9c251..063fed4 100644 +--- a/libc/pwd_grp/lckpwdf.c ++++ b/libc/pwd_grp/lckpwdf.c +@@ -27,15 +27,9 @@ + #include <sys/file.h> + #include <paths.h> + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER; +-# define LOCK __pthread_mutex_lock(&mylock) +-# define UNLOCK __pthread_mutex_unlock(&mylock); +-#else +-# define LOCK +-# define UNLOCK +-#endif ++#include <bits/uClibc_mutex.h> ++ ++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + + /* How long to wait for getting the lock before returning with an + error. */ +@@ -57,18 +51,18 @@ int lckpwdf (void) + struct sigaction new_act; /* New signal action. */ + struct flock fl; /* Information struct for locking. */ + int result; ++ int rv = -1; + + if (lock_fd != -1) + /* Still locked by own process. */ + return -1; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + + lock_fd = open (_PATH_PASSWD, O_WRONLY); + if (lock_fd == -1) { + /* Cannot create lock file. */ +- UNLOCK; +- return -1; ++ goto DONE; + } + + /* Make sure file gets correctly closed when process finished. */ +@@ -77,16 +71,14 @@ int lckpwdf (void) + /* Cannot get file flags. */ + close(lock_fd); + lock_fd = -1; +- UNLOCK; +- return -1; ++ goto DONE; + } + flags |= FD_CLOEXEC; /* Close on exit. */ + if (fcntl (lock_fd, F_SETFD, flags) < 0) { + /* Cannot set new flags. */ + close(lock_fd); + lock_fd = -1; +- UNLOCK; +- return -1; ++ goto DONE; + } + + /* Now we have to get exclusive write access. Since multiple +@@ -107,8 +99,7 @@ int lckpwdf (void) + /* Cannot install signal handler. */ + close(lock_fd); + lock_fd = -1; +- UNLOCK; +- return -1; ++ goto DONE; + } + + /* Now make sure the alarm signal is not blocked. */ +@@ -118,8 +109,7 @@ int lckpwdf (void) + sigaction (SIGALRM, &saved_act, NULL); + close(lock_fd); + lock_fd = -1; +- UNLOCK; +- return -1; ++ goto DONE; + } + + /* Start timer. If we cannot get the lock in the specified time we +@@ -146,12 +136,14 @@ int lckpwdf (void) + if (result < 0) { + close(lock_fd); + lock_fd = -1; +- UNLOCK; +- return -1; ++ goto DONE; + } + +- UNLOCK; +- return 0; ++ rv = 0; ++ ++ DONE: ++ __UCLIBC_MUTEX_UNLOCK(mylock); ++ return rv; + } + + +@@ -164,11 +156,11 @@ int ulckpwdf (void) + result = -1; + } + else { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + result = close (lock_fd); + /* Mark descriptor as unused. */ + lock_fd = -1; +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + + return result; +diff --git a/libc/pwd_grp/pwd_grp.c b/libc/pwd_grp/pwd_grp.c +index 91c0d83..a302c7c 100644 +--- a/libc/pwd_grp/pwd_grp.c ++++ b/libc/pwd_grp/pwd_grp.c +@@ -42,9 +42,8 @@ + #include <pwd.h> + #include <grp.h> + #include <shadow.h> +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-#endif ++ ++#include <bits/uClibc_mutex.h> + + /**********************************************************************/ + /* Sizes for staticly allocated buffers. */ +@@ -445,34 +444,27 @@ int getpw(uid_t uid, char *buf) + /**********************************************************************/ + #ifdef L_getpwent_r + +-#ifdef __UCLIBC_HAS_THREADS__ +-static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER; +-# define LOCK __pthread_mutex_lock(&mylock) +-# define UNLOCK __pthread_mutex_unlock(&mylock); +-#else +-# define LOCK ((void) 0) +-# define UNLOCK ((void) 0) +-#endif ++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + + static FILE *pwf /*= NULL*/; + + void setpwent(void) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (pwf) { + rewind(pwf); + } +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + + void endpwent(void) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (pwf) { + fclose(pwf); + pwf = NULL; + } +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + + +@@ -482,7 +474,7 @@ int getpwent_r(struct passwd *__restrict + { + int rv; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + + *result = NULL; /* In case of error... */ + +@@ -500,7 +492,7 @@ int getpwent_r(struct passwd *__restrict + } + + ERR: +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + + return rv; + } +@@ -509,34 +501,27 @@ int getpwent_r(struct passwd *__restrict + /**********************************************************************/ + #ifdef L_getgrent_r + +-#ifdef __UCLIBC_HAS_THREADS__ +-static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER; +-# define LOCK __pthread_mutex_lock(&mylock) +-# define UNLOCK __pthread_mutex_unlock(&mylock); +-#else +-# define LOCK ((void) 0) +-# define UNLOCK ((void) 0) +-#endif ++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + + static FILE *grf /*= NULL*/; + + void setgrent(void) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (grf) { + rewind(grf); + } +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + + void endgrent(void) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (grf) { + fclose(grf); + grf = NULL; + } +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + + int getgrent_r(struct group *__restrict resultbuf, +@@ -545,7 +530,7 @@ int getgrent_r(struct group *__restrict + { + int rv; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + + *result = NULL; /* In case of error... */ + +@@ -563,7 +548,7 @@ int getgrent_r(struct group *__restrict + } + + ERR: +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + + return rv; + } +@@ -572,34 +557,27 @@ int getgrent_r(struct group *__restrict + /**********************************************************************/ + #ifdef L_getspent_r + +-#ifdef __UCLIBC_HAS_THREADS__ +-static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER; +-# define LOCK __pthread_mutex_lock(&mylock) +-# define UNLOCK __pthread_mutex_unlock(&mylock); +-#else +-# define LOCK ((void) 0) +-# define UNLOCK ((void) 0) +-#endif ++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + + static FILE *spf /*= NULL*/; + + void setspent(void) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (spf) { + rewind(spf); + } +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + + void endspent(void) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (spf) { + fclose(spf); + spf = NULL; + } +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + + int getspent_r(struct spwd *resultbuf, char *buffer, +@@ -607,7 +585,7 @@ int getspent_r(struct spwd *resultbuf, c + { + int rv; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + + *result = NULL; /* In case of error... */ + +@@ -625,7 +603,7 @@ int getspent_r(struct spwd *resultbuf, c + } + + ERR: +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + + return rv; + } +diff --git a/libc/stdio/_READ.c b/libc/stdio/_READ.c +index 7d3c38c..fe1bc91 100644 +--- a/libc/stdio/_READ.c ++++ b/libc/stdio/_READ.c +@@ -41,7 +41,7 @@ size_t __stdio_READ(register FILE *strea + #warning EINTR? + #endif + /* RETRY: */ +- if ((rv = __READ(stream, buf, bufsize)) <= 0) { ++ if ((rv = __READ(stream, (char *) buf, bufsize)) <= 0) { + if (rv == 0) { + __STDIO_STREAM_SET_EOF(stream); + } else { +diff --git a/libc/stdio/_WRITE.c b/libc/stdio/_WRITE.c +index d300d39..4131eb7 100644 +--- a/libc/stdio/_WRITE.c ++++ b/libc/stdio/_WRITE.c +@@ -47,7 +47,7 @@ size_t __stdio_WRITE(register FILE *stre + return bufsize; + } + stodo = (todo <= SSIZE_MAX) ? todo : SSIZE_MAX; +- if ((rv = __WRITE(stream, buf, stodo)) >= 0) { ++ if ((rv = __WRITE(stream, (char *) buf, stodo)) >= 0) { + #ifdef __UCLIBC_MJN3_ONLY__ + #warning TODO: Make custom stream write return check optional. + #endif +diff --git a/libc/stdio/_fopen.c b/libc/stdio/_fopen.c +index f7f5bb6..4984f11 100644 +--- a/libc/stdio/_fopen.c ++++ b/libc/stdio/_fopen.c +@@ -194,10 +194,23 @@ FILE *_stdio_fopen(intptr_t fname_or_mod + #endif + + #ifdef __STDIO_HAS_OPENLIST +- __STDIO_THREADLOCK_OPENLIST; +- stream->__nextopen = _stdio_openlist; /* New files are inserted at */ +- _stdio_openlist = stream; /* the head of the list. */ +- __STDIO_THREADUNLOCK_OPENLIST; ++#if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS) ++ if (!(stream->__modeflags & __FLAG_FREEFILE)) ++ { ++ /* An freopen call so the file was never removed from the list. */ ++ } ++ else ++#endif ++ { ++ /* We have to lock the del mutex in case another thread wants to fclose() ++ * the last file. */ ++ __STDIO_THREADLOCK_OPENLIST_DEL; ++ __STDIO_THREADLOCK_OPENLIST_ADD; ++ stream->__nextopen = _stdio_openlist; /* New files are inserted at */ ++ _stdio_openlist = stream; /* the head of the list. */ ++ __STDIO_THREADUNLOCK_OPENLIST_ADD; ++ __STDIO_THREADUNLOCK_OPENLIST_DEL; ++ } + #endif + + __STDIO_STREAM_VALIDATE(stream); +diff --git a/libc/stdio/_stdio.c b/libc/stdio/_stdio.c +index 4aae3c4..9cfe02c 100644 +--- a/libc/stdio/_stdio.c ++++ b/libc/stdio/_stdio.c +@@ -151,8 +151,12 @@ FILE *__stdout = _stdio_streams + 1; /* + FILE *_stdio_openlist = _stdio_streams; + + # ifdef __UCLIBC_HAS_THREADS__ +-pthread_mutex_t _stdio_openlist_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +-int _stdio_openlist_delflag = 0; ++__UCLIBC_MUTEX_INIT(_stdio_openlist_add_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); ++#ifdef __STDIO_BUFFERS ++__UCLIBC_MUTEX_INIT(_stdio_openlist_del_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); ++volatile int _stdio_openlist_use_count = 0; ++int _stdio_openlist_del_count = 0; ++#endif + # endif + + #endif +@@ -162,10 +166,10 @@ int _stdio_openlist_delflag = 0; + /* 2 if threading not initialized and 0 otherwise; */ + int _stdio_user_locking = 2; + +-void __stdio_init_mutex(pthread_mutex_t *m) ++void __stdio_init_mutex(__UCLIBC_MUTEX_TYPE *m) + { +- static const pthread_mutex_t __stdio_mutex_initializer +- = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; ++ const __UCLIBC_MUTEX_STATIC(__stdio_mutex_initializer, ++ PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + + memcpy(m, &__stdio_mutex_initializer, sizeof(__stdio_mutex_initializer)); + } +@@ -184,7 +188,11 @@ void _stdio_term(void) + * locked, then I suppose there is a chance that a pointer in the + * chain might be corrupt due to a partial store. + */ +- __stdio_init_mutex(&_stdio_openlist_lock); ++ __stdio_init_mutex(&_stdio_openlist_add_lock); ++#warning check ++#ifdef __STDIO_BUFFERS ++ __stdio_init_mutex(&_stdio_openlist_del_lock); ++#endif + + /* Next we need to worry about the streams themselves. If a stream + * is currently locked, then it may be in an invalid state. So we +@@ -192,7 +200,7 @@ void _stdio_term(void) + * Then we reinitialize the locks. + */ + for (ptr = _stdio_openlist ; ptr ; ptr = ptr->__nextopen ) { +- if (__STDIO_ALWAYS_THREADTRYLOCK(ptr)) { ++ if (__STDIO_ALWAYS_THREADTRYLOCK_CANCEL_UNSAFE(ptr)) { + /* The stream is already locked, so we don't want to touch it. + * However, if we have custom streams, we can't just close it + * or leave it locked since a custom stream may be stacked +@@ -258,10 +266,6 @@ void _stdio_init(void) + #error Assumption violated about __MASK_READING and __FLAG_UNGOT + #endif + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-#endif +- + #ifndef NDEBUG + + void _stdio_validate_FILE(const FILE *stream) +diff --git a/libc/stdio/_stdio.h b/libc/stdio/_stdio.h +index e3c2c58..decf57d 100644 +--- a/libc/stdio/_stdio.h ++++ b/libc/stdio/_stdio.h +@@ -22,23 +22,57 @@ + #include <wchar.h> + #endif + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> ++#include <bits/uClibc_mutex.h> + +-#define __STDIO_THREADLOCK_OPENLIST \ +- __pthread_mutex_lock(&_stdio_openlist_lock) ++#define __STDIO_THREADLOCK_OPENLIST_ADD \ ++ __UCLIBC_MUTEX_LOCK(_stdio_openlist_add_lock) + +-#define __STDIO_THREADUNLOCK_OPENLIST \ +- __pthread_mutex_unlock(&_stdio_openlist_lock) ++#define __STDIO_THREADUNLOCK_OPENLIST_ADD \ ++ __UCLIBC_MUTEX_UNLOCK(_stdio_openlist_add_lock) + +-#define __STDIO_THREADTRYLOCK_OPENLIST \ +- __pthread_mutex_trylock(&_stdio_openlist_lock) ++#ifdef __STDIO_BUFFERS + +-#else ++#define __STDIO_THREADLOCK_OPENLIST_DEL \ ++ __UCLIBC_MUTEX_LOCK(_stdio_openlist_del_lock) ++ ++#define __STDIO_THREADUNLOCK_OPENLIST_DEL \ ++ __UCLIBC_MUTEX_UNLOCK(_stdio_openlist_del_lock) + +-#define __STDIO_THREADLOCK_OPENLIST ((void)0) +-#define __STDIO_THREADUNLOCK_OPENLIST ((void)0) ++#define __STDIO_OPENLIST_INC_USE \ ++do { \ ++ __STDIO_THREADLOCK_OPENLIST_DEL; \ ++ ++_stdio_openlist_use_count; \ ++ __STDIO_THREADUNLOCK_OPENLIST_DEL; \ ++} while (0) ++ ++extern void _stdio_openlist_dec_use(void); ++ ++#define __STDIO_OPENLIST_DEC_USE \ ++ _stdio_openlist_dec_use() ++ ++#define __STDIO_OPENLIST_INC_DEL_CNT \ ++do { \ ++ __STDIO_THREADLOCK_OPENLIST_DEL; \ ++ ++_stdio_openlist_del_count; \ ++ __STDIO_THREADUNLOCK_OPENLIST_DEL; \ ++} while (0) ++ ++#define __STDIO_OPENLIST_DEC_DEL_CNT \ ++do { \ ++ __STDIO_THREADLOCK_OPENLIST_DEL; \ ++ --_stdio_openlist_del_count; \ ++ __STDIO_THREADUNLOCK_OPENLIST_DEL; \ ++} while (0) ++ ++#endif /* __STDIO_BUFFERS */ + ++#ifndef __STDIO_THREADLOCK_OPENLIST_DEL ++#define __STDIO_THREADLOCK_OPENLIST_DEL ((void)0) ++#define __STDIO_THREADUNLOCK_OPENLIST_DEL ((void)0) ++#define __STDIO_OPENLIST_INC_USE ((void)0) ++#define __STDIO_OPENLIST_DEC_USE ((void)0) ++#define __STDIO_OPENLIST_INC_DEL_CNT ((void)0) ++#define __STDIO_OPENLIST_DEC_DEL_CNT ((void)0) + #endif + + #define __UNDEFINED_OR_NONPORTABLE ((void)0) +diff --git a/libc/stdio/fclose.c b/libc/stdio/fclose.c +index 4df2e42..dfababc 100644 +--- a/libc/stdio/fclose.c ++++ b/libc/stdio/fclose.c +@@ -12,30 +12,34 @@ int fclose(register FILE *stream) + int rv = 0; + __STDIO_AUTO_THREADLOCK_VAR; + +- /* First, remove the file from the open file list. */ +-#ifdef __STDIO_HAS_OPENLIST +- { +- register FILE *ptr; +- +- __STDIO_THREADLOCK_OPENLIST; +- if ((ptr = _stdio_openlist) == stream) { +- _stdio_openlist = stream->__nextopen; +- } else { +- while (ptr) { +- if (ptr->__nextopen == stream) { +- ptr->__nextopen = stream->__nextopen; +- break; +- } +- ptr = ptr->__nextopen; +- } +- } +- __STDIO_THREADUNLOCK_OPENLIST; +- +- if (!ptr) { /* Did not find stream in the open file list! */ +- return EOF; +- } +- } +-#endif ++#warning dead code... but may want to simply check and not remove ++/* #ifdef __STDIO_HAS_OPENLIST */ ++/* #if !defined(__UCLIBC_HAS_THREADS__) || !defined(__STDIO_BUFFERS) */ ++/* /\* First, remove the file from the open file list. *\/ */ ++/* { */ ++/* register FILE *ptr; */ ++ ++/* __STDIO_THREADLOCK_OPENLIST; */ ++/* if ((ptr = _stdio_openlist) == stream) { */ ++/* #warning does a mod!!! */ ++/* _stdio_openlist = stream->__nextopen; */ ++/* } else { */ ++/* while (ptr) { */ ++/* if (ptr->__nextopen == stream) { */ ++/* ptr->__nextopen = stream->__nextopen; */ ++/* break; */ ++/* } */ ++/* ptr = ptr->__nextopen; */ ++/* } */ ++/* } */ ++/* __STDIO_THREADUNLOCK_OPENLIST; */ ++ ++/* if (!ptr) { /\* Did not find stream in the open file list! *\/ */ ++/* return EOF; */ ++/* } */ ++/* } */ ++/* #endif */ ++/* #endif */ + + __STDIO_AUTO_THREADLOCK(stream); + +@@ -80,7 +84,15 @@ int fclose(register FILE *stream) + __STDIO_AUTO_THREADUNLOCK(stream); + + __STDIO_STREAM_FREE_BUFFER(stream); ++#warning... inefficient - locks and unlocks twice and walks whole list ++#if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS) ++ /* inefficient - locks/unlocks twice and walks whole list */ ++ __STDIO_OPENLIST_INC_USE; ++ __STDIO_OPENLIST_INC_DEL_CNT; ++ __STDIO_OPENLIST_DEC_USE; /* This with free the file if necessary. */ ++#else + __STDIO_STREAM_FREE_FILE(stream); ++#endif + + return rv; + } +diff --git a/libc/stdio/fcloseall.c b/libc/stdio/fcloseall.c +index dbb6000..f62281a 100644 +--- a/libc/stdio/fcloseall.c ++++ b/libc/stdio/fcloseall.c +@@ -19,14 +19,34 @@ int fcloseall (void) + #ifdef __STDIO_HAS_OPENLIST + + int retval = 0; ++ FILE *f; + +- __STDIO_THREADLOCK_OPENLIST; +- while (_stdio_openlist) { +- if (fclose(_stdio_openlist)) { ++#warning remove dead code ++/* __STDIO_THREADLOCK_OPENLIST; */ ++/* while (_stdio_openlist) { */ ++/* if (fclose(_stdio_openlist)) { */ ++/* retval = EOF; */ ++/* } */ ++/* } */ ++/* __STDIO_THREADUNLOCK_OPENLIST; */ ++ ++ __STDIO_OPENLIST_INC_USE; ++ ++#warning should probably have a get_head() operation ++ __STDIO_THREADLOCK_OPENLIST_ADD; ++ f = _stdio_openlist; ++ __STDIO_THREADUNLOCK_OPENLIST_ADD; ++ ++ while (f) { ++#warning should probably have a get_next() operation ++ FILE *n = f->__nextopen; ++ if (fclose(f)) { + retval = EOF; + } ++ f = n; + } +- __STDIO_THREADUNLOCK_OPENLIST; ++ ++ __STDIO_OPENLIST_DEC_USE; + + return retval; + +diff --git a/libc/stdio/fflush.c b/libc/stdio/fflush.c +index 6baa0ec..66b65cd 100644 +--- a/libc/stdio/fflush.c ++++ b/libc/stdio/fflush.c +@@ -20,23 +20,50 @@ weak_alias(__fflush_unlocked,fflush_unlo + weak_alias(__fflush_unlocked,fflush); + #endif + +-#ifdef __UCLIBC_HAS_THREADS__ + /* Even if the stream is set to user-locking, we still need to lock + * when all (lbf) writing streams are flushed. */ +-#define MY_STDIO_THREADLOCK(STREAM) \ +- if (_stdio_user_locking != 2) { \ +- __STDIO_ALWAYS_THREADLOCK(STREAM); \ +- } + +-#define MY_STDIO_THREADUNLOCK(STREAM) \ +- if (_stdio_user_locking != 2) { \ +- __STDIO_ALWAYS_THREADUNLOCK(STREAM); \ +- } +-#else +-#define MY_STDIO_THREADLOCK(STREAM) ((void)0) +-#define MY_STDIO_THREADUNLOCK(STREAM) ((void)0) +-#endif ++#define __MY_STDIO_THREADLOCK(__stream) \ ++ __UCLIBC_MUTEX_CONDITIONAL_LOCK((__stream)->__lock, \ ++ (_stdio_user_locking != 2)) ++ ++#define __MY_STDIO_THREADUNLOCK(__stream) \ ++ __UCLIBC_MUTEX_CONDITIONAL_UNLOCK((__stream)->__lock, \ ++ (_stdio_user_locking != 2)) + ++#if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS) ++void _stdio_openlist_dec_use(void) ++{ ++ __STDIO_THREADLOCK_OPENLIST_DEL; ++ if ((_stdio_openlist_use_count == 1) && (_stdio_openlist_del_count > 0)) { ++ FILE *p = NULL; ++ FILE *n; ++ FILE *stream; ++ ++ __STDIO_THREADLOCK_OPENLIST_ADD; ++ for (stream = _stdio_openlist; stream; stream = n) { ++#warning walk the list and clear out all fclosed()d files ++ n = stream->__nextopen; ++#warning fix for nonatomic ++ if ((stream->__modeflags & (__FLAG_READONLY|__FLAG_WRITEONLY)) ++ == (__FLAG_READONLY|__FLAG_WRITEONLY) ++ ) { /* The file was closed so remove from the list. */ ++ if (!p) { ++ _stdio_openlist = n; ++ } else { ++ p->__nextopen = n; ++ } ++ __STDIO_STREAM_FREE_FILE(stream); ++ } else { ++ p = stream; ++ } ++ } ++ __STDIO_THREADUNLOCK_OPENLIST_DEL; ++ } ++ --_stdio_openlist_use_count; ++ __STDIO_THREADUNLOCK_OPENLIST_DEL; ++} ++#endif + + int __fflush_unlocked(register FILE *stream) + { +@@ -60,23 +87,39 @@ int __fflush_unlocked(register FILE *str + } + + if (!stream) { /* Flush all (lbf) writing streams. */ +- __STDIO_THREADLOCK_OPENLIST; +- for (stream = _stdio_openlist; stream ; stream = stream->__nextopen) { +- MY_STDIO_THREADLOCK(stream); +- if (!(((stream->__modeflags | bufmask) +- ^ (__FLAG_WRITING|__FLAG_LBF) +- ) & (__FLAG_WRITING|__MASK_BUFMODE)) +- ) { +- if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) { +- __STDIO_STREAM_DISABLE_PUTC(stream); +- __STDIO_STREAM_CLEAR_WRITING(stream); +- } else { +- retval = EOF; ++ ++ __STDIO_OPENLIST_INC_USE; ++ ++ __STDIO_THREADLOCK_OPENLIST_ADD; ++ stream = _stdio_openlist; ++ __STDIO_THREADUNLOCK_OPENLIST_ADD; ++ ++ while(stream) { ++ /* We only care about currently writing streams and do not want to ++ * block trying to obtain mutexes on non-writing streams. */ ++#warning fix for nonatomic ++#warning unnecessary check if no threads ++ if (__STDIO_STREAM_IS_WRITING(stream)) { /* ONLY IF ATOMIC!!! */ ++ __MY_STDIO_THREADLOCK(stream); ++ /* Need to check again once we have the lock. */ ++ if (!(((stream->__modeflags | bufmask) ++ ^ (__FLAG_WRITING|__FLAG_LBF) ++ ) & (__FLAG_WRITING|__MASK_BUFMODE)) ++ ) { ++ if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) { ++ __STDIO_STREAM_DISABLE_PUTC(stream); ++ __STDIO_STREAM_CLEAR_WRITING(stream); ++ } else { ++ retval = EOF; ++ } + } ++ __MY_STDIO_THREADUNLOCK(stream); + } +- MY_STDIO_THREADUNLOCK(stream); ++ stream = stream->__nextopen; + } +- __STDIO_THREADUNLOCK_OPENLIST; ++ ++ __STDIO_OPENLIST_DEC_USE; ++ + } else if (__STDIO_STREAM_IS_WRITING(stream)) { + if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) { + __STDIO_STREAM_DISABLE_PUTC(stream); +diff --git a/libc/stdio/flockfile.c b/libc/stdio/flockfile.c +index 0dcc7c2..3fad711 100644 +--- a/libc/stdio/flockfile.c ++++ b/libc/stdio/flockfile.c +@@ -11,6 +11,6 @@ void flockfile(FILE *stream) + { + __STDIO_STREAM_VALIDATE(stream); + +- __STDIO_ALWAYS_THREADLOCK(stream); ++ __STDIO_ALWAYS_THREADLOCK_CANCEL_UNSAFE(stream); + } + +diff --git a/libc/stdio/freopen.c b/libc/stdio/freopen.c +index 0eccaac..36b8488 100644 +--- a/libc/stdio/freopen.c ++++ b/libc/stdio/freopen.c +@@ -42,6 +42,8 @@ FILE *freopen(const char * __restrict fi + + __STDIO_STREAM_VALIDATE(stream); + ++ __STDIO_OPENLIST_INC_USE; /* Do not remove the file from the list. */ ++ + /* First, flush and close, but don't deallocate, the stream. */ + /* This also removes the stream for the open file list. */ + dynmode = (stream->__modeflags & (__FLAG_FREEBUF|__FLAG_FREEFILE)); +@@ -57,9 +59,16 @@ FILE *freopen(const char * __restrict fi + + fp = _stdio_fopen(((intptr_t) filename), mode, stream, FILEDES_ARG); + ++#warning if fp is NULL, then we do not free file (but beware stdin,stdout,stderr) ++ if (fp) { ++ __STDIO_OPENLIST_DEC_DEL_CNT; ++ } ++ + /* Reset the allocation flags. */ + stream->__modeflags |= dynmode; + ++ __STDIO_OPENLIST_DEC_USE; ++ + __STDIO_AUTO_THREADUNLOCK(stream); + + return fp; +diff --git a/libc/stdio/ftello.c b/libc/stdio/ftello.c +index 7092f34..69385ce 100644 +--- a/libc/stdio/ftello.c ++++ b/libc/stdio/ftello.c +@@ -48,7 +48,10 @@ OFFSET_TYPE FTELL(register FILE *stream) + + __STDIO_STREAM_VALIDATE(stream); + +- if ((__SEEK(stream, &pos, SEEK_CUR) < 0) ++ if ((__SEEK(stream, &pos, ++ ((__STDIO_STREAM_IS_WRITING(stream) ++ && (stream->__modeflags & __FLAG_APPEND)) ++ ? SEEK_END : SEEK_CUR)) < 0) + || (__stdio_adjust_position(stream, &pos) < 0)) { + pos = -1; + } +diff --git a/libc/stdio/ftrylockfile.c b/libc/stdio/ftrylockfile.c +index d85b8ff..0d2e156 100644 +--- a/libc/stdio/ftrylockfile.c ++++ b/libc/stdio/ftrylockfile.c +@@ -15,5 +15,5 @@ int ftrylockfile(FILE *stream) + { + __STDIO_STREAM_VALIDATE(stream); + +- return __STDIO_ALWAYS_THREADTRYLOCK(stream); ++ return __STDIO_ALWAYS_THREADTRYLOCK_CANCEL_UNSAFE(stream); + } +diff --git a/libc/stdio/funlockfile.c b/libc/stdio/funlockfile.c +index 048c093..2ddf097 100644 +--- a/libc/stdio/funlockfile.c ++++ b/libc/stdio/funlockfile.c +@@ -11,5 +11,5 @@ void funlockfile(FILE *stream) + { + __STDIO_STREAM_VALIDATE(stream); + +- __STDIO_ALWAYS_THREADUNLOCK(stream); ++ __STDIO_ALWAYS_THREADUNLOCK_CANCEL_UNSAFE(stream); + } +diff --git a/libc/stdio/popen.c b/libc/stdio/popen.c +index c7887ad..ab8d296 100644 +--- a/libc/stdio/popen.c ++++ b/libc/stdio/popen.c +@@ -14,6 +14,7 @@ + * Fix failure exit code for failed execve(). + */ + ++#warning hmm... susv3 says "Pipe streams are byte-oriented." + + #include <stdio.h> + #include <stdlib.h> +@@ -21,6 +22,8 @@ + #include <unistd.h> + #include <sys/wait.h> + ++#include <bits/uClibc_mutex.h> ++ + /* uClinux-2.0 has vfork, but Linux 2.0 doesn't */ + #include <sys/syscall.h> + #if ! defined __NR_vfork +@@ -29,19 +32,11 @@ + # define VFORK_UNLOCK ((void) 0) + #endif + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER; +-# define LOCK __pthread_mutex_lock(&mylock) +-# define UNLOCK __pthread_mutex_unlock(&mylock); +-#else +-# define LOCK ((void) 0) +-# define UNLOCK ((void) 0) +-#endif ++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + + #ifndef VFORK_LOCK +-# define VFORK_LOCK LOCK +-# define VFORK_UNLOCK UNLOCK ++# define VFORK_LOCK __UCLIBC_MUTEX_LOCK(mylock) ++# define VFORK_UNLOCK __UCLIBC_MUTEX_UNLOCK(mylock) + #endif + + struct popen_list_item { +@@ -118,10 +113,10 @@ FILE *popen(const char *command, const c + if (pid > 0) { /* Parent of vfork... */ + pi->pid = pid; + pi->f = fp; +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + pi->next = popen_list; + popen_list = pi; +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + + return fp; + } +@@ -136,6 +131,8 @@ FILE *popen(const char *command, const c + return NULL; + } + ++#warning is pclose correct wrt the new mutex semantics? ++ + int pclose(FILE *stream) + { + struct popen_list_item *p; +@@ -144,7 +141,7 @@ int pclose(FILE *stream) + + /* First, find the list entry corresponding to stream and remove it + * from the list. Set p to the list item (NULL if not found). */ +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if ((p = popen_list) != NULL) { + if (p->f == stream) { + popen_list = p->next; +@@ -163,7 +160,7 @@ int pclose(FILE *stream) + } while (1); + } + } +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + + if (p) { + pid = p->pid; /* Save the pid we need */ +diff --git a/libc/stdio/setvbuf.c b/libc/stdio/setvbuf.c +index 3fe62c6..6d53ab1 100644 +--- a/libc/stdio/setvbuf.c ++++ b/libc/stdio/setvbuf.c +@@ -75,8 +75,8 @@ int setvbuf(register FILE * __restrict s + } + + stream->__modeflags |= alloc_flag; +- stream->__bufstart = buf; +- stream->__bufend = buf + size; ++ stream->__bufstart = (unsigned char *) buf; ++ stream->__bufend = (unsigned char *) buf + size; + __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream); + __STDIO_STREAM_DISABLE_GETC(stream); + __STDIO_STREAM_DISABLE_PUTC(stream); +diff --git a/libc/stdio/vasprintf.c b/libc/stdio/vasprintf.c +index 688ab7c..6d7664d 100644 +--- a/libc/stdio/vasprintf.c ++++ b/libc/stdio/vasprintf.c +@@ -63,6 +63,8 @@ int vasprintf(char **__restrict buf, con + free(*buf); + *buf = NULL; + } ++ } else { ++ rv = -1; + } + } + +diff --git a/libc/stdio/vdprintf.c b/libc/stdio/vdprintf.c +index de8362c..7cb707f 100644 +--- a/libc/stdio/vdprintf.c ++++ b/libc/stdio/vdprintf.c +@@ -15,8 +15,8 @@ int vdprintf(int filedes, const char * _ + #ifdef __STDIO_BUFFERS + char buf[64]; /* TODO: provide _optional_ buffering? */ + +- f.__bufend = buf + sizeof(buf); +- f.__bufstart = buf; ++ f.__bufend = (unsigned char *) buf + sizeof(buf); ++ f.__bufstart = (unsigned char *) buf; + __STDIO_STREAM_DISABLE_GETC(&f); + __STDIO_STREAM_DISABLE_PUTC(&f); + __STDIO_STREAM_INIT_BUFREAD_BUFPOS(&f); +diff --git a/libc/stdio/vfprintf.c b/libc/stdio/vfprintf.c +index 10114f0..9214e3b 100644 +--- a/libc/stdio/vfprintf.c ++++ b/libc/stdio/vfprintf.c +@@ -569,7 +569,7 @@ int _ppfs_init(register ppfs_t *ppfs, co + ppfs->fmtpos = fmt0; /* rewind */ + } + +-#ifdef NL_MAX_ARG ++#ifdef NL_ARGMAX + /* If we have positional args, make sure we know all the types. */ + { + register int *p = ppfs->argtype; +@@ -581,7 +581,7 @@ int _ppfs_init(register ppfs_t *ppfs, co + ++p; + } + } +-#endif /* NL_MAX_ARG */ ++#endif /* NL_ARGMAX */ + + return 0; + } +@@ -1214,7 +1214,7 @@ static size_t _fp_out_narrow(FILE *fp, i + } + len = buflen; + } +- return r + OUTNSTR(fp, (const char *) buf, len); ++ return r + OUTNSTR(fp, (const unsigned char *) buf, len); + } + + #endif /* __STDIO_PRINTF_FLOAT */ +diff --git a/libc/stdlib/abort.c b/libc/stdlib/abort.c +index 77c2cdc..9f69918 100644 +--- a/libc/stdlib/abort.c ++++ b/libc/stdlib/abort.c +@@ -70,16 +70,9 @@ extern void _exit __P((int __status)) __ + static int been_there_done_that = 0; + + /* Be prepared in case multiple threads try to abort() */ +-#ifdef __UCLIBC_HAS_THREADS__ +-# include <pthread.h> +-static pthread_mutex_t mylock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +-# define LOCK __pthread_mutex_lock(&mylock) +-# define UNLOCK __pthread_mutex_unlock(&mylock) +-#else +-# define LOCK +-# define UNLOCK +-#endif ++#include <bits/uClibc_mutex.h> + ++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + + /* Cause an abnormal program termination with core-dump */ + void abort(void) +@@ -87,7 +80,7 @@ void abort(void) + sigset_t sigset; + + /* Make sure we acquire the lock before proceeding */ +- LOCK; ++ __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE(mylock); + + /* Unmask SIGABRT to be sure we can get it */ + if (__sigemptyset(&sigset) == 0 && __sigaddset(&sigset, SIGABRT) == 0) { +@@ -110,9 +103,9 @@ void abort(void) + #endif + + abort_it: +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE(mylock); + raise(SIGABRT); +- LOCK; ++ __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE(mylock); + } + + /* Still here? Try to remove any signal handlers */ +diff --git a/libc/stdlib/atexit.c b/libc/stdlib/atexit.c +index 280f42c..b028068 100644 +--- a/libc/stdlib/atexit.c ++++ b/libc/stdlib/atexit.c +@@ -40,17 +40,9 @@ + #include <stdlib.h> + #include <errno.h> + ++#include <bits/uClibc_mutex.h> + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-extern pthread_mutex_t mylock; +-# define LOCK __pthread_mutex_lock(&mylock) +-# define UNLOCK __pthread_mutex_unlock(&mylock); +-#else +-# define LOCK +-# define UNLOCK +-#endif +- ++__UCLIBC_MUTEX_EXTERN(__atexit_lock); + + typedef void (*aefuncp) (void); /* atexit function pointer */ + typedef void (*oefuncp) (int, void *); /* on_exit function pointer */ +@@ -90,8 +82,9 @@ extern struct exit_function __exit_funct + int atexit(aefuncp func) + { + struct exit_function *efp; ++ int rv = -1; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(__atexit_lock); + if (func) { + #ifdef __UCLIBC_DYNAMIC_ATEXIT__ + /* If we are out of function table slots, make some more */ +@@ -99,18 +92,16 @@ int atexit(aefuncp func) + efp=realloc(__exit_function_table, + (__exit_slots+20)*sizeof(struct exit_function)); + if (efp==NULL) { +- UNLOCK; + __set_errno(ENOMEM); +- return -1; ++ goto DONE; + } + __exit_function_table = efp; + __exit_slots+=20; + } + #else + if (__exit_count >= __UCLIBC_MAX_ATEXIT) { +- UNLOCK; + __set_errno(ENOMEM); +- return -1; ++ goto DONE; + } + #endif + __exit_cleanup = __exit_handler; /* enable cleanup */ +@@ -118,8 +109,12 @@ int atexit(aefuncp func) + efp->type = ef_atexit; + efp->funcs.atexit = func; + } +- UNLOCK; +- return 0; ++ ++ rv = 0; ++ ++ DONE: ++ __UCLIBC_MUTEX_UNLOCK(__atexit_lock); ++ return rv; + } + #endif + +@@ -133,8 +128,9 @@ int atexit(aefuncp func) + int on_exit(oefuncp func, void *arg) + { + struct exit_function *efp; ++ int rv = -1; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(__atexit_lock); + if (func) { + #ifdef __UCLIBC_DYNAMIC_ATEXIT__ + /* If we are out of function table slots, make some more */ +@@ -142,18 +138,16 @@ int on_exit(oefuncp func, void *arg) + efp=realloc(__exit_function_table, + (__exit_slots+20)*sizeof(struct exit_function)); + if (efp==NULL) { +- UNLOCK; + __set_errno(ENOMEM); +- return -1; ++ goto DONE; + } + __exit_function_table=efp; + __exit_slots+=20; + } + #else + if (__exit_count >= __UCLIBC_MAX_ATEXIT) { +- UNLOCK; + __set_errno(ENOMEM); +- return -1; ++ goto DONE; + } + #endif + +@@ -163,8 +157,12 @@ int on_exit(oefuncp func, void *arg) + efp->funcs.on_exit.func = func; + efp->funcs.on_exit.arg = arg; + } +- UNLOCK; +- return 0; ++ ++ rv = 0; ++ ++ DONE: ++ __UCLIBC_MUTEX_UNLOCK(__atexit_lock); ++ return rv; + } + #endif + +@@ -214,9 +212,8 @@ void __exit_handler(int status) + #ifdef L_exit + extern void weak_function _stdio_term(void); + void (*__exit_cleanup) (int) = 0; +-#ifdef __UCLIBC_HAS_THREADS__ +-pthread_mutex_t mylock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +-#endif ++ ++__UCLIBC_MUTEX_INIT(__atexit_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + + #ifdef __UCLIBC_CTOR_DTOR__ + extern void (*__app_fini)(void); +@@ -229,11 +226,11 @@ extern void (*__rtld_fini)(void); + void exit(int rv) + { + /* Perform exit-specific cleanup (atexit and on_exit) */ +- LOCK; ++ __UCLIBC_MUTEX_LOCK(__atexit_lock); + if (__exit_cleanup) { + __exit_cleanup(rv); + } +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(__atexit_lock); + + #ifdef __UCLIBC_CTOR_DTOR__ + if (__app_fini != NULL) +diff --git a/libc/stdlib/malloc-simple/alloc.c b/libc/stdlib/malloc-simple/alloc.c +index ed14c37..519a875 100644 +--- a/libc/stdlib/malloc-simple/alloc.c ++++ b/libc/stdlib/malloc-simple/alloc.c +@@ -108,15 +108,14 @@ void free(void *ptr) + #endif + + #ifdef L_memalign +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-pthread_mutex_t __malloc_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +-# define LOCK __pthread_mutex_lock(&__malloc_lock) +-# define UNLOCK __pthread_mutex_unlock(&__malloc_lock); +-#else +-# define LOCK +-# define UNLOCK +-#endif ++ ++#include <bits/uClibc_mutex.h> ++ ++__UCLIBC_MUTEX_EXTERN(__malloc_lock); ++ ++#define __MALLOC_LOCK __UCLIBC_MUTEX_LOCK(__malloc_lock) ++#define __MALLOC_UNLOCK __UCLIBC_MUTEX_UNLOCK(__malloc_lock) ++ + + /* List of blocks allocated with memalign or valloc */ + struct alignlist +@@ -135,7 +134,7 @@ int __libc_free_aligned(void *ptr) + if (ptr == NULL) + return 0; + +- LOCK; ++ __MALLOC_LOCK; + for (l = _aligned_blocks; l != NULL; l = l->next) { + if (l->aligned == ptr) { + /* Mark the block as free */ +@@ -146,7 +145,7 @@ int __libc_free_aligned(void *ptr) + return 1; + } + } +- UNLOCK; ++ __MALLOC_UNLOCK; + return 0; + } + void * memalign (size_t alignment, size_t size) +@@ -159,10 +158,10 @@ void * memalign (size_t alignment, size_ + return NULL; + + adj = (unsigned long int) ((unsigned long int) ((char *) result - +- (char *) NULL)) % alignment; ++ (char *) NULL)) % alignment; + if (adj != 0) { + struct alignlist *l; +- LOCK; ++ __MALLOC_LOCK; + for (l = _aligned_blocks; l != NULL; l = l->next) + if (l->aligned == NULL) + /* This slot is free. Use it. */ +@@ -171,15 +170,16 @@ void * memalign (size_t alignment, size_ + l = (struct alignlist *) malloc (sizeof (struct alignlist)); + if (l == NULL) { + free(result); +- UNLOCK; +- return NULL; ++ result = NULL; ++ goto DONE; + } + l->next = _aligned_blocks; + _aligned_blocks = l; + } + l->exact = result; + result = l->aligned = (char *) result + alignment - adj; +- UNLOCK; ++ DONE: ++ __MALLOC_UNLOCK; + } + + return result; +diff --git a/libc/stdlib/malloc-standard/calloc.c b/libc/stdlib/malloc-standard/calloc.c +index a67dad7..4277954 100644 +--- a/libc/stdlib/malloc-standard/calloc.c ++++ b/libc/stdlib/malloc-standard/calloc.c +@@ -8,7 +8,7 @@ + VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at +- ftp://gee.cs.oswego.edu/pub/misc/malloc.c ++ ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + + Hacked up for uClibc by Erik Andersen <andersen@codepoet.org> +@@ -31,63 +31,63 @@ void* calloc(size_t n_elements, size_t e + * to fall through and call malloc(0) */ + size = n_elements * elem_size; + if (n_elements && elem_size != (size / n_elements)) { +- __set_errno(ENOMEM); +- return NULL; ++ __set_errno(ENOMEM); ++ return NULL; + } + +- LOCK; ++ __MALLOC_LOCK; + mem = malloc(size); + if (mem != 0) { +- p = mem2chunk(mem); ++ p = mem2chunk(mem); + +- if (!chunk_is_mmapped(p)) +- { +- /* +- Unroll clear of <= 36 bytes (72 if 8byte sizes) +- We know that contents have an odd number of +- size_t-sized words; minimally 3. +- */ +- +- d = (size_t*)mem; +- clearsize = chunksize(p) - (sizeof(size_t)); +- nclears = clearsize / sizeof(size_t); +- assert(nclears >= 3); +- +- if (nclears > 9) +- memset(d, 0, clearsize); +- +- else { +- *(d+0) = 0; +- *(d+1) = 0; +- *(d+2) = 0; +- if (nclears > 4) { +- *(d+3) = 0; +- *(d+4) = 0; +- if (nclears > 6) { +- *(d+5) = 0; +- *(d+6) = 0; +- if (nclears > 8) { +- *(d+7) = 0; +- *(d+8) = 0; ++ if (!chunk_is_mmapped(p)) ++ { ++ /* ++ Unroll clear of <= 36 bytes (72 if 8byte sizes) ++ We know that contents have an odd number of ++ size_t-sized words; minimally 3. ++ */ ++ ++ d = (size_t*)mem; ++ clearsize = chunksize(p) - (sizeof(size_t)); ++ nclears = clearsize / sizeof(size_t); ++ assert(nclears >= 3); ++ ++ if (nclears > 9) ++ memset(d, 0, clearsize); ++ ++ else { ++ *(d+0) = 0; ++ *(d+1) = 0; ++ *(d+2) = 0; ++ if (nclears > 4) { ++ *(d+3) = 0; ++ *(d+4) = 0; ++ if (nclears > 6) { ++ *(d+5) = 0; ++ *(d+6) = 0; ++ if (nclears > 8) { ++ *(d+7) = 0; ++ *(d+8) = 0; ++ } ++ } ++ } ++ } + } +- } +- } +- } +- } + #if 0 +- else +- { +- /* Standard unix mmap using /dev/zero clears memory so calloc +- * doesn't need to actually zero anything.... +- */ +- d = (size_t*)mem; +- /* Note the additional (sizeof(size_t)) */ +- clearsize = chunksize(p) - 2*(sizeof(size_t)); +- memset(d, 0, clearsize); +- } ++ else ++ { ++ /* Standard unix mmap using /dev/zero clears memory so calloc ++ * doesn't need to actually zero anything.... ++ */ ++ d = (size_t*)mem; ++ /* Note the additional (sizeof(size_t)) */ ++ clearsize = chunksize(p) - 2*(sizeof(size_t)); ++ memset(d, 0, clearsize); ++ } + #endif + } +- UNLOCK; ++ __MALLOC_UNLOCK; + return mem; + } + +diff --git a/libc/stdlib/malloc-standard/free.c b/libc/stdlib/malloc-standard/free.c +index 94e1d65..4e08ef7 100644 +--- a/libc/stdlib/malloc-standard/free.c ++++ b/libc/stdlib/malloc-standard/free.c +@@ -8,7 +8,7 @@ + VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at +- ftp://gee.cs.oswego.edu/pub/misc/malloc.c ++ ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + + Hacked up for uClibc by Erik Andersen <andersen@codepoet.org> +@@ -42,71 +42,71 @@ static int __malloc_trim(size_t pad, mst + + if (extra > 0) { + +- /* +- Only proceed if end of memory is where we last set it. +- This avoids problems if there were foreign sbrk calls. +- */ +- current_brk = (char*)(MORECORE(0)); +- if (current_brk == (char*)(av->top) + top_size) { +- +- /* +- Attempt to release memory. We ignore MORECORE return value, +- and instead call again to find out where new end of memory is. +- This avoids problems if first call releases less than we asked, +- of if failure somehow altered brk value. (We could still +- encounter problems if it altered brk in some very bad way, +- but the only thing we can do is adjust anyway, which will cause +- some downstream failure.) +- */ +- +- MORECORE(-extra); +- new_brk = (char*)(MORECORE(0)); +- +- if (new_brk != (char*)MORECORE_FAILURE) { +- released = (long)(current_brk - new_brk); +- +- if (released != 0) { +- /* Success. Adjust top. */ +- av->sbrked_mem -= released; +- set_head(av->top, (top_size - released) | PREV_INUSE); +- check_malloc_state(); +- return 1; ++ /* ++ Only proceed if end of memory is where we last set it. ++ This avoids problems if there were foreign sbrk calls. ++ */ ++ current_brk = (char*)(MORECORE(0)); ++ if (current_brk == (char*)(av->top) + top_size) { ++ ++ /* ++ Attempt to release memory. We ignore MORECORE return value, ++ and instead call again to find out where new end of memory is. ++ This avoids problems if first call releases less than we asked, ++ of if failure somehow altered brk value. (We could still ++ encounter problems if it altered brk in some very bad way, ++ but the only thing we can do is adjust anyway, which will cause ++ some downstream failure.) ++ */ ++ ++ MORECORE(-extra); ++ new_brk = (char*)(MORECORE(0)); ++ ++ if (new_brk != (char*)MORECORE_FAILURE) { ++ released = (long)(current_brk - new_brk); ++ ++ if (released != 0) { ++ /* Success. Adjust top. */ ++ av->sbrked_mem -= released; ++ set_head(av->top, (top_size - released) | PREV_INUSE); ++ check_malloc_state(); ++ return 1; ++ } ++ } + } +- } +- } + } + return 0; + } + + /* ------------------------- malloc_trim ------------------------- +- malloc_trim(size_t pad); ++ malloc_trim(size_t pad); + +- If possible, gives memory back to the system (via negative +- arguments to sbrk) if there is unused memory at the `high' end of +- the malloc pool. You can call this after freeing large blocks of +- memory to potentially reduce the system-level memory requirements +- of a program. However, it cannot guarantee to reduce memory. Under +- some allocation patterns, some large free blocks of memory will be +- locked between two used chunks, so they cannot be given back to +- the system. +- +- The `pad' argument to malloc_trim represents the amount of free +- trailing space to leave untrimmed. If this argument is zero, +- only the minimum amount of memory to maintain internal data +- structures will be left (one page or less). Non-zero arguments +- can be supplied to maintain enough trailing space to service +- future expected allocations without having to re-obtain memory +- from the system. +- +- Malloc_trim returns 1 if it actually released any memory, else 0. +- On systems that do not support "negative sbrks", it will always +- return 0. ++ If possible, gives memory back to the system (via negative ++ arguments to sbrk) if there is unused memory at the `high' end of ++ the malloc pool. You can call this after freeing large blocks of ++ memory to potentially reduce the system-level memory requirements ++ of a program. However, it cannot guarantee to reduce memory. Under ++ some allocation patterns, some large free blocks of memory will be ++ locked between two used chunks, so they cannot be given back to ++ the system. ++ ++ The `pad' argument to malloc_trim represents the amount of free ++ trailing space to leave untrimmed. If this argument is zero, ++ only the minimum amount of memory to maintain internal data ++ structures will be left (one page or less). Non-zero arguments ++ can be supplied to maintain enough trailing space to service ++ future expected allocations without having to re-obtain memory ++ from the system. ++ ++ Malloc_trim returns 1 if it actually released any memory, else 0. ++ On systems that do not support "negative sbrks", it will always ++ return 0. + */ + int malloc_trim(size_t pad) + { +- mstate av = get_malloc_state(); +- __malloc_consolidate(av); +- return __malloc_trim(pad, av); ++ mstate av = get_malloc_state(); ++ __malloc_consolidate(av); ++ return __malloc_trim(pad, av); + } + + /* +@@ -125,8 +125,8 @@ static void malloc_init_state(mstate av) + + /* Establish circular links for normal bins */ + for (i = 1; i < NBINS; ++i) { +- bin = bin_at(av,i); +- bin->fd = bin->bk = bin; ++ bin = bin_at(av,i); ++ bin->fd = bin->bk = bin; + } + + av->top_pad = DEFAULT_TOP_PAD; +@@ -157,15 +157,15 @@ static void malloc_init_state(mstate av) + + /* ------------------------- __malloc_consolidate ------------------------- + +- __malloc_consolidate is a specialized version of free() that tears +- down chunks held in fastbins. Free itself cannot be used for this +- purpose since, among other things, it might place chunks back onto +- fastbins. So, instead, we need to use a minor variant of the same +- code. +- +- Also, because this routine needs to be called the first time through +- malloc anyway, it turns out to be the perfect place to trigger +- initialization code. ++__malloc_consolidate is a specialized version of free() that tears ++down chunks held in fastbins. Free itself cannot be used for this ++purpose since, among other things, it might place chunks back onto ++fastbins. So, instead, we need to use a minor variant of the same ++code. ++ ++Also, because this routine needs to be called the first time through ++malloc anyway, it turns out to be the perfect place to trigger ++initialization code. + */ + void __malloc_consolidate(mstate av) + { +@@ -186,78 +186,78 @@ void __malloc_consolidate(mstate av) + mchunkptr fwd; + + /* +- If max_fast is 0, we know that av hasn't +- yet been initialized, in which case do so below +- */ ++ If max_fast is 0, we know that av hasn't ++ yet been initialized, in which case do so below ++ */ + + if (av->max_fast != 0) { +- clear_fastchunks(av); ++ clear_fastchunks(av); + +- unsorted_bin = unsorted_chunks(av); ++ unsorted_bin = unsorted_chunks(av); + +- /* +- Remove each chunk from fast bin and consolidate it, placing it +- then in unsorted bin. Among other reasons for doing this, +- placing in unsorted bin avoids needing to calculate actual bins +- until malloc is sure that chunks aren't immediately going to be +- reused anyway. +- */ +- +- maxfb = &(av->fastbins[fastbin_index(av->max_fast)]); +- fb = &(av->fastbins[0]); +- do { +- if ( (p = *fb) != 0) { +- *fb = 0; ++ /* ++ Remove each chunk from fast bin and consolidate it, placing it ++ then in unsorted bin. Among other reasons for doing this, ++ placing in unsorted bin avoids needing to calculate actual bins ++ until malloc is sure that chunks aren't immediately going to be ++ reused anyway. ++ */ + ++ maxfb = &(av->fastbins[fastbin_index(av->max_fast)]); ++ fb = &(av->fastbins[0]); + do { +- check_inuse_chunk(p); +- nextp = p->fd; ++ if ( (p = *fb) != 0) { ++ *fb = 0; + +- /* Slightly streamlined version of consolidation code in free() */ +- size = p->size & ~PREV_INUSE; +- nextchunk = chunk_at_offset(p, size); +- nextsize = chunksize(nextchunk); ++ do { ++ check_inuse_chunk(p); ++ nextp = p->fd; ++ ++ /* Slightly streamlined version of consolidation code in free() */ ++ size = p->size & ~PREV_INUSE; ++ nextchunk = chunk_at_offset(p, size); ++ nextsize = chunksize(nextchunk); ++ ++ if (!prev_inuse(p)) { ++ prevsize = p->prev_size; ++ size += prevsize; ++ p = chunk_at_offset(p, -((long) prevsize)); ++ unlink(p, bck, fwd); ++ } ++ ++ if (nextchunk != av->top) { ++ nextinuse = inuse_bit_at_offset(nextchunk, nextsize); ++ set_head(nextchunk, nextsize); ++ ++ if (!nextinuse) { ++ size += nextsize; ++ unlink(nextchunk, bck, fwd); ++ } ++ ++ first_unsorted = unsorted_bin->fd; ++ unsorted_bin->fd = p; ++ first_unsorted->bk = p; ++ ++ set_head(p, size | PREV_INUSE); ++ p->bk = unsorted_bin; ++ p->fd = first_unsorted; ++ set_foot(p, size); ++ } ++ ++ else { ++ size += nextsize; ++ set_head(p, size | PREV_INUSE); ++ av->top = p; ++ } + +- if (!prev_inuse(p)) { +- prevsize = p->prev_size; +- size += prevsize; +- p = chunk_at_offset(p, -((long) prevsize)); +- unlink(p, bck, fwd); +- } ++ } while ( (p = nextp) != 0); + +- if (nextchunk != av->top) { +- nextinuse = inuse_bit_at_offset(nextchunk, nextsize); +- set_head(nextchunk, nextsize); +- +- if (!nextinuse) { +- size += nextsize; +- unlink(nextchunk, bck, fwd); + } +- +- first_unsorted = unsorted_bin->fd; +- unsorted_bin->fd = p; +- first_unsorted->bk = p; +- +- set_head(p, size | PREV_INUSE); +- p->bk = unsorted_bin; +- p->fd = first_unsorted; +- set_foot(p, size); +- } +- +- else { +- size += nextsize; +- set_head(p, size | PREV_INUSE); +- av->top = p; +- } +- +- } while ( (p = nextp) != 0); +- +- } +- } while (fb++ != maxfb); ++ } while (fb++ != maxfb); + } + else { +- malloc_init_state(av); +- check_malloc_state(); ++ malloc_init_state(av); ++ check_malloc_state(); + } + } + +@@ -279,9 +279,9 @@ void free(void* mem) + + /* free(0) has no effect */ + if (mem == NULL) +- return; ++ return; + +- LOCK; ++ __MALLOC_LOCK; + av = get_malloc_state(); + p = mem2chunk(mem); + size = chunksize(p); +@@ -289,9 +289,9 @@ void free(void* mem) + check_inuse_chunk(p); + + /* +- If eligible, place chunk on a fastbin so it can be found +- and used quickly in malloc. +- */ ++ If eligible, place chunk on a fastbin so it can be found ++ and used quickly in malloc. ++ */ + + if ((unsigned long)(size) <= (unsigned long)(av->max_fast) + +@@ -300,114 +300,114 @@ void free(void* mem) + bordering top into fastbins */ + && (chunk_at_offset(p, size) != av->top) + #endif +- ) { ++ ) { + +- set_fastchunks(av); +- fb = &(av->fastbins[fastbin_index(size)]); +- p->fd = *fb; +- *fb = p; ++ set_fastchunks(av); ++ fb = &(av->fastbins[fastbin_index(size)]); ++ p->fd = *fb; ++ *fb = p; + } + + /* +- Consolidate other non-mmapped chunks as they arrive. +- */ ++ Consolidate other non-mmapped chunks as they arrive. ++ */ + + else if (!chunk_is_mmapped(p)) { +- set_anychunks(av); ++ set_anychunks(av); ++ ++ nextchunk = chunk_at_offset(p, size); ++ nextsize = chunksize(nextchunk); ++ ++ /* consolidate backward */ ++ if (!prev_inuse(p)) { ++ prevsize = p->prev_size; ++ size += prevsize; ++ p = chunk_at_offset(p, -((long) prevsize)); ++ unlink(p, bck, fwd); ++ } ++ ++ if (nextchunk != av->top) { ++ /* get and clear inuse bit */ ++ nextinuse = inuse_bit_at_offset(nextchunk, nextsize); ++ set_head(nextchunk, nextsize); ++ ++ /* consolidate forward */ ++ if (!nextinuse) { ++ unlink(nextchunk, bck, fwd); ++ size += nextsize; ++ } ++ ++ /* ++ Place the chunk in unsorted chunk list. Chunks are ++ not placed into regular bins until after they have ++ been given one chance to be used in malloc. ++ */ ++ ++ bck = unsorted_chunks(av); ++ fwd = bck->fd; ++ p->bk = bck; ++ p->fd = fwd; ++ bck->fd = p; ++ fwd->bk = p; + +- nextchunk = chunk_at_offset(p, size); +- nextsize = chunksize(nextchunk); ++ set_head(p, size | PREV_INUSE); ++ set_foot(p, size); ++ ++ check_free_chunk(p); ++ } ++ ++ /* ++ If the chunk borders the current high end of memory, ++ consolidate into top ++ */ + +- /* consolidate backward */ +- if (!prev_inuse(p)) { +- prevsize = p->prev_size; +- size += prevsize; +- p = chunk_at_offset(p, -((long) prevsize)); +- unlink(p, bck, fwd); +- } +- +- if (nextchunk != av->top) { +- /* get and clear inuse bit */ +- nextinuse = inuse_bit_at_offset(nextchunk, nextsize); +- set_head(nextchunk, nextsize); +- +- /* consolidate forward */ +- if (!nextinuse) { +- unlink(nextchunk, bck, fwd); +- size += nextsize; +- } +- +- /* +- Place the chunk in unsorted chunk list. Chunks are +- not placed into regular bins until after they have +- been given one chance to be used in malloc. +- */ +- +- bck = unsorted_chunks(av); +- fwd = bck->fd; +- p->bk = bck; +- p->fd = fwd; +- bck->fd = p; +- fwd->bk = p; +- +- set_head(p, size | PREV_INUSE); +- set_foot(p, size); +- +- check_free_chunk(p); +- } +- +- /* +- If the chunk borders the current high end of memory, +- consolidate into top +- */ +- +- else { +- size += nextsize; +- set_head(p, size | PREV_INUSE); +- av->top = p; +- check_chunk(p); +- } +- +- /* +- If freeing a large space, consolidate possibly-surrounding +- chunks. Then, if the total unused topmost memory exceeds trim +- threshold, ask malloc_trim to reduce top. +- +- Unless max_fast is 0, we don't know if there are fastbins +- bordering top, so we cannot tell for sure whether threshold +- has been reached unless fastbins are consolidated. But we +- don't want to consolidate on each free. As a compromise, +- consolidation is performed if FASTBIN_CONSOLIDATION_THRESHOLD +- is reached. +- */ +- +- if ((unsigned long)(size) >= FASTBIN_CONSOLIDATION_THRESHOLD) { +- if (have_fastchunks(av)) +- __malloc_consolidate(av); +- +- if ((unsigned long)(chunksize(av->top)) >= +- (unsigned long)(av->trim_threshold)) +- __malloc_trim(av->top_pad, av); +- } ++ else { ++ size += nextsize; ++ set_head(p, size | PREV_INUSE); ++ av->top = p; ++ check_chunk(p); ++ } ++ ++ /* ++ If freeing a large space, consolidate possibly-surrounding ++ chunks. Then, if the total unused topmost memory exceeds trim ++ threshold, ask malloc_trim to reduce top. ++ ++ Unless max_fast is 0, we don't know if there are fastbins ++ bordering top, so we cannot tell for sure whether threshold ++ has been reached unless fastbins are consolidated. But we ++ don't want to consolidate on each free. As a compromise, ++ consolidation is performed if FASTBIN_CONSOLIDATION_THRESHOLD ++ is reached. ++ */ ++ ++ if ((unsigned long)(size) >= FASTBIN_CONSOLIDATION_THRESHOLD) { ++ if (have_fastchunks(av)) ++ __malloc_consolidate(av); ++ ++ if ((unsigned long)(chunksize(av->top)) >= ++ (unsigned long)(av->trim_threshold)) ++ __malloc_trim(av->top_pad, av); ++ } + + } + /* +- If the chunk was allocated via mmap, release via munmap() +- Note that if HAVE_MMAP is false but chunk_is_mmapped is +- true, then user must have overwritten memory. There's nothing +- we can do to catch this error unless DEBUG is set, in which case +- check_inuse_chunk (above) will have triggered error. +- */ ++ If the chunk was allocated via mmap, release via munmap() ++ Note that if HAVE_MMAP is false but chunk_is_mmapped is ++ true, then user must have overwritten memory. There's nothing ++ we can do to catch this error unless DEBUG is set, in which case ++ check_inuse_chunk (above) will have triggered error. ++ */ + + else { +- int ret; +- size_t offset = p->prev_size; +- av->n_mmaps--; +- av->mmapped_mem -= (size + offset); +- ret = munmap((char*)p - offset, size + offset); +- /* munmap returns non-zero on failure */ +- assert(ret == 0); ++ int ret; ++ size_t offset = p->prev_size; ++ av->n_mmaps--; ++ av->mmapped_mem -= (size + offset); ++ ret = munmap((char*)p - offset, size + offset); ++ /* munmap returns non-zero on failure */ ++ assert(ret == 0); + } +- UNLOCK; ++ __MALLOC_UNLOCK; + } + +diff --git a/libc/stdlib/malloc-standard/mallinfo.c b/libc/stdlib/malloc-standard/mallinfo.c +index 51ac423..1e0875c 100644 +--- a/libc/stdlib/malloc-standard/mallinfo.c ++++ b/libc/stdlib/malloc-standard/mallinfo.c +@@ -8,7 +8,7 @@ + VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at +- ftp://gee.cs.oswego.edu/pub/misc/malloc.c ++ ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + + Hacked up for uClibc by Erik Andersen <andersen@codepoet.org> +@@ -30,11 +30,11 @@ struct mallinfo mallinfo(void) + int nblocks; + int nfastblocks; + +- LOCK; ++ __MALLOC_LOCK; + av = get_malloc_state(); + /* Ensure initialization */ + if (av->top == 0) { +- __malloc_consolidate(av); ++ __malloc_consolidate(av); + } + + check_malloc_state(); +@@ -48,21 +48,21 @@ struct mallinfo mallinfo(void) + fastavail = 0; + + for (i = 0; i < NFASTBINS; ++i) { +- for (p = av->fastbins[i]; p != 0; p = p->fd) { +- ++nfastblocks; +- fastavail += chunksize(p); +- } ++ for (p = av->fastbins[i]; p != 0; p = p->fd) { ++ ++nfastblocks; ++ fastavail += chunksize(p); ++ } + } + + avail += fastavail; + + /* traverse regular bins */ + for (i = 1; i < NBINS; ++i) { +- b = bin_at(av, i); +- for (p = last(b); p != b; p = p->bk) { +- ++nblocks; +- avail += chunksize(p); +- } ++ b = bin_at(av, i); ++ for (p = last(b); p != b; p = p->bk) { ++ ++nblocks; ++ avail += chunksize(p); ++ } + } + + mi.smblks = nfastblocks; +@@ -75,7 +75,7 @@ struct mallinfo mallinfo(void) + mi.fsmblks = fastavail; + mi.keepcost = chunksize(av->top); + mi.usmblks = av->max_total_mem; +- UNLOCK; ++ __MALLOC_UNLOCK; + return mi; + } + +@@ -84,23 +84,40 @@ void malloc_stats(FILE *file) + struct mallinfo mi; + + if (file==NULL) { +- file = stderr; ++ file = stderr; + } + + mi = mallinfo(); +- fprintf(file, "total bytes allocated = %10u\n", (unsigned int)(mi.arena + mi.hblkhd)); +- fprintf(file, "total bytes in use bytes = %10u\n", (unsigned int)(mi.uordblks + mi.hblkhd)); +- fprintf(file, "total non-mmapped bytes allocated = %10d\n", mi.arena); +- fprintf(file, "number of mmapped regions = %10d\n", mi.hblks); +- fprintf(file, "total allocated mmap space = %10d\n", mi.hblkhd); +- fprintf(file, "total allocated sbrk space = %10d\n", mi.uordblks); ++ fprintf(file, ++ "total bytes allocated = %10u\n" ++ "total bytes in use bytes = %10u\n" ++ "total non-mmapped bytes allocated = %10d\n" ++ "number of mmapped regions = %10d\n" ++ "total allocated mmap space = %10d\n" ++ "total allocated sbrk space = %10d\n" + #if 0 +- fprintf(file, "number of free chunks = %10d\n", mi.ordblks); +- fprintf(file, "number of fastbin blocks = %10d\n", mi.smblks); +- fprintf(file, "space in freed fastbin blocks = %10d\n", mi.fsmblks); ++ "number of free chunks = %10d\n" ++ "number of fastbin blocks = %10d\n" ++ "space in freed fastbin blocks = %10d\n" + #endif +- fprintf(file, "maximum total allocated space = %10d\n", mi.usmblks); +- fprintf(file, "total free space = %10d\n", mi.fordblks); +- fprintf(file, "memory releasable via malloc_trim = %10d\n", mi.keepcost); ++ "maximum total allocated space = %10d\n" ++ "total free space = %10d\n" ++ "memory releasable via malloc_trim = %10d\n", ++ ++ (unsigned int)(mi.arena + mi.hblkhd), ++ (unsigned int)(mi.uordblks + mi.hblkhd), ++ mi.arena, ++ mi.hblks, ++ mi.hblkhd, ++ mi.uordblks, ++#if 0 ++ mi.ordblks, ++ mi.smblks, ++ mi.fsmblks, ++#endif ++ mi.usmblks, ++ mi.fordblks, ++ mi.keepcost ++ ); + } + +diff --git a/libc/stdlib/malloc-standard/malloc.c b/libc/stdlib/malloc-standard/malloc.c +index 7025e83..60494a0 100644 +--- a/libc/stdlib/malloc-standard/malloc.c ++++ b/libc/stdlib/malloc-standard/malloc.c +@@ -8,7 +8,7 @@ + VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at +- ftp://gee.cs.oswego.edu/pub/misc/malloc.c ++ ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + + Hacked up for uClibc by Erik Andersen <andersen@codepoet.org> +@@ -17,17 +17,14 @@ + #define _GNU_SOURCE + #include "malloc.h" + +- +-#ifdef __UCLIBC_HAS_THREADS__ +-pthread_mutex_t __malloc_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +-#endif ++__UCLIBC_MUTEX_INIT(__malloc_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + + /* +- There is exactly one instance of this struct in this malloc. +- If you are adapting this malloc in a way that does NOT use a static +- malloc_state, you MUST explicitly zero-fill it before using. This +- malloc relies on the property that malloc_state is initialized to +- all zeroes (as is true of C statics). ++ There is exactly one instance of this struct in this malloc. ++ If you are adapting this malloc in a way that does NOT use a static ++ malloc_state, you MUST explicitly zero-fill it before using. This ++ malloc relies on the property that malloc_state is initialized to ++ all zeroes (as is true of C statics). + */ + struct malloc_state __malloc_state; /* never directly referenced */ + +@@ -77,30 +74,30 @@ void __do_check_chunk(mchunkptr p) + + if (!chunk_is_mmapped(p)) { + +- /* Has legal address ... */ +- if (p != av->top) { +- if (contiguous(av)) { +- assert(((char*)p) >= min_address); +- assert(((char*)p + sz) <= ((char*)(av->top))); +- } +- } +- else { +- /* top size is always at least MINSIZE */ +- assert((unsigned long)(sz) >= MINSIZE); +- /* top predecessor always marked inuse */ +- assert(prev_inuse(p)); +- } ++ /* Has legal address ... */ ++ if (p != av->top) { ++ if (contiguous(av)) { ++ assert(((char*)p) >= min_address); ++ assert(((char*)p + sz) <= ((char*)(av->top))); ++ } ++ } ++ else { ++ /* top size is always at least MINSIZE */ ++ assert((unsigned long)(sz) >= MINSIZE); ++ /* top predecessor always marked inuse */ ++ assert(prev_inuse(p)); ++ } + + } + else { +- /* address is outside main heap */ +- if (contiguous(av) && av->top != initial_top(av)) { +- assert(((char*)p) < min_address || ((char*)p) > max_address); +- } +- /* chunk is page-aligned */ +- assert(((p->prev_size + sz) & (av->pagesize-1)) == 0); +- /* mem is aligned */ +- assert(aligned_OK(chunk2mem(p))); ++ /* address is outside main heap */ ++ if (contiguous(av) && av->top != initial_top(av)) { ++ assert(((char*)p) < min_address || ((char*)p) > max_address); ++ } ++ /* chunk is page-aligned */ ++ assert(((p->prev_size + sz) & (av->pagesize-1)) == 0); ++ /* mem is aligned */ ++ assert(aligned_OK(chunk2mem(p))); + } + } + +@@ -121,21 +118,21 @@ void __do_check_free_chunk(mchunkptr p) + + /* Unless a special marker, must have OK fields */ + if ((unsigned long)(sz) >= MINSIZE) +- { +- assert((sz & MALLOC_ALIGN_MASK) == 0); +- assert(aligned_OK(chunk2mem(p))); +- /* ... matching footer field */ +- assert(next->prev_size == sz); +- /* ... and is fully consolidated */ +- assert(prev_inuse(p)); +- assert (next == av->top || inuse(next)); +- +- /* ... and has minimally sane links */ +- assert(p->fd->bk == p); +- assert(p->bk->fd == p); +- } ++ { ++ assert((sz & MALLOC_ALIGN_MASK) == 0); ++ assert(aligned_OK(chunk2mem(p))); ++ /* ... matching footer field */ ++ assert(next->prev_size == sz); ++ /* ... and is fully consolidated */ ++ assert(prev_inuse(p)); ++ assert (next == av->top || inuse(next)); ++ ++ /* ... and has minimally sane links */ ++ assert(p->fd->bk == p); ++ assert(p->bk->fd == p); ++ } + else /* markers are always of size (sizeof(size_t)) */ +- assert(sz == (sizeof(size_t))); ++ assert(sz == (sizeof(size_t))); + } + + /* Properties of inuse chunks */ +@@ -146,7 +143,7 @@ void __do_check_inuse_chunk(mchunkptr p) + __do_check_chunk(p); + + if (chunk_is_mmapped(p)) +- return; /* mmapped chunks have no next/prev */ ++ return; /* mmapped chunks have no next/prev */ + + /* Check whether it claims to be in use ... */ + assert(inuse(p)); +@@ -156,20 +153,20 @@ void __do_check_inuse_chunk(mchunkptr p) + /* ... and is surrounded by OK chunks. + Since more things can be checked with free chunks than inuse ones, + if an inuse chunk borders them and debug is on, it's worth doing them. +- */ ++ */ + if (!prev_inuse(p)) { +- /* Note that we cannot even look at prev unless it is not inuse */ +- mchunkptr prv = prev_chunk(p); +- assert(next_chunk(prv) == p); +- __do_check_free_chunk(prv); ++ /* Note that we cannot even look at prev unless it is not inuse */ ++ mchunkptr prv = prev_chunk(p); ++ assert(next_chunk(prv) == p); ++ __do_check_free_chunk(prv); + } + + if (next == av->top) { +- assert(prev_inuse(next)); +- assert(chunksize(next) >= MINSIZE); ++ assert(prev_inuse(next)); ++ assert(chunksize(next) >= MINSIZE); + } + else if (!inuse(next)) +- __do_check_free_chunk(next); ++ __do_check_free_chunk(next); + } + + /* Properties of chunks recycled from fastbins */ +@@ -198,14 +195,14 @@ void __do_check_malloced_chunk(mchunkptr + __do_check_remalloced_chunk(p, s); + + /* +- ... plus, must obey implementation invariant that prev_inuse is +- always true of any allocated chunk; i.e., that each allocated +- chunk borders either a previously allocated and still in-use +- chunk, or the base of its memory arena. This is ensured +- by making all allocations from the the `lowest' part of any found +- chunk. This does not necessarily hold however for chunks +- recycled via fastbins. +- */ ++ ... plus, must obey implementation invariant that prev_inuse is ++ always true of any allocated chunk; i.e., that each allocated ++ chunk borders either a previously allocated and still in-use ++ chunk, or the base of its memory arena. This is ensured ++ by making all allocations from the the `lowest' part of any found ++ chunk. This does not necessarily hold however for chunks ++ recycled via fastbins. ++ */ + + assert(prev_inuse(p)); + } +@@ -243,7 +240,7 @@ void __do_check_malloc_state(void) + + /* cannot run remaining checks until fully initialized */ + if (av->top == 0 || av->top == initial_top(av)) +- return; ++ return; + + /* pagesize is a power of 2 */ + assert((av->pagesize & (av->pagesize-1)) == 0); +@@ -256,64 +253,64 @@ void __do_check_malloc_state(void) + max_fast_bin = fastbin_index(av->max_fast); + + for (i = 0; i < NFASTBINS; ++i) { +- p = av->fastbins[i]; ++ p = av->fastbins[i]; + +- /* all bins past max_fast are empty */ +- if (i > max_fast_bin) +- assert(p == 0); +- +- while (p != 0) { +- /* each chunk claims to be inuse */ +- __do_check_inuse_chunk(p); +- total += chunksize(p); +- /* chunk belongs in this bin */ +- assert(fastbin_index(chunksize(p)) == i); +- p = p->fd; +- } ++ /* all bins past max_fast are empty */ ++ if (i > max_fast_bin) ++ assert(p == 0); ++ ++ while (p != 0) { ++ /* each chunk claims to be inuse */ ++ __do_check_inuse_chunk(p); ++ total += chunksize(p); ++ /* chunk belongs in this bin */ ++ assert(fastbin_index(chunksize(p)) == i); ++ p = p->fd; ++ } + } + + if (total != 0) +- assert(have_fastchunks(av)); ++ assert(have_fastchunks(av)); + else if (!have_fastchunks(av)) +- assert(total == 0); ++ assert(total == 0); + + /* check normal bins */ + for (i = 1; i < NBINS; ++i) { +- b = bin_at(av,i); ++ b = bin_at(av,i); + +- /* binmap is accurate (except for bin 1 == unsorted_chunks) */ +- if (i >= 2) { +- binbit = get_binmap(av,i); +- empty = last(b) == b; +- if (!binbit) +- assert(empty); +- else if (!empty) +- assert(binbit); +- } +- +- for (p = last(b); p != b; p = p->bk) { +- /* each chunk claims to be free */ +- __do_check_free_chunk(p); +- size = chunksize(p); +- total += size; +- if (i >= 2) { +- /* chunk belongs in bin */ +- idx = bin_index(size); +- assert(idx == i); +- /* lists are sorted */ +- if ((unsigned long) size >= (unsigned long)(FIRST_SORTED_BIN_SIZE)) { +- assert(p->bk == b || +- (unsigned long)chunksize(p->bk) >= +- (unsigned long)chunksize(p)); +- } +- } +- /* chunk is followed by a legal chain of inuse chunks */ +- for (q = next_chunk(p); +- (q != av->top && inuse(q) && +- (unsigned long)(chunksize(q)) >= MINSIZE); +- q = next_chunk(q)) +- __do_check_inuse_chunk(q); +- } ++ /* binmap is accurate (except for bin 1 == unsorted_chunks) */ ++ if (i >= 2) { ++ binbit = get_binmap(av,i); ++ empty = last(b) == b; ++ if (!binbit) ++ assert(empty); ++ else if (!empty) ++ assert(binbit); ++ } ++ ++ for (p = last(b); p != b; p = p->bk) { ++ /* each chunk claims to be free */ ++ __do_check_free_chunk(p); ++ size = chunksize(p); ++ total += size; ++ if (i >= 2) { ++ /* chunk belongs in bin */ ++ idx = bin_index(size); ++ assert(idx == i); ++ /* lists are sorted */ ++ if ((unsigned long) size >= (unsigned long)(FIRST_SORTED_BIN_SIZE)) { ++ assert(p->bk == b || ++ (unsigned long)chunksize(p->bk) >= ++ (unsigned long)chunksize(p)); ++ } ++ } ++ /* chunk is followed by a legal chain of inuse chunks */ ++ for (q = next_chunk(p); ++ (q != av->top && inuse(q) && ++ (unsigned long)(chunksize(q)) >= MINSIZE); ++ q = next_chunk(q)) ++ __do_check_inuse_chunk(q); ++ } + } + + /* top chunk is OK */ +@@ -326,13 +323,13 @@ void __do_check_malloc_state(void) + assert(av->n_mmaps <= av->max_n_mmaps); + + assert((unsigned long)(av->sbrked_mem) <= +- (unsigned long)(av->max_sbrked_mem)); ++ (unsigned long)(av->max_sbrked_mem)); + + assert((unsigned long)(av->mmapped_mem) <= +- (unsigned long)(av->max_mmapped_mem)); ++ (unsigned long)(av->max_mmapped_mem)); + + assert((unsigned long)(av->max_total_mem) >= +- (unsigned long)(av->mmapped_mem) + (unsigned long)(av->sbrked_mem)); ++ (unsigned long)(av->mmapped_mem) + (unsigned long)(av->sbrked_mem)); + } + #endif + +@@ -370,84 +367,84 @@ static void* __malloc_alloc(size_t nb, m + size_t pagemask = av->pagesize - 1; + + /* +- If there is space available in fastbins, consolidate and retry +- malloc from scratch rather than getting memory from system. This +- can occur only if nb is in smallbin range so we didn't consolidate +- upon entry to malloc. It is much easier to handle this case here +- than in malloc proper. +- */ ++ If there is space available in fastbins, consolidate and retry ++ malloc from scratch rather than getting memory from system. This ++ can occur only if nb is in smallbin range so we didn't consolidate ++ upon entry to malloc. It is much easier to handle this case here ++ than in malloc proper. ++ */ + + if (have_fastchunks(av)) { +- assert(in_smallbin_range(nb)); +- __malloc_consolidate(av); +- return malloc(nb - MALLOC_ALIGN_MASK); ++ assert(in_smallbin_range(nb)); ++ __malloc_consolidate(av); ++ return malloc(nb - MALLOC_ALIGN_MASK); + } + + + /* +- If have mmap, and the request size meets the mmap threshold, and +- the system supports mmap, and there are few enough currently +- allocated mmapped regions, try to directly map this request +- rather than expanding top. +- */ ++ If have mmap, and the request size meets the mmap threshold, and ++ the system supports mmap, and there are few enough currently ++ allocated mmapped regions, try to directly map this request ++ rather than expanding top. ++ */ + + if ((unsigned long)(nb) >= (unsigned long)(av->mmap_threshold) && + (av->n_mmaps < av->n_mmaps_max)) { + +- char* mm; /* return value from mmap call*/ +- +- /* +- Round up size to nearest page. For mmapped chunks, the overhead +- is one (sizeof(size_t)) unit larger than for normal chunks, because there +- is no following chunk whose prev_size field could be used. +- */ +- size = (nb + (sizeof(size_t)) + MALLOC_ALIGN_MASK + pagemask) & ~pagemask; +- +- /* Don't try if size wraps around 0 */ +- if ((unsigned long)(size) > (unsigned long)(nb)) { +- +- mm = (char*)(MMAP(0, size, PROT_READ|PROT_WRITE)); +- +- if (mm != (char*)(MORECORE_FAILURE)) { ++ char* mm; /* return value from mmap call*/ + + /* +- The offset to the start of the mmapped region is stored +- in the prev_size field of the chunk. This allows us to adjust +- returned start address to meet alignment requirements here +- and in memalign(), and still be able to compute proper +- address argument for later munmap in free() and realloc(). +- */ +- +- front_misalign = (size_t)chunk2mem(mm) & MALLOC_ALIGN_MASK; +- if (front_misalign > 0) { +- correction = MALLOC_ALIGNMENT - front_misalign; +- p = (mchunkptr)(mm + correction); +- p->prev_size = correction; +- set_head(p, (size - correction) |IS_MMAPPED); +- } +- else { +- p = (mchunkptr)mm; +- p->prev_size = 0; +- set_head(p, size|IS_MMAPPED); +- } ++ Round up size to nearest page. For mmapped chunks, the overhead ++ is one (sizeof(size_t)) unit larger than for normal chunks, because there ++ is no following chunk whose prev_size field could be used. ++ */ ++ size = (nb + (sizeof(size_t)) + MALLOC_ALIGN_MASK + pagemask) & ~pagemask; ++ ++ /* Don't try if size wraps around 0 */ ++ if ((unsigned long)(size) > (unsigned long)(nb)) { ++ ++ mm = (char*)(MMAP(0, size, PROT_READ|PROT_WRITE)); ++ ++ if (mm != (char*)(MORECORE_FAILURE)) { ++ ++ /* ++ The offset to the start of the mmapped region is stored ++ in the prev_size field of the chunk. This allows us to adjust ++ returned start address to meet alignment requirements here ++ and in memalign(), and still be able to compute proper ++ address argument for later munmap in free() and realloc(). ++ */ ++ ++ front_misalign = (size_t)chunk2mem(mm) & MALLOC_ALIGN_MASK; ++ if (front_misalign > 0) { ++ correction = MALLOC_ALIGNMENT - front_misalign; ++ p = (mchunkptr)(mm + correction); ++ p->prev_size = correction; ++ set_head(p, (size - correction) |IS_MMAPPED); ++ } ++ else { ++ p = (mchunkptr)mm; ++ p->prev_size = 0; ++ set_head(p, size|IS_MMAPPED); ++ } ++ ++ /* update statistics */ ++ ++ if (++av->n_mmaps > av->max_n_mmaps) ++ av->max_n_mmaps = av->n_mmaps; ++ ++ sum = av->mmapped_mem += size; ++ if (sum > (unsigned long)(av->max_mmapped_mem)) ++ av->max_mmapped_mem = sum; ++ sum += av->sbrked_mem; ++ if (sum > (unsigned long)(av->max_total_mem)) ++ av->max_total_mem = sum; + +- /* update statistics */ ++ check_chunk(p); + +- if (++av->n_mmaps > av->max_n_mmaps) +- av->max_n_mmaps = av->n_mmaps; +- +- sum = av->mmapped_mem += size; +- if (sum > (unsigned long)(av->max_mmapped_mem)) +- av->max_mmapped_mem = sum; +- sum += av->sbrked_mem; +- if (sum > (unsigned long)(av->max_total_mem)) +- av->max_total_mem = sum; +- +- check_chunk(p); +- +- return chunk2mem(p); +- } +- } ++ return chunk2mem(p); ++ } ++ } + } + + /* Record incoming configuration of top */ +@@ -462,8 +459,8 @@ static void* __malloc_alloc(size_t nb, m + * be at least MINSIZE and to have prev_inuse set. */ + + assert((old_top == initial_top(av) && old_size == 0) || +- ((unsigned long) (old_size) >= MINSIZE && +- prev_inuse(old_top))); ++ ((unsigned long) (old_size) >= MINSIZE && ++ prev_inuse(old_top))); + + /* Precondition: not enough current space to satisfy nb request */ + assert((unsigned long)(old_size) < (unsigned long)(nb + MINSIZE)); +@@ -477,272 +474,272 @@ static void* __malloc_alloc(size_t nb, m + size = nb + av->top_pad + MINSIZE; + + /* +- If contiguous, we can subtract out existing space that we hope to +- combine with new space. We add it back later only if +- we don't actually get contiguous space. +- */ ++ If contiguous, we can subtract out existing space that we hope to ++ combine with new space. We add it back later only if ++ we don't actually get contiguous space. ++ */ + + if (contiguous(av)) +- size -= old_size; ++ size -= old_size; + + /* +- Round to a multiple of page size. +- If MORECORE is not contiguous, this ensures that we only call it +- with whole-page arguments. And if MORECORE is contiguous and +- this is not first time through, this preserves page-alignment of +- previous calls. Otherwise, we correct to page-align below. +- */ ++ Round to a multiple of page size. ++ If MORECORE is not contiguous, this ensures that we only call it ++ with whole-page arguments. And if MORECORE is contiguous and ++ this is not first time through, this preserves page-alignment of ++ previous calls. Otherwise, we correct to page-align below. ++ */ + + size = (size + pagemask) & ~pagemask; + + /* +- Don't try to call MORECORE if argument is so big as to appear +- negative. Note that since mmap takes size_t arg, it may succeed +- below even if we cannot call MORECORE. +- */ ++ Don't try to call MORECORE if argument is so big as to appear ++ negative. Note that since mmap takes size_t arg, it may succeed ++ below even if we cannot call MORECORE. ++ */ + + if (size > 0) +- brk = (char*)(MORECORE(size)); ++ brk = (char*)(MORECORE(size)); + + /* +- If have mmap, try using it as a backup when MORECORE fails or +- cannot be used. This is worth doing on systems that have "holes" in +- address space, so sbrk cannot extend to give contiguous space, but +- space is available elsewhere. Note that we ignore mmap max count +- and threshold limits, since the space will not be used as a +- segregated mmap region. +- */ ++ If have mmap, try using it as a backup when MORECORE fails or ++ cannot be used. This is worth doing on systems that have "holes" in ++ address space, so sbrk cannot extend to give contiguous space, but ++ space is available elsewhere. Note that we ignore mmap max count ++ and threshold limits, since the space will not be used as a ++ segregated mmap region. ++ */ + + if (brk == (char*)(MORECORE_FAILURE)) { + +- /* Cannot merge with old top, so add its size back in */ +- if (contiguous(av)) +- size = (size + old_size + pagemask) & ~pagemask; +- +- /* If we are relying on mmap as backup, then use larger units */ +- if ((unsigned long)(size) < (unsigned long)(MMAP_AS_MORECORE_SIZE)) +- size = MMAP_AS_MORECORE_SIZE; +- +- /* Don't try if size wraps around 0 */ +- if ((unsigned long)(size) > (unsigned long)(nb)) { +- +- brk = (char*)(MMAP(0, size, PROT_READ|PROT_WRITE)); +- +- if (brk != (char*)(MORECORE_FAILURE)) { +- +- /* We do not need, and cannot use, another sbrk call to find end */ +- snd_brk = brk + size; +- +- /* Record that we no longer have a contiguous sbrk region. +- After the first time mmap is used as backup, we do not +- ever rely on contiguous space since this could incorrectly +- bridge regions. +- */ +- set_noncontiguous(av); +- } +- } ++ /* Cannot merge with old top, so add its size back in */ ++ if (contiguous(av)) ++ size = (size + old_size + pagemask) & ~pagemask; ++ ++ /* If we are relying on mmap as backup, then use larger units */ ++ if ((unsigned long)(size) < (unsigned long)(MMAP_AS_MORECORE_SIZE)) ++ size = MMAP_AS_MORECORE_SIZE; ++ ++ /* Don't try if size wraps around 0 */ ++ if ((unsigned long)(size) > (unsigned long)(nb)) { ++ ++ brk = (char*)(MMAP(0, size, PROT_READ|PROT_WRITE)); ++ ++ if (brk != (char*)(MORECORE_FAILURE)) { ++ ++ /* We do not need, and cannot use, another sbrk call to find end */ ++ snd_brk = brk + size; ++ ++ /* Record that we no longer have a contiguous sbrk region. ++ After the first time mmap is used as backup, we do not ++ ever rely on contiguous space since this could incorrectly ++ bridge regions. ++ */ ++ set_noncontiguous(av); ++ } ++ } + } + + if (brk != (char*)(MORECORE_FAILURE)) { +- av->sbrked_mem += size; ++ av->sbrked_mem += size; + +- /* +- If MORECORE extends previous space, we can likewise extend top size. +- */ +- +- if (brk == old_end && snd_brk == (char*)(MORECORE_FAILURE)) { +- set_head(old_top, (size + old_size) | PREV_INUSE); +- } +- +- /* +- Otherwise, make adjustments: +- +- * If the first time through or noncontiguous, we need to call sbrk +- just to find out where the end of memory lies. +- +- * We need to ensure that all returned chunks from malloc will meet +- MALLOC_ALIGNMENT +- +- * If there was an intervening foreign sbrk, we need to adjust sbrk +- request size to account for fact that we will not be able to +- combine new space with existing space in old_top. +- +- * Almost all systems internally allocate whole pages at a time, in +- which case we might as well use the whole last page of request. +- So we allocate enough more memory to hit a page boundary now, +- which in turn causes future contiguous calls to page-align. +- */ +- +- else { +- front_misalign = 0; +- end_misalign = 0; +- correction = 0; +- aligned_brk = brk; +- +- /* +- If MORECORE returns an address lower than we have seen before, +- we know it isn't really contiguous. This and some subsequent +- checks help cope with non-conforming MORECORE functions and +- the presence of "foreign" calls to MORECORE from outside of +- malloc or by other threads. We cannot guarantee to detect +- these in all cases, but cope with the ones we do detect. +- */ +- if (contiguous(av) && old_size != 0 && brk < old_end) { +- set_noncontiguous(av); +- } +- +- /* handle contiguous cases */ +- if (contiguous(av)) { +- +- /* We can tolerate forward non-contiguities here (usually due +- to foreign calls) but treat them as part of our space for +- stats reporting. */ +- if (old_size != 0) +- av->sbrked_mem += brk - old_end; +- +- /* Guarantee alignment of first new chunk made from this space */ +- +- front_misalign = (size_t)chunk2mem(brk) & MALLOC_ALIGN_MASK; +- if (front_misalign > 0) { +- +- /* +- Skip over some bytes to arrive at an aligned position. +- We don't need to specially mark these wasted front bytes. +- They will never be accessed anyway because +- prev_inuse of av->top (and any chunk created from its start) +- is always true after initialization. +- */ ++ /* ++ If MORECORE extends previous space, we can likewise extend top size. ++ */ + +- correction = MALLOC_ALIGNMENT - front_misalign; +- aligned_brk += correction; ++ if (brk == old_end && snd_brk == (char*)(MORECORE_FAILURE)) { ++ set_head(old_top, (size + old_size) | PREV_INUSE); + } + + /* +- If this isn't adjacent to existing space, then we will not +- be able to merge with old_top space, so must add to 2nd request. +- */ +- +- correction += old_size; +- +- /* Extend the end address to hit a page boundary */ +- end_misalign = (size_t)(brk + size + correction); +- correction += ((end_misalign + pagemask) & ~pagemask) - end_misalign; +- +- assert(correction >= 0); +- snd_brk = (char*)(MORECORE(correction)); +- +- if (snd_brk == (char*)(MORECORE_FAILURE)) { +- /* +- If can't allocate correction, try to at least find out current +- brk. It might be enough to proceed without failing. +- */ +- correction = 0; +- snd_brk = (char*)(MORECORE(0)); +- } +- else if (snd_brk < brk) { +- /* +- If the second call gives noncontiguous space even though +- it says it won't, the only course of action is to ignore +- results of second call, and conservatively estimate where +- the first call left us. Also set noncontiguous, so this +- won't happen again, leaving at most one hole. +- +- Note that this check is intrinsically incomplete. Because +- MORECORE is allowed to give more space than we ask for, +- there is no reliable way to detect a noncontiguity +- producing a forward gap for the second call. +- */ +- snd_brk = brk + size; +- correction = 0; +- set_noncontiguous(av); +- } +- +- } +- +- /* handle non-contiguous cases */ +- else { +- /* MORECORE/mmap must correctly align */ +- assert(aligned_OK(chunk2mem(brk))); +- +- /* Find out current end of memory */ +- if (snd_brk == (char*)(MORECORE_FAILURE)) { +- snd_brk = (char*)(MORECORE(0)); +- av->sbrked_mem += snd_brk - brk - size; +- } +- } +- +- /* Adjust top based on results of second sbrk */ +- if (snd_brk != (char*)(MORECORE_FAILURE)) { +- av->top = (mchunkptr)aligned_brk; +- set_head(av->top, (snd_brk - aligned_brk + correction) | PREV_INUSE); +- av->sbrked_mem += correction; ++ Otherwise, make adjustments: + +- /* +- If not the first time through, we either have a +- gap due to foreign sbrk or a non-contiguous region. Insert a +- double fencepost at old_top to prevent consolidation with space +- we don't own. These fenceposts are artificial chunks that are +- marked as inuse and are in any case too small to use. We need +- two to make sizes and alignments work out. +- */ +- +- if (old_size != 0) { +- /* Shrink old_top to insert fenceposts, keeping size a +- multiple of MALLOC_ALIGNMENT. We know there is at least +- enough space in old_top to do this. +- */ +- old_size = (old_size - 3*(sizeof(size_t))) & ~MALLOC_ALIGN_MASK; +- set_head(old_top, old_size | PREV_INUSE); +- +- /* +- Note that the following assignments completely overwrite +- old_top when old_size was previously MINSIZE. This is +- intentional. We need the fencepost, even if old_top otherwise gets +- lost. +- */ +- chunk_at_offset(old_top, old_size )->size = +- (sizeof(size_t))|PREV_INUSE; +- +- chunk_at_offset(old_top, old_size + (sizeof(size_t)))->size = +- (sizeof(size_t))|PREV_INUSE; +- +- /* If possible, release the rest, suppressing trimming. */ +- if (old_size >= MINSIZE) { +- size_t tt = av->trim_threshold; +- av->trim_threshold = (size_t)(-1); +- free(chunk2mem(old_top)); +- av->trim_threshold = tt; +- } +- } +- } +- } +- +- /* Update statistics */ +- sum = av->sbrked_mem; +- if (sum > (unsigned long)(av->max_sbrked_mem)) +- av->max_sbrked_mem = sum; +- +- sum += av->mmapped_mem; +- if (sum > (unsigned long)(av->max_total_mem)) +- av->max_total_mem = sum; +- +- check_malloc_state(); +- +- /* finally, do the allocation */ +- +- p = av->top; +- size = chunksize(p); +- +- /* check that one of the above allocation paths succeeded */ +- if ((unsigned long)(size) >= (unsigned long)(nb + MINSIZE)) { +- remainder_size = size - nb; +- remainder = chunk_at_offset(p, nb); +- av->top = remainder; +- set_head(p, nb | PREV_INUSE); +- set_head(remainder, remainder_size | PREV_INUSE); +- check_malloced_chunk(p, nb); +- return chunk2mem(p); +- } ++ * If the first time through or noncontiguous, we need to call sbrk ++ just to find out where the end of memory lies. ++ ++ * We need to ensure that all returned chunks from malloc will meet ++ MALLOC_ALIGNMENT ++ ++ * If there was an intervening foreign sbrk, we need to adjust sbrk ++ request size to account for fact that we will not be able to ++ combine new space with existing space in old_top. ++ ++ * Almost all systems internally allocate whole pages at a time, in ++ which case we might as well use the whole last page of request. ++ So we allocate enough more memory to hit a page boundary now, ++ which in turn causes future contiguous calls to page-align. ++ */ ++ ++ else { ++ front_misalign = 0; ++ end_misalign = 0; ++ correction = 0; ++ aligned_brk = brk; ++ ++ /* ++ If MORECORE returns an address lower than we have seen before, ++ we know it isn't really contiguous. This and some subsequent ++ checks help cope with non-conforming MORECORE functions and ++ the presence of "foreign" calls to MORECORE from outside of ++ malloc or by other threads. We cannot guarantee to detect ++ these in all cases, but cope with the ones we do detect. ++ */ ++ if (contiguous(av) && old_size != 0 && brk < old_end) { ++ set_noncontiguous(av); ++ } ++ ++ /* handle contiguous cases */ ++ if (contiguous(av)) { ++ ++ /* We can tolerate forward non-contiguities here (usually due ++ to foreign calls) but treat them as part of our space for ++ stats reporting. */ ++ if (old_size != 0) ++ av->sbrked_mem += brk - old_end; ++ ++ /* Guarantee alignment of first new chunk made from this space */ ++ ++ front_misalign = (size_t)chunk2mem(brk) & MALLOC_ALIGN_MASK; ++ if (front_misalign > 0) { ++ ++ /* ++ Skip over some bytes to arrive at an aligned position. ++ We don't need to specially mark these wasted front bytes. ++ They will never be accessed anyway because ++ prev_inuse of av->top (and any chunk created from its start) ++ is always true after initialization. ++ */ ++ ++ correction = MALLOC_ALIGNMENT - front_misalign; ++ aligned_brk += correction; ++ } ++ ++ /* ++ If this isn't adjacent to existing space, then we will not ++ be able to merge with old_top space, so must add to 2nd request. ++ */ ++ ++ correction += old_size; ++ ++ /* Extend the end address to hit a page boundary */ ++ end_misalign = (size_t)(brk + size + correction); ++ correction += ((end_misalign + pagemask) & ~pagemask) - end_misalign; ++ ++ assert(correction >= 0); ++ snd_brk = (char*)(MORECORE(correction)); ++ ++ if (snd_brk == (char*)(MORECORE_FAILURE)) { ++ /* ++ If can't allocate correction, try to at least find out current ++ brk. It might be enough to proceed without failing. ++ */ ++ correction = 0; ++ snd_brk = (char*)(MORECORE(0)); ++ } ++ else if (snd_brk < brk) { ++ /* ++ If the second call gives noncontiguous space even though ++ it says it won't, the only course of action is to ignore ++ results of second call, and conservatively estimate where ++ the first call left us. Also set noncontiguous, so this ++ won't happen again, leaving at most one hole. ++ ++ Note that this check is intrinsically incomplete. Because ++ MORECORE is allowed to give more space than we ask for, ++ there is no reliable way to detect a noncontiguity ++ producing a forward gap for the second call. ++ */ ++ snd_brk = brk + size; ++ correction = 0; ++ set_noncontiguous(av); ++ } ++ ++ } ++ ++ /* handle non-contiguous cases */ ++ else { ++ /* MORECORE/mmap must correctly align */ ++ assert(aligned_OK(chunk2mem(brk))); ++ ++ /* Find out current end of memory */ ++ if (snd_brk == (char*)(MORECORE_FAILURE)) { ++ snd_brk = (char*)(MORECORE(0)); ++ av->sbrked_mem += snd_brk - brk - size; ++ } ++ } ++ ++ /* Adjust top based on results of second sbrk */ ++ if (snd_brk != (char*)(MORECORE_FAILURE)) { ++ av->top = (mchunkptr)aligned_brk; ++ set_head(av->top, (snd_brk - aligned_brk + correction) | PREV_INUSE); ++ av->sbrked_mem += correction; ++ ++ /* ++ If not the first time through, we either have a ++ gap due to foreign sbrk or a non-contiguous region. Insert a ++ double fencepost at old_top to prevent consolidation with space ++ we don't own. These fenceposts are artificial chunks that are ++ marked as inuse and are in any case too small to use. We need ++ two to make sizes and alignments work out. ++ */ ++ ++ if (old_size != 0) { ++ /* Shrink old_top to insert fenceposts, keeping size a ++ multiple of MALLOC_ALIGNMENT. We know there is at least ++ enough space in old_top to do this. ++ */ ++ old_size = (old_size - 3*(sizeof(size_t))) & ~MALLOC_ALIGN_MASK; ++ set_head(old_top, old_size | PREV_INUSE); ++ ++ /* ++ Note that the following assignments completely overwrite ++ old_top when old_size was previously MINSIZE. This is ++ intentional. We need the fencepost, even if old_top otherwise gets ++ lost. ++ */ ++ chunk_at_offset(old_top, old_size )->size = ++ (sizeof(size_t))|PREV_INUSE; ++ ++ chunk_at_offset(old_top, old_size + (sizeof(size_t)))->size = ++ (sizeof(size_t))|PREV_INUSE; ++ ++ /* If possible, release the rest, suppressing trimming. */ ++ if (old_size >= MINSIZE) { ++ size_t tt = av->trim_threshold; ++ av->trim_threshold = (size_t)(-1); ++ free(chunk2mem(old_top)); ++ av->trim_threshold = tt; ++ } ++ } ++ } ++ } ++ ++ /* Update statistics */ ++ sum = av->sbrked_mem; ++ if (sum > (unsigned long)(av->max_sbrked_mem)) ++ av->max_sbrked_mem = sum; ++ ++ sum += av->mmapped_mem; ++ if (sum > (unsigned long)(av->max_total_mem)) ++ av->max_total_mem = sum; ++ ++ check_malloc_state(); ++ ++ /* finally, do the allocation */ ++ ++ p = av->top; ++ size = chunksize(p); ++ ++ /* check that one of the above allocation paths succeeded */ ++ if ((unsigned long)(size) >= (unsigned long)(nb + MINSIZE)) { ++ remainder_size = size - nb; ++ remainder = chunk_at_offset(p, nb); ++ av->top = remainder; ++ set_head(p, nb | PREV_INUSE); ++ set_head(remainder, remainder_size | PREV_INUSE); ++ check_malloced_chunk(p, nb); ++ return chunk2mem(p); ++ } + + } + +@@ -767,25 +764,25 @@ static int __malloc_largebin_index(unsig + #if defined(__GNUC__) && defined(i386) + + __asm__("bsrl %1,%0\n\t" +- : "=r" (m) +- : "g" (x)); ++ : "=r" (m) ++ : "g" (x)); + + #else + { +- /* +- Based on branch-free nlz algorithm in chapter 5 of Henry +- S. Warren Jr's book "Hacker's Delight". +- */ +- +- unsigned int n = ((x - 0x100) >> 16) & 8; +- x <<= n; +- m = ((x - 0x1000) >> 16) & 4; +- n += m; +- x <<= m; +- m = ((x - 0x4000) >> 16) & 2; +- n += m; +- x = (x << m) >> 14; +- m = 13 - n + (x & ~(x>>1)); ++ /* ++ Based on branch-free nlz algorithm in chapter 5 of Henry ++ S. Warren Jr's book "Hacker's Delight". ++ */ ++ ++ unsigned int n = ((x - 0x100) >> 16) & 8; ++ x <<= n; ++ m = ((x - 0x1000) >> 16) & 4; ++ n += m; ++ x <<= m; ++ m = ((x - 0x4000) >> 16) & 2; ++ n += m; ++ x = (x << m) >> 14; ++ m = 13 - n + (x & ~(x>>1)); + } + #endif + +@@ -826,69 +823,70 @@ void* malloc(size_t bytes) + mchunkptr fwd; /* misc temp for linking */ + mchunkptr bck; /* misc temp for linking */ + void * sysmem; ++ void * retval; + + #if !defined(__MALLOC_GLIBC_COMPAT__) + if (!bytes) return NULL; + #endif + +- LOCK; ++ __MALLOC_LOCK; + av = get_malloc_state(); + /* +- Convert request size to internal form by adding (sizeof(size_t)) bytes +- overhead plus possibly more to obtain necessary alignment and/or +- to obtain a size of at least MINSIZE, the smallest allocatable +- size. Also, checked_request2size traps (returning 0) request sizes +- that are so large that they wrap around zero when padded and +- aligned. +- */ ++ Convert request size to internal form by adding (sizeof(size_t)) bytes ++ overhead plus possibly more to obtain necessary alignment and/or ++ to obtain a size of at least MINSIZE, the smallest allocatable ++ size. Also, checked_request2size traps (returning 0) request sizes ++ that are so large that they wrap around zero when padded and ++ aligned. ++ */ + + checked_request2size(bytes, nb); + + /* +- Bypass search if no frees yet +- */ ++ Bypass search if no frees yet ++ */ + if (!have_anychunks(av)) { +- if (av->max_fast == 0) /* initialization check */ +- __malloc_consolidate(av); +- goto use_top; ++ if (av->max_fast == 0) /* initialization check */ ++ __malloc_consolidate(av); ++ goto use_top; + } + + /* +- If the size qualifies as a fastbin, first check corresponding bin. +- */ ++ If the size qualifies as a fastbin, first check corresponding bin. ++ */ + + if ((unsigned long)(nb) <= (unsigned long)(av->max_fast)) { +- fb = &(av->fastbins[(fastbin_index(nb))]); +- if ( (victim = *fb) != 0) { +- *fb = victim->fd; +- check_remalloced_chunk(victim, nb); +- UNLOCK; +- return chunk2mem(victim); +- } ++ fb = &(av->fastbins[(fastbin_index(nb))]); ++ if ( (victim = *fb) != 0) { ++ *fb = victim->fd; ++ check_remalloced_chunk(victim, nb); ++ retval = chunk2mem(victim); ++ goto DONE; ++ } + } + + /* +- If a small request, check regular bin. Since these "smallbins" +- hold one size each, no searching within bins is necessary. +- (For a large request, we need to wait until unsorted chunks are +- processed to find best fit. But for small ones, fits are exact +- anyway, so we can check now, which is faster.) +- */ ++ If a small request, check regular bin. Since these "smallbins" ++ hold one size each, no searching within bins is necessary. ++ (For a large request, we need to wait until unsorted chunks are ++ processed to find best fit. But for small ones, fits are exact ++ anyway, so we can check now, which is faster.) ++ */ + + if (in_smallbin_range(nb)) { +- idx = smallbin_index(nb); +- bin = bin_at(av,idx); ++ idx = smallbin_index(nb); ++ bin = bin_at(av,idx); + +- if ( (victim = last(bin)) != bin) { +- bck = victim->bk; +- set_inuse_bit_at_offset(victim, nb); +- bin->bk = bck; +- bck->fd = bin; +- +- check_malloced_chunk(victim, nb); +- UNLOCK; +- return chunk2mem(victim); +- } ++ if ( (victim = last(bin)) != bin) { ++ bck = victim->bk; ++ set_inuse_bit_at_offset(victim, nb); ++ bin->bk = bck; ++ bck->fd = bin; ++ ++ check_malloced_chunk(victim, nb); ++ retval = chunk2mem(victim); ++ goto DONE; ++ } + } + + /* If this is a large request, consolidate fastbins before continuing. +@@ -899,154 +897,154 @@ void* malloc(size_t bytes) + large requests, but less often mixtures, so consolidation is not + invoked all that often in most programs. And the programs that + it is called frequently in otherwise tend to fragment. +- */ ++ */ + + else { +- idx = __malloc_largebin_index(nb); +- if (have_fastchunks(av)) +- __malloc_consolidate(av); ++ idx = __malloc_largebin_index(nb); ++ if (have_fastchunks(av)) ++ __malloc_consolidate(av); + } + + /* +- Process recently freed or remaindered chunks, taking one only if +- it is exact fit, or, if this a small request, the chunk is remainder from +- the most recent non-exact fit. Place other traversed chunks in +- bins. Note that this step is the only place in any routine where +- chunks are placed in bins. +- */ ++ Process recently freed or remaindered chunks, taking one only if ++ it is exact fit, or, if this a small request, the chunk is remainder from ++ the most recent non-exact fit. Place other traversed chunks in ++ bins. Note that this step is the only place in any routine where ++ chunks are placed in bins. ++ */ + + while ( (victim = unsorted_chunks(av)->bk) != unsorted_chunks(av)) { +- bck = victim->bk; +- size = chunksize(victim); ++ bck = victim->bk; ++ size = chunksize(victim); ++ ++ /* If a small request, try to use last remainder if it is the ++ only chunk in unsorted bin. This helps promote locality for ++ runs of consecutive small requests. This is the only ++ exception to best-fit, and applies only when there is ++ no exact fit for a small chunk. ++ */ ++ ++ if (in_smallbin_range(nb) && ++ bck == unsorted_chunks(av) && ++ victim == av->last_remainder && ++ (unsigned long)(size) > (unsigned long)(nb + MINSIZE)) { ++ ++ /* split and reattach remainder */ ++ remainder_size = size - nb; ++ remainder = chunk_at_offset(victim, nb); ++ unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder; ++ av->last_remainder = remainder; ++ remainder->bk = remainder->fd = unsorted_chunks(av); ++ ++ set_head(victim, nb | PREV_INUSE); ++ set_head(remainder, remainder_size | PREV_INUSE); ++ set_foot(remainder, remainder_size); ++ ++ check_malloced_chunk(victim, nb); ++ retval = chunk2mem(victim); ++ goto DONE; ++ } ++ ++ /* remove from unsorted list */ ++ unsorted_chunks(av)->bk = bck; ++ bck->fd = unsorted_chunks(av); ++ ++ /* Take now instead of binning if exact fit */ ++ ++ if (size == nb) { ++ set_inuse_bit_at_offset(victim, size); ++ check_malloced_chunk(victim, nb); ++ retval = chunk2mem(victim); ++ goto DONE; ++ } ++ ++ /* place chunk in bin */ + +- /* If a small request, try to use last remainder if it is the +- only chunk in unsorted bin. This helps promote locality for +- runs of consecutive small requests. This is the only +- exception to best-fit, and applies only when there is +- no exact fit for a small chunk. +- */ +- +- if (in_smallbin_range(nb) && +- bck == unsorted_chunks(av) && +- victim == av->last_remainder && +- (unsigned long)(size) > (unsigned long)(nb + MINSIZE)) { +- +- /* split and reattach remainder */ +- remainder_size = size - nb; +- remainder = chunk_at_offset(victim, nb); +- unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder; +- av->last_remainder = remainder; +- remainder->bk = remainder->fd = unsorted_chunks(av); +- +- set_head(victim, nb | PREV_INUSE); +- set_head(remainder, remainder_size | PREV_INUSE); +- set_foot(remainder, remainder_size); +- +- check_malloced_chunk(victim, nb); +- UNLOCK; +- return chunk2mem(victim); +- } +- +- /* remove from unsorted list */ +- unsorted_chunks(av)->bk = bck; +- bck->fd = unsorted_chunks(av); +- +- /* Take now instead of binning if exact fit */ +- +- if (size == nb) { +- set_inuse_bit_at_offset(victim, size); +- check_malloced_chunk(victim, nb); +- UNLOCK; +- return chunk2mem(victim); +- } +- +- /* place chunk in bin */ +- +- if (in_smallbin_range(size)) { +- victim_index = smallbin_index(size); +- bck = bin_at(av, victim_index); +- fwd = bck->fd; +- } +- else { +- victim_index = __malloc_largebin_index(size); +- bck = bin_at(av, victim_index); +- fwd = bck->fd; +- +- if (fwd != bck) { +- /* if smaller than smallest, place first */ +- if ((unsigned long)(size) < (unsigned long)(bck->bk->size)) { +- fwd = bck; +- bck = bck->bk; +- } +- else if ((unsigned long)(size) >= +- (unsigned long)(FIRST_SORTED_BIN_SIZE)) { +- +- /* maintain large bins in sorted order */ +- size |= PREV_INUSE; /* Or with inuse bit to speed comparisons */ +- while ((unsigned long)(size) < (unsigned long)(fwd->size)) +- fwd = fwd->fd; +- bck = fwd->bk; +- } +- } +- } +- +- mark_bin(av, victim_index); +- victim->bk = bck; +- victim->fd = fwd; +- fwd->bk = victim; +- bck->fd = victim; ++ if (in_smallbin_range(size)) { ++ victim_index = smallbin_index(size); ++ bck = bin_at(av, victim_index); ++ fwd = bck->fd; ++ } ++ else { ++ victim_index = __malloc_largebin_index(size); ++ bck = bin_at(av, victim_index); ++ fwd = bck->fd; ++ ++ if (fwd != bck) { ++ /* if smaller than smallest, place first */ ++ if ((unsigned long)(size) < (unsigned long)(bck->bk->size)) { ++ fwd = bck; ++ bck = bck->bk; ++ } ++ else if ((unsigned long)(size) >= ++ (unsigned long)(FIRST_SORTED_BIN_SIZE)) { ++ ++ /* maintain large bins in sorted order */ ++ size |= PREV_INUSE; /* Or with inuse bit to speed comparisons */ ++ while ((unsigned long)(size) < (unsigned long)(fwd->size)) ++ fwd = fwd->fd; ++ bck = fwd->bk; ++ } ++ } ++ } ++ ++ mark_bin(av, victim_index); ++ victim->bk = bck; ++ victim->fd = fwd; ++ fwd->bk = victim; ++ bck->fd = victim; + } + + /* +- If a large request, scan through the chunks of current bin to +- find one that fits. (This will be the smallest that fits unless +- FIRST_SORTED_BIN_SIZE has been changed from default.) This is +- the only step where an unbounded number of chunks might be +- scanned without doing anything useful with them. However the +- lists tend to be short. +- */ ++ If a large request, scan through the chunks of current bin to ++ find one that fits. (This will be the smallest that fits unless ++ FIRST_SORTED_BIN_SIZE has been changed from default.) This is ++ the only step where an unbounded number of chunks might be ++ scanned without doing anything useful with them. However the ++ lists tend to be short. ++ */ + + if (!in_smallbin_range(nb)) { +- bin = bin_at(av, idx); +- +- for (victim = last(bin); victim != bin; victim = victim->bk) { +- size = chunksize(victim); ++ bin = bin_at(av, idx); + +- if ((unsigned long)(size) >= (unsigned long)(nb)) { +- remainder_size = size - nb; +- unlink(victim, bck, fwd); ++ for (victim = last(bin); victim != bin; victim = victim->bk) { ++ size = chunksize(victim); + +- /* Exhaust */ +- if (remainder_size < MINSIZE) { +- set_inuse_bit_at_offset(victim, size); +- check_malloced_chunk(victim, nb); +- UNLOCK; +- return chunk2mem(victim); +- } +- /* Split */ +- else { +- remainder = chunk_at_offset(victim, nb); +- unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder; +- remainder->bk = remainder->fd = unsorted_chunks(av); +- set_head(victim, nb | PREV_INUSE); +- set_head(remainder, remainder_size | PREV_INUSE); +- set_foot(remainder, remainder_size); +- check_malloced_chunk(victim, nb); +- UNLOCK; +- return chunk2mem(victim); ++ if ((unsigned long)(size) >= (unsigned long)(nb)) { ++ remainder_size = size - nb; ++ unlink(victim, bck, fwd); ++ ++ /* Exhaust */ ++ if (remainder_size < MINSIZE) { ++ set_inuse_bit_at_offset(victim, size); ++ check_malloced_chunk(victim, nb); ++ retval = chunk2mem(victim); ++ goto DONE; ++ } ++ /* Split */ ++ else { ++ remainder = chunk_at_offset(victim, nb); ++ unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder; ++ remainder->bk = remainder->fd = unsorted_chunks(av); ++ set_head(victim, nb | PREV_INUSE); ++ set_head(remainder, remainder_size | PREV_INUSE); ++ set_foot(remainder, remainder_size); ++ check_malloced_chunk(victim, nb); ++ retval = chunk2mem(victim); ++ goto DONE; ++ } ++ } + } +- } +- } + } + + /* +- Search for a chunk by scanning bins, starting with next largest +- bin. This search is strictly by best-fit; i.e., the smallest +- (with ties going to approximately the least recently used) chunk +- that fits is selected. ++ Search for a chunk by scanning bins, starting with next largest ++ bin. This search is strictly by best-fit; i.e., the smallest ++ (with ties going to approximately the least recently used) chunk ++ that fits is selected. + +- The bitmap avoids needing to check that most blocks are nonempty. +- */ ++ The bitmap avoids needing to check that most blocks are nonempty. ++ */ + + ++idx; + bin = bin_at(av,idx); +@@ -1056,109 +1054,111 @@ void* malloc(size_t bytes) + + for (;;) { + +- /* Skip rest of block if there are no more set bits in this block. */ +- if (bit > map || bit == 0) { +- do { +- if (++block >= BINMAPSIZE) /* out of bins */ +- goto use_top; +- } while ( (map = av->binmap[block]) == 0); +- +- bin = bin_at(av, (block << BINMAPSHIFT)); +- bit = 1; +- } +- +- /* Advance to bin with set bit. There must be one. */ +- while ((bit & map) == 0) { +- bin = next_bin(bin); +- bit <<= 1; +- assert(bit != 0); +- } +- +- /* Inspect the bin. It is likely to be non-empty */ +- victim = last(bin); +- +- /* If a false alarm (empty bin), clear the bit. */ +- if (victim == bin) { +- av->binmap[block] = map &= ~bit; /* Write through */ +- bin = next_bin(bin); +- bit <<= 1; +- } +- +- else { +- size = chunksize(victim); +- +- /* We know the first chunk in this bin is big enough to use. */ +- assert((unsigned long)(size) >= (unsigned long)(nb)); +- +- remainder_size = size - nb; +- +- /* unlink */ +- bck = victim->bk; +- bin->bk = bck; +- bck->fd = bin; +- +- /* Exhaust */ +- if (remainder_size < MINSIZE) { +- set_inuse_bit_at_offset(victim, size); +- check_malloced_chunk(victim, nb); +- UNLOCK; +- return chunk2mem(victim); +- } ++ /* Skip rest of block if there are no more set bits in this block. */ ++ if (bit > map || bit == 0) { ++ do { ++ if (++block >= BINMAPSIZE) /* out of bins */ ++ goto use_top; ++ } while ( (map = av->binmap[block]) == 0); + +- /* Split */ +- else { +- remainder = chunk_at_offset(victim, nb); ++ bin = bin_at(av, (block << BINMAPSHIFT)); ++ bit = 1; ++ } + +- unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder; +- remainder->bk = remainder->fd = unsorted_chunks(av); +- /* advertise as last remainder */ +- if (in_smallbin_range(nb)) +- av->last_remainder = remainder; ++ /* Advance to bin with set bit. There must be one. */ ++ while ((bit & map) == 0) { ++ bin = next_bin(bin); ++ bit <<= 1; ++ assert(bit != 0); ++ } + +- set_head(victim, nb | PREV_INUSE); +- set_head(remainder, remainder_size | PREV_INUSE); +- set_foot(remainder, remainder_size); +- check_malloced_chunk(victim, nb); +- UNLOCK; +- return chunk2mem(victim); +- } +- } ++ /* Inspect the bin. It is likely to be non-empty */ ++ victim = last(bin); ++ ++ /* If a false alarm (empty bin), clear the bit. */ ++ if (victim == bin) { ++ av->binmap[block] = map &= ~bit; /* Write through */ ++ bin = next_bin(bin); ++ bit <<= 1; ++ } ++ ++ else { ++ size = chunksize(victim); ++ ++ /* We know the first chunk in this bin is big enough to use. */ ++ assert((unsigned long)(size) >= (unsigned long)(nb)); ++ ++ remainder_size = size - nb; ++ ++ /* unlink */ ++ bck = victim->bk; ++ bin->bk = bck; ++ bck->fd = bin; ++ ++ /* Exhaust */ ++ if (remainder_size < MINSIZE) { ++ set_inuse_bit_at_offset(victim, size); ++ check_malloced_chunk(victim, nb); ++ retval = chunk2mem(victim); ++ goto DONE; ++ } ++ ++ /* Split */ ++ else { ++ remainder = chunk_at_offset(victim, nb); ++ ++ unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder; ++ remainder->bk = remainder->fd = unsorted_chunks(av); ++ /* advertise as last remainder */ ++ if (in_smallbin_range(nb)) ++ av->last_remainder = remainder; ++ ++ set_head(victim, nb | PREV_INUSE); ++ set_head(remainder, remainder_size | PREV_INUSE); ++ set_foot(remainder, remainder_size); ++ check_malloced_chunk(victim, nb); ++ retval = chunk2mem(victim); ++ goto DONE; ++ } ++ } + } + +-use_top: ++ use_top: + /* +- If large enough, split off the chunk bordering the end of memory +- (held in av->top). Note that this is in accord with the best-fit +- search rule. In effect, av->top is treated as larger (and thus +- less well fitting) than any other available chunk since it can +- be extended to be as large as necessary (up to system +- limitations). +- +- We require that av->top always exists (i.e., has size >= +- MINSIZE) after initialization, so if it would otherwise be +- exhuasted by current request, it is replenished. (The main +- reason for ensuring it exists is that we may need MINSIZE space +- to put in fenceposts in sysmalloc.) +- */ ++ If large enough, split off the chunk bordering the end of memory ++ (held in av->top). Note that this is in accord with the best-fit ++ search rule. In effect, av->top is treated as larger (and thus ++ less well fitting) than any other available chunk since it can ++ be extended to be as large as necessary (up to system ++ limitations). ++ ++ We require that av->top always exists (i.e., has size >= ++ MINSIZE) after initialization, so if it would otherwise be ++ exhuasted by current request, it is replenished. (The main ++ reason for ensuring it exists is that we may need MINSIZE space ++ to put in fenceposts in sysmalloc.) ++ */ + + victim = av->top; + size = chunksize(victim); + + if ((unsigned long)(size) >= (unsigned long)(nb + MINSIZE)) { +- remainder_size = size - nb; +- remainder = chunk_at_offset(victim, nb); +- av->top = remainder; +- set_head(victim, nb | PREV_INUSE); +- set_head(remainder, remainder_size | PREV_INUSE); +- +- check_malloced_chunk(victim, nb); +- UNLOCK; +- return chunk2mem(victim); ++ remainder_size = size - nb; ++ remainder = chunk_at_offset(victim, nb); ++ av->top = remainder; ++ set_head(victim, nb | PREV_INUSE); ++ set_head(remainder, remainder_size | PREV_INUSE); ++ ++ check_malloced_chunk(victim, nb); ++ retval = chunk2mem(victim); ++ goto DONE; + } + + /* If no space in top, relay to handle system-dependent cases */ + sysmem = __malloc_alloc(nb, av); +- UNLOCK; +- return sysmem; ++ retval = sysmem; ++ DONE: ++ __MALLOC_UNLOCK; ++ return retval; + } + +diff --git a/libc/stdlib/malloc-standard/malloc.h b/libc/stdlib/malloc-standard/malloc.h +index fbc1492..14a0dd9 100644 +--- a/libc/stdlib/malloc-standard/malloc.h ++++ b/libc/stdlib/malloc-standard/malloc.h +@@ -22,16 +22,12 @@ + #include <malloc.h> + #include <stdlib.h> + ++#include <bits/uClibc_mutex.h> + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-extern pthread_mutex_t __malloc_lock; +-# define LOCK __pthread_mutex_lock(&__malloc_lock) +-# define UNLOCK __pthread_mutex_unlock(&__malloc_lock); +-#else +-# define LOCK +-# define UNLOCK +-#endif ++__UCLIBC_MUTEX_EXTERN(__malloc_lock); ++ ++#define __MALLOC_LOCK __UCLIBC_MUTEX_LOCK(__malloc_lock) ++#define __MALLOC_UNLOCK __UCLIBC_MUTEX_UNLOCK(__malloc_lock) + + + +diff --git a/libc/stdlib/malloc-standard/mallopt.c b/libc/stdlib/malloc-standard/mallopt.c +index e287920..41aa614 100644 +--- a/libc/stdlib/malloc-standard/mallopt.c ++++ b/libc/stdlib/malloc-standard/mallopt.c +@@ -8,7 +8,7 @@ + VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at +- ftp://gee.cs.oswego.edu/pub/misc/malloc.c ++ ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + + Hacked up for uClibc by Erik Andersen <andersen@codepoet.org> +@@ -25,40 +25,40 @@ int mallopt(int param_number, int value) + + ret = 0; + +- LOCK; ++ __MALLOC_LOCK; + av = get_malloc_state(); + /* Ensure initialization/consolidation */ + __malloc_consolidate(av); + + switch(param_number) { +- case M_MXFAST: +- if (value >= 0 && value <= MAX_FAST_SIZE) { +- set_max_fast(av, value); +- ret = 1; +- } +- break; +- +- case M_TRIM_THRESHOLD: +- av->trim_threshold = value; +- ret = 1; +- break; +- +- case M_TOP_PAD: +- av->top_pad = value; +- ret = 1; +- break; +- +- case M_MMAP_THRESHOLD: +- av->mmap_threshold = value; +- ret = 1; +- break; +- +- case M_MMAP_MAX: +- av->n_mmaps_max = value; +- ret = 1; +- break; ++ case M_MXFAST: ++ if (value >= 0 && value <= MAX_FAST_SIZE) { ++ set_max_fast(av, value); ++ ret = 1; ++ } ++ break; ++ ++ case M_TRIM_THRESHOLD: ++ av->trim_threshold = value; ++ ret = 1; ++ break; ++ ++ case M_TOP_PAD: ++ av->top_pad = value; ++ ret = 1; ++ break; ++ ++ case M_MMAP_THRESHOLD: ++ av->mmap_threshold = value; ++ ret = 1; ++ break; ++ ++ case M_MMAP_MAX: ++ av->n_mmaps_max = value; ++ ret = 1; ++ break; + } +- UNLOCK; ++ __MALLOC_UNLOCK; + return ret; + } + +diff --git a/libc/stdlib/malloc-standard/memalign.c b/libc/stdlib/malloc-standard/memalign.c +index bd95362..e78d752 100644 +--- a/libc/stdlib/malloc-standard/memalign.c ++++ b/libc/stdlib/malloc-standard/memalign.c +@@ -8,7 +8,7 @@ + VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at +- ftp://gee.cs.oswego.edu/pub/misc/malloc.c ++ ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + + Hacked up for uClibc by Erik Andersen <andersen@codepoet.org> +@@ -35,6 +35,7 @@ void* memalign(size_t alignment, size_t + mchunkptr remainder; /* spare room at end to split off */ + unsigned long remainder_size; /* its size */ + size_t size; ++ void *retval; + + /* If need less alignment than we give anyway, just relay to malloc */ + +@@ -46,12 +47,12 @@ void* memalign(size_t alignment, size_t + + /* Make sure alignment is power of 2 (in case MINSIZE is not). */ + if ((alignment & (alignment - 1)) != 0) { +- size_t a = MALLOC_ALIGNMENT * 2; +- while ((unsigned long)a < (unsigned long)alignment) a <<= 1; +- alignment = a; ++ size_t a = MALLOC_ALIGNMENT * 2; ++ while ((unsigned long)a < (unsigned long)alignment) a <<= 1; ++ alignment = a; + } + +- LOCK; ++ __MALLOC_LOCK; + checked_request2size(bytes, nb); + + /* Strategy: find a spot within that chunk that meets the alignment +@@ -63,64 +64,67 @@ void* memalign(size_t alignment, size_t + m = (char*)(malloc(nb + alignment + MINSIZE)); + + if (m == 0) { +- UNLOCK; +- return 0; /* propagate failure */ ++ retval = 0; /* propagate failure */ ++ goto DONE; + } + + p = mem2chunk(m); + + if ((((unsigned long)(m)) % alignment) != 0) { /* misaligned */ + +- /* +- Find an aligned spot inside chunk. Since we need to give back +- leading space in a chunk of at least MINSIZE, if the first +- calculation places us at a spot with less than MINSIZE leader, +- we can move to the next aligned spot -- we've allocated enough +- total room so that this is always possible. +- */ +- +- brk = (char*)mem2chunk((unsigned long)(((unsigned long)(m + alignment - 1)) & +- -((signed long) alignment))); +- if ((unsigned long)(brk - (char*)(p)) < MINSIZE) +- brk += alignment; +- +- newp = (mchunkptr)brk; +- leadsize = brk - (char*)(p); +- newsize = chunksize(p) - leadsize; +- +- /* For mmapped chunks, just adjust offset */ +- if (chunk_is_mmapped(p)) { +- newp->prev_size = p->prev_size + leadsize; +- set_head(newp, newsize|IS_MMAPPED); +- UNLOCK; +- return chunk2mem(newp); +- } +- +- /* Otherwise, give back leader, use the rest */ +- set_head(newp, newsize | PREV_INUSE); +- set_inuse_bit_at_offset(newp, newsize); +- set_head_size(p, leadsize); +- free(chunk2mem(p)); +- p = newp; ++ /* ++ Find an aligned spot inside chunk. Since we need to give back ++ leading space in a chunk of at least MINSIZE, if the first ++ calculation places us at a spot with less than MINSIZE leader, ++ we can move to the next aligned spot -- we've allocated enough ++ total room so that this is always possible. ++ */ ++ ++ brk = (char*)mem2chunk((unsigned long)(((unsigned long)(m + alignment - 1)) & ++ -((signed long) alignment))); ++ if ((unsigned long)(brk - (char*)(p)) < MINSIZE) ++ brk += alignment; ++ ++ newp = (mchunkptr)brk; ++ leadsize = brk - (char*)(p); ++ newsize = chunksize(p) - leadsize; ++ ++ /* For mmapped chunks, just adjust offset */ ++ if (chunk_is_mmapped(p)) { ++ newp->prev_size = p->prev_size + leadsize; ++ set_head(newp, newsize|IS_MMAPPED); ++ retval = chunk2mem(newp); ++ goto DONE; ++ } ++ ++ /* Otherwise, give back leader, use the rest */ ++ set_head(newp, newsize | PREV_INUSE); ++ set_inuse_bit_at_offset(newp, newsize); ++ set_head_size(p, leadsize); ++ free(chunk2mem(p)); ++ p = newp; + +- assert (newsize >= nb && +- (((unsigned long)(chunk2mem(p))) % alignment) == 0); ++ assert (newsize >= nb && ++ (((unsigned long)(chunk2mem(p))) % alignment) == 0); + } + + /* Also give back spare room at the end */ + if (!chunk_is_mmapped(p)) { +- size = chunksize(p); +- if ((unsigned long)(size) > (unsigned long)(nb + MINSIZE)) { +- remainder_size = size - nb; +- remainder = chunk_at_offset(p, nb); +- set_head(remainder, remainder_size | PREV_INUSE); +- set_head_size(p, nb); +- free(chunk2mem(remainder)); +- } ++ size = chunksize(p); ++ if ((unsigned long)(size) > (unsigned long)(nb + MINSIZE)) { ++ remainder_size = size - nb; ++ remainder = chunk_at_offset(p, nb); ++ set_head(remainder, remainder_size | PREV_INUSE); ++ set_head_size(p, nb); ++ free(chunk2mem(remainder)); ++ } + } + + check_inuse_chunk(p); +- UNLOCK; +- return chunk2mem(p); ++ retval = chunk2mem(p); ++ ++ DONE: ++ __MALLOC_UNLOCK; ++ return retval; + } + +diff --git a/libc/stdlib/malloc-standard/realloc.c b/libc/stdlib/malloc-standard/realloc.c +index 1950130..9ca4b26 100644 +--- a/libc/stdlib/malloc-standard/realloc.c ++++ b/libc/stdlib/malloc-standard/realloc.c +@@ -8,7 +8,7 @@ + VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at +- ftp://gee.cs.oswego.edu/pub/misc/malloc.c ++ ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + + Hacked up for uClibc by Erik Andersen <andersen@codepoet.org> +@@ -23,14 +23,14 @@ void* realloc(void* oldmem, size_t bytes + { + mstate av; + +- size_t nb; /* padded request size */ ++ size_t nb; /* padded request size */ + + mchunkptr oldp; /* chunk corresponding to oldmem */ +- size_t oldsize; /* its size */ ++ size_t oldsize; /* its size */ + + mchunkptr newp; /* chunk to return */ +- size_t newsize; /* its size */ +- void* newmem; /* corresponding user mem */ ++ size_t newsize; /* its size */ ++ void* newmem; /* corresponding user mem */ + + mchunkptr next; /* next contiguous chunk after oldp */ + +@@ -40,21 +40,23 @@ void* realloc(void* oldmem, size_t bytes + mchunkptr bck; /* misc temp for linking */ + mchunkptr fwd; /* misc temp for linking */ + +- unsigned long copysize; /* bytes to copy */ ++ unsigned long copysize; /* bytes to copy */ + unsigned int ncopies; /* size_t words to copy */ +- size_t* s; /* copy source */ +- size_t* d; /* copy destination */ ++ size_t* s; /* copy source */ ++ size_t* d; /* copy destination */ ++ ++ void *retval; + + + /* Check for special cases. */ + if (! oldmem) +- return malloc(bytes); ++ return malloc(bytes); + if (! bytes) { +- free (oldmem); +- return malloc(bytes); ++ free (oldmem); ++ return malloc(bytes); + } + +- LOCK; ++ __MALLOC_LOCK; + av = get_malloc_state(); + checked_request2size(bytes, nb); + +@@ -65,173 +67,176 @@ void* realloc(void* oldmem, size_t bytes + + if (!chunk_is_mmapped(oldp)) { + +- if ((unsigned long)(oldsize) >= (unsigned long)(nb)) { +- /* already big enough; split below */ +- newp = oldp; +- newsize = oldsize; +- } +- +- else { +- next = chunk_at_offset(oldp, oldsize); +- +- /* Try to expand forward into top */ +- if (next == av->top && +- (unsigned long)(newsize = oldsize + chunksize(next)) >= +- (unsigned long)(nb + MINSIZE)) { +- set_head_size(oldp, nb); +- av->top = chunk_at_offset(oldp, nb); +- set_head(av->top, (newsize - nb) | PREV_INUSE); +- UNLOCK; +- return chunk2mem(oldp); +- } +- +- /* Try to expand forward into next chunk; split off remainder below */ +- else if (next != av->top && +- !inuse(next) && +- (unsigned long)(newsize = oldsize + chunksize(next)) >= +- (unsigned long)(nb)) { +- newp = oldp; +- unlink(next, bck, fwd); +- } +- +- /* allocate, copy, free */ +- else { +- newmem = malloc(nb - MALLOC_ALIGN_MASK); +- if (newmem == 0) { +- UNLOCK; +- return 0; /* propagate failure */ +- } +- +- newp = mem2chunk(newmem); +- newsize = chunksize(newp); +- +- /* +- Avoid copy if newp is next chunk after oldp. +- */ +- if (newp == next) { +- newsize += oldsize; +- newp = oldp; ++ if ((unsigned long)(oldsize) >= (unsigned long)(nb)) { ++ /* already big enough; split below */ ++ newp = oldp; ++ newsize = oldsize; + } ++ + else { +- /* +- Unroll copy of <= 36 bytes (72 if 8byte sizes) +- We know that contents have an odd number of +- size_t-sized words; minimally 3. +- */ +- +- copysize = oldsize - (sizeof(size_t)); +- s = (size_t*)(oldmem); +- d = (size_t*)(newmem); +- ncopies = copysize / sizeof(size_t); +- assert(ncopies >= 3); +- +- if (ncopies > 9) +- memcpy(d, s, copysize); +- +- else { +- *(d+0) = *(s+0); +- *(d+1) = *(s+1); +- *(d+2) = *(s+2); +- if (ncopies > 4) { +- *(d+3) = *(s+3); +- *(d+4) = *(s+4); +- if (ncopies > 6) { +- *(d+5) = *(s+5); +- *(d+6) = *(s+6); +- if (ncopies > 8) { +- *(d+7) = *(s+7); +- *(d+8) = *(s+8); ++ next = chunk_at_offset(oldp, oldsize); ++ ++ /* Try to expand forward into top */ ++ if (next == av->top && ++ (unsigned long)(newsize = oldsize + chunksize(next)) >= ++ (unsigned long)(nb + MINSIZE)) { ++ set_head_size(oldp, nb); ++ av->top = chunk_at_offset(oldp, nb); ++ set_head(av->top, (newsize - nb) | PREV_INUSE); ++ retval = chunk2mem(oldp); ++ goto DONE; ++ } ++ ++ /* Try to expand forward into next chunk; split off remainder below */ ++ else if (next != av->top && ++ !inuse(next) && ++ (unsigned long)(newsize = oldsize + chunksize(next)) >= ++ (unsigned long)(nb)) { ++ newp = oldp; ++ unlink(next, bck, fwd); ++ } ++ ++ /* allocate, copy, free */ ++ else { ++ newmem = malloc(nb - MALLOC_ALIGN_MASK); ++ if (newmem == 0) { ++ retval = 0; /* propagate failure */ ++ goto DONE; ++ } ++ ++ newp = mem2chunk(newmem); ++ newsize = chunksize(newp); ++ ++ /* ++ Avoid copy if newp is next chunk after oldp. ++ */ ++ if (newp == next) { ++ newsize += oldsize; ++ newp = oldp; ++ } ++ else { ++ /* ++ Unroll copy of <= 36 bytes (72 if 8byte sizes) ++ We know that contents have an odd number of ++ size_t-sized words; minimally 3. ++ */ ++ ++ copysize = oldsize - (sizeof(size_t)); ++ s = (size_t*)(oldmem); ++ d = (size_t*)(newmem); ++ ncopies = copysize / sizeof(size_t); ++ assert(ncopies >= 3); ++ ++ if (ncopies > 9) ++ memcpy(d, s, copysize); ++ ++ else { ++ *(d+0) = *(s+0); ++ *(d+1) = *(s+1); ++ *(d+2) = *(s+2); ++ if (ncopies > 4) { ++ *(d+3) = *(s+3); ++ *(d+4) = *(s+4); ++ if (ncopies > 6) { ++ *(d+5) = *(s+5); ++ *(d+6) = *(s+6); ++ if (ncopies > 8) { ++ *(d+7) = *(s+7); ++ *(d+8) = *(s+8); ++ } ++ } ++ } ++ } ++ ++ free(oldmem); ++ check_inuse_chunk(newp); ++ retval = chunk2mem(newp); ++ goto DONE; + } +- } + } +- } ++ } ++ ++ /* If possible, free extra space in old or extended chunk */ ++ ++ assert((unsigned long)(newsize) >= (unsigned long)(nb)); ++ ++ remainder_size = newsize - nb; + +- free(oldmem); +- check_inuse_chunk(newp); +- UNLOCK; +- return chunk2mem(newp); +- } +- } +- } +- +- /* If possible, free extra space in old or extended chunk */ +- +- assert((unsigned long)(newsize) >= (unsigned long)(nb)); +- +- remainder_size = newsize - nb; +- +- if (remainder_size < MINSIZE) { /* not enough extra to split off */ +- set_head_size(newp, newsize); +- set_inuse_bit_at_offset(newp, newsize); +- } +- else { /* split remainder */ +- remainder = chunk_at_offset(newp, nb); +- set_head_size(newp, nb); +- set_head(remainder, remainder_size | PREV_INUSE); +- /* Mark remainder as inuse so free() won't complain */ +- set_inuse_bit_at_offset(remainder, remainder_size); +- free(chunk2mem(remainder)); +- } +- +- check_inuse_chunk(newp); +- UNLOCK; +- return chunk2mem(newp); ++ if (remainder_size < MINSIZE) { /* not enough extra to split off */ ++ set_head_size(newp, newsize); ++ set_inuse_bit_at_offset(newp, newsize); ++ } ++ else { /* split remainder */ ++ remainder = chunk_at_offset(newp, nb); ++ set_head_size(newp, nb); ++ set_head(remainder, remainder_size | PREV_INUSE); ++ /* Mark remainder as inuse so free() won't complain */ ++ set_inuse_bit_at_offset(remainder, remainder_size); ++ free(chunk2mem(remainder)); ++ } ++ ++ check_inuse_chunk(newp); ++ retval = chunk2mem(newp); ++ goto DONE; + } + + /* +- Handle mmap cases +- */ ++ Handle mmap cases ++ */ + + else { +- size_t offset = oldp->prev_size; +- size_t pagemask = av->pagesize - 1; +- char *cp; +- unsigned long sum; +- +- /* Note the extra (sizeof(size_t)) overhead */ +- newsize = (nb + offset + (sizeof(size_t)) + pagemask) & ~pagemask; +- +- /* don't need to remap if still within same page */ +- if (oldsize == newsize - offset) { +- UNLOCK; +- return oldmem; +- } +- +- cp = (char*)mremap((char*)oldp - offset, oldsize + offset, newsize, 1); +- +- if (cp != (char*)MORECORE_FAILURE) { +- +- newp = (mchunkptr)(cp + offset); +- set_head(newp, (newsize - offset)|IS_MMAPPED); +- +- assert(aligned_OK(chunk2mem(newp))); +- assert((newp->prev_size == offset)); +- +- /* update statistics */ +- sum = av->mmapped_mem += newsize - oldsize; +- if (sum > (unsigned long)(av->max_mmapped_mem)) +- av->max_mmapped_mem = sum; +- sum += av->sbrked_mem; +- if (sum > (unsigned long)(av->max_total_mem)) +- av->max_total_mem = sum; +- +- UNLOCK; +- return chunk2mem(newp); +- } +- +- /* Note the extra (sizeof(size_t)) overhead. */ +- if ((unsigned long)(oldsize) >= (unsigned long)(nb + (sizeof(size_t)))) +- newmem = oldmem; /* do nothing */ +- else { +- /* Must alloc, copy, free. */ +- newmem = malloc(nb - MALLOC_ALIGN_MASK); +- if (newmem != 0) { +- memcpy(newmem, oldmem, oldsize - 2*(sizeof(size_t))); +- free(oldmem); +- } +- } +- UNLOCK; +- return newmem; ++ size_t offset = oldp->prev_size; ++ size_t pagemask = av->pagesize - 1; ++ char *cp; ++ unsigned long sum; ++ ++ /* Note the extra (sizeof(size_t)) overhead */ ++ newsize = (nb + offset + (sizeof(size_t)) + pagemask) & ~pagemask; ++ ++ /* don't need to remap if still within same page */ ++ if (oldsize == newsize - offset) { ++ retval = oldmem; ++ goto DONE; ++ } ++ ++ cp = (char*)mremap((char*)oldp - offset, oldsize + offset, newsize, 1); ++ ++ if (cp != (char*)MORECORE_FAILURE) { ++ ++ newp = (mchunkptr)(cp + offset); ++ set_head(newp, (newsize - offset)|IS_MMAPPED); ++ ++ assert(aligned_OK(chunk2mem(newp))); ++ assert((newp->prev_size == offset)); ++ ++ /* update statistics */ ++ sum = av->mmapped_mem += newsize - oldsize; ++ if (sum > (unsigned long)(av->max_mmapped_mem)) ++ av->max_mmapped_mem = sum; ++ sum += av->sbrked_mem; ++ if (sum > (unsigned long)(av->max_total_mem)) ++ av->max_total_mem = sum; ++ ++ retval = chunk2mem(newp); ++ goto DONE; ++ } ++ ++ /* Note the extra (sizeof(size_t)) overhead. */ ++ if ((unsigned long)(oldsize) >= (unsigned long)(nb + (sizeof(size_t)))) ++ newmem = oldmem; /* do nothing */ ++ else { ++ /* Must alloc, copy, free. */ ++ newmem = malloc(nb - MALLOC_ALIGN_MASK); ++ if (newmem != 0) { ++ memcpy(newmem, oldmem, oldsize - 2*(sizeof(size_t))); ++ free(oldmem); ++ } ++ } ++ retval = newmem; + } ++ ++ DONE: ++ __MALLOC_UNLOCK; ++ return retval; + } + +diff --git a/libc/stdlib/random.c b/libc/stdlib/random.c +index b0a00e1..1bd63bc 100644 +--- a/libc/stdlib/random.c ++++ b/libc/stdlib/random.c +@@ -27,16 +27,14 @@ + #include <limits.h> + #include <stddef.h> + #include <stdlib.h> +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> ++ + /* POSIX.1c requires that there is mutual exclusion for the `rand' and + `srand' functions to prevent concurrent calls from modifying common + data. */ +-static pthread_mutex_t lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +-#else +-#define __pthread_mutex_lock(x) +-#define __pthread_mutex_unlock(x) +-#endif ++ ++#include <bits/uClibc_mutex.h> ++ ++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + + /* An improved random number generation package. In addition to the standard + rand()/srand() like interface, this package also has a special state info +@@ -184,9 +182,9 @@ static struct random_data unsafe_state = + for default usage relies on values produced by this routine. */ + void srandom (unsigned int x) + { +- __pthread_mutex_lock(&lock); ++ __UCLIBC_MUTEX_LOCK(mylock); + srandom_r (x, &unsafe_state); +- __pthread_mutex_unlock(&lock); ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + weak_alias (srandom, srand) + +@@ -205,10 +203,10 @@ char * initstate (unsigned int seed, cha + { + int32_t *ostate; + +- __pthread_mutex_lock(&lock); ++ __UCLIBC_MUTEX_LOCK(mylock); + ostate = &unsafe_state.state[-1]; + initstate_r (seed, arg_state, n, &unsafe_state); +- __pthread_mutex_unlock(&lock); ++ __UCLIBC_MUTEX_UNLOCK(mylock); + return (char *) ostate; + } + +@@ -224,11 +222,11 @@ char * setstate (char *arg_state) + { + int32_t *ostate; + +- __pthread_mutex_lock(&lock); ++ __UCLIBC_MUTEX_LOCK(mylock); + ostate = &unsafe_state.state[-1]; + if (setstate_r (arg_state, &unsafe_state) < 0) + ostate = NULL; +- __pthread_mutex_unlock(&lock); ++ __UCLIBC_MUTEX_UNLOCK(mylock); + return (char *) ostate; + } + +@@ -247,9 +245,9 @@ long int random () + { + int32_t retval; + +- __pthread_mutex_lock(&lock); ++ __UCLIBC_MUTEX_LOCK(mylock); + random_r (&unsafe_state, &retval); +- __pthread_mutex_unlock(&lock); ++ __UCLIBC_MUTEX_UNLOCK(mylock); + return retval; + } + +diff --git a/libc/stdlib/setenv.c b/libc/stdlib/setenv.c +index d0cfe52..2d899cc 100644 +--- a/libc/stdlib/setenv.c ++++ b/libc/stdlib/setenv.c +@@ -17,7 +17,7 @@ + 02111-1307 USA. + + modified for uClibc by Erik Andersen <andersen@codepoet.org> +- */ ++*/ + + #define _GNU_SOURCE + #include <features.h> +@@ -26,16 +26,9 @@ + #include <string.h> + #include <unistd.h> + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER; +-# define LOCK __pthread_mutex_lock(&mylock) +-# define UNLOCK __pthread_mutex_unlock(&mylock); +-#else +-# define LOCK +-# define UNLOCK +-#endif ++#include <bits/uClibc_mutex.h> + ++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + + /* If this variable is not a null pointer we allocated the current + environment. */ +@@ -49,14 +42,15 @@ static char **last_environ; + to reuse values once generated for a `setenv' call since we can never + free the strings. */ + int __add_to_environ (const char *name, const char *value, +- const char *combined, int replace) ++ const char *combined, int replace) + { + register char **ep; + register size_t size; + const size_t namelen = strlen (name); + const size_t vallen = value != NULL ? strlen (value) + 1 : 0; ++ int rv = -1; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + + /* We have to get the pointer now that we have the lock and not earlier + since another thread might have created a new environment. */ +@@ -64,72 +58,72 @@ int __add_to_environ (const char *name, + + size = 0; + if (ep != NULL) { +- for (; *ep != NULL; ++ep) { +- if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=') +- break; +- else +- ++size; +- } ++ for (; *ep != NULL; ++ep) { ++ if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=') ++ break; ++ else ++ ++size; ++ } + } + + if (ep == NULL || *ep == NULL) { +- char **new_environ; ++ char **new_environ; + +- /* We allocated this space; we can extend it. */ +- new_environ = (char **) realloc (last_environ, +- (size + 2) * sizeof (char *)); +- if (new_environ == NULL) { +- UNLOCK; +- return -1; +- } +- +- /* If the whole entry is given add it. */ +- if (combined != NULL) { +- /* We must not add the string to the search tree since it belongs +- to the user. */ +- new_environ[size] = (char *) combined; +- } else { +- /* See whether the value is already known. */ +- new_environ[size] = (char *) malloc (namelen + 1 + vallen); +- if (new_environ[size] == NULL) { +- __set_errno (ENOMEM); +- UNLOCK; +- return -1; +- } +- +- memcpy (new_environ[size], name, namelen); +- new_environ[size][namelen] = '='; +- memcpy (&new_environ[size][namelen + 1], value, vallen); +- } +- +- if (__environ != last_environ) { +- memcpy ((char *) new_environ, (char *) __environ, +- size * sizeof (char *)); +- } ++ /* We allocated this space; we can extend it. */ ++ new_environ = (char **) realloc (last_environ, ++ (size + 2) * sizeof (char *)); ++ if (new_environ == NULL) { ++ goto DONE; ++ } ++ ++ /* If the whole entry is given add it. */ ++ if (combined != NULL) { ++ /* We must not add the string to the search tree since it belongs ++ to the user. */ ++ new_environ[size] = (char *) combined; ++ } else { ++ /* See whether the value is already known. */ ++ new_environ[size] = (char *) malloc (namelen + 1 + vallen); ++ if (new_environ[size] == NULL) { ++ __set_errno (ENOMEM); ++ goto DONE; ++ } ++ ++ memcpy (new_environ[size], name, namelen); ++ new_environ[size][namelen] = '='; ++ memcpy (&new_environ[size][namelen + 1], value, vallen); ++ } ++ ++ if (__environ != last_environ) { ++ memcpy ((char *) new_environ, (char *) __environ, ++ size * sizeof (char *)); ++ } + +- new_environ[size + 1] = NULL; +- last_environ = __environ = new_environ; ++ new_environ[size + 1] = NULL; ++ last_environ = __environ = new_environ; + } else if (replace) { +- char *np; ++ char *np; + +- /* Use the user string if given. */ +- if (combined != NULL) { +- np = (char *) combined; +- } else { +- np = malloc (namelen + 1 + vallen); +- if (np == NULL) { +- UNLOCK; +- return -1; +- } +- memcpy (np, name, namelen); +- np[namelen] = '='; +- memcpy (&np[namelen + 1], value, vallen); +- } +- *ep = np; +- } +- +- UNLOCK; +- return 0; ++ /* Use the user string if given. */ ++ if (combined != NULL) { ++ np = (char *) combined; ++ } else { ++ np = malloc (namelen + 1 + vallen); ++ if (np == NULL) { ++ goto DONE; ++ } ++ memcpy (np, name, namelen); ++ np[namelen] = '='; ++ memcpy (&np[namelen + 1], value, vallen); ++ } ++ *ep = np; ++ } ++ ++ rv = 0; ++ ++ DONE: ++ __UCLIBC_MUTEX_UNLOCK(mylock); ++ return rv; + } + + int setenv (const char *name, const char *value, int replace) +@@ -143,26 +137,26 @@ int unsetenv (const char *name) + char **ep; + + if (name == NULL || *name == '\0' || strchr (name, '=') != NULL) { +- __set_errno (EINVAL); +- return -1; ++ __set_errno (EINVAL); ++ return -1; + } + + len = strlen (name); +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + ep = __environ; + while (*ep != NULL) { +- if (!strncmp (*ep, name, len) && (*ep)[len] == '=') { +- /* Found it. Remove this pointer by moving later ones back. */ +- char **dp = ep; +- do { +- dp[0] = dp[1]; +- } while (*dp++); +- /* Continue the loop in case NAME appears again. */ +- } else { +- ++ep; +- } ++ if (!strncmp (*ep, name, len) && (*ep)[len] == '=') { ++ /* Found it. Remove this pointer by moving later ones back. */ ++ char **dp = ep; ++ do { ++ dp[0] = dp[1]; ++ } while (*dp++); ++ /* Continue the loop in case NAME appears again. */ ++ } else { ++ ++ep; ++ } + } +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + return 0; + } + +@@ -171,15 +165,15 @@ int unsetenv (const char *name) + for Fortran 77) requires this function. */ + int clearenv (void) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (__environ == last_environ && __environ != NULL) { +- /* We allocated this environment so we can free it. */ +- free (__environ); +- last_environ = NULL; ++ /* We allocated this environment so we can free it. */ ++ free (__environ); ++ last_environ = NULL; + } + /* Clear the environment pointer removes the whole environment. */ + __environ = NULL; +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + return 0; + } + +@@ -190,10 +184,10 @@ int putenv (char *string) + const char *const name_end = strchr (string, '='); + + if (name_end != NULL) { +- char *name = strndup(string, name_end - string); +- result = __add_to_environ (name, NULL, string, 1); +- free(name); +- return(result); ++ char *name = strndup(string, name_end - string); ++ result = __add_to_environ (name, NULL, string, 1); ++ free(name); ++ return(result); + } + unsetenv (string); + return 0; +diff --git a/libc/sysdeps/linux/common/bits/uClibc_stdio.h b/libc/sysdeps/linux/common/bits/uClibc_stdio.h +index 40cd5fe..3c6911e 100644 +--- a/libc/sysdeps/linux/common/bits/uClibc_stdio.h ++++ b/libc/sysdeps/linux/common/bits/uClibc_stdio.h +@@ -116,9 +116,7 @@ + #endif + + /**********************************************************************/ +-#ifdef __UCLIBC_HAS_THREADS__ +-/* Need this for pthread_mutex_t. */ +-#include <bits/pthreadtypes.h> ++#include <bits/uClibc_mutex.h> + + /* user_locking + * 0 : do auto locking/unlocking +@@ -132,43 +130,37 @@ + * This way, we avoid calling the weak lock/unlock functions. + */ + +-#define __STDIO_AUTO_THREADLOCK_VAR int __infunc_user_locking +- +-#define __STDIO_AUTO_THREADLOCK(__stream) \ +- if ((__infunc_user_locking = (__stream)->__user_locking) == 0) { \ +- __pthread_mutex_lock(&(__stream)->__lock); \ +- } +- +-#define __STDIO_AUTO_THREADUNLOCK(__stream) \ +- if (__infunc_user_locking == 0) { \ +- __pthread_mutex_unlock(&(__stream)->__lock); \ +- } ++#define __STDIO_AUTO_THREADLOCK_VAR \ ++ __UCLIBC_MUTEX_AUTO_LOCK_VAR(__infunc_user_locking) + +-#define __STDIO_SET_USER_LOCKING(__stream) ((__stream)->__user_locking = 1) ++#define __STDIO_AUTO_THREADLOCK(__stream) \ ++ __UCLIBC_MUTEX_AUTO_LOCK((__stream)->__lock, __infunc_user_locking, \ ++ (__stream)->__user_locking) + +-#define __STDIO_ALWAYS_THREADLOCK(__stream) \ +- __pthread_mutex_lock(&(__stream)->__lock) ++#define __STDIO_AUTO_THREADUNLOCK(__stream) \ ++ __UCLIBC_MUTEX_AUTO_UNLOCK((__stream)->__lock, __infunc_user_locking) + +-#define __STDIO_ALWAYS_THREADTRYLOCK(__stream) \ +- __pthread_mutex_trylock(&(__stream)->__lock) ++#define __STDIO_ALWAYS_THREADLOCK(__stream) \ ++ __UCLIBC_MUTEX_LOCK((__stream)->__lock) + +-#define __STDIO_ALWAYS_THREADUNLOCK(__stream) \ +- __pthread_mutex_unlock(&(__stream)->__lock) ++#define __STDIO_ALWAYS_THREADUNLOCK(__stream) \ ++ __UCLIBC_MUTEX_UNLOCK((__stream)->__lock) + +-#else /* __UCLIBC_HAS_THREADS__ */ ++#define __STDIO_ALWAYS_THREADLOCK_CANCEL_UNSAFE(__stream) \ ++ __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE((__stream)->__lock) + +-#define __STDIO_AUTO_THREADLOCK_VAR ((void)0) ++#define __STDIO_ALWAYS_THREADTRYLOCK_CANCEL_UNSAFE(__stream) \ ++ __UCLIBC_MUTEX_TRYLOCK_CANCEL_UNSAFE((__stream)->__lock) + +-#define __STDIO_AUTO_THREADLOCK(__stream) ((void)0) +-#define __STDIO_AUTO_THREADUNLOCK(__stream) ((void)0) ++#define __STDIO_ALWAYS_THREADUNLOCK_CANCEL_UNSAFE(__stream) \ ++ __UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE((__stream)->__lock) + ++#ifdef __UCLIBC_HAS_THREADS__ ++#define __STDIO_SET_USER_LOCKING(__stream) ((__stream)->__user_locking = 1) ++#else + #define __STDIO_SET_USER_LOCKING(__stream) ((void)0) ++#endif + +-#define __STDIO_ALWAYS_THREADLOCK(__stream) ((void)0) +-#define __STDIO_ALWAYS_THREADTRYLOCK(__stream) (0) /* Always succeed. */ +-#define __STDIO_ALWAYS_THREADUNLOCK(__stream) ((void)0) +- +-#endif /* __UCLIBC_HAS_THREADS__ */ + /**********************************************************************/ + + #define __STDIO_IOFBF 0 /* Fully buffered. */ +@@ -283,7 +275,7 @@ struct __STDIO_FILE_STRUCT { + #endif + #ifdef __UCLIBC_HAS_THREADS__ + int __user_locking; +- pthread_mutex_t __lock; ++ __UCLIBC_MUTEX(__lock); + #endif + /* Everything after this is unimplemented... and may be trashed. */ + #if __STDIO_BUILTIN_BUF_SIZE > 0 +@@ -358,10 +350,14 @@ extern void _stdio_term(void); + extern struct __STDIO_FILE_STRUCT *_stdio_openlist; + + #ifdef __UCLIBC_HAS_THREADS__ +-extern pthread_mutex_t _stdio_openlist_lock; +-extern int _stdio_openlist_delflag; ++__UCLIBC_MUTEX_EXTERN(_stdio_openlist_add_lock); ++#ifdef __STDIO_BUFFERS ++__UCLIBC_MUTEX_EXTERN(_stdio_openlist_del_lock); ++extern volatile int _stdio_openlist_use_count; /* _stdio_openlist_del_lock */ ++extern int _stdio_openlist_del_count; /* _stdio_openlist_del_lock */ ++#endif + extern int _stdio_user_locking; +-extern void __stdio_init_mutex(pthread_mutex_t *m); ++extern void __stdio_init_mutex(__UCLIBC_MUTEX_TYPE *m); + #endif + + #endif +diff --git a/libc/sysdeps/linux/common/getdents.c b/libc/sysdeps/linux/common/getdents.c +index ab6a276..23463e5 100644 +--- a/libc/sysdeps/linux/common/getdents.c ++++ b/libc/sysdeps/linux/common/getdents.c +@@ -30,8 +30,6 @@ + #include <sys/syscall.h> + + +-#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +- + struct kernel_dirent + { + long d_ino; +diff --git a/libc/sysdeps/linux/common/sigprocmask.c b/libc/sysdeps/linux/common/sigprocmask.c +index 70ff366..565318d 100644 +--- a/libc/sysdeps/linux/common/sigprocmask.c ++++ b/libc/sysdeps/linux/common/sigprocmask.c +@@ -23,6 +23,8 @@ int sigprocmask(int how, const sigset_t + if (set && + #if (SIG_BLOCK == 0) && (SIG_UNBLOCK == 1) && (SIG_SETMASK == 2) + (((unsigned int) how) > 2) ++#elif (SIG_BLOCK == 1) && (SIG_UNBLOCK == 2) && (SIG_SETMASK == 3) ++ (((unsigned int)(how-1)) > 2) + #else + #warning "compile time assumption violated.. slow path..." + ((how != SIG_BLOCK) && (how != SIG_UNBLOCK) +@@ -48,6 +50,8 @@ int sigprocmask(int how, const sigset_t + if (set && + #if (SIG_BLOCK == 0) && (SIG_UNBLOCK == 1) && (SIG_SETMASK == 2) + (((unsigned int) how) > 2) ++#elif (SIG_BLOCK == 1) && (SIG_UNBLOCK == 2) && (SIG_SETMASK == 3) ++ (((unsigned int)(how-1)) > 2) + #else + #warning "compile time assumption violated.. slow path..." + ((how != SIG_BLOCK) && (how != SIG_UNBLOCK) +diff --git a/libc/sysdeps/linux/mips/bits/kernel_sigaction.h b/libc/sysdeps/linux/mips/bits/kernel_sigaction.h +index b6f52cc..317e5b3 100644 +--- a/libc/sysdeps/linux/mips/bits/kernel_sigaction.h ++++ b/libc/sysdeps/linux/mips/bits/kernel_sigaction.h +@@ -38,3 +38,6 @@ struct kernel_sigaction { + void (*sa_restorer)(void); + int s_resv[1]; /* reserved */ + }; ++ ++extern int __syscall_rt_sigaction (int, const struct kernel_sigaction *__unbounded, ++ struct kernel_sigaction *__unbounded, size_t); +diff --git a/libc/sysdeps/linux/mips/pipe.S b/libc/sysdeps/linux/mips/pipe.S +index c3afae5..cd88074 100644 +--- a/libc/sysdeps/linux/mips/pipe.S ++++ b/libc/sysdeps/linux/mips/pipe.S +@@ -7,25 +7,36 @@ + #include <asm/unistd.h> + #include <asm/regdef.h> + +- .globl pipe +- .ent pipe, 0 ++ .globl pipe ++ .ent pipe, 0 + pipe: +- addiu sp,sp,-24 +- sw a0,16(sp) +- li v0,__NR_pipe +- syscall +- beqz a3, 1f +- la t3, errno +- sw v0, (t3) +- li v0, -1 +- b 2f ++ .frame sp, 24, sp ++#ifdef __PIC__ ++ .set noreorder ++ .cpload $25 ++ .set reorder ++ addiu sp,sp,-24 ++ .cprestore 16 ++#else ++ addiu sp,sp,-24 ++#endif ++ sw a0,16(sp) ++ li v0,__NR_pipe ++ syscall ++ beqz a3, 1f ++#ifdef __PIC__ ++ la t0, __syscall_error ++ jr t9 ++#else ++ j __syscall_error ++#endif + 1: +- lw a0, 16(sp) +- sw v0, 0(a0) +- sw v1, 4(a0) +- li v0, 0 ++ lw a0, 16(sp) ++ sw v0, 0(a0) ++ sw v1, 4(a0) ++ li v0, 0 + 2: +- addiu sp,sp,24 +- j ra +- .end pipe +- .size pipe,.-pipe ++ addiu sp,sp,24 ++ j ra ++ .end pipe ++ .size pipe,.-pipe +diff --git a/libcrypt/des.c b/libcrypt/des.c +index 3b49a7a..f7a6be1 100644 +--- a/libcrypt/des.c ++++ b/libcrypt/des.c +@@ -504,7 +504,7 @@ do_des( u_int32_t l_in, u_int32_t r_in, + kl = kl1; + kr = kr1; + round = 16; +- while (round--) { ++ do { + /* + * Expand R to 48 bits (simulate the E-box). + */ +@@ -540,7 +540,7 @@ do_des( u_int32_t l_in, u_int32_t r_in, + f ^= l; + l = r; + r = f; +- } ++ } while (--round); + r = l; + l = f; + } +diff --git a/libpthread/linuxthreads/ptfork.c b/libpthread/linuxthreads/ptfork.c +index eb544f3..cfec2b7 100644 +--- a/libpthread/linuxthreads/ptfork.c ++++ b/libpthread/linuxthreads/ptfork.c +@@ -26,6 +26,15 @@ + #include "pthread.h" + #include "internals.h" + ++#warning hack alert... should be sufficent for system(), but what about other libc mutexes? ++#include <bits/uClibc_mutex.h> ++ ++__UCLIBC_MUTEX_EXTERN(__malloc_lock); ++ ++#define __MALLOC_LOCK __UCLIBC_MUTEX_LOCK(__malloc_lock) ++#define __MALLOC_UNLOCK __UCLIBC_MUTEX_UNLOCK(__malloc_lock) ++#warning hack alert block end ++ + struct handler_list { + void (*handler)(void); + struct handler_list * next; +@@ -91,9 +100,18 @@ pid_t __fork(void) + parent = pthread_atfork_parent; + pthread_mutex_unlock(&pthread_atfork_lock); + pthread_call_handlers(prepare); ++ ++#warning hack alert ++ __MALLOC_LOCK; ++ + pid = __libc_fork(); ++ ++#warning hack alert ++ __MALLOC_UNLOCK; ++ + if (pid == 0) { + __pthread_reset_main_thread(); ++#warning need to reconsider __fresetlockfiles! + __fresetlockfiles(); + pthread_call_handlers(child); + } else { +diff -urN -x .git uClibc-0.9.28/libc/sysdeps/linux/common/bits/uClibc_mutex.h uClibc-mjn3/libc/sysdeps/linux/common/bits/uClibc_mutex.h +--- uClibc-0.9.28/libc/sysdeps/linux/common/bits/uClibc_mutex.h 1969-12-31 17:00:00.000000000 -0700 ++++ uClibc-mjn3/libc/sysdeps/linux/common/bits/uClibc_mutex.h 2006-03-08 11:21:58.000000000 -0700 +@@ -0,0 +1,87 @@ ++/* Copyright (C) 2006 Manuel Novoa III <mjn3@codepoet.org> ++ * ++ * GNU Library General Public License (LGPL) version 2 or later. ++ * ++ * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. ++ */ ++ ++#ifndef _UCLIBC_MUTEX_H ++#define _UCLIBC_MUTEX_H ++ ++#include <features.h> ++ ++#ifdef __UCLIBC_HAS_THREADS__ ++ ++#include <pthread.h> ++ ++#define __UCLIBC_MUTEX_TYPE pthread_mutex_t ++ ++#define __UCLIBC_MUTEX(M) pthread_mutex_t M ++#define __UCLIBC_MUTEX_INIT(M,I) pthread_mutex_t M = I ++#define __UCLIBC_MUTEX_STATIC(M,I) static pthread_mutex_t M = I ++#define __UCLIBC_MUTEX_EXTERN(M) extern pthread_mutex_t M ++ ++#define __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE(M) \ ++ __pthread_mutex_lock(&(M)) ++ ++#define __UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE(M) \ ++ __pthread_mutex_unlock(&(M)) ++ ++#define __UCLIBC_MUTEX_TRYLOCK_CANCEL_UNSAFE(M) \ ++ __pthread_mutex_trylock(&(M)) ++ ++#define __UCLIBC_MUTEX_CONDITIONAL_LOCK(M,C) \ ++ do { \ ++ struct _pthread_cleanup_buffer __infunc_pthread_cleanup_buffer; \ ++ if (C) { \ ++ _pthread_cleanup_push_defer(&__infunc_pthread_cleanup_buffer, \ ++ __pthread_mutex_unlock, \ ++ &(M)); \ ++ __pthread_mutex_lock(&(M)); \ ++ } \ ++ ((void)0) ++ ++#define __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(M,C) \ ++ if (C) { \ ++ _pthread_cleanup_pop_restore(&__infunc_pthread_cleanup_buffer,1);\ ++ } \ ++ } while (0) ++ ++#define __UCLIBC_MUTEX_AUTO_LOCK_VAR(A) int A ++ ++#define __UCLIBC_MUTEX_AUTO_LOCK(M,A,V) \ ++ __UCLIBC_MUTEX_CONDITIONAL_LOCK(M,((A=(V)) == 0)) ++ ++#define __UCLIBC_MUTEX_AUTO_UNLOCK(M,A) \ ++ __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(M,(A == 0)) ++ ++#define __UCLIBC_MUTEX_LOCK(M) \ ++ __UCLIBC_MUTEX_CONDITIONAL_LOCK(M, 1) ++ ++#define __UCLIBC_MUTEX_UNLOCK(M) \ ++ __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(M, 1) ++ ++#else ++ ++#define __UCLIBC_MUTEX(M) void *__UCLIBC_MUTEX_DUMMY_ ## M ++#define __UCLIBC_MUTEX_INIT(M,I) extern void *__UCLIBC_MUTEX_DUMMY_ ## M ++#define __UCLIBC_MUTEX_STATIC(M) extern void *__UCLIBC_MUTEX_DUMMY_ ## M ++#define __UCLIBC_MUTEX_EXTERN(M) extern void *__UCLIBC_MUTEX_DUMMY_ ## M ++ ++#define __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE(M) ((void)0) ++#define __UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE(M) ((void)0) ++#define __UCLIBC_MUTEX_TRYLOCK_CANCEL_UNSAFE(M) (0) /* Always succeed? */ ++ ++#define __UCLIBC_MUTEX_CONDITIONAL_LOCK(M,C) ((void)0) ++#define __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(M,C) ((void)0) ++ ++#define __UCLIBC_MUTEX_AUTO_LOCK_VAR(A) ((void)0) ++#define __UCLIBC_MUTEX_AUTO_LOCK(M,A,V) ((void)0) ++#define __UCLIBC_MUTEX_AUTO_UNLOCK(M,A) ((void)0) ++ ++#define __UCLIBC_MUTEX_LOCK(M) ((void)0) ++#define __UCLIBC_MUTEX_UNLOCK(M) ((void)0) ++ ++#endif ++ ++#endif /* _UCLIBC_MUTEX_H */ +diff -urN -x .git uClibc-0.9.28/libc/sysdeps/linux/mips/pipe.c uClibc-mjn3/libc/sysdeps/linux/mips/pipe.c +--- uClibc-0.9.28/libc/sysdeps/linux/mips/pipe.c 2005-08-17 16:49:44.000000000 -0600 ++++ uClibc-mjn3/libc/sysdeps/linux/mips/pipe.c 1969-12-31 17:00:00.000000000 -0700 +@@ -1,23 +0,0 @@ +-/* pipe system call for Linux/MIPS */ +- +-/*see uClibc's sh/pipe.c and glibc-2.2.4's mips/pipe.S */ +- +-#include <errno.h> +-#include <unistd.h> +-#include <syscall.h> +- +-int pipe(int *fd) +-{ +- register long int res __asm__ ("$2"); // v0 +- register long int res2 __asm__ ("$3"); // v1 +- +- asm ("move\t$4,%2\n\t" // $4 = a0 +- "syscall" /* Perform the system call. */ +- : "=r" (res) +- : "0" (__NR_pipe), "r" (fd) +- : "$4", "$7"); +- +- fd[0] = res; +- fd[1] = res2; +- return(0); +-} diff --git a/toolchain/uClibc/uClibc-0.9.28-new_dst_rules.patch b/toolchain/uClibc/uClibc-0.9.28-new_dst_rules.patch new file mode 100644 index 000000000..af1a23897 --- /dev/null +++ b/toolchain/uClibc/uClibc-0.9.28-new_dst_rules.patch @@ -0,0 +1,99 @@ +--- uClibc/libc/misc/time/time.c (revision 16488) ++++ uClibc/libc/misc/time/time.c (working copy) +@@ -155,6 +155,20 @@ + #define TZNAME_MAX _POSIX_TZNAME_MAX + #endif + ++#if defined (L_tzset) || defined (L_localtime_r) || defined(L_strftime) || \ ++ defined(L__time_mktime) || defined(L__time_mktime_tzi) ++ ++void _time_tzset (int); ++ ++#ifndef L__time_mktime ++ ++ /* Jan 1, 2007 Z - tm = 0,0,0,1,0,107,1,0,0 */ ++ ++const static time_t new_rule_starts = 1167609600; ++ ++#endif ++#endif ++ + /**********************************************************************/ + /* The era code is currently unfinished. */ + /* #define ENABLE_ERA_CODE */ +@@ -544,7 +558,7 @@ + { + TZLOCK; + +- tzset(); ++ _time_tzset(*timer < new_rule_starts); + + __time_localtime_tzi(timer, result, _time_tzinfo); + +@@ -968,7 +982,8 @@ + unsigned char mod; + unsigned char code; + +- tzset(); /* We'll, let's get this out of the way. */ ++ /* We'll, let's get this out of the way. */ ++ _time_tzset(_time_mktime((struct tm *) timeptr, 0) < new_rule_starts); + + lvl = 0; + p = format; +@@ -1650,7 +1665,9 @@ + 6, 0, 0, /* Note: overloaded for non-M non-J case... */ + 0, 1, 0, /* J */ + ',', 'M', '4', '.', '1', '.', '0', +- ',', 'M', '1', '0', '.', '5', '.', '0', 0 ++ ',', 'M', '1', '0', '.', '5', '.', '0', 0, ++ ',', 'M', '3', '.', '2', '.', '0', ++ ',', 'M', '1', '1', '.', '1', '.', '0', 0 + }; + + #define TZ vals +@@ -1658,6 +1675,7 @@ + #define RANGE (vals + 7) + #define RULE (vals + 11 - 1) + #define DEFAULT_RULES (vals + 22) ++#define DEFAULT_2007_RULES (vals + 38) + + /* Initialize to UTC. */ + int daylight = 0; +@@ -1782,6 +1800,11 @@ + + void tzset(void) + { ++ _time_tzset((time(NULL)) < new_rule_starts); ++} ++ ++void _time_tzset(int use_old_rules) ++{ + register const char *e; + register char *s; + long off; +@@ -1904,7 +1927,15 @@ + } else { /* OK, we have dst, so get some rules. */ + count = 0; + if (!*e) { /* No rules so default to US rules. */ +- e = DEFAULT_RULES; ++ e = use_old_rules ? DEFAULT_RULES : DEFAULT_2007_RULES; ++#ifdef DEBUG_TZSET ++ if (e == DEFAULT_RULES) ++ printf("tzset: Using old rules.\n"); ++ else if (e == DEFAULT_2007_RULES) ++ printf("tzset: Using new rules\n"); ++ else ++ printf("tzset: Using undefined rules\n"); ++#endif /* DEBUG_TZSET */ + } + + do { +@@ -2238,6 +2269,8 @@ + --d; + } + ++ _time_tzset (x.tm_year < 2007); /* tm_year was expanded above */ ++ + #ifdef __BCC__ + d = p[5] - 1; + days = -719163L + ((long)d)*365 + ((d/4) - (d/100) + (d/400) + p[3] + p[7]); |