Procházet zdrojové kódy

A patch set that should probably become uClibc-0.9.28.1

Eric Andersen před 18 roky
rodič
revize
c78e178f37

+ 635 - 0
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)

+ 5190 - 0
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 */
+ 

+ 247 - 0
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 */

+ 8631 - 0
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);
+-}

+ 99 - 0
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]);