.else
CFLAGS += -D__DARWIN_UNIX03=0
.endif
+.if (${MACHINE_ARCH} == i386)
+CFLAGS += -march=prescott -msse3
+.endif
CFLAGS += -D__LIBC__ -DNOID -I${.CURDIR}/include
.ifdef ALTLIBCHEADERS
INCLUDEDIR = ${ALTLIBCHEADERS}
#include <fcntl.h>
#include <sys/errno.h>
#include <sys/stat.h>
-#include <sys/time.h>
#include <sys/xattr.h>
#include <sys/syscall.h>
#include <sys/param.h>
}
copyfile_debug(1, "debug value set to: %d\n", s->debug);
}
+
if (COPYFILE_CHECK & flags)
return copyfile_check(s);
}
} else if (COPYFILE_UNPACK & flags)
{
- if (!(COPYFILE_STAT & flags || COPYFILE_ACL & flags))
- fix_perms = !copyfile_fix_perms(s, &original_fsec, 1);
-
if (copyfile_unpack(s) < 0)
ret = -1;
} else
filesec_free(original_fsec);
- if (state == NULL) {
- if (copyfile_free(s) < 0) {
- ret = -1;
- }
- }
-
+ if (state == NULL)
+ ret -= copyfile_free(s);
return ret;
}
static int copyfile_close(copyfile_state_t s)
{
- if (s->src_fd >= 0)
+ if (s->src_fd != -2)
close(s->src_fd);
- if (s->dst_fd >= 0 && close(s->dst_fd))
+ if (s->dst_fd != -2 && close(s->dst_fd))
{
copyfile_warn("close on %s", s->dst);
return -1;
if (on)
{
- if(fstatx_np(s->dst_fd, &sb, *fsec))
+ if(statx_np(s->dst, &sb, *fsec))
goto error;
tmp_fsec = filesec_dup(*fsec);
return -1;
}
- while((s->dst_fd = open(s->dst, oflags, s->sb.st_mode | S_IWUSR)) < 0)
+ while((s->dst_fd = openx_np(s->dst, oflags, s->fsec)) < 0)
{
- /*
- * We set S_IWUSR because fsetxattr does not -- at the time this comment
- * was written -- allow one to set an extended attribute on a file descriptor
- * for a read-only file, even if the file descriptor is opened for writing.
- * This will only matter if the file does not already exist.
- */
- switch(errno)
+ if (EEXIST == errno)
{
- case EEXIST:
- copyfile_debug(3, "open failed, retrying (%s)", s->dst);
- if (s->flags & COPYFILE_EXCL)
- break;
- oflags = oflags & ~O_CREAT;
- if (s->flags & (COPYFILE_PACK | COPYFILE_DATA))
- {
- copyfile_debug(4, "truncating existing file (%s)", s->dst);
- oflags |= O_TRUNC;
- }
- continue;
- case EACCES:
- if(chmod(s->dst, (s->sb.st_mode | S_IWUSR) & ~S_IFMT) == 0)
- continue;
- else {
- break;
- }
+ oflags = oflags & ~O_CREAT;
+ continue;
}
copyfile_warn("open on %s", s->dst);
return -1;
}
}
- if (!filesec_set_property(fsec_dst, FILESEC_ACL, &acl_dst))
+ if (!filesec_set_property(s->fsec, FILESEC_ACL, &acl_dst))
{
copyfile_debug(1, "altered acl");
}
}
no_acl:
- if (fchmodx_np(s->dst_fd, fsec_dst) < 0 && errno != ENOTSUP)
- {
+ if (fchmodx_np(s->dst_fd, s->fsec) < 0 && errno != ENOTSUP)
copyfile_warn("setting security information: %s", s->dst);
- ret = -1;
- }
cleanup:
filesec_free(fsec_dst);
u_int32_t type; /* entry type: see list, 0 invalid */
u_int32_t offset; /* entry data offset from the beginning of the file. */
u_int32_t length; /* entry data length in bytes. */
-} apple_double_entry_t;
+} __attribute__((packed)) apple_double_entry_t;
typedef struct apple_double_header
apple_double_entry_t entries[2]; /* 'finfo' & 'rsrc' always exist */
u_int8_t finfo[FINDERINFOSIZE]; /* Must start with Finder Info (32 bytes) */
u_int8_t pad[2]; /* get better alignment inside attr_header */
-} apple_double_header_t;
+} __attribute__((packed)) apple_double_header_t;
/* Entries are aligned on 4 byte boundaries */
u_int16_t flags;
u_int8_t namelen; /* length of name including NULL termination char */
u_int8_t name[1]; /* NULL-terminated UTF-8 name (up to 128 bytes max) */
-} attr_entry_t;
+} __attribute__((packed)) attr_entry_t;
/* Header + entries must fit into 64K */
u_int32_t reserved[3];
u_int16_t flags;
u_int16_t num_attrs;
-} attr_header_t;
+} __attribute__((packed)) attr_header_t;
#pragma options align=reset
#endif
}
-static const u_int32_t emptyfinfo[8] = {0};
+static u_int32_t emptyfinfo[8] = {0};
static int copyfile_unpack(copyfile_state_t s)
{
- ssize_t bytes;
- void * buffer, * endptr;
+ int bytes;
+ void * buffer;
apple_double_header_t *adhdr;
size_t hdrsize;
int error = 0;
hdrsize = ATTR_MAX_HDR_SIZE;
buffer = calloc(1, hdrsize);
- if (buffer == NULL) {
- copyfile_debug(1, "copyfile_unpack: calloc(1, %u) returned NULL", hdrsize);
- error = -1;
- goto exit;
- } else
- endptr = (char*)buffer + hdrsize;
-
bytes = pread(s->src_fd, buffer, hdrsize, 0);
if (bytes < 0)
int count;
int i;
- if (hdrsize < sizeof(attr_header_t)) {
- copyfile_warn("bad attribute header: %u < %u", hdrsize, sizeof(attr_header_t));
- error = -1;
- goto exit;
- }
-
attrhdr = (attr_header_t *)buffer;
swap_attrhdr(attrhdr);
if (attrhdr->magic != ATTR_HDR_MAGIC)
}
count = attrhdr->num_attrs;
entry = (attr_entry_t *)&attrhdr[1];
-
for (i = 0; i < count; i++)
{
void * dataptr;
- /*
- * First we do some simple sanity checking.
- * +) See if entry is within the buffer's range;
- *
- * +) Check the attribute name length; if it's longer than the
- * maximum, we truncate it down. (We could error out as well;
- * I'm not sure which is the better way to go here.)
- *
- * +) If, given the name length, it goes beyond the end of
- * the buffer, error out.
- *
- * +) If the last byte isn't a NUL, make it a NUL. (Since we
- * truncated the name length above, we truncate the name here.)
- *
- * +) If entry->offset is so large that it causes dataptr to
- * go beyond the end of the buffer -- or, worse, so large that
- * it wraps around! -- we error out.
- *
- * +) If entry->length would cause the entry to go beyond the
- * end of the buffer (or, worse, wrap around to before it),
- * *or* if the length is larger than the hdrsize, we error out.
- * (An explanation of that: what we're checking for there is
- * the small range of values such that offset+length would cause
- * it to go beyond endptr, and then wrap around past buffer. We
- * care about this because we are passing entry->length down to
- * fgetxattr() below, and an erroneously large value could cause
- * problems there. By making sure that it's less than hdrsize,
- * which has already been sanity-checked above, we're safe.
- * That may mean that the check against < buffer is unnecessary.)
- */
- if ((void*)entry >= endptr || (void*)entry < buffer) {
- if (COPYFILE_VERBOSE & s->flags)
- copyfile_warn("Incomplete or corrupt attribute entry");
- error = -1;
- goto exit;
- }
-
- if (((void*)entry + sizeof(*entry)) > endptr) {
- if (COPYFILE_VERBOSE & s->flags)
- copyfile_warn("Incomplete or corrupt attribute entry");
- error = -1;
- goto exit;
- }
-
- if (entry->namelen < 2) {
- if (COPYFILE_VERBOSE & s->flags)
- copyfile_warn("Corrupt attribute entry (only %d bytes)", entry->namelen);
- error = -1;
- goto exit;
- }
- if (entry->namelen > ATTR_MAX_NAME_LEN + 1) {
- if (COPYFILE_VERBOSE & s->flags)
- copyfile_warn("Corrupt attribute entry (name length is %d bytes)", entry->namelen);
- error = -1;
- goto exit;
- }
- if ((void*)(entry->name + entry->namelen) >= endptr) {
- if (COPYFILE_VERBOSE & s->flags)
- copyfile_warn("Incomplete or corrupt attribute entry");
- error = -1;
- goto exit;
- }
-
- /* Because namelen includes the NUL, we check one byte back */
- if (entry->name[entry->namelen-1] != 0) {
- if (COPYFILE_VERBOSE & s->flags)
- copyfile_warn("Corrupt attribute entry (name is not NUL-terminated)");
- error = -1;
- goto exit;
- }
-
- copyfile_debug(3, "extracting \"%s\" (%d bytes) at offset %u",
- entry->name, entry->length, entry->offset);
-
- dataptr = (char *)attrhdr + entry->offset;
-
- if (dataptr >= endptr || dataptr < buffer) {
- copyfile_debug(1, "Entry %d overflows: offset = %u", entry->offset);
- error = -1;
- goto exit;
- }
- if ((dataptr + entry->length) > endptr ||
- ((dataptr + entry->length) < buffer) ||
- (entry->length > hdrsize)) {
- if (COPYFILE_VERBOSE & s->flags)
- copyfile_warn("Incomplete or corrupt attribute entry");
- copyfile_debug(1, "Entry %d length overflows: dataptr = %u, offset = %u, length = %u, buffer = %u, endptr = %u",
- i, dataptr, entry->offset, entry->length, buffer, endptr);
- error = -1;
- goto exit;
- }
-
- if (COPYFILE_ACL & s->flags && strcmp((char*)entry->name, XATTR_SECURITY_NAME) == 0)
copyfile_debug(2, "extracting \"%s\" (%d bytes)",
entry->name, entry->length);
dataptr = (char *)attrhdr + entry->offset;
if (COPYFILE_ACL & s->flags && strncmp(entry->name, XATTR_SECURITY_NAME, strlen(XATTR_SECURITY_NAME)) == 0)
{
acl_t acl;
- char *tacl = strdup(dataptr);
- if (tacl)
+ if ((acl = acl_from_text(dataptr)) != NULL)
{
- tacl[entry->length] = 0; /* Ensure it is NUL-terminated */
- if (acl = acl_from_text(tacl))
+ if (filesec_set_property(s->fsec, FILESEC_ACL, &acl) < 0)
{
- filesec_t tfsec = filesec_init();
- if (tfsec)
- {
- if (filesec_set_property(tfsec, FILESEC_ACL, &acl) < 0)
+ acl_t acl;
+ if ((acl = acl_from_text(dataptr)) != NULL)
{
- copyfile_debug(1, "setting acl");
- error = -1;
+ if (filesec_set_property(s->fsec, FILESEC_ACL, &acl) < 0)
+ {
+ copyfile_debug(1, "setting acl");
+ }
+ else if (fchmodx_np(s->dst_fd, s->fsec) < 0 && errno != ENOTSUP)
+ copyfile_warn("setting security information");
+ acl_free(acl);
}
- else if (fchmodx_np(s->dst_fd, tfsec) < 0 && errno != ENOTSUP)
- {
- error = -1;
- copyfile_debug(1, "applying acl to file");
- }
- filesec_free(tfsec);
- }
- acl_free(acl);
+ } else
+ if (COPYFILE_XATTR & s->flags && (fsetxattr(s->dst_fd, entry->name, dataptr, entry->length, 0, 0))) {
+ if (COPYFILE_VERBOSE & s->flags)
+ copyfile_warn("error %d setting attribute %s", error, entry->name);
+ goto exit;
}
- free(tacl);
+ else if (fchmodx_np(s->dst_fd, s->fsec) < 0 && errno != ENOTSUP)
+ copyfile_warn("setting security information");
+ acl_free(acl);
}
- if (error)
- goto exit;
} else
if (COPYFILE_XATTR & s->flags && (fsetxattr(s->dst_fd, entry->name, dataptr, entry->length, 0, 0))) {
if (COPYFILE_VERBOSE & s->flags)
/*
* Extract the Finder Info.
*/
- if (adhdr->entries[0].offset > (hdrsize - sizeof(emptyfinfo))) {
- error = -1;
- goto exit;
- }
-
if (bcmp((u_int8_t*)buffer + adhdr->entries[0].offset, emptyfinfo, sizeof(emptyfinfo)) != 0)
{
copyfile_debug(1, " extracting \"%s\" (32 bytes)", XATTR_FINDERINFO_NAME);
if (adhdr->entries[1].type == AD_RESOURCE &&
adhdr->entries[1].length > 0)
{
- void * rsrcforkdata = NULL;
+ void * rsrcforkdata;
size_t length;
off_t offset;
- struct stat sb;
- struct timeval tval[2];
length = adhdr->entries[1].length;
offset = adhdr->entries[1].offset;
rsrcforkdata = malloc(length);
- if (rsrcforkdata == NULL) {
- copyfile_debug(1, "could not allocate %u bytes for rsrcforkdata",
- length);
- error = -1;
- goto bad;
- }
-
- if (fstat(s->dst_fd, &sb) < 0)
- {
- copyfile_debug(1, "couldn't stat destination file");
- error = -1;
- goto exit;
- }
-
bytes = pread(s->src_fd, rsrcforkdata, length, offset);
if (bytes < length)
{
(int)bytes, (int)length);
}
error = -1;
- goto bad;
+ goto exit;
}
error = fsetxattr(s->dst_fd, XATTR_RESOURCEFORK_NAME, rsrcforkdata, bytes, 0, 0);
if (error)
{
copyfile_debug(1, "error %d setting resource fork attribute", error);
error = -1;
- goto bad;
+ goto exit;
}
- copyfile_debug(1, "extracting \"%s\" (%d bytes)",
+ copyfile_debug(1, "extracting \"%s\" (%d bytes)",
XATTR_RESOURCEFORK_NAME, (int)length);
-
- tval[0].tv_sec = sb.st_atime;
- tval[1].tv_sec = sb.st_mtime;
- tval[0].tv_usec = tval[1].tv_usec = 0;
-
- if (futimes(s->dst_fd, tval))
- {
- copyfile_warn("cannot set time on destination file %s", s->dst ? s->dst : "<no filename>");
- }
-
-bad:
- if (rsrcforkdata)
- free(rsrcforkdata);
+ free(rsrcforkdata);
}
exit:
- if (buffer) free(buffer);
+ free(buffer);
return error;
}
static int copyfile_pack(copyfile_state_t s)
{
- char *attrnamebuf = NULL, *endnamebuf;
- void *databuf = NULL;
- attr_header_t *filehdr, *endfilehdr;
+ char *attrnamebuf;
+ void *databuf;
+ attr_header_t *filehdr;
attr_entry_t *entry;
- ssize_t listsize = 0;
+ ssize_t listsize;
char *nameptr;
int namelen;
int entrylen;
int error = 0;
filehdr = (attr_header_t *) calloc(1, ATTR_MAX_SIZE);
- if (filehdr == NULL) {
- error = -1;
- goto exit;
- } else {
- endfilehdr = ((void*)filehdr) + ATTR_MAX_SIZE;
- }
-
attrnamebuf = calloc(1, ATTR_MAX_HDR_SIZE);
- if (attrnamebuf == NULL) {
- error = -1;
- goto exit;
- } else {
- endnamebuf = ((char*)attrnamebuf) + ATTR_MAX_HDR_SIZE;
- }
/*
* Fill in the Apple Double Header defaults.
*/
- filehdr->appledouble.magic = SWAP32 (ADH_MAGIC);
- filehdr->appledouble.version = SWAP32 (ADH_VERSION);
- filehdr->appledouble.numEntries = SWAP16 (2);
- filehdr->appledouble.entries[0].type = SWAP32 (AD_FINDERINFO);
- filehdr->appledouble.entries[0].offset = SWAP32 (offsetof(apple_double_header_t, finfo));
- filehdr->appledouble.entries[0].length = SWAP32 (FINDERINFOSIZE);
- filehdr->appledouble.entries[1].type = SWAP32 (AD_RESOURCE);
- filehdr->appledouble.entries[1].offset = SWAP32 (offsetof(apple_double_header_t, pad));
+ filehdr->appledouble.magic = ADH_MAGIC;
+ filehdr->appledouble.version = ADH_VERSION;
+ filehdr->appledouble.numEntries = 2;
+ filehdr->appledouble.entries[0].type = AD_FINDERINFO;
+ filehdr->appledouble.entries[0].offset = offsetof(apple_double_header_t, finfo);
+ filehdr->appledouble.entries[0].length = FINDERINFOSIZE;
+ filehdr->appledouble.entries[1].type = AD_RESOURCE;
+ filehdr->appledouble.entries[1].offset = offsetof(apple_double_header_t, pad);
filehdr->appledouble.entries[1].length = 0;
bcopy(ADH_MACOSX, filehdr->appledouble.filler, sizeof(filehdr->appledouble.filler));
/*
* Fill in the initial Attribute Header.
*/
- filehdr->magic = SWAP32 (ATTR_HDR_MAGIC);
- filehdr->debug_tag = SWAP32 (s->sb.st_ino);
- filehdr->data_start = SWAP32 (sizeof(attr_header_t));
+ filehdr->magic = ATTR_HDR_MAGIC;
+ filehdr->debug_tag = s->sb.st_ino;
+ filehdr->data_start = sizeof(attr_header_t);
/*
* Collect the attribute names.
if (COPYFILE_XATTR & s->flags)
{
- ssize_t left = ATTR_MAX_HDR_SIZE - offset;
- if ((listsize = flistxattr(s->src_fd, attrnamebuf + offset, left, 0)) <= 0)
+ if ((listsize = flistxattr(s->src_fd, attrnamebuf + offset, ATTR_MAX_HDR_SIZE, 0)) <= 0)
{
copyfile_debug(1, "no extended attributes found (%d)", errno);
}
- if (listsize > left)
+ if (listsize > ATTR_MAX_HDR_SIZE)
{
copyfile_debug(1, "extended attribute list too long");
listsize = ATTR_MAX_HDR_SIZE;
}
listsize += offset;
- endnamebuf = attrnamebuf + listsize;
- if (endnamebuf > (attrnamebuf + ATTR_MAX_HDR_SIZE)) {
- error = -1;
- goto exit;
- }
- for (nameptr = attrnamebuf; nameptr <endnamebuf; nameptr += namelen)
+ for (nameptr = attrnamebuf; nameptr < attrnamebuf + listsize; nameptr += namelen)
{
namelen = strlen(nameptr) + 1;
/* Skip over FinderInfo or Resource Fork names */
- if (strcmp(nameptr, XATTR_FINDERINFO_NAME) == 0 ||
- strcmp(nameptr, XATTR_RESOURCEFORK_NAME) == 0)
+ if (strncmp(nameptr, XATTR_FINDERINFO_NAME, strlen(XATTR_FINDERINFO_NAME)) == 0 ||
+ strncmp(nameptr, XATTR_RESOURCEFORK_NAME, strlen(XATTR_RESOURCEFORK_NAME)) == 0)
continue;
- /* The system should prevent this from happening, but... */
- if (namelen > XATTR_MAXNAMELEN + 1) {
- namelen = XATTR_MAXNAMELEN + 1;
- }
entry->namelen = namelen;
entry->flags = 0;
bcopy(nameptr, &entry->name[0], namelen);
entrylen = ATTR_ENTRY_LENGTH(namelen);
entry = (attr_entry_t *)(((char *)entry) + entrylen);
-
- if ((void*)entry > (void*)endfilehdr) {
- error = -1;
- goto exit;
- }
-
+
/* Update the attributes header. */
filehdr->num_attrs++;
filehdr->data_start += entrylen;
for (nameptr = attrnamebuf; nameptr < attrnamebuf + listsize; nameptr += namelen + 1)
{
+ nameptr = nameptr;
namelen = strlen(nameptr);
- if (strcmp(nameptr, XATTR_SECURITY_NAME) == 0)
+ if (strncmp(nameptr, XATTR_SECURITY_NAME, strlen(XATTR_SECURITY_NAME)) == 0)
copyfile_pack_acl(s, &databuf, &datasize);
else
/* Check for Finder Info. */
- if (strcmp(nameptr, XATTR_FINDERINFO_NAME) == 0)
+ if (strncmp(nameptr, XATTR_FINDERINFO_NAME, strlen(XATTR_FINDERINFO_NAME)) == 0)
{
datasize = fgetxattr(s->src_fd, nameptr, (u_int8_t*)filehdr + filehdr->appledouble.entries[0].offset, 32, 0, 0);
if (datasize < 0)
continue; /* finder info doesn't have an attribute entry */
} else
/* Check for Resource Fork. */
- if (strcmp(nameptr, XATTR_RESOURCEFORK_NAME) == 0)
+ if (strncmp(nameptr, XATTR_RESOURCEFORK_NAME, strlen(XATTR_RESOURCEFORK_NAME)) == 0)
{
hasrsrcfork = 1;
continue;
goto next;
}
databuf = malloc(datasize);
- if (databuf == NULL) {
- error = -1;
- continue;
- }
datasize = fgetxattr(s->src_fd, nameptr, databuf, datasize, 0, 0);
}
* the case when there are lots of attributes or one of
* the attributes is very large.
*/
- if (entry->offset > ATTR_MAX_SIZE ||
- (entry->offset + datasize > ATTR_MAX_SIZE)) {
- error = -1;
- } else {
- bcopy(databuf, (char*)filehdr + entry->offset, datasize);
- }
+ bcopy(databuf, (char*)filehdr + entry->offset, datasize);
free(databuf);
copyfile_debug(1, "copied %ld bytes of \"%s\" data @ offset 0x%08x", datasize, nameptr, entry->offset);
filehdr->appledouble.entries[0].length =
filehdr->appledouble.entries[1].offset - filehdr->appledouble.entries[0].offset;
- filehdr->total_size = SWAP32 (filehdr->appledouble.entries[1].offset);
+ filehdr->total_size = filehdr->appledouble.entries[1].offset;
}
/* Copy Resource Fork. */
/* Write the header to disk. */
datasize = filehdr->appledouble.entries[1].offset;
+ swap_adhdr(&filehdr->appledouble);
+ swap_attrhdr(filehdr);
+
if (pwrite(s->dst_fd, filehdr, datasize, 0) != datasize)
{
if (COPYFILE_VERBOSE & s->flags)
goto exit;
}
exit:
- if (filehdr) free(filehdr);
- if (attrnamebuf) free(attrnamebuf);
+ free(filehdr);
+ free(attrnamebuf);
if (error)
return error;
---- hash_page.c.orig 2006-04-22 23:04:55.000000000 -0700
-+++ hash_page.c 2006-04-23 00:23:46.000000000 -0700
+--- hash_page.c.orig Thu Mar 21 14:46:26 2002
++++ hash_page.c Sat Oct 18 18:31:10 2003
@@ -74,7 +74,7 @@
#include <db.h>
#include "hash.h"
static u_int32_t *fetch_bitmap(HTAB *, int);
static u_int32_t first_free(u_int32_t);
-@@ -586,7 +586,7 @@
- int is_bucket, is_bitmap;
- {
- int fd, page, size;
-- int wsize;
-+ int wsize, max;
-
- size = hashp->BSIZE;
- if ((hashp->fp == -1) && open_temp(hashp))
-@@ -595,7 +595,6 @@
-
- if (hashp->LORDER != BYTE_ORDER) {
- int i;
-- int max;
-
- if (is_bitmap) {
- max = hashp->BSIZE >> 2; /* divide by 4 */
-@@ -619,6 +618,18 @@
- errno = EFTYPE;
- return (-1);
- }
-+ /* 4485533 - reswap the in-memory copy */
-+ if (hashp->LORDER != BYTE_ORDER) {
-+ int i;
-+
-+ if (is_bitmap) {
-+ for (i = 0; i < max; i++)
-+ M_32_SWAP(((int *)p)[i]);
-+ } else {
-+ for (i = 0; i <= max; i++)
-+ M_16_SWAP(((u_int16_t *)p)[i]);
-+ }
-+ }
- return (0);
- }
-
+++ /dev/null
---- mpool.c.orig 2006-12-13 22:19:43.000000000 -0800
-+++ mpool.c 2006-12-13 22:27:26.000000000 -0800
-@@ -294,10 +294,16 @@
- BKT *bp;
-
- /* Walk the lru chain, flushing any dirty pages to disk. */
-- TAILQ_FOREACH(bp, &mp->lqh, q)
-- if (bp->flags & MPOOL_DIRTY &&
-- mpool_write(mp, bp) == RET_ERROR)
-- return (RET_ERROR);
-+ TAILQ_FOREACH(bp, &mp->lqh, q) {
-+ if (bp->flags & MPOOL_DIRTY)
-+ if (mpool_write(mp, bp) == RET_ERROR) {
-+ return (RET_ERROR);
-+ } else {
-+ /* 4892134: Re-run through the user's pgin filter. */
-+ if (mp->pgin != NULL)
-+ (mp->pgin)(mp->pgcookie, bp->pgno, bp->page);
-+ }
-+ }
-
- /* Sync the file descriptor. */
- return (_fsync(mp->fd) ? RET_ERROR : RET_SUCCESS);
/*-
- * Copyright (c) 2004, 2005 David Schultz <das@FreeBSD.ORG>
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gdtoa/_hdtoa.c,v 1.3 2005/01/18 18:44:07 das Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gdtoa/_hdtoa.c,v 1.2 2004/01/21 04:51:50 grehan Exp $");
#include <float.h>
+#include <inttypes.h>
#include <limits.h>
#include <math.h>
+#include <stdlib.h>
#include "fpmath.h"
#include "gdtoaimp.h"
#define INFSTR "Infinity"
#define NANSTR "NaN"
-#define DBL_ADJ (DBL_MAX_EXP - 2 + ((DBL_MANT_DIG - 1) % 4))
-#define LDBL_ADJ (LDBL_MAX_EXP - 2 + ((LDBL_MANT_DIG - 1) % 4))
+#define DBL_BIAS (DBL_MAX_EXP - 1)
+#define LDBL_BIAS (LDBL_MAX_EXP - 1)
+
+#ifdef LDBL_IMPLICIT_NBIT
+#define LDBL_NBIT_ADJ 0
+#else
+#define LDBL_NBIT_ADJ 1
+#endif
+
+/*
+ * Efficiently compute the log2 of an integer. Uses a combination of
+ * arcane tricks found in fortune and arcane tricks not (yet) in
+ * fortune. This routine behaves similarly to fls(9).
+ */
+static int
+log2_32(uint32_t n)
+{
+
+ n |= (n >> 1);
+ n |= (n >> 2);
+ n |= (n >> 4);
+ n |= (n >> 8);
+ n |= (n >> 16);
+
+ n = (n & 0x55555555) + ((n & 0xaaaaaaaa) >> 1);
+ n = (n & 0x33333333) + ((n & 0xcccccccc) >> 2);
+ n = (n & 0x0f0f0f0f) + ((n & 0xf0f0f0f0) >> 4);
+ n = (n & 0x00ff00ff) + ((n & 0xff00ff00) >> 8);
+ n = (n & 0x0000ffff) + ((n & 0xffff0000) >> 16);
+ return (n - 1);
+}
+
+#if (LDBL_MANH_SIZE > 32 || LDBL_MANL_SIZE > 32)
+
+static int
+log2_64(uint64_t n)
+{
+
+ if (n >> 32 != 0)
+ return (log2_32((uint32_t)(n >> 32)) + 32);
+ else
+ return (log2_32((uint32_t)n));
+}
+
+#endif /* (LDBL_MANH_SIZE > 32 || LDBL_MANL_SIZE > 32) */
/*
* Round up the given digit string. If the digit string is fff...f,
__hdtoa(double d, const char *xdigs, int ndigits, int *decpt, int *sign,
char **rve)
{
- static const int sigfigs = (DBL_MANT_DIG + 3) / 4;
union IEEEd2bits u;
char *s, *s0;
int bufsize;
+ int impnbit; /* implicit normalization bit */
+ int pos;
+ int shift; /* for subnormals, # of shifts required to normalize */
+ int sigfigs; /* number of significant hex figures in result */
u.d = d;
*sign = u.bits.sign;
switch (fpclassify(d)) {
case FP_NORMAL:
- *decpt = u.bits.exp - DBL_ADJ;
+ sigfigs = (DBL_MANT_DIG + 3) / 4;
+ impnbit = 1 << ((DBL_MANT_DIG - 1) % 4);
+ *decpt = u.bits.exp - DBL_BIAS + 1 -
+ ((DBL_MANT_DIG - 1) % 4);
break;
case FP_ZERO:
*decpt = 1;
return (nrv_alloc("0", rve, 1));
case FP_SUBNORMAL:
- u.d *= 0x1p514;
- *decpt = u.bits.exp - (514 + DBL_ADJ);
+ /*
+ * The position of the highest-order bit tells us by
+ * how much to adjust the exponent (decpt). The
+ * adjustment is raised to the next nibble boundary
+ * since we will later choose the leftmost hexadecimal
+ * digit so that all subsequent digits align on nibble
+ * boundaries.
+ */
+ if (u.bits.manh != 0) {
+ pos = log2_32(u.bits.manh);
+ shift = DBL_MANH_SIZE - pos;
+ } else {
+ pos = log2_32(u.bits.manl);
+ shift = DBL_MANH_SIZE + DBL_MANL_SIZE - pos;
+ }
+ sigfigs = (3 + DBL_MANT_DIG - shift) / 4;
+ impnbit = 0;
+ *decpt = DBL_MIN_EXP - ((shift + 3) & ~(4 - 1));
break;
case FP_INFINITE:
*decpt = INT_MAX;
* At this point, we have snarfed all the bits in the
* mantissa, with the possible exception of the highest-order
* (partial) nibble, which is dealt with by the next
- * statement. We also tack on the implicit normalization bit.
+ * statement. That nibble is usually in manh, but it could be
+ * in manl instead for small subnormals. We also tack on the
+ * implicit normalization bit if appropriate.
*/
- *s = u.bits.manh | (1U << ((DBL_MANT_DIG - 1) % 4));
+ *s = u.bits.manh | u.bits.manl | impnbit;
/* If ndigits < 0, we are expected to auto-size the precision. */
if (ndigits < 0) {
/*
* This is the long double version of __hdtoa().
+ *
+ * On architectures that have an explicit integer bit, unnormals and
+ * pseudo-denormals cause problems in the conversion routine, so they
+ * are ``fixed'' by effectively toggling the integer bit. Although
+ * this is not correct behavior, the hardware will not produce these
+ * formats externally.
*/
char *
__hldtoa(long double e, const char *xdigs, int ndigits, int *decpt, int *sign,
char **rve)
{
- static const int sigfigs = (LDBL_MANT_DIG + 3) / 4;
union IEEEl2bits u;
char *s, *s0;
int bufsize;
+ int impnbit; /* implicit normalization bit */
+ int pos;
+ int shift; /* for subnormals, # of shifts required to normalize */
+ int sigfigs; /* number of significant hex figures in result */
u.e = e;
*sign = u.bits.sign;
switch (fpclassify(e)) {
case FP_NORMAL:
- *decpt = u.bits.exp - LDBL_ADJ;
+ sigfigs = (LDBL_MANT_DIG + 3) / 4;
+ impnbit = 1 << ((LDBL_MANT_DIG - 1) % 4);
+ *decpt = u.bits.exp - LDBL_BIAS + 1 -
+ ((LDBL_MANT_DIG - 1) % 4);
break;
case FP_ZERO:
*decpt = 1;
return (nrv_alloc("0", rve, 1));
case FP_SUBNORMAL:
- u.e *= 0x1p514L;
- *decpt = u.bits.exp - (514 + LDBL_ADJ);
+ /*
+ * The position of the highest-order bit tells us by
+ * how much to adjust the exponent (decpt). The
+ * adjustment is raised to the next nibble boundary
+ * since we will later choose the leftmost hexadecimal
+ * digit so that all subsequent digits align on nibble
+ * boundaries.
+ */
+#ifdef LDBL_IMPLICIT_NBIT
+ /* Don't trust the normalization bit to be off. */
+ u.bits.manh &= ~(~0ULL << (LDBL_MANH_SIZE - 1));
+#endif
+ if (u.bits.manh != 0) {
+#if LDBL_MANH_SIZE > 32
+ pos = log2_64(u.bits.manh);
+#else
+ pos = log2_32(u.bits.manh);
+#endif
+ shift = LDBL_MANH_SIZE - LDBL_NBIT_ADJ - pos;
+ } else {
+#if LDBL_MANL_SIZE > 32
+ pos = log2_64(u.bits.manl);
+#else
+ pos = log2_32(u.bits.manl);
+#endif
+ shift = LDBL_MANH_SIZE + LDBL_MANL_SIZE -
+ LDBL_NBIT_ADJ - pos;
+ }
+ sigfigs = (3 + LDBL_MANT_DIG - LDBL_NBIT_ADJ - shift) / 4;
+ *decpt = LDBL_MIN_EXP + LDBL_NBIT_ADJ -
+ ((shift + 3) & ~(4 - 1));
+ impnbit = 0;
break;
case FP_INFINITE:
*decpt = INT_MAX;
* At this point, we have snarfed all the bits in the
* mantissa, with the possible exception of the highest-order
* (partial) nibble, which is dealt with by the next
- * statement. We also tack on the implicit normalization bit.
+ * statement. That nibble is usually in manh, but it could be
+ * in manl instead for small subnormals. We also tack on the
+ * implicit normalization bit if appropriate.
*/
- *s = u.bits.manh | (1U << ((LDBL_MANT_DIG - 1) % 4));
+ *s = u.bits.manh | u.bits.manl | impnbit;
/* If ndigits < 0, we are expected to auto-size the precision. */
if (ndigits < 0) {
---- _hdtoa.c.orig 2006-01-31 15:21:41.000000000 -0800
-+++ _hdtoa.c 2006-01-31 23:37:12.000000000 -0800
-@@ -223,6 +223,10 @@
- union IEEEl2bits u;
- char *s, *s0;
- int bufsize;
+--- _hdtoa.c.orig 2004-06-03 15:22:08.000000000 -0700
++++ _hdtoa.c 2004-08-28 17:10:21.000000000 -0700
+@@ -32,6 +32,9 @@
+ #include <limits.h>
+ #include <math.h>
+ #include <stdlib.h>
++#ifdef LDBL_HEAD_TAIL_PAIR
++#include <alloca.h>
++#endif /* LDBL_HEAD_TAIL_PAIR */
+ #include "fpmath.h"
+ #include "gdtoaimp.h"
+
+@@ -301,16 +304,31 @@
+ int pos;
+ int shift; /* for subnormals, # of shifts required to normalize */
+ int sigfigs; /* number of significant hex figures in result */
+#ifdef LDBL_HEAD_TAIL_PAIR
+ uint32_t bits[4];
-+ int i, pos;
++ int i;
+#endif /* LDBL_HEAD_TAIL_PAIR */
u.e = e;
*sign = u.bits.sign;
-@@ -270,6 +274,19 @@
+
++#ifdef LDBL_HEAD_TAIL_PAIR
++ switch (__fpclassifyd(u.d[0])) {
++#else /* LDBL_HEAD_TAIL_PAIR */
+ switch (fpclassify(e)) {
++#endif /* LDBL_HEAD_TAIL_PAIR */
+ case FP_NORMAL:
++#ifdef LDBL_HEAD_TAIL_PAIR
+ sigfigs = (LDBL_MANT_DIG + 3) / 4;
+ impnbit = 1 << ((LDBL_MANT_DIG - 1) % 4);
+ *decpt = u.bits.exp - LDBL_BIAS + 1 -
+ ((LDBL_MANT_DIG - 1) % 4);
++#else /* LDBL_HEAD_TAIL_PAIR */
++ sigfigs = (LDBL_MANT_DIG + 3) / 4;
++ impnbit = 1 << ((LDBL_MANT_DIG - 1) % 4);
++ *decpt = u.bits.exp - LDBL_BIAS + 1 -
++ ((LDBL_MANT_DIG - 1) % 4);
++#endif /* LDBL_HEAD_TAIL_PAIR */
+ break;
+ case FP_ZERO:
+ *decpt = 1;
+@@ -328,13 +346,26 @@
+ /* Don't trust the normalization bit to be off. */
+ u.bits.manh &= ~(~0ULL << (LDBL_MANH_SIZE - 1));
+ #endif
++#ifndef LDBL_HEAD_TAIL_PAIR
+ if (u.bits.manh != 0) {
++#endif /* LDBL_HEAD_TAIL_PAIR */
+ #if LDBL_MANH_SIZE > 32
+ pos = log2_64(u.bits.manh);
+ #else
+ pos = log2_32(u.bits.manh);
+ #endif
+ shift = LDBL_MANH_SIZE - LDBL_NBIT_ADJ - pos;
++#ifdef LDBL_HEAD_TAIL_PAIR
++ sigfigs = (3 + LDBL_MANT_DIG - LDBL_NBIT_ADJ - shift) / 4;
++ // we use DBL_MIN_EXP below because the head double is
++ // subnormal (and the tail double is zero)
++ *decpt = DBL_MIN_EXP + LDBL_NBIT_ADJ;
++ pos = (LDBL_MANT_DIG + 3) % 4;
++ if (pos < shift)
++ *decpt -= pos + ((shift - pos + 3) & ~(4 - 1));
++ else
++ *decpt -= shift;
++#else /* LDBL_HEAD_TAIL_PAIR */
+ } else {
+ #if LDBL_MANL_SIZE > 32
+ pos = log2_64(u.bits.manl);
+@@ -345,8 +376,9 @@
+ LDBL_NBIT_ADJ - pos;
+ }
+ sigfigs = (3 + LDBL_MANT_DIG - LDBL_NBIT_ADJ - shift) / 4;
+- *decpt = LDBL_MIN_EXP + LDBL_NBIT_ADJ -
++ *decpt = DBL_MIN_EXP + LDBL_NBIT_ADJ -
+ ((shift + 3) & ~(4 - 1));
++#endif /* LDBL_HEAD_TAIL_PAIR */
+ impnbit = 0;
+ break;
+ case FP_INFINITE:
+@@ -381,6 +413,19 @@
*/
for (s = s0 + bufsize - 1; s > s0 + sigfigs - 1; s--)
*s = 0;
for (; s > s0 + sigfigs - (LDBL_MANL_SIZE / 4) - 1 && s > s0; s--) {
*s = u.bits.manl & 0xf;
u.bits.manl >>= 4;
-@@ -278,6 +295,7 @@
+@@ -389,6 +434,7 @@
*s = u.bits.manh & 0xf;
u.bits.manh >>= 4;
}
/*
* At this point, we have snarfed all the bits in the
-@@ -285,7 +303,11 @@
- * (partial) nibble, which is dealt with by the next
- * statement. We also tack on the implicit normalization bit.
+@@ -398,7 +444,11 @@
+ * in manl instead for small subnormals. We also tack on the
+ * implicit normalization bit if appropriate.
*/
+#ifdef LDBL_HEAD_TAIL_PAIR
-+ *s = bits[i];
++ *s = bits[i] | impnbit;
+#else /* LDBL_HEAD_TAIL_PAIR */
- *s = u.bits.manh | (1U << ((LDBL_MANT_DIG - 1) % 4));
+ *s = u.bits.manh | u.bits.manl | impnbit;
+#endif /* LDBL_HEAD_TAIL_PAIR */
/* If ndigits < 0, we are expected to auto-size the precision. */
---- _ldtoa.c.orig 2004-12-08 22:50:28.000000000 -0800
-+++ _ldtoa.c 2004-12-08 22:52:58.000000000 -0800
+--- _ldtoa.c.orig 2004-06-03 15:17:18.000000000 -0700
++++ _ldtoa.c 2005-10-08 22:43:25.000000000 -0700
@@ -61,14 +61,34 @@
char *ret;
union IEEEl2bits u;
kind = STRTOG_Normal;
#ifdef LDBL_IMPLICIT_NBIT
bits[LDBL_MANT_DIG / 32] |= 1 << ((LDBL_MANT_DIG - 1) % 32);
-@@ -77,12 +97,14 @@
+@@ -77,12 +97,12 @@
case FP_ZERO:
kind = STRTOG_Zero;
break;
+#if !defined(__ppc__) && !defined(__ppc64__)
case FP_SUBNORMAL:
kind = STRTOG_Denormal;
- #ifdef LDBL_IMPLICIT_NBIT
+-#ifdef LDBL_IMPLICIT_NBIT
be++;
- #endif
+-#endif
break;
+#endif /* !defined(__ppc__) && !defined(__ppc64__) */
case FP_INFINITE:
kind = STRTOG_Infinite;
break;
-@@ -96,5 +118,9 @@
+@@ -96,5 +116,9 @@
ret = gdtoa(&fpi, be, (ULong *)bits, &kind, mode, ndigits, decpt, rve);
if (*decpt == -32768)
*decpt = INT_MAX;
* with " at " changed at "@" and " dot " changed to "."). */
#include "gdtoaimp.h"
+#ifndef NO_FENV_H
+#include <fenv.h>
+#endif
#ifdef USE_LOCALE
#include "locale.h"
switch(s[1]) {
case 'x':
case 'X':
- switch((i = gethex(&s, &fpi, &exp, &bb, sign)) & STRTOG_Retmask) {
+ {
+#if defined(FE_DOWNWARD) && defined(FE_TONEAREST) && defined(FE_TOWARDZERO) && defined(FE_UPWARD)
+ FPI fpi1 = fpi;
+ switch(fegetround()) {
+ case FE_TOWARDZERO: fpi1.rounding = 0; break;
+ case FE_UPWARD: fpi1.rounding = 2; break;
+ case FE_DOWNWARD: fpi1.rounding = 3;
+ }
+#else
+#define fpi1 fpi
+#endif
+ switch((i = gethex(&s, &fpi1, &exp, &bb, sign)) & STRTOG_Retmask) {
case STRTOG_NoNumber:
s = s00;
sign = 0;
Bfree(bb);
}
ULtod(((U*)&rv)->L, bits, exp, i);
- }
+ }}
goto ret;
}
}
---- gdtoa-strtod.c.orig 2005-01-20 20:12:37.000000000 -0800
-+++ gdtoa-strtod.c 2005-02-17 01:31:26.000000000 -0800
+--- gdtoa-strtod.c.orig 2005-10-08 11:32:33.000000000 -0700
++++ gdtoa-strtod.c 2005-10-08 11:38:17.000000000 -0700
@@ -29,6 +29,8 @@
/* Please send bug reports to David M. Gay (dmg at acm dot org,
* with " at " changed at "@" and " dot " changed to "."). */
+#include "xlocale_private.h"
+
#include "gdtoaimp.h"
-
- #ifdef USE_LOCALE
-@@ -56,11 +58,11 @@
+ #ifndef NO_FENV_H
+ #include <fenv.h>
+@@ -59,11 +61,11 @@
#endif
double
#endif
{
#ifdef Avoid_Underflow
-@@ -112,7 +114,7 @@
- switch(s[1]) {
- case 'x':
- case 'X':
-- switch((i = gethex(&s, &fpi, &exp, &bb, sign)) & STRTOG_Retmask) {
-+ switch((i = gethex(&s, &fpi, &exp, &bb, sign, loc)) & STRTOG_Retmask) {
+@@ -126,7 +128,7 @@
+ #else
+ #define fpi1 fpi
+ #endif
+- switch((i = gethex(&s, &fpi1, &exp, &bb, sign)) & STRTOG_Retmask) {
++ switch((i = gethex(&s, &fpi1, &exp, &bb, sign, loc)) & STRTOG_Retmask) {
case STRTOG_NoNumber:
s = s00;
sign = 0;
-@@ -142,8 +144,9 @@
+@@ -156,8 +158,9 @@
else if (nd < 16)
z = 10*z + c - '0';
nd0 = nd;
#else
if (c == '.')
#endif
-@@ -966,3 +969,13 @@
+@@ -980,3 +983,13 @@
return sign ? -dval(rv) : dval(rv);
}
}
bb0 = 0; /* trailing zero bits in rvb */
e2 = rve + rvbits - nbits;
- if (e2 > fpi->emax) {
- rvb->wds = 0;
- irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
-#ifndef NO_ERRNO
- errno = ERANGE;
-#endif
- infnanexp:
- *exp = fpi->emax + 1;
- goto ret;
- }
+ if (e2 > fpi->emax + 1)
+ goto huge;
rve1 = rve + rvbits - nbits;
if (e2 < (emin = fpi->emin)) {
denorm = 1;
Bfree(bs);
Bfree(bd0);
Bfree(delta);
+ if (rve > fpi->emax) {
+ huge:
+ rvb->wds = 0;
+ irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
+#ifndef NO_ERRNO
+ errno = ERANGE;
+#endif
+ infnanexp:
+ *exp = fpi->emax + 1;
+ }
ret:
if (denorm) {
if (sudden_underflow) {
---- gdtoa-strtodg.c.orig 2005-01-20 20:12:37.000000000 -0800
-+++ gdtoa-strtodg.c 2005-02-17 01:32:24.000000000 -0800
+--- gdtoa-strtodg.c.orig 2005-10-08 11:33:23.000000000 -0700
++++ gdtoa-strtodg.c 2005-10-08 11:40:57.000000000 -0700
@@ -29,6 +29,8 @@
/* Please send bug reports to David M. Gay (dmg at acm dot org,
* with " at " changed at "@" and " dot " changed to "."). */
#else
if (c == '.')
#endif
-@@ -676,6 +679,9 @@
+@@ -668,6 +671,9 @@
rvb->x[0] = 0;
*exp = emin;
irv = STRTOG_Underflow | STRTOG_Inexlo;
--- gdtoa_strtopx.c.orig 2005-01-20 20:12:37.000000000 -0800
-+++ gdtoa_strtopx.c 2005-02-17 01:54:02.000000000 -0800
++++ gdtoa_strtopx.c 2005-10-08 17:10:15.000000000 -0700
@@ -29,6 +29,8 @@
/* Please send bug reports to David M. Gay (dmg at acm dot org,
* with " at " changed at "@" and " dot " changed to "."). */
switch(k & STRTOG_Retmask) {
case STRTOG_NoNumber:
case STRTOG_Zero:
+@@ -87,7 +89,8 @@
+
+ case STRTOG_Infinite:
+ L[_0] = 0x7fff;
+- L[_1] = L[_2] = L[_3] = L[_4] = 0;
++ L[_1] = 0x8000;
++ L[_2] = L[_3] = L[_4] = 0;
+ break;
+
+ case STRTOG_NaN:
---- popen.c.orig Mon May 24 23:50:41 2004
-+++ popen.c Tue May 25 00:09:39 2004
+--- popen.c.orig 2003-05-20 15:21:02.000000000 -0700
++++ popen.c 2005-09-17 16:08:55.000000000 -0700
@@ -43,6 +43,7 @@
#include "namespace.h"
#include <sys/param.h>
if ((cur = malloc(sizeof(struct pid))) == NULL) {
(void)_close(pdes[0]);
+@@ -104,7 +106,7 @@
+ argv[3] = NULL;
+
+ THREAD_LOCK();
+- switch (pid = vfork()) {
++ switch (pid = fork()) {
+ case -1: /* Error. */
+ THREAD_UNLOCK();
+ (void)_close(pdes[0]);
@@ -138,7 +140,7 @@
(void)_close(pdes[1]);
}
---- setprogname.c.orig Mon Apr 28 15:05:02 2003
-+++ setprogname.c Fri May 16 14:13:59 2003
-@@ -3,6 +3,8 @@
+--- setprogname.c.orig 2003-05-20 15:21:02.000000000 -0700
++++ setprogname.c 2005-10-26 00:58:44.000000000 -0700
+@@ -3,6 +3,10 @@
#include <stdlib.h>
#include <string.h>
++#include <sys/param.h>
++#include <sys/sysctl.h>
+#include <crt_externs.h>
+#define __progname (*_NSGetProgname())
#include "libc_private.h"
-@@ -13,7 +15,7 @@
-
+@@ -10,10 +14,20 @@
+ setprogname(const char *progname)
+ {
+ const char *p;
+-
++ char buf[2*MAXCOMLEN+1];
++ int mib[2];
++
p = strrchr(progname, '/');
if (p != NULL)
- __progname = p + 1;
-+ __progname = (char *)(p + 1);
++ __progname = (char *)(++p);
else
- __progname = progname;
-+ __progname = (char *)progname;
++ __progname = (char *)(p = progname);
++
++ strlcpy(&buf[0], p, sizeof(buf));
++
++ mib[0] = CTL_KERN;
++ mib[1] = KERN_PROCNAME;
++
++ /* ignore errors as this is not a hard error */
++ sysctl(mib, 2, NULL, NULL, &buf[0], 2*MAXCOMLEN);
}
#include <errno.h>
#include <uuid/uuid.h>
+/*
+ * Versions of copy_int/copy_ext that retain native endianity.
+ */
+extern ssize_t acl_copy_ext_native(void *buf_p, acl_t acl, ssize_t size);
+extern acl_t acl_copy_int_native(const void *buf_p);
struct _filesec {
int fs_valid;
if (fsec->fs_aclbuf == _FILESEC_REMOVE_ACL) {
*(acl_t *)propptr = _FILESEC_REMOVE_ACL;
} else {
- *(acl_t *)propptr = acl_copy_int(fsec->fs_aclbuf);
+ *(acl_t *)propptr = acl_copy_int_native(fsec->fs_aclbuf);
if (*(acl_t *)propptr == NULL)
error = errno;
}
error = errno;
break;
}
- copysize = acl_copy_ext(aclbuf, acl, aclsize);
+ copysize = acl_copy_ext_native(aclbuf, acl, aclsize);
if (copysize < 0) {
free(aclbuf);
error = EINVAL;
/*************** Recording stack ***********/
-static void *first_frame_address(void) {
+// The three functions below are marked as noinline to ensure consistent inlining across
+// all versions of GCC and all compiler flags. The malloc stack logging code expects
+// these functions to not be inlined.
+// For details, see <rdar://problem/4199620>.
+//
+// The performance cost of not inlining these functions is negligible, and they're only
+// called when MallocStackLogging is set anyway, so they won't affect normal usage.
+
+static __attribute__((noinline)) void *first_frame_address(void) {
#if defined(__i386__)
- return __builtin_frame_address(1);
+ return __builtin_frame_address(0);
#elif defined(__ppc__) || defined(__ppc64__)
void *addr;
#warning __builtin_frame_address IS BROKEN IN BEAKER: RADAR #2340421
#endif
}
-static void *next_frame_address(void *addr) {
+static __attribute__((noinline)) void *next_frame_address(void *addr) {
void *ret;
#if defined(__MACH__) && defined(__i386__)
__asm__ volatile("movl (%1),%0" : "=r" (ret) : "r" (addr));
#error ********** Unimplemented architecture
#endif
-void thread_stack_pcs(vm_address_t *buffer, unsigned max, unsigned *nb) {
+__attribute__((noinline)) void thread_stack_pcs(vm_address_t *buffer, unsigned max, unsigned *nb) {
void *addr;
addr = first_frame_address();
*nb = 0;
* @APPLE_LICENSE_HEADER_END@
*/
+#include <mach/i386/syscall_sw.h>
+
.text
.align 2, 0x90
.globl ___pthread_set_self
pushl 4(%esp)
pushl $0
movl $3,%eax
- lcall $0x3b,$0
+ MACHDEP_SYSCALL_TRAP
addl $8,%esp
movw %ax,%gs
ret
bzero.s \
memcpy.s \
memmove.s \
- strcmp.s
+ strlen.s \
+ strcpy.s \
+ strcmp.s \
+ strncpy.s \
+ strncmp.s \
+ memcmp.s \
+ bcmp.s \
+ memset.s
--- /dev/null
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ * bcmp() is implemented in memcmp.s, as it is equivalent to memcmp() in OSX.
+ * (The two symbols, bcmp and memcmp, have the same value.)
+ * This empty file is here to prevent the Free BSD machine independent version
+ * from building.
+ */
--- /dev/null
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+
+// *************** ***********
+// * M E M C M P * and * B C M P *
+// *************** ***********
+//
+// int memcmp(const char *s1, const char *s2, size_t len);
+// int bcmp(const char *s1, const char *s2, size_t len);
+//
+// Bcmp returns (+,0,-), whereas memcmp returns the true difference
+// between the first differing bytes, but we treat them identically.
+//
+// We optimize the compare by doing it with SSE. This introduces
+// a complication: if we blindly did vector loads from both sides until
+// finding a difference, we might get a spurious page fault by
+// reading bytes past the difference. To avoid this, we never do a load
+// that crosses a page boundary.
+
+#define kShort 18 // too short for vectors (must be >16)
+
+ .text
+ .align 4
+
+ .globl _memcmp
+ .globl _bcmp
+
+_memcmp: // int memcmp(const char *s1,const char *s2,size_t len);
+_bcmp: // int bcmp(const char *s1,const char *s2,size_t len);
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%ecx // get length
+ movl 12(%esp),%esi // get LHS ptr
+ movl 16(%esp),%edi // get RHS ptr
+ cmpl $(kShort),%ecx // worth accelerating?
+ ja LNotShort // yes
+
+
+// Too short to bother with parallel compares. Loop over bytes.
+// %esi = LHS ptr
+// %edi = RHS ptr
+// %ecx = length (<= kShort)
+
+LShort:
+ testl %ecx,%ecx // 0-length?
+ jnz LShortLoop // no
+ xorl %eax,%eax // return 0
+ jmp LExit
+ .align 4,0x90 // align inner loops to optimize I-fetch
+LShortLoop: // loop over bytes
+ movzb (%esi),%eax // get LHS byte
+ movzb (%edi),%edx // get RHS byte
+ incl %esi
+ incl %edi
+ subl %edx,%eax // compare them
+ jnz LExit // done if not equal
+ decl %ecx // decrement length
+ jnz LShortLoop
+LExit: // return value is in %eax
+ popl %edi
+ popl %esi
+ ret
+
+LNotEqual: // here from LLoopOverBytes with LHS in eax
+ movzb (%edi),%edx // get RHS byte
+ subl %edx,%eax // generate return value (nonzero)
+ popl %edi
+ popl %esi
+ ret
+
+
+// Loop over bytes until we reach end of a page.
+// %esi = LHS ptr
+// %edi = RHS ptr
+// %ecx = length remaining after end of loop (ie, already adjusted)
+// %edx = #bytes until next page (1..15)
+
+ .align 4,0x90 // align inner loops to optimize I-fetch
+LLoopOverBytes:
+ movzb (%esi),%eax // get LHS byte
+ inc %esi
+ cmpb (%edi),%al // compare to RHS byte
+ jnz LNotEqual // done if not equal
+ inc %edi
+ dec %edx // more to go?
+ jnz LLoopOverBytes
+
+
+// Long enough to justify overhead of setting up vector compares. In order to
+// avoid spurious page faults, we loop over:
+//
+// min( length, bytes_in_LHS_page, bytes_in_RHS_page) >> 4
+//
+// 16-byte chunks. When we near a page end, we have to revert to a byte-by-byte
+// comparison until reaching the next page, then resume the vector comparison.
+// %esi = LHS ptr
+// %edi = RHS ptr
+// %ecx = length (> kShort)
+
+LNotShort:
+ movl %esi,%eax // copy ptrs
+ movl %edi,%edx
+ andl $4095,%eax // mask down to page offsets
+ andl $4095,%edx
+ cmpl %eax,%edx // which is bigger?
+ cmova %edx,%eax // %eax = max(LHS offset, RHS offset);
+ movl $4096,%edx
+ subl %eax,%edx // get #bytes to next page crossing
+ cmpl %ecx,%edx // will operand run out first?
+ cmova %ecx,%edx // get min(length remaining, bytes to page end)
+ movl %edx,%eax
+ shrl $4,%edx // get #chunks till end of operand or page
+ jnz LLoopOverChunks // enter vector loop
+
+// Too near page end for vectors.
+
+ subl %eax,%ecx // adjust length remaining
+ movl %eax,%edx // %edx <- #bytes to page end
+ cmpl $(kShort),%ecx // will there be enough after we cross page for vectors?
+ ja LLoopOverBytes // yes
+ addl %eax,%ecx // no, restore total length remaining
+ jmp LShortLoop // compare rest byte-by-byte (%ecx != 0)
+
+
+// Loop over 16-byte chunks.
+// %esi = LHS ptr
+// %edi = RHS ptr
+// %ecx = length remaining
+// %edx = chunk count
+
+ .align 4,0x90 // align inner loops to optimize I-fetch
+LLoopOverChunks:
+ movdqu (%esi),%xmm0 // get LHS
+ movdqu (%edi),%xmm1 // get RHS
+ addl $16,%esi
+ pcmpeqb %xmm1,%xmm0 // compare LHS to RHS
+ addl $16,%edi
+ pmovmskb %xmm0,%eax // collect comparison result bits (1 if equal)
+ subl $16,%ecx // adjust length remaining
+ xorl $0xFFFF,%eax // all equal?
+ jne LDifferent // no, we found differing bytes
+ dec %edx // more to go?
+ jnz LLoopOverChunks
+
+ cmpl $(kShort),%ecx // a lot more to compare?
+ jbe LShort // no
+ jmp LNotShort // compute distance to next page crossing etc
+
+
+// Found a difference.
+// %esi = LHS ptr, already advanced by 16
+// %edi = RHS ptr, already advanced by 16
+// %eax = complemented compare vector (ie, 0 == equal)
+
+LDifferent:
+ bsf %eax,%edx // which byte differed?
+ subl $16,%esi // point to byte 0 while we wait for bit scan
+ subl $16,%edi
+ movzb (%esi,%edx),%eax // get LHS byte
+ movzb (%edi,%edx),%ecx // get RHS byte
+ subl %ecx,%eax // compute difference (ie, return value)
+ popl %edi
+ popl %esi
+ ret
--- /dev/null
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * The contents of this file constitute Original Code as defined in and
+ * are subject to the Apple Public Source License Version 1.1 (the
+ * "License"). You may not use this file except in compliance with the
+ * License. Please obtain a copy of the License at
+ * http://www.apple.com/publicsource and read it before using this file.
+ *
+ * This Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#include <machine/cpu_capabilities.h>
+
+
+/* This file contains the following functions:
+ *
+ * void *memset(void *b, int c, size_t len);
+ * void memset_pattern4(void *b, const void *c4, size_t len);
+ * void memset_pattern8(void *b, const void *c8, size_t len);
+ * void memset_pattern16(void *b, const void *c16, size_t len);
+ *
+ * Calls of memset() with c==0 are routed to the bzero() routine. Most of the
+ * others go to _COMM_PAGE_MEMSET_PATTERN, which is entered as follows:
+ * %edi = ptr to memory to set (aligned)
+ * %edx = length (which can be short, though we bias in favor of long operands)
+ * %xmm0 = the pattern to store
+ * Return conditions:
+ * %eax, %edi, %esi, %ecx, and %edx all trashed
+ *
+ * NB: we avoid "stos" family of instructions (stosl, stosb), as they are very slow
+ * on P4s and probably other processors.
+ */
+
+ #define kShort 255 // for nonzero memset(), too short for commpage
+
+
+ .text
+ .globl _memset
+ .align 2
+_memset: // void *memset(void *b, int c, size_t len);
+ movl 8(%esp),%eax // get 1-byte pattern
+ movl 12(%esp),%edx // get length
+ andl $0xFF,%eax // (c==0) ?
+ jnz LNonzero // not a bzero
+
+ movl $(_COMM_PAGE_BZERO),%eax// map memset(p,0,n) into bzero(p,n)
+ movl %edx,8(%esp) // put count where bzero() expects it
+ jmp %eax // enter commpage
+
+
+ // Handle memset of a nonzero value.
+
+LNonzero:
+ pushl %edi // save a few nonvolatiles
+ pushl %esi
+ movl %eax,%esi // replicate byte in %al into all four bytes
+ movl 12(%esp),%edi // point to operand
+ shll $8,%esi
+ orl %esi,%eax
+ movl %eax,%esi
+ shll $16,%esi
+ orl %esi,%eax // now %eax has "c" in all 4 bytes
+ cmpl $(kShort),%edx // is operand too short for SSE?
+ ja LCallCommpage // no
+
+// Nonzero memset() too short to call commpage.
+// %eax = replicated 4-byte pattern
+// %edi = ptr
+// %edx = length (<= kShort)
+
+ cmpl $16,%edx // long enough to word align?
+ jge 3f // yes
+ test %edx,%edx // length==0?
+ jz 6f
+1:
+ movb %al,(%edi) // pack in a byte
+ inc %edi
+ dec %edx
+ jnz 1b
+ jmp 6f
+2:
+ movb %al,(%edi) // pack in a byte
+ inc %edi
+ dec %edx
+3:
+ test $3,%edi // is ptr doubleword aligned?
+ jnz 2b // no
+ movl %edx,%ecx // copy length
+ shrl $2,%edx // #doublewords to store
+4:
+ movl %eax,(%edi) // store aligned doubleword
+ addl $4,%edi
+ dec %edx
+ jnz 4b
+ andl $3,%ecx // any leftover bytes?
+ jz 6f // no
+5:
+ movb %al,(%edi) // pack in a byte
+ inc %edi
+ dec %ecx
+ jnz 5b
+6:
+ movl 12(%esp),%eax // get return value (ie, original ptr)
+ popl %esi
+ popl %edi
+ ret
+
+// Nonzero memset() is long enough to call commpage.
+// %eax = replicated 4-byte pattern
+// %edi = ptr
+// %edx = length (> kShort)
+
+LCallCommpage:
+ movd %eax,%xmm0 // move %eax to low 4 bytes of %xmm0
+ pshufd $(0x00),%xmm0,%xmm0 // replicate across the vector
+ movl %edi,%ecx // copy dest ptr
+ negl %ecx
+ andl $15,%ecx // get #bytes to align ptr
+ jz 2f // skip if already aligned
+ subl %ecx,%edx // decrement length
+1:
+ movb %al,(%edi) // pack in a byte
+ inc %edi
+ dec %ecx
+ jnz 1b
+2: // ptr aligned, length long enough to justify
+ movl $(_COMM_PAGE_MEMSET_PATTERN),%eax
+ call %eax // call commpage to do the heavy lifting
+ movl 12(%esp),%eax // get return value (ie, original ptr)
+ popl %esi
+ popl %edi
+ ret
+
+
+// Handle memset of a 16-byte pattern.
+
+ .globl _memset_pattern16
+ .align 2, 0x90
+_memset_pattern16: // void memset_pattern16(void *b, const void *c16, size_t len);
+ pushl %edi
+ pushl %esi
+ movl 20(%esp),%edx // get length
+ movl 16(%esp),%esi // get ptr to 16-byte pattern
+ movl 12(%esp),%edi // point to operand
+ movdqu (%esi),%xmm0 // load the pattern
+ jmp LAlignPtr
+
+
+// Handle memset of an 8-byte pattern.
+
+ .globl _memset_pattern8
+ .align 2, 0x90
+_memset_pattern8: // void memset_pattern8(void *b, const void *c8, size_t len);
+ pushl %edi
+ pushl %esi
+ movl 20(%esp),%edx // get length
+ movl 16(%esp),%esi // get ptr to 8-byte pattern
+ movl 12(%esp),%edi // point to operand
+ movq (%esi),%xmm0 // load pattern into low 8 bytes
+ punpcklqdq %xmm0,%xmm0 // replicate into all 16
+ jmp LAlignPtr
+
+// Handle memset of a 4-byte pattern.
+
+ .globl _memset_pattern4
+ .align 2, 0x90
+_memset_pattern4: // void memset_pattern4(void *b, const void *c4, size_t len);
+ pushl %edi
+ pushl %esi
+ movl 20(%esp),%edx // get length
+ movl 16(%esp),%esi // get ptr to 4-byte pattern
+ movl 12(%esp),%edi // point to operand
+ movd (%esi),%xmm0 // load pattern into low 4 bytes
+ pshufd $(0x00),%xmm0,%xmm0 // replicate the 4 bytes across the vector
+
+
+// Align ptr if necessary. We must rotate the pattern right for each byte we
+// store while aligning the ptr. Since there is no rotate instruction in SSE3,
+// we have to synthesize the rotates.
+// %edi = ptr
+// %edx = length
+// %xmm0 = pattern
+
+LAlignPtr: // NB: can drop down to here!
+ cmpl $100,%edx // long enough to bother aligning ptr?
+ movl %edi,%ecx // copy ptr
+ jb LReady // not long enough
+ negl %ecx
+ andl $15,%ecx // get #bytes to align ptr
+ jz LReady // already aligned
+ subl %ecx,%edx // adjust length
+
+ test $1,%cl // 1-byte store required?
+ movd %xmm0,%eax // get 4 low bytes in %eax
+ jz 2f // no
+ movdqa %xmm0,%xmm1 // copy pattern so we can shift in both directions
+ movb %al,(%edi) // pack in the low-order byte
+ psrldq $1,%xmm0 // shift pattern right 1 byte
+ inc %edi
+ pslldq $15,%xmm1 // shift pattern left 15 bytes
+ shrl $8,%eax // in case 2-byte store is required
+ por %xmm1,%xmm0 // complete right rotate of pattern by 1 byte
+2:
+ test $2,%cl // 2-byte store required?
+ jz 4f // no
+ psrldq $2,%xmm0 // shift pattern down 2 bytes
+ movw %ax,(%edi) // pack in next two bytes
+ pinsrw $7,%eax,%xmm0 // insert low word of %eax into high word of %xmm0
+ addl $2,%edi // adjust ptr
+4:
+ test $4,%cl // 4-byte store required?
+ jz 8f // no
+ movd %xmm0,(%edi) // store low 4 bytes of %xmm0
+ pshufd $(0x39),%xmm0,%xmm0 // rotate %xmm0 right 4 bytes (mask == 00 11 10 01)
+ addl $4,%edi // adjust ptr
+8:
+ test $8,%cl // 8-byte store required?
+ jz LReady // no
+ movq %xmm0,(%edi) // store low 8 bytes of %xmm0
+ pshufd $(0x4e),%xmm0,%xmm0 // rotate %xmm0 right 8 bytes (mask == 01 00 11 10)
+ addl $8,%edi // adjust ptr
+
+// Ptr is aligned if practical, we're ready to call commpage to do the heavy lifting.
+
+LReady:
+ movl $(_COMM_PAGE_MEMSET_PATTERN),%eax
+ call %eax // call commpage to do the heavy lifting
+ popl %esi
+ popl %edi
+ ret
/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
*
* @APPLE_LICENSE_HEADER_END@
*/
-.text
-.globl _strcmp
-_strcmp:
- movl 0x04(%esp),%eax
- movl 0x08(%esp),%edx
- jmp L2 /* Jump into the loop! */
-
- .align 2,0x90
-L1: incl %eax
- incl %edx
-L2: movb (%eax),%cl
- testb %cl,%cl /* null terminator??? */
- jz L3
- cmpb %cl,(%edx) /* chars match??? */
- jne L3
- incl %eax
- incl %edx
- movb (%eax),%cl
- testb %cl,%cl
- jz L3
- cmpb %cl,(%edx)
- jne L3
- incl %eax
- incl %edx
- movb (%eax),%cl
- testb %cl,%cl
- jz L3
- cmpb %cl,(%edx)
- jne L3
- incl %eax
- incl %edx
- movb (%eax),%cl
- testb %cl,%cl
- jz L3
- cmpb %cl,(%edx)
- jne L3
- incl %eax
- incl %edx
- movb (%eax),%cl
- testb %cl,%cl
- jz L3
- cmpb %cl,(%edx)
- jne L3
- incl %eax
- incl %edx
- movb (%eax),%cl
- testb %cl,%cl
- jz L3
- cmpb %cl,(%edx)
- jne L3
- incl %eax
- incl %edx
- movb (%eax),%cl
- testb %cl,%cl
- jz L3
- cmpb %cl,(%edx)
- jne L3
- incl %eax
- incl %edx
- movb (%eax),%cl
- testb %cl,%cl
- jz L3
- cmpb %cl,(%edx)
- je L1
- .align 2, 0x90
-L3: movzbl (%eax),%eax /* unsigned comparison */
- movzbl (%edx),%edx
- subl %edx,%eax
- ret
+
+
+// ***************
+// * S T R C M P *
+// ***************
+//
+// int strcmp(const char *s1, const char *s2);
+//
+// We optimize the compare by doing it in parallel, using SSE. This introduces
+// a complication: if we blindly did vector loads from both sides until
+// finding a difference (or 0), we might get a spurious page fault by
+// reading bytes past the difference. To avoid this, we never do a load
+// that crosses a page boundary.
+
+ .text
+ .globl _strcmp
+
+ .align 4
+_strcmp: // int strcmp(const char *s1,const char *s2);
+ pushl %esi
+ pushl %edi
+ movl 12(%esp),%esi // get LHS ptr
+ movl 16(%esp),%edi // get RHS ptr
+
+
+// In order to avoid spurious page faults, we loop over:
+//
+// min( bytes_in_LHS_page, bytes_in_RHS_page) >> 4
+//
+// 16-byte chunks. When we near a page end, we have to revert to a byte-by-byte
+// comparison until reaching the next page, then resume the vector comparison.
+// %esi = LHS ptr
+// %edi = RHS ptr
+
+LNextChunk:
+ movl %esi,%eax // copy ptrs
+ movl %edi,%edx
+ andl $4095,%eax // mask down to page offsets
+ andl $4095,%edx
+ cmpl %eax,%edx // which is bigger?
+ cmova %edx,%eax // %eax = max(LHS offset, RHS offset);
+ movl $4096,%edx
+ subl %eax,%edx // get #bytes to next page crossing
+ movl %edx,%eax
+ shrl $4,%edx // get #chunks till end of operand or page
+ jnz LLoopOverChunks // enter vector loop
+ movl %eax,%edx // no chunks...
+ jmp LLoopOverBytes // ...so loop over bytes until page end
+
+
+// Loop over bytes.
+// %esi = LHS ptr
+// %edi = RHS ptr
+// %edx = byte count
+
+ .align 4,0x90 // align inner loops to optimize I-fetch
+LLoopOverBytes:
+ movzb (%esi),%eax // get LHS byte
+ movzb (%edi),%ecx // get RHS byte
+ inc %esi
+ inc %edi
+ testl %eax,%eax // 0?
+ jz LExit0 // yes, we're done
+ subl %ecx,%eax // compare them
+ jnz LExit // done if not equal
+ dec %edx // more to go?
+ jnz LLoopOverBytes
+
+ jmp LNextChunk // we've come to end of page
+
+
+// Loop over 16-byte chunks.
+// %esi = LHS ptr
+// %edi = RHS ptr
+// %edx = chunk count
+
+ .align 4,0x90 // align inner loops to optimize I-fetch
+LLoopOverChunks:
+ movdqu (%esi),%xmm1 // get LHS
+ movdqu (%edi),%xmm2 // get RHS
+ pxor %xmm0,%xmm0 // get some 0s in the shadow of the loads
+ addl $16,%esi
+ pcmpeqb %xmm1,%xmm2 // compare LHS to RHS
+ pcmpeqb %xmm1,%xmm0 // compare LHS to 0s
+ addl $16,%edi
+ pmovmskb %xmm2,%eax // get result mask for comparison of LHS and RHS
+ pmovmskb %xmm0,%ecx // get result mask for 0 check
+ xorl $0xFFFF,%eax // complement compare mask so 1 means "not equal"
+ orl %ecx,%eax // combine the masks and check for 1-bits
+ jnz LFoundDiffOr0 // we found differing bytes or a 0-byte
+ dec %edx // more to go?
+ jnz LLoopOverChunks
+
+ jmp LNextChunk // compare up to next page boundary
+
+
+// Found a zero and/or a difference in vector compare.
+// %esi = LHS ptr, already advanced by 16
+// %edi = RHS ptr, already advanced by 16
+// %eax = bit n set if bytes n differed or were 0
+
+LFoundDiffOr0:
+ bsf %eax,%edx // which byte differed or was 0?
+ subl $16,%esi // point to start of vectors while we wait for bit scan
+ subl $16,%edi
+ movzb (%esi,%edx),%eax // get LHS byte
+ movzb (%edi,%edx),%ecx // get RHS byte
+ subl %ecx,%eax // compute difference (ie, return value)
+ popl %edi
+ popl %esi
+ ret
+
+
+// Found a zero and/or difference in byte loop.
+// %eax = LHS byte
+// %ecx = RHS byte
+
+LExit0:
+ subl %ecx,%eax // compute difference (ie, return value)
+LExit: // here with difference already in %eax
+ popl %edi
+ popl %esi
+ ret
--- /dev/null
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+
+// ***************
+// * S T R C P Y *
+// ***************
+//
+// char *strcpy(const char *dst, const char *src);
+//
+// We optimize the move by doing it vector parallel. This introduces
+// a complication: if we blindly did vector load/stores until finding
+// a 0, we might get a spurious page fault by touching bytes past it.
+// To avoid this, we never do a load that crosses a page boundary,
+// and never store a byte we don't have to.
+//
+// We align the destination, because unaligned vector stores are slow.
+
+ .text
+ .globl _strcpy
+
+ .align 4
+_strcpy: // char *strcpy(const char *dst, const char *src);
+ pushl %edi
+ movl 8(%esp),%edi // get dest ptr
+ movl 12(%esp),%ecx // get source ptr
+ movl %edi,%edx // copy dest ptr
+ negl %edx
+ andl $15,%edx // how many bytes to align dest ptr?
+ jnz LLoopOverBytes // not aligned, so go do so
+
+
+// In order to avoid spurious page faults, we loop until nearing the source page
+// end. Then we revert to a byte-by-byte loop for 16 bytes until the page is crossed,
+// then resume the vector loop.
+// %ecx = source ptr (unaligned)
+// %edi = dest ptr (aligned)
+
+LNextChunk:
+ movl %ecx,%eax // copy source ptr
+ movl $4096,%edx
+ andl $4095,%eax // get offset into source page
+ subl %eax,%edx // get #bytes remaining in source page
+ shrl $4,%edx // get #chunks till end of page
+ jnz LLoopOverChunks // enter vector loop
+ movl $16,%edx // move 16 bytes to cross page but keep dest aligned
+ jmp LLoopOverBytes
+
+
+// Loop over bytes.
+// %ecx = source ptr
+// %edi = dest ptr
+// %edx = byte count
+
+ .align 4,0x90 // align inner loops to optimize I-fetch
+LLoopOverBytes:
+ movzb (%ecx),%eax // get source byte
+ inc %ecx
+ movb %al,(%edi) // pack into dest
+ inc %edi
+ testl %eax,%eax // 0?
+ jz LDone // yes, we're done
+ dec %edx // more to go?
+ jnz LLoopOverBytes
+
+ jmp LNextChunk // we've come to end of page
+
+
+// Loop over 16-byte chunks.
+// %ecx = source ptr (unaligned)
+// %edi = dest ptr (aligned)
+// %edx = chunk count
+
+ .align 4,0x90 // align inner loops to optimize I-fetch
+LLoopOverChunks:
+ movdqu (%ecx),%xmm1 // get source
+ pxor %xmm0,%xmm0 // get some 0s
+ addl $16,%ecx
+ pcmpeqb %xmm1,%xmm0 // compare source to 0s
+ pmovmskb %xmm0,%eax // get result mask for 0 check
+ testl %eax,%eax // any 0s?
+ jnz LFound0 // yes, exit loop
+ movdqa %xmm1,(%edi) // no 0s so do aligned store into destination
+ addl $16,%edi
+ dec %edx // more to go?
+ jnz LLoopOverChunks
+
+ movl $16,%edx // move 16 bytes
+ jmp LLoopOverBytes // cross page but keep dest aligned
+
+
+// Found a zero in the vector. Figure out where it is, and store the bytes
+// up to it.
+// %edi = dest ptr (aligned)
+// %eax = result mask
+// %xmm1 = source vector
+
+LFound0:
+ bsf %eax,%edx // find first 0
+ inc %edx // we need to store the 0 too
+ test $16,%dl // was 0 last byte?
+ jz 8f // no
+ movdqa %xmm1,(%edi) // yes, store entire vector
+ jmp LDone
+8:
+ test $8,%dl // 8-byte store required?
+ jz 4f // no
+ movq %xmm1,(%edi) // pack in 8 low bytes
+ psrldq $8,%xmm1 // then shift vector down 8 bytes
+ addl $8,%edi
+4:
+ test $4,%dl // 4-byte store required?
+ jz 3f // no
+ movd %xmm1,(%edi) // pack in 4 low bytes
+ psrldq $4,%xmm1 // then shift vector down 4 bytes
+ addl $4,%edi
+3:
+ andl $3,%edx // more to go?
+ jz LDone // no
+ movd %xmm1,%eax // move remainders out of vector into %eax
+1: // loop on up to three bytes
+ movb %al,(%edi) // pack in next byte
+ shrl $8,%eax // shift next byte into position
+ inc %edi
+ dec %edx
+ jnz 1b
+
+LDone:
+ movl 8(%esp),%eax // original dest ptr is return value
+ popl %edi
+ ret
--- /dev/null
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * The contents of this file constitute Original Code as defined in and
+ * are subject to the Apple Public Source License Version 1.1 (the
+ * "License"). You may not use this file except in compliance with the
+ * License. Please obtain a copy of the License at
+ * http://www.apple.com/publicsource and read it before using this file.
+ *
+ * This Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ * Strlen, for processors with SSE3.
+ *
+ * Note that all memory references must be aligned, in order to avoid spurious
+ * page faults. Thus we have to load the aligned 16-byte chunk containing the
+ * first byte of the operand, then mask out false 0s that may occur before the
+ * first byte.
+ *
+ * We favor the fall-through (ie, short operand) path.
+ */
+
+ .text
+ .globl _strlen
+ .align 4, 0x90
+_strlen: // size_t strlen(char *b);
+ movl 4(%esp),%edx // get ptr to string
+ pxor %xmm0,%xmm0 // zero %xmm0
+ movl %edx,%ecx // copy ptr
+ andl $(-16),%edx // 16-byte align ptr
+ orl $(-1),%eax
+ pcmpeqb (%edx),%xmm0 // check whole qw for 0s
+ andl $15,%ecx // get #bytes in aligned dq before operand
+ shl %cl,%eax // create mask for the bytes of aligned dq in operand
+ pmovmskb %xmm0,%ecx // collect mask of 0-bytes
+ andl %eax,%ecx // mask out any 0s that occur before 1st byte
+ jz LEnterLoop // no 0-bytes (ie, 1-bits), so enter by-16 loop
+
+// We've found a 0-byte.
+// %edx = aligned address of 16-byte block containing the terminating 0-byte
+// %ecx = compare bit vector
+
+LFoundIt:
+ bsf %ecx,%eax // find first 1-bit (ie, first 0-byte)
+ movl 4(%esp),%ecx // recover ptr to 1st byte in string
+ addl %edx,%eax // get address of the 0-byte
+ subl %ecx,%eax // subtract address of 1st byte to get string length
+ ret
+
+// Loop over aligned 16-byte blocks:
+// %edx = address of previous block
+
+LEnterLoop:
+ pxor %xmm0,%xmm0 // get some 0-bytes
+ addl $16,%edx // advance ptr
+LLoop:
+ movdqa (%edx),%xmm1 // get next chunk
+ addl $16,%edx
+ pcmpeqb %xmm0,%xmm1 // check for 0s
+ pmovmskb %xmm1,%ecx // collect mask of 0-bytes
+ test %ecx,%ecx // any 0-bytes?
+ jz LLoop // no 0-bytes, so get next dq
+
+ subl $16,%edx // back up ptr
+ jmp LFoundIt
+
+
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+
+// *****************
+// * S T R N C M P *
+// *****************
+//
+// int strncmp(const char *s1, const char *s2, size_t len);
+//
+// We optimize the compare by doing it vector parallel. This introduces
+// a complication: if we blindly did vector loads from both sides until
+// finding a difference (or 0), we might get a spurious page fault by
+// reading bytes past the difference. To avoid this, we never do a load
+// that crosses a page boundary.
+
+#define kShort 20 // too short for vectors (must be >16)
+
+ .text
+ .globl _strncmp
+
+ .align 4
+_strncmp: // int strncmp(const char *s1, const char *s2, size_t len);
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%ecx // get length
+ movl 12(%esp),%esi // get LHS ptr
+ movl 16(%esp),%edi // get RHS ptr
+ push %ebx
+ cmpl $(kShort),%ecx // worth accelerating?
+ ja LNotShort // yes
+
+
+// Too short to bother with parallel compares. Loop over bytes.
+// %esi = LHS ptr
+// %edi = RHS ptr
+// %ecx = length (<= kShort)
+
+LShort:
+ testl %ecx,%ecx // 0-length?
+ jnz LShortLoop // no
+ jmp LReturn0 // yes, return 0
+ .align 4,0x90 // align inner loops to optimize I-fetch
+LShortLoop: // loop over bytes
+ movzb (%esi),%eax // get LHS byte
+ movzb (%edi),%ebx // get RHS byte
+ incl %esi
+ incl %edi
+ testl %eax,%eax // LHS==0 ?
+ jz LNotEqual // yes, this terminates comparison
+ subl %ebx,%eax // compare them
+ jnz LExit // done if not equal
+ decl %ecx // decrement length
+ jnz LShortLoop
+LReturn0:
+ xorl %eax,%eax // all bytes equal, so return 0
+LExit: // return value is in %eax
+ popl %ebx
+ popl %edi
+ popl %esi
+ ret
+
+LNotEqual: // LHS in eax, RHS in ebx
+ subl %ebx,%eax // generate return value (nonzero)
+ popl %ebx
+ popl %edi
+ popl %esi
+ ret
+
+
+// Loop over bytes until we reach end of a page.
+// %esi = LHS ptr
+// %edi = RHS ptr
+// %ecx = length remaining after end of loop (ie, already adjusted)
+// %edx = #bytes until next page (1..15)
+
+ .align 4,0x90 // align inner loops to optimize I-fetch
+LLoopOverBytes:
+ movzb (%esi),%eax // get LHS byte
+ movzb (%edi),%ebx // get RHS byte
+ inc %esi
+ inc %edi
+ testl %eax,%eax // LHS==0 ?
+ jz LNotEqual // yes, this terminates comparison
+ subl %ebx,%eax // compare them
+ jnz LExit // done if not equal
+ dec %edx // more to go?
+ jnz LLoopOverBytes
+
+
+// Long enough to justify overhead of setting up vector compares. In order to
+// avoid spurious page faults, we loop over:
+//
+// min( length, bytes_in_LHS_page, bytes_in_RHS_page) >> 4
+//
+// 16-byte chunks. When we near a page end, we have to revert to a byte-by-byte
+// comparison until reaching the next page, then resume the vector comparison.
+// %esi = LHS ptr
+// %edi = RHS ptr
+// %ecx = length (> kShort)
+
+LNotShort:
+ movl %esi,%eax // copy ptrs
+ movl %edi,%edx
+ andl $4095,%eax // mask down to page offsets
+ andl $4095,%edx
+ cmpl %eax,%edx // which is bigger?
+ cmova %edx,%eax // %eax = max(LHS offset, RHS offset);
+ movl $4096,%edx
+ subl %eax,%edx // get #bytes to next page crossing
+ cmpl %ecx,%edx // will operand run out first?
+ cmova %ecx,%edx // get min(length remaining, bytes to page end)
+ movl %edx,%eax
+ shrl $4,%edx // get #chunks till end of operand or page
+ jnz LLoopOverChunks // enter vector loop
+
+// Too near page end for vectors.
+
+ subl %eax,%ecx // adjust length remaining
+ movl %eax,%edx // %edx <- #bytes to page end
+ cmpl $(kShort),%ecx // will there be enough after we cross page for vectors?
+ ja LLoopOverBytes // yes
+ addl %eax,%ecx // no, restore total length remaining
+ jmp LShortLoop // compare rest byte-by-byte (%ecx != 0)
+
+
+// Loop over 16-byte chunks.
+// %esi = LHS ptr
+// %edi = RHS ptr
+// %ecx = length remaining
+// %edx = chunk count
+
+ .align 4,0x90 // align inner loops to optimize I-fetch
+LLoopOverChunks:
+ movdqu (%esi),%xmm1 // get LHS
+ movdqu (%edi),%xmm2 // get RHS
+ pxor %xmm0,%xmm0 // get some 0s in the shadow of the loads
+ addl $16,%esi
+ pcmpeqb %xmm1,%xmm2 // compare LHS to RHS
+ pcmpeqb %xmm1,%xmm0 // compare LHS to 0s
+ addl $16,%edi
+ pmovmskb %xmm2,%eax // get result mask for comparison of LHS and RHS
+ pmovmskb %xmm0,%ebx // get result mask for 0 check
+ subl $16,%ecx // decrement length remaining
+ xorl $0xFFFF,%eax // complement compare mask so 1 means "not equal"
+ orl %ebx,%eax // combine the masks and check for 1-bits
+ jnz LFoundDiffOr0 // we found differing bytes or a 0-byte
+ dec %edx // more to go?
+ jnz LLoopOverChunks // yes
+
+ cmpl $(kShort),%ecx // a lot more to compare?
+ jbe LShort // no
+ jmp LNotShort // compute distance to next page crossing etc
+
+
+// Found a zero and/or a difference in vector compare.
+// %esi = LHS ptr, already advanced by 16
+// %edi = RHS ptr, already advanced by 16
+// %eax = bit n set if bytes n differed or were 0
+
+LFoundDiffOr0:
+ bsf %eax,%edx // which byte differed or was 0?
+ subl $16,%esi // point to start of vectors while we wait for bit scan
+ subl $16,%edi
+ movzb (%esi,%edx),%eax // get LHS byte
+ movzb (%edi,%edx),%ecx // get RHS byte
+ popl %ebx
+ popl %edi
+ subl %ecx,%eax // compute difference (ie, return value)
+ popl %esi
+ ret
--- /dev/null
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#include <machine/cpu_capabilities.h>
+
+
+// *****************
+// * S T R N C P Y *
+// *****************
+//
+// char *strncpy(const char *dst, const char *src, size_t n);
+//
+// We optimize the move by doing it vector parallel. This introduces
+// a complication: if we blindly did vector load/stores until finding
+// a 0, we might get a spurious page fault by touching bytes past it.
+// To avoid this, we never do a load that crosses a page boundary,
+// and never store a byte we don't have to.
+//
+// We align the destination, because unaligned vector stores are slow.
+//
+// Recall that strncpy() zero fills the remainder of the dest buffer,
+// and does not terminate the string if it's length is greater than or
+// equal to n.
+
+#define kShort 31 // too short to bother with vector loop
+
+ .text
+ .globl _strncpy
+
+ .align 4
+_strncpy: // char *strncpy(const char *dst, const char *src, size_t n);
+ pushl %edi
+ pushl %esi
+ movl 12(%esp),%edi // get dest ptr
+ movl 16(%esp),%esi // get source ptr
+ movl 20(%esp),%ecx // get length
+ movl %edi,%edx // copy dest ptr
+ negl %edx
+ andl $15,%edx // how many bytes to align dest ptr?
+ jnz LCheckShortCopy // align destination first
+
+
+// In order to avoid spurious page faults, we loop until nearing the source page
+// end. Then we revert to a byte-by-byte loop for 16 bytes until the page is crossed,
+// then resume the vector loop.
+// %esi = source ptr (unaligned)
+// %edi = dest ptr (aligned)
+// %ecx = buffer length remaining
+
+LNextChunk: // NB: can drop down to here
+ movl %esi,%eax // copy source ptr
+ movl $4096,%edx
+ andl $4095,%eax // get offset into source page
+ subl %eax,%edx // get #bytes remaining in source page
+ cmpl %ecx,%edx // will buffer run out before the page end?
+ cmova %ecx,%edx // get min(length remaining, bytes to page end)
+ shrl $4,%edx // get #chunks till end of page
+ jnz LLoopOverChunks // enter vector loop
+
+// We can't use the chunk loop yet. Check for short and empty buffers, then use byte loop.
+
+LCrossPage: // if buffer is large enough, cross source page
+ movl $16,%edx // move 16 bytes to cross page but keep dest aligned
+LCheckShortCopy: // we propose to copy %edx bytes in byte loop
+ cmpl $(kShort),%ecx // much left?
+ ja LLoopOverBytes // yes, loop over bytes then more chunks
+ movl %ecx,%edx // no, use the byte loop for everything
+ testl %ecx,%ecx // have we filled buffer?
+ jnz LLoopOverBytes // no
+ jmp LDone
+
+
+// Loop over bytes.
+// %esi = source ptr
+// %edi = dest ptr
+// %ecx = buffer length remaining
+// %edx = count of bytes to loop over (<= buffer length)
+
+ .align 4,0x90 // align inner loops to optimize I-fetch
+LLoopOverBytes:
+ movzb (%esi),%eax // get source byte
+ inc %esi
+ dec %ecx // decrement length
+ movb %al,(%edi) // pack into dest
+ inc %edi
+ testl %eax,%eax // 0?
+ jz LZeroBuffer // yes, we're done copying string
+ dec %edx // more to go?
+ jnz LLoopOverBytes
+
+ testl %ecx,%ecx // at end of buffer?
+ jnz LNextChunk // no, xfer chunks
+ jmp LDone // yes
+
+
+// Loop over 16-byte chunks.
+// %esi = source ptr (unaligned)
+// %edi = dest ptr (aligned)
+// %ecx = buffer length remaining
+// %edx = chunk count
+
+ .align 4,0x90 // align inner loops to optimize I-fetch
+LLoopOverChunks:
+ movdqu (%esi),%xmm1 // get source
+ pxor %xmm0,%xmm0 // get some 0s
+ addl $16,%esi
+ pcmpeqb %xmm1,%xmm0 // compare source to 0s
+ pmovmskb %xmm0,%eax // get result mask for 0 check
+ testl %eax,%eax // any 0s?
+ jnz LFound0 // yes, exit loop
+ movdqa %xmm1,(%edi) // no 0s so do aligned store into destination
+ addl $16,%edi
+ subl $16,%ecx // decrement length remaining
+ dec %edx // more to go?
+ jnz LLoopOverChunks
+
+ jmp LCrossPage // cross page but keep dest aligned
+
+
+// Found a zero in the vector. Figure out where it is, and store the bytes
+// up to it. It is possible that we should check to be sure (%ecx >= 16), and
+// just do an aligned store of %xmm1 if so. But if we did, we'd be doing byte
+// stores into the same double quadword in bzero(), which might hit a hazard.
+// Experimentation needed.
+// %edi = dest ptr (aligned)
+// %eax = result mask
+// %ecx = buffer length remaining
+// %xmm1 = source vector
+
+LFound0:
+ bsf %eax,%edx // find first 0
+ subl %edx,%ecx // decrement remaining buffer length
+ test $8,%dl // 8-byte store required?
+ jz 4f // no
+ movq %xmm1,(%edi) // pack in 8 low bytes
+ psrldq $8,%xmm1 // then shift vector down 8 bytes
+ addl $8,%edi
+4:
+ test $4,%dl // 4-byte store required?
+ jz 3f // no
+ movd %xmm1,(%edi) // pack in 4 low bytes
+ psrldq $4,%xmm1 // then shift vector down 4 bytes
+ addl $4,%edi
+3:
+ andl $3,%edx // more to go?
+ jz LZeroBuffer // no
+ movd %xmm1,%eax // move remainders out of vector into %eax
+1: // loop on up to three bytes
+ movb %al,(%edi) // pack in next byte
+ shrl $8,%eax // shift next byte into position
+ inc %edi
+ dec %edx
+ jnz 1b
+
+// We've copied the string. Now zero the rest of the buffer, using commpage bzero().
+// %edi = dest ptr
+// %ecx = buffer length remaining
+
+LZeroBuffer:
+ pushl %ecx // remaining buffer size
+ pushl %edi // ptr to 1st unstored byte
+ movl $(_COMM_PAGE_BZERO),%eax
+ call %eax
+ addl $8,%esp // pop off the arguments
+
+LDone:
+ movl 12(%esp),%eax // original dest ptr is return value
+ popl %esi
+ popl %edi
+ ret
__pthread_canceled.s \
__pthread_markcancel.s \
__semwait_signal.s \
+ __sysenter_trap.s \
_setjmp.s \
_setlogin.s \
_sysctl.s \
chflags.s \
chmod.s \
chown.s \
+ commpage.c \
chroot.s \
close.s \
connect.s \
getsockopt.s \
getuid.s \
getxattr.s \
+ i386_gettimeofday.s \
+ i386_get_ldt.s \
+ i386_set_ldt.s \
ioctl.s \
issetugid.s \
kevent.s \
DECLARE(_OSAtomicTestAndSet)
movl 4(%esp), %eax
movl 8(%esp), %edx
+ movl %eax, %ecx
+ andl $-8, %ecx
+ notl %eax
+ andl $7, %eax
+ orl %ecx, %eax
call *_COMM_PAGE_BTS
setc %al
ret
DECLARE(_OSAtomicTestAndClear)
movl 4(%esp), %eax
movl 8(%esp), %edx
+ movl %eax, %ecx
+ andl $-8, %ecx
+ notl %eax
+ andl $7, %eax
+ orl %ecx, %eax
call *_COMM_PAGE_BTC
setc %al
ret
/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2005 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <architecture/i386/asm_help.h>
#include <mach/i386/syscall_sw.h>
+/*
+ * We have two entry points. int's is used for syscalls which need to preserve
+ * %ecx across the call, or return a 64-bit value in %eax:%edx. sysenter is used
+ * for the majority of syscalls which just return a value in %eax.
+ */
-#define UNIX_SYSCALL_TRAP lcall $0x2b, $0
-#define MACHDEP_SYSCALL_TRAP lcall $0x7, $0
-
+#define UNIX_SYSCALL_SYSENTER SYSENTER_PAD call __sysenter_trap
/*
* This is the same as UNIX_SYSCALL, but it can call an alternate error
.globl error_ret ;\
LEAF(_##name, 0) ;\
movl $ SYS_##name, %eax ;\
- UNIX_SYSCALL_TRAP ;\
+ UNIX_SYSCALL_SYSENTER ;\
jnb 2f ;\
BRANCH_EXTERN(error_ret) ;\
2:
#define UNIX_SYSCALL(name, nargs) \
.globl cerror ;\
+LEAF(_##name, 0) ;\
+ movl $ SYS_##name, %eax ;\
+ UNIX_SYSCALL_SYSENTER ;\
+ jnb 2f ;\
+ BRANCH_EXTERN(cerror) ;\
+2:
+
+#define UNIX_SYSCALL_INT(name, nargs) \
+ .globl cerror ;\
LEAF(_##name, 0) ;\
movl $ SYS_##name, %eax ;\
UNIX_SYSCALL_TRAP ;\
2:
#define UNIX_SYSCALL_NONAME(name, nargs) \
+ .globl cerror ;\
+ movl $ SYS_##name, %eax ;\
+ UNIX_SYSCALL_SYSENTER ;\
+ jnb 2f ;\
+ BRANCH_EXTERN(cerror) ;\
+2:
+
+#define UNIX_SYSCALL_INT_NONAME(name, nargs) \
.globl cerror ;\
movl $ SYS_##name, %eax ;\
UNIX_SYSCALL_TRAP ;\
--- /dev/null
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+.text
+.align 2,0x90
+.private_extern __sysenter_trap
+__sysenter_trap:
+ popl %edx
+ movl %esp, %ecx
+ sysenter
#define JB_FS 64
#define JB_GS 68
+#define SAVE_SEG_REGS 1
LEAF(__setjmp, 0)
movl 4(%esp), %ecx // jmp_buf (struct sigcontext *)
#if SAVE_SEG_REGS
// segment registers
mov JB_SS(%ecx), %ss
- mov JB_CS(%ecx), %cs
+ // mov JB_CS(%ecx), %cs // can't set cs?
mov JB_DS(%ecx), %ds
mov JB_ES(%ecx), %es
mov JB_FS(%ecx), %fs
movl $45, %eax /* Yes; make ENOTSUP for compatibility */
LABEL(cerror)
REG_TO_EXTERN(%eax, _errno)
- pushl %eax
+ mov %esp,%edx
+ andl $0xfffffff0,%esp
+ subl $16,%esp
+ movl %edx,4(%esp)
+ movl %eax,(%esp)
CALL_EXTERN(_cthread_set_errno_self)
- addl $4,%esp
+ movl 4(%esp),%esp
movl $-1,%eax
movl $-1,%edx /* in case a 64-bit value is returned */
ret
--- /dev/null
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
*/
#include "SYS.h"
-LEAF(_fork, 0)
+LEAF(_fork, 0)
+ subl $28, %esp // Align the stack, with 16 bytes of extra padding that we'll need
CALL_EXTERN(__cthread_fork_prepare)
#if defined(__DYNAMIC__)
// Just like __cthread_fork_prepare we need to prevent threads on the child's
LC1:
.ascii "__dyld_fork_prepare\0"
.text
- subl $4,%esp // allocate space for the address parameter
- leal 0(%esp),%eax // get the address of the allocated space
- pushl %eax // push the address of the allocated space
+ // Put a pointer to 8(%esp) in 4(%esp) for _dyld_func_lookup to fill in.
+ leal 0x8(%esp),%eax // get the address where we're going to store the pointer
+ movl %eax, 0x4(%esp) // copy the address of the pointer
call 1f
1: popl %eax
leal LC1-1b(%eax),%eax
- pushl %eax // push the name of the function to look up
+ movl %eax, 0x0(%esp) // copy the name of the function to look up
call __dyld_func_lookup
- addl $8,%esp // remove parameters to __dyld_func_lookup
- movl 0(%esp),%eax // move the value returned in address parameter
- addl $4,%esp // deallocate the space for the address param
+ movl 0x8(%esp),%eax // move the value returned in address parameter
call *%eax // call __dyld_fork_prepare indirectly
#endif
movl $ SYS_fork,%eax; // code for fork -> eax
- UNIX_SYSCALL_TRAP; // do the system call
+ UNIX_SYSCALL_TRAP // do the system call
jnc L1 // jump if CF==0
#if defined(__DYNAMIC__)
LC2:
.ascii "__dyld_fork_parent\0"
.text
- pushl %eax // save the return value (errno)
- subl $4,%esp // allocate space for the address parameter
- leal 0(%esp),%eax // get the address of the allocated space
- pushl %eax // push the address of the allocated space
+ movl %eax, 0xc(%esp) // save the return value (errno)
+ leal 0x8(%esp),%eax // get the address where we're going to store the pointer
+ movl %eax, 0x4(%esp) // copy the address of the pointer
call 1f
1: popl %eax
leal LC2-1b(%eax),%eax
- pushl %eax // push the name of the function to look up
+ movl %eax, 0x0(%esp) // copy the name of the function to look up
call __dyld_func_lookup
- addl $8,%esp // remove parameters to __dyld_func_lookup
- movl 0(%esp),%eax // move the value returned in address parameter
- addl $4,%esp // deallocate the space for the address param
+ movl 0x8(%esp),%eax // move the value returned in address parameter
call *%eax // call __dyld_fork_parent indirectly
- popl %eax // restore the return value (errno)
+ movl 0xc(%esp), %eax // restore the return value (errno)
#endif
CALL_EXTERN(cerror)
CALL_EXTERN(__cthread_fork_parent)
movl $-1,%eax
+ addl $28, %esp // restore the stack
ret
L1:
#if defined(__DYNAMIC__)
// Here on the child side of the fork we need to tell the dynamic linker that
// we have forked. To do this we call __dyld_fork_child in the dyanmic
-// linker. But since we can't dynamicly bind anything until this is done we
+// linker. But since we can't dynamically bind anything until this is done we
// do this by using the private extern __dyld_func_lookup() function to get the
// address of __dyld_fork_child (the 'C' code equivlent):
//
.ascii "__dyld_fork_child\0"
.text
- subl $4,%esp // allocate space for the address parameter
- leal 0(%esp),%eax // get the address of the allocated space
- pushl %eax // push the address of the allocated space
+ leal 0x8(%esp),%eax // get the address where we're going to store the pointer
+ movl %eax, 0x4(%esp) // copy the address of the pointer
call 1f
1: popl %eax
leal LC0-1b(%eax),%eax
- pushl %eax // push the name of the function to look up
+ movl %eax, 0x0(%esp) // copy the name of the function to look up
call __dyld_func_lookup
- addl $8,%esp // remove parameters to __dyld_func_lookup
- movl 0(%esp),%eax // move the value returned in address parameter
- addl $4,%esp // deallocate the space for the address param
+ movl 0x8(%esp),%eax // move the value returned in address parameter
call *%eax // call __dyld_fork_child indirectly
#endif
xorl %eax, %eax
.ascii "__dyld_fork_child_final\0"
.text
- subl $4,%esp // allocate space for the address parameter
- leal 0(%esp),%eax // get the address of the allocated space
- pushl %eax // push the address of the allocated space
+ leal 0x8(%esp),%eax // get the address where we're going to store the pointer
+ movl %eax, 0x4(%esp) // copy the address of the pointer
call 1f
1: popl %eax
leal LC10-1b(%eax),%eax
- pushl %eax // push the name of the function to look up
+ movl %eax, 0x0(%esp) // copy the name of the function to look up
call __dyld_func_lookup
- addl $8,%esp // remove parameters to __dyld_func_lookup
- movl 0(%esp),%eax // move the value returned in address parameter
- addl $4,%esp // deallocate the space for the address param
+ movl 0x8(%esp),%eax // move the value returned in address parameter
call *%eax // call __dyld_fork_child_final indirectly
#endif
xorl %eax,%eax // zero eax
+ addl $28, %esp // restore the stack
ret
//parent here...
L2:
- push %eax // save pid
+ movl %eax, 0xc(%esp) // save pid
#if defined(__DYNAMIC__)
// __dyld_fork_parent() is called by the parent process after a fork syscall.
// This releases the dyld lock acquired by __dyld_fork_prepare().
- subl $4,%esp // allocate space for the address parameter
- leal 0(%esp),%eax // get the address of the allocated space
- pushl %eax // push the address of the allocated space
+ leal 0x8(%esp),%eax // get the address where we're going to store the pointer
+ movl %eax, 0x4(%esp) // copy the address of the allocated space
call 1f
1: popl %eax
leal LC2-1b(%eax),%eax
- pushl %eax // push the name of the function to look up
+ movl %eax, 0x0(%esp) // copy the name of the function to look up
call __dyld_func_lookup
- addl $8,%esp // remove parameters to __dyld_func_lookup
- movl 0(%esp),%eax // move the value returned in address parameter
- addl $4,%esp // deallocate the space for the address param
+ movl 0x8(%esp),%eax // move the value returned in address parameter
call *%eax // call __dyld_fork_parent indirectly
#endif
CALL_EXTERN_AGAIN(__cthread_fork_parent)
- pop %eax
+ movl 0xc(%esp), %eax // return pid
+ addl $28, %esp // restore the stack
ret
UNIX_SYSCALL_NONAME(getpid, 0)
movl %eax, %edx
xorl %eax, %eax
+ GET_CURRENT_PID
lock
cmpxchgl %edx, __current_pid
movl %edx, %eax
--- /dev/null
+/*
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#include <sys/syscall.h>
+#include <architecture/i386/asm_help.h>
+#include <mach/i386/syscall_sw.h>
+
+.text
+.globl cerror
+LEAF(_i386_get_ldt, 0)
+ movl $6,%eax
+ MACHDEP_SYSCALL_TRAP
+ jnb 2f
+ BRANCH_EXTERN(cerror)
+2: ret
--- /dev/null
+/*
+ * Copyright (c) 1999-2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/* Copyright 1998 Apple Computer, Inc. */
+
+#include "SYS.h"
+
+#define __APPLE_API_PRIVATE
+#include <machine/cpu_capabilities.h>
+#undef __APPLE_API_PRIVATE
+
+LABEL(___commpage_gettimeofday)
+ mov $ _COMM_PAGE_GETTIMEOFDAY,%eax
+ jmp %eax
+
+/*
+ * This syscall is special cased: the timeval is returned in eax/edx.
+ */
+LABEL(___gettimeofday)
+ UNIX_SYSCALL_INT_NONAME(gettimeofday,0)
+ mov 4(%esp),%ecx
+ mov %eax,(%ecx)
+ mov %edx,4(%ecx)
+ xor %eax,%eax
+ ret
--- /dev/null
+/*
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#include <sys/syscall.h>
+#include <architecture/i386/asm_help.h>
+#include <mach/i386/syscall_sw.h>
+
+.text
+.globl cerror
+LEAF(_i386_set_ldt, 0)
+ movl $5,%eax
+ MACHDEP_SYSCALL_TRAP
+ jnb 2f
+ BRANCH_EXTERN(cerror)
+2: ret
*/
#include "SYS.h"
-UNIX_SYSCALL(lseek, 3)
+UNIX_SYSCALL_INT(lseek, 3)
ret
*/
#include "SYS.h"
-UNIX_SYSCALL(pipe, 0)
+UNIX_SYSCALL_INT(pipe, 0)
movl 4(%esp),%ecx
movl %eax,(%ecx)
movl %edx,4(%ecx)
movl %ecx, JB_SAVEMASK(%eax) // jmpbuf[_JBLEN] = savemask;
cmpl $0, %ecx // if savemask != 0
jne _setjmp // setjmp(jmpbuf);
- BRANCH_EXTERN(__setjmp) // else
- // _setjmp(jmpbuf);
+ jmp L_do__setjmp // else _setjmp(jmpbuf);
LEAF(_setjmp, 0)
+ subl $4, %esp // make space for return from sigprocmask
+ pushl %esp // oset
+ pushl $0 // set = NULL
+ pushl $1 // how = SIG_BLOCK
+ CALL_EXTERN(_sigprocmask)
+ movl 12(%esp),%eax // save the mask
+ addl $16, %esp // restore original esp
movl 4(%esp), %ecx // jmp_buf (struct sigcontext *)
- pushl %ecx // save ecx
-
- // call sigstack to get the current signal stack
- subl $12, %esp // space for return structure
- pushl %esp
- pushl $0
- CALL_EXTERN(_sigaltstack)
- movl 12(%esp), %eax // save stack pointer
- movl %eax, JB_ONSTACK(%ecx)
- addl $20, %esp
-
- // call sigblock to get signal mask
- pushl $0
- CALL_EXTERN(_sigblock)
- addl $4, %esp
- popl %ecx // restore ecx
movl %eax, JB_MASK(%ecx)
-
- // now build sigcontext
- movl %ebx, JB_EBX(%ecx)
- movl %edi, JB_EDI(%ecx)
- movl %esi, JB_ESI(%ecx)
- movl %ebp, JB_EBP(%ecx)
-
- // EIP is set to the frame return address value
- movl (%esp), %eax
- movl %eax, JB_EIP(%ecx)
- // ESP is set to the frame return address plus 4
- movl %esp, %eax
- addl $4, %eax
- movl %eax, JB_ESP(%ecx)
-
- // segment registers
- movl $0, JB_SS(%ecx)
- mov %ss, JB_SS(%ecx)
- movl $0, JB_CS(%ecx)
- mov %cs, JB_CS(%ecx)
- movl $0, JB_DS(%ecx)
- mov %ds, JB_DS(%ecx)
- movl $0, JB_ES(%ecx)
- mov %es, JB_ES(%ecx)
- movl $0, JB_FS(%ecx)
- mov %fs, JB_FS(%ecx)
- movl $0, JB_GS(%ecx)
- mov %gs, JB_GS(%ecx)
-
- // save eflags - you can't use movl
- pushf
- popl %eax
- movl %eax, JB_EFLAGS(%ecx)
-
- // return 0
- xorl %eax, %eax
- ret
+L_do__setjmp:
+ BRANCH_EXTERN(__setjmp)
LEAF(_siglongjmp, 0)
movl 4(%esp), %eax // sigjmp_buf * jmpbuf;
cmpl $0, JB_SAVEMASK(%eax) // if jmpbuf[_JBLEN] != 0
jne _longjmp // longjmp(jmpbuf, var);
- BRANCH_EXTERN(__longjmp) // else
- // _longjmp(jmpbuf, var);
+ jmp L_do__longjmp // else _longjmp(jmpbuf, var);
LEAF(_longjmp, 0)
- subl $2,%esp
- fnstcw (%esp) // save FP control word
- fninit // reset FP coprocessor
- fldcw (%esp) // restore FP control word
- addl $2,%esp
- movl 4(%esp), %eax // address of jmp_buf (saved context)
- movl 8(%esp), %edx // return value
- movl %edx, JB_EAX(%eax) // return value into saved context
- movl $ SYS_sigreturn, %eax // sigreturn system call
- UNIX_SYSCALL_TRAP
- addl $8, %esp
- CALL_EXTERN(_longjmperror)
- CALL_EXTERN(_abort)
+ movl 4(%esp), %ecx // address of jmp_buf (saved context)
+ movl JB_MASK(%ecx),%eax // get the mask
+ pushl %eax // store the mask
+ movl %esp, %edx // save the address where we stored the mask
+ pushl $0 // oset = NULL
+ pushl %edx // set
+ pushl $3 // how = SIG_SETMASK
+ CALL_EXTERN_AGAIN(_sigprocmask)
+ addl $16, %esp // restore original esp
+L_do__longjmp:
+ BRANCH_EXTERN(__longjmp) // else
END(_longjmp)
*/
#include "SYS.h"
-UNIX_SYSCALL(sigaltstack, 3)
+UNIX_SYSCALL_INT(sigaltstack, 3)
ret
*/
#include "SYS.h"
-UNIX_SYSCALL(sigreturn, 1)
+UNIX_SYSCALL_INT(sigreturn, 2)
ret
/* 23.1.6.4 ACL Format translation */
extern ssize_t acl_copy_ext(void *buf_p, acl_t acl, ssize_t size);
+extern ssize_t acl_copy_ext_native(void *buf_p, acl_t acl, ssize_t size);
extern acl_t acl_copy_int(const void *buf_p);
+extern acl_t acl_copy_int_native(const void *buf_p);
extern acl_t acl_from_text(const char *buf_p);
extern ssize_t acl_size(acl_t acl);
extern char *acl_to_text(acl_t acl, ssize_t *len_p);
__END_DECLS
-#endif _SYS_ACL_H
+#endif /* _SYS_ACL_H */
#define RB_DEBUGGER 0x1000 /* enter debugger NOW */
(void) host_reboot(master_host_port, RB_DEBUGGER);
+
+ /* 4279008 - don't return */
+ abort();
}
#include <pwd.h>
#include <grp.h>
+#include <libkern/OSByteOrder.h>
+
#include "aclvar.h"
+/*
+ * NOTE: the copy_int/copy_ext functions are duplicated here, one version of each for
+ * each of native and portable endianity. A more elegant solution might be called for
+ * if the functions become much more complicated.
+ */
+
+/*
+ * acl_t -> external representation, portable endianity
+ */
ssize_t
acl_copy_ext(void *buf, acl_t acl, ssize_t size)
{
return(-1);
}
+ /* export the header */
+ ext->fsec_magic = OSSwapHostToBigInt32(KAUTH_FILESEC_MAGIC);
+ ext->fsec_entrycount = OSSwapHostToBigInt32(acl->a_entries);
+ ext->fsec_flags = OSSwapHostToBigInt32(acl->a_flags);
+
+ /* copy ACEs */
+ for (i = 0; i < acl->a_entries; i++) {
+ /* ACE contents are almost identical */
+ ext->fsec_ace[i].ace_applicable = acl->a_ace[i].ae_applicable;
+ ext->fsec_ace[i].ace_flags =
+ OSSwapHostToBigInt32((acl->a_ace[i].ae_tag & KAUTH_ACE_KINDMASK) | (acl->a_ace[i].ae_flags & ~KAUTH_ACE_KINDMASK));
+ ext->fsec_ace[i].ace_rights = OSSwapHostToBigInt32(acl->a_ace[i].ae_perms);
+ }
+
+ return(reqsize);
+}
+
+/*
+ * acl_t -> external representation, native system endianity
+ */
+ssize_t
+acl_copy_ext_native(void *buf, acl_t acl, ssize_t size)
+{
+ struct kauth_filesec *ext = (struct kauth_filesec *)buf;
+ ssize_t reqsize;
+ int i;
+
+ /* validate arguments, compute required size */
+ reqsize = acl_size(acl);
+ if (reqsize < 0)
+ return(-1);
+ if (reqsize > size) {
+ errno = ERANGE;
+ return(-1);
+ }
+
/* export the header */
ext->fsec_magic = KAUTH_FILESEC_MAGIC;
ext->fsec_entrycount = acl->a_entries;
return(reqsize);
}
+/*
+ * external representation, portable system endianity -> acl_t
+ *
+ * Unlike acl_copy_ext, we can't mung the buffer as it doesn't belong to us.
+ */
acl_t
acl_copy_int(const void *buf)
{
acl_t ap;
int i;
+ if (ext->fsec_magic != OSSwapHostToBigInt32(KAUTH_FILESEC_MAGIC)) {
+ errno = EINVAL;
+ return(NULL);
+ }
+
+ if ((ap = acl_init(OSSwapBigToHostInt32(ext->fsec_entrycount))) != NULL) {
+ /* copy useful header fields */
+ ap->a_flags = OSSwapBigToHostInt32(ext->fsec_flags);
+ ap->a_entries = OSSwapBigToHostInt32(ext->fsec_entrycount);
+ /* copy ACEs */
+ for (i = 0; i < ap->a_entries; i++) {
+ /* ACE contents are literally identical */
+ ap->a_ace[i].ae_magic = _ACL_ENTRY_MAGIC;
+ ap->a_ace[i].ae_applicable = ext->fsec_ace[i].ace_applicable;
+ ap->a_ace[i].ae_flags = OSSwapBigToHostInt32(ext->fsec_ace[i].ace_flags) & ~KAUTH_ACE_KINDMASK;
+ ap->a_ace[i].ae_tag = OSSwapBigToHostInt32(ext->fsec_ace[i].ace_flags) & KAUTH_ACE_KINDMASK;
+ ap->a_ace[i].ae_perms = OSSwapBigToHostInt32(ext->fsec_ace[i].ace_rights);
+ }
+ }
+ return(ap);
+}
+
+/*
+ * external representation, native system endianity -> acl_t
+ */
+acl_t
+acl_copy_int_native(const void *buf)
+{
+ struct kauth_filesec *ext = (struct kauth_filesec *)buf;
+ acl_t ap;
+ int i;
+
if (ext->fsec_magic != KAUTH_FILESEC_MAGIC) {
errno = EINVAL;
return(NULL);
/* copy ACEs */
for (i = 0; i < ap->a_entries; i++) {
/* ACE contents are literally identical */
-/* XXX Consider writing the magic out to the persistent store
- * to detect corruption
- */
ap->a_ace[i].ae_magic = _ACL_ENTRY_MAGIC;
ap->a_ace[i].ae_applicable = ext->fsec_ace[i].ace_applicable;
ap->a_ace[i].ae_flags = ext->fsec_ace[i].ace_flags & ~KAUTH_ACE_KINDMASK;
/*
- * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2005 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* Note also that the "seconds" field of the timeval is a long, so
* it's size is mode dependent.
*/
-MI_ENTRY_POINT(___ppc_gettimeofday)
+MI_ENTRY_POINT(___gettimeofday)
mr r12,r3 // save ptr to timeval
SYSCALL_NONAME(gettimeofday,0)
- mr. r12,r12 // was timeval ptr null?
- beq 3f
stg r3,0(r12) // "stw" in 32-bit mode, "std" in 64-bit mode
stw r4,GPR_BYTES(r12)
li r3,0
-3:
blr
TEXT
ALIGN
-.globl _spin_lock_try
LEAF(__spin_lock_try, 0)
-_spin_lock_try:
movl $(_COMM_PAGE_SPINLOCK_TRY), %eax
jmpl %eax
---- printf.3.orig Fri Mar 11 17:08:43 2005
-+++ printf.3 Fri Mar 11 17:04:50 2005
+--- printf.3.orig 2004-11-25 11:38:35.000000000 -0800
++++ printf.3 2005-08-09 22:37:08.000000000 -0700
@@ -101,6 +101,12 @@
dynamically allocate a new string with
.Xr malloc 3 .
.It
+An optional separator character (
+.Cm \ , | \; | \ : | _
-+) used for separating multiple values when printing an AltiVec vector,
++) used for separating multiple values when printing an AltiVec or SSE vector,
+or other multi-value unit.
+.Pp
-+NOTE: This is an AltiVec only extension onto the
++NOTE: This is an extension to the
+.Fn printf
+specification.
+Behaviour of these values for
An optional decimal digit string specifying a minimum field width.
If the converted value has fewer characters than the field width, it will
be padded with spaces on the left (or right, if the left-adjustment
-@@ -379,6 +399,28 @@
+@@ -379,6 +399,34 @@
.It Sy Modifier Ta Cm c Ta Cm s
.It Cm l No (ell) Ta Vt wint_t Ta Vt "wchar_t *"
.El
+.Pp
+The AltiVec Technology Programming Interface Manual also defines five additional length modifiers
-+which can be used (in place of the conventional length modifiers) for the printing of AltiVec vectors:
++which can be used (in place of the conventional length modifiers) for the printing of AltiVec or SSE vectors:
+.Bl -tag -compact
+.It Cm v
+Treat the argument as a vector value, unit length will be determined by the conversion
+Treat the argument as a vector of 4 32-bit units.
+.El
+.Pp
-+NOTE: The vector length specifiers are AltiVec only extensions onto the
++NOTE: The vector length specifiers are extensions to the
+.Fn printf
+specification.
+Behaviour of these values for
+is only defined for operating systems conforming to the
+AltiVec Technology Programming Interface Manual.
+(At time of writing this includes only Mac OS X 10.2 and later.)
++.Pp
++As a further extension, for SSE2 64-bit units:
++.Bl -tag -compact
++.It Cm vll, llv
++Treat the argument as a vector of 2 64-bit units.
++.El
.It
A character that specifies the type of conversion to be applied.
.El
-@@ -792,12 +834,8 @@
+@@ -792,12 +840,8 @@
.Xr fmtcheck 3 ,
.Xr scanf 3 ,
.Xr setlocale 3 ,
--- vfprintf.c.orig 2004-11-25 11:38:35.000000000 -0800
-+++ vfprintf.c 2005-02-24 15:16:20.000000000 -0800
++++ vfprintf.c 2005-11-08 22:43:11.000000000 -0800
@@ -40,6 +40,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/lib/libc/stdio/vfprintf.c,v 1.68 2004/08/26 06:25:28 des Exp $");
#include <stdarg.h>
#include "un-namespace.h"
-@@ -66,6 +69,12 @@
+@@ -66,6 +69,13 @@
#include "local.h"
#include "fvwrite.h"
-+#ifdef ALTIVEC
-+#include <machine/cpu_capabilities.h>
-+
-+#define VECTORTYPE vector unsigned char
-+#endif /* ALTIVEC */
++#ifdef VECTORS
++typedef __attribute__ ((vector_size(16))) unsigned char VECTORTYPE;
++#ifdef __SSE2__
++#define V64TYPE
++#endif /* __SSE2__ */
++#endif /* VECTORS */
+
union arg {
int intarg;
u_int uintarg;
-@@ -93,6 +102,16 @@
+@@ -93,6 +103,21 @@
#endif
wint_t wintarg;
wchar_t *pwchararg;
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ VECTORTYPE vectorarg;
+ unsigned char vuchararg[16];
+ signed char vchararg[16];
+ unsigned int vuintarg[4];
+ signed int vintarg[4];
+ float vfloatarg[4];
-+#endif /* ALTIVEC */
++#ifdef V64TYPE
++ double vdoublearg[2];
++ unsigned long long vulonglongarg[2];
++ long long vlonglongarg[2];
++#endif /* V64TYPE */
++#endif /* VECTORS */
};
/*
-@@ -103,19 +122,56 @@
+@@ -103,16 +128,20 @@
T_LONG, T_U_LONG, TP_LONG, T_LLONG, T_U_LLONG, TP_LLONG,
T_PTRDIFFT, TP_PTRDIFFT, T_SIZET, TP_SIZET,
T_INTMAXT, T_UINTMAXT, TP_INTMAXT, TP_VOID, TP_CHAR, TP_SCHAR,
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR, T_VECTOR
-+#else /* ! ALTIVEC */
++#else /* ! VECTORS */
T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
};
static int __sprint(FILE *, struct __suio *);
static void __find_arguments(const char *, va_list, union arg **);
static void __grow_type_table(int, enum typeid **, int *);
-+ /*
-+ * Get the argument indexed by nextarg. If the argument table is
-+ * built, use it to get the argument. If its not, get the next
-+ * argument (and arguments must be gotten sequentially).
-+ */
-+#define GETARG(type) \
-+ ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
-+ (nextarg++, va_arg(ap, type)))
-+
-+#ifdef ALTIVEC
-+#define hasAltivec (_cpu_capabilities & kHasAltivec)
-+/*-----------------------------------------------------------------------
-+ * getvec() must be a real subroutine. If it is a #define, then __vfprintf()
-+ * would have its calling sequence changed by Altivec so that a non-Altivec
-+ * processor would crash on illegal instruction. By isolating the calling
-+ * sequence in getvec(), __vprintf() is callable by a non-Altivec processor.
-+ *-----------------------------------------------------------------------*/
-+static va_list getvec(union arg *, const union arg *, int, va_list) __attribute__((noinline));
-+
-+static va_list
-+getvec(union arg *dst, const union arg *argtable, int nextarg, va_list ap)
-+{
-+ dst->vectorarg = GETARG(VECTORTYPE);
-+ return ap;
-+}
-+
-+#define SETVEC(dst) \
-+{ \
-+ ap = getvec(&dst, argtable, nextarg, ap); \
-+ nextarg++; \
-+}
-+#endif /* ALTIVEC */
-+
- /*
- * Flush out all the vectors defined by the given uio,
- * then reset it so that it can be reused.
-@@ -141,7 +197,7 @@
+@@ -141,7 +170,7 @@
* worries about ungetc buffers and so forth.
*/
static int
{
int ret;
FILE fake;
-@@ -160,7 +216,7 @@
+@@ -160,7 +189,7 @@
fake._lbfsize = 0; /* not actually used, but Just In Case */
/* do the work, then copy any error status */
if (ret >= 0 && __fflush(&fake))
ret = EOF;
if (fake._flags & __SERR)
-@@ -336,7 +392,7 @@
+@@ -336,7 +365,7 @@
* that the wide char. string ends in a null character.
*/
static char *
{
static const mbstate_t initial;
mbstate_t mbs;
-@@ -354,7 +410,7 @@
+@@ -354,7 +383,7 @@
p = wcsarg;
mbs = initial;
for (;;) {
if (clen == 0 || clen == (size_t)-1 ||
nbytes + clen > prec)
break;
-@@ -363,7 +419,7 @@
+@@ -363,7 +392,7 @@
} else {
p = wcsarg;
mbs = initial;
if (nbytes == (size_t)-1)
return (NULL);
}
-@@ -378,7 +434,7 @@
+@@ -378,7 +407,7 @@
p = wcsarg;
mbs = initial;
while (mbp - convbuf < nbytes) {
if (clen == 0 || clen == (size_t)-1)
break;
mbp += clen;
-@@ -402,7 +458,21 @@
+@@ -402,7 +431,21 @@
int ret;
FLOCKFILE(fp);
FUNLOCKFILE(fp);
return (ret);
}
-@@ -451,12 +521,15 @@
+@@ -451,12 +494,15 @@
#define PTRDIFFT 0x800 /* ptrdiff_t */
#define INTMAXT 0x1000 /* intmax_t */
#define CHARINT 0x2000 /* print char using int format */
-+#ifdef ALTIVEC
-+#define VECTOR 0x4000 /* Altivec vector */
-+#endif /* ALTIVEC */
++#ifdef VECTORS
++#define VECTOR 0x4000 /* Altivec or SSE vector */
++#endif /* VECTORS */
/*
* Non-MT-safe version
{
char *fmt; /* format string */
int ch; /* character from fmt */
-@@ -502,6 +575,11 @@
+@@ -502,6 +548,11 @@
int nseps; /* number of group separators with ' */
int nrepeats; /* number of repeats of the last group */
#endif
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ union arg vval; /* Vector argument. */
+ char *pct; /* Pointer to '%' at beginning of specifier. */
+ char vsep; /* Vector separator character. */
u_long ulval; /* integer arguments %[diouxX] */
uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */
int base; /* base for [diouxX] conversion */
-@@ -574,15 +652,6 @@
- }
-
- /*
-- * Get the argument indexed by nextarg. If the argument table is
-- * built, use it to get the argument. If its not, get the next
-- * argument (and arguments must be gotten sequentially).
-- */
--#define GETARG(type) \
-- ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
-- (nextarg++, va_arg(ap, type)))
--
-- /*
- * To extend shorts properly, we need both signed and unsigned
- * argument extraction methods.
- */
-@@ -633,22 +702,23 @@
+@@ -633,22 +684,23 @@
val = GETARG (int); \
}
fmt = (char *)fmt0;
argtable = NULL;
-@@ -675,6 +745,9 @@
+@@ -675,6 +727,9 @@
}
if (ch == '\0')
goto done;
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ pct = fmt;
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
fmt++; /* skip over '%' */
flags = 0;
-@@ -683,6 +756,9 @@
+@@ -683,6 +738,9 @@
prec = -1;
sign = '\0';
ox[1] = '\0';
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ vsep = 'X'; /* Illegal value, changed to defaults later. */
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
rflag: ch = *fmt++;
reswitch: switch (ch) {
-@@ -698,6 +774,11 @@
+@@ -698,6 +756,11 @@
case '#':
flags |= ALT;
goto rflag;
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ case ',': case ';': case ':': case '_':
+ vsep = ch;
+ goto rflag;
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
case '*':
/*-
* ``A negative field width argument is taken as a
-@@ -718,8 +799,8 @@
+@@ -718,8 +781,8 @@
goto rflag;
case '\'':
flags |= GROUPING;
goto rflag;
case '.':
if ((ch = *fmt++) == '*') {
-@@ -793,14 +874,20 @@
+@@ -793,14 +856,18 @@
flags |= LONGINT;
/*FALLTHROUGH*/
case 'c':
-+#ifdef ALTIVEC
-+ if (flags & VECTOR) {
-+ SETVEC(vval);
++#ifdef VECTORS
++ if (flags & VECTOR)
+ break;
-+ }
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
if (flags & LONGINT) {
static const mbstate_t initial;
mbstate_t mbs;
if (mbseqlen == (size_t)-1) {
fp->_flags |= __SERR;
goto error;
-@@ -817,6 +904,12 @@
+@@ -817,6 +884,10 @@
/*FALLTHROUGH*/
case 'd':
case 'i':
-+#ifdef ALTIVEC
-+ if (flags & VECTOR) {
-+ SETVEC(vval);
++#ifdef VECTORS
++ if (flags & VECTOR)
+ break;
-+ }
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
if (flags & INTMAX_SIZE) {
ujval = SJARG();
if ((intmax_t)ujval < 0) {
-@@ -835,6 +928,13 @@
+@@ -835,6 +906,12 @@
#ifndef NO_FLOATING_POINT
case 'a':
case 'A':
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ if (flags & VECTOR) {
+ flags |= FPT;
-+ SETVEC(vval);
+ break;
+ }
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
if (ch == 'a') {
ox[1] = 'x';
xdigs = xdigs_lower;
-@@ -848,6 +948,12 @@
+@@ -848,6 +925,12 @@
prec++;
if (dtoaresult != NULL)
freedtoa(dtoaresult);
if (flags & LONGDBL) {
fparg.ldbl = GETARG(long double);
dtoaresult = cp =
-@@ -859,6 +965,7 @@
+@@ -859,6 +942,7 @@
__hdtoa(fparg.dbl, xdigs, prec,
&expt, &signflag, &dtoaend);
}
if (prec < 0)
prec = dtoaend - cp;
if (expt == INT_MAX)
-@@ -866,6 +973,13 @@
+@@ -866,6 +950,12 @@
goto fp_common;
case 'e':
case 'E':
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ if (flags & VECTOR) {
+ flags |= FPT;
-+ SETVEC(vval);
+ break;
+ }
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
expchar = ch;
if (prec < 0) /* account for digit before decpt */
prec = DEFPREC + 1;
-@@ -874,10 +988,24 @@
+@@ -874,10 +964,22 @@
goto fp_begin;
case 'f':
case 'F':
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ if (flags & VECTOR) {
+ flags |= FPT;
-+ SETVEC(vval);
+ break;
+ }
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
expchar = '\0';
goto fp_begin;
case 'g':
case 'G':
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ if (flags & VECTOR) {
+ flags |= FPT;
-+ SETVEC(vval);
+ break;
+ }
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
expchar = ch - ('g' - 'e');
if (prec == 0)
prec = 1;
-@@ -886,6 +1014,14 @@
+@@ -886,6 +988,14 @@
prec = DEFPREC;
if (dtoaresult != NULL)
freedtoa(dtoaresult);
if (flags & LONGDBL) {
fparg.ldbl = GETARG(long double);
dtoaresult = cp =
-@@ -899,6 +1035,7 @@
+@@ -899,6 +1009,7 @@
if (expt == 9999)
expt = INT_MAX;
}
fp_common:
if (signflag)
sign = '-';
-@@ -993,6 +1130,12 @@
+@@ -993,6 +1104,10 @@
flags |= LONGINT;
/*FALLTHROUGH*/
case 'o':
-+#ifdef ALTIVEC
-+ if (flags & VECTOR) {
-+ SETVEC(vval);
++#ifdef VECTORS
++ if (flags & VECTOR)
+ break;
-+ }
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
if (flags & INTMAX_SIZE)
ujval = UJARG();
else
-@@ -1007,6 +1150,12 @@
+@@ -1007,6 +1122,10 @@
* defined manner.''
* -- ANSI X3J11
*/
-+#ifdef ALTIVEC
-+ if (flags & VECTOR) {
-+ SETVEC(vval);
++#ifdef VECTORS
++ if (flags & VECTOR)
+ break;
-+ }
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
ujval = (uintmax_t)(uintptr_t)GETARG(void *);
base = 16;
xdigs = xdigs_lower;
-@@ -1025,7 +1174,7 @@
+@@ -1025,7 +1144,7 @@
if ((wcp = GETARG(wchar_t *)) == NULL)
cp = "(null)";
else {
if (convbuf == NULL) {
fp->_flags |= __SERR;
goto error;
-@@ -1056,6 +1205,12 @@
+@@ -1056,6 +1175,10 @@
flags |= LONGINT;
/*FALLTHROUGH*/
case 'u':
-+#ifdef ALTIVEC
-+ if (flags & VECTOR) {
-+ SETVEC(vval);
++#ifdef VECTORS
++ if (flags & VECTOR)
+ break;
-+ }
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
if (flags & INTMAX_SIZE)
ujval = UJARG();
else
-@@ -1068,6 +1223,12 @@
+@@ -1068,6 +1191,10 @@
case 'x':
xdigs = xdigs_lower;
hex:
-+#ifdef ALTIVEC
-+ if (flags & VECTOR) {
-+ SETVEC(vval);
++#ifdef VECTORS
++ if (flags & VECTOR)
+ break;
-+ }
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
if (flags & INTMAX_SIZE)
ujval = UJARG();
else
-@@ -1112,6 +1273,14 @@
+@@ -1112,6 +1239,11 @@
if (size > BUF) /* should never happen */
abort();
break;
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ case 'v':
-+ if (hasAltivec) {
-+ flags |= VECTOR;
-+ goto rflag;
-+ }
-+ /* drap through */
-+#endif /* ALTIVEC */
++ flags |= VECTOR;
++ goto rflag;
++#endif /* VECTORS */
default: /* "%?" prints ?, unless ? is NUL */
if (ch == '\0')
goto done;
-@@ -1123,6 +1292,184 @@
+@@ -1123,6 +1255,290 @@
break;
}
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ if (flags & VECTOR) {
+ /*
+ * Do the minimum amount of work necessary to construct
+ int i, j; /* Counter. */
+ int vcnt; /* Number of elements in vector. */
+ char *vfmt; /* Pointer to format specifier. */
-+ char vfmt_buf[32]; /* Static buffer for format spec. */
++#define EXTRAHH 2
++ char vfmt_buf[32 + EXTRAHH]; /* Static buffer for format spec. */
+ int vwidth = 0; /* Width specified via '*'. */
+ int vprec = 0; /* Precision specified via '*'. */
-+ union { /* Element. */
-+ int i;
-+ float f;
-+ } velm;
+ char *vstr; /* Used for asprintf(). */
+ int vlen; /* Length returned by asprintf(). */
++ enum {
++ V_CHAR, V_SHORT, V_INT,
++ V_PCHAR, V_PSHORT, V_PINT,
++ V_FLOAT,
++#ifdef V64TYPE
++ V_LONGLONG, V_PLONGLONG,
++ V_DOUBLE,
++#endif /* V64TYPE */
++ } vtype;
+
++ vval.vectorarg = GETARG(VECTORTYPE);
+ /*
+ * Set vfmt. If vfmt_buf may not be big enough,
+ * malloc() space, taking care to free it later.
++ * (EXTRAHH is for possible extra "hh")
+ */
-+ if (&fmt[-1] - pct < sizeof(vfmt_buf))
++ if (&fmt[-1] - pct + EXTRAHH < sizeof(vfmt_buf))
+ vfmt = vfmt_buf;
+ else
-+ vfmt = (char *)malloc(&fmt[-1] - pct + 1);
++ vfmt = (char *)malloc(&fmt[-1] - pct + EXTRAHH + 1);
+
+ /* Set the separator character, if not specified. */
+ if (vsep == 'X') {
+ * finish up the format specifier.
+ */
+ if (flags & SHORTINT) {
-+ if (ch != 'c')
++ switch (ch) {
++ case 'c':
++ vtype = V_SHORT;
++ break;
++ case 'p':
++ vtype = V_PSHORT;
++ break;
++ default:
+ vfmt[j++] = 'h';
++ vtype = V_SHORT;
++ break;
++ }
+ vcnt = 8;
+ } else if (flags & LONGINT) {
-+ if (ch != 'c')
-+ vfmt[j++] = 'l';
+ vcnt = 4;
++ vtype = (ch == 'p') ? V_PINT : V_INT;
++#ifdef V64TYPE
++ } else if (flags & LLONGINT) {
++ switch (ch) {
++ case 'a':
++ case 'A':
++ case 'e':
++ case 'E':
++ case 'f':
++ case 'g':
++ case 'G':
++ vcnt = 2;
++ vtype = V_DOUBLE;
++ break;
++ case 'd':
++ case 'i':
++ case 'u':
++ case 'o':
++ case 'p':
++ case 'x':
++ case 'X':
++ vfmt[j++] = 'l';
++ vfmt[j++] = 'l';
++ vcnt = 2;
++ vtype = (ch == 'p') ? V_PLONGLONG : V_LONGLONG;
++ break;
++ default:
++ /*
++ * The default case should never
++ * happen.
++ */
++ case 'c':
++ vcnt = 16;
++ vtype = V_CHAR;
++ }
++#endif /* V64TYPE */
+ } else {
+ switch (ch) {
+ case 'a':
+ case 'g':
+ case 'G':
+ vcnt = 4;
++ vtype = V_FLOAT;
+ break;
+ default:
+ /*
+ * The default case should never
+ * happen.
+ */
-+ case 'c':
+ case 'd':
+ case 'i':
+ case 'u':
+ case 'o':
-+ case 'p':
+ case 'x':
+ case 'X':
++ vfmt[j++] = 'h';
++ vfmt[j++] = 'h';
++ /* drop through */
++ case 'p':
++ case 'c':
+ vcnt = 16;
++ vtype = (ch == 'p') ? V_PCHAR : V_CHAR;
+ }
+ }
+ vfmt[j++] = ch;
+ vfmt[j++] = '\0';
+
+/* Get a vector element. */
-+#define VPRINT(cnt, ind, args...) do { \
-+ if (flags & FPT) { \
-+ velm.f = vval.vfloatarg[ind]; \
-+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, velm.f); \
-+ } else { \
-+ switch (cnt) { \
-+ default: \
-+ /* The default case should never happen. */ \
-+ case 4: \
-+ velm.i = (unsigned)vval.vintarg[ind]; \
-+ break; \
-+ case 8: \
-+ velm.i = (unsigned short)vval.vshortarg[ind]; \
-+ break; \
-+ case 16: \
-+ velm.i = (unsigned char)vval.vchararg[ind]; \
-+ break; \
-+ } \
-+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, velm.i); \
++#ifdef V64TYPE
++#define VPRINT(type, ind, args...) do { \
++ switch (type) { \
++ case V_CHAR: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
++ break; \
++ case V_PCHAR: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuchararg[ind]); \
++ break; \
++ case V_SHORT: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
++ break; \
++ case V_PSHORT: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vushortarg[ind]); \
++ break; \
++ case V_INT: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
++ break; \
++ case V_PINT: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuintarg[ind]); \
++ break; \
++ case V_LONGLONG: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vulonglongarg[ind]); \
++ break; \
++ case V_PLONGLONG: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vulonglongarg[ind]); \
++ break; \
++ case V_FLOAT: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
++ break; \
++ case V_DOUBLE: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vdoublearg[ind]); \
++ break; \
++ } \
++ ret += vlen; \
++ PRINT(vstr, vlen); \
++ FLUSH(); \
++ free(vstr); \
++} while (0)
++#else /* !V64TYPE */
++#define VPRINT(type, ind, args...) do { \
++ switch (type) { \
++ case V_CHAR: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
++ break; \
++ case V_PCHAR: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuchararg[ind]); \
++ break; \
++ case V_SHORT: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
++ break; \
++ case V_PSHORT: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vushortarg[ind]); \
++ break; \
++ case V_INT: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
++ break; \
++ case V_PINT: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuintarg[ind]); \
++ break; \
++ case V_FLOAT: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
++ break; \
+ } \
+ ret += vlen; \
+ PRINT(vstr, vlen); \
+ FLUSH(); \
+ free(vstr); \
+} while (0)
++#endif /* V64TYPE */
+
+ /* Actually print. */
+ if (vwidth == 0) {
+ if (vprec == 0) {
+ /* First element. */
-+ VPRINT(vcnt, 0);
++ VPRINT(vtype, 0);
+ for (i = 1; i < vcnt; i++) {
+ /* Separator. */
-+ PRINT(&vsep, 1);
++ if(vsep)
++ PRINT(&vsep, 1);
+
+ /* Element. */
-+ VPRINT(vcnt, i);
++ VPRINT(vtype, i);
+ }
+ } else {
+ /* First element. */
-+ VPRINT(vcnt, 0, prec);
++ VPRINT(vtype, 0, prec);
+ for (i = 1; i < vcnt; i++) {
+ /* Separator. */
-+ PRINT(&vsep, 1);
++ if(vsep)
++ PRINT(&vsep, 1);
+
+ /* Element. */
-+ VPRINT(vcnt, i, prec);
++ VPRINT(vtype, i, prec);
+ }
+ }
+ } else {
+ if (vprec == 0) {
+ /* First element. */
-+ VPRINT(vcnt, 0, width);
++ VPRINT(vtype, 0, width);
+ for (i = 1; i < vcnt; i++) {
+ /* Separator. */
-+ PRINT(&vsep, 1);
++ if(vsep)
++ PRINT(&vsep, 1);
+
+ /* Element. */
-+ VPRINT(vcnt, i, width);
++ VPRINT(vtype, i, width);
+ }
+ } else {
+ /* First element. */
-+ VPRINT(vcnt, 0, width, prec);
++ VPRINT(vtype, 0, width, prec);
+ for (i = 1; i < vcnt; i++) {
+ /* Separator. */
-+ PRINT(&vsep, 1);
++ if(vsep)
++ PRINT(&vsep, 1);
+
+ /* Element. */
-+ VPRINT(vcnt, i, width, prec);
++ VPRINT(vtype, i, width, prec);
+ }
+ }
+ }
+
+ continue;
+ }
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
/*
* All reasonable formats wind up here. At this point, `cp'
* points to a string which (if not flags&LADJUST) should be
-@@ -1406,6 +1753,11 @@
+@@ -1406,6 +1822,11 @@
if (flags & LONGINT)
ADDTYPE(T_WINT);
else
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ if (flags & VECTOR)
+ ADDTYPE(T_VECTOR);
+ else
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
ADDTYPE(T_INT);
break;
case 'D':
-@@ -1413,6 +1765,11 @@
+@@ -1413,6 +1834,11 @@
/*FALLTHROUGH*/
case 'd':
case 'i':
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ if (flags & VECTOR)
+ ADDTYPE(T_VECTOR);
+ else
ADDSARG();
break;
#ifndef NO_FLOATING_POINT
-@@ -1423,6 +1780,11 @@
+@@ -1423,6 +1849,11 @@
case 'f':
case 'g':
case 'G':
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ if (flags & VECTOR)
+ ADDTYPE(T_VECTOR);
+ else
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
if (flags & LONGDBL)
ADDTYPE(T_LONG_DOUBLE);
else
-@@ -1451,9 +1813,19 @@
+@@ -1451,9 +1882,19 @@
flags |= LONGINT;
/*FALLTHROUGH*/
case 'o':
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ if (flags & VECTOR)
+ ADDTYPE(T_VECTOR);
+ else
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
ADDUARG();
break;
case 'p':
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ if (flags & VECTOR)
+ ADDTYPE(T_VECTOR);
+ else
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
ADDTYPE(TP_VOID);
break;
case 'S':
-@@ -1471,6 +1843,11 @@
+@@ -1471,6 +1912,11 @@
case 'u':
case 'X':
case 'x':
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ if (flags & VECTOR)
+ ADDTYPE(T_VECTOR);
+ else
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
ADDUARG();
break;
default: /* "%?" prints ?, unless ? is NUL */
-@@ -1537,7 +1914,7 @@
+@@ -1537,7 +1983,7 @@
(*argtable) [n].sizearg = va_arg (ap, size_t);
break;
case TP_SIZET:
break;
case T_INTMAXT:
(*argtable) [n].intmaxarg = va_arg (ap, intmax_t);
-@@ -1556,6 +1933,12 @@
+@@ -1556,6 +2002,11 @@
(*argtable) [n].longdoublearg = va_arg (ap, long double);
break;
#endif
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ case T_VECTOR:
-+ if (hasAltivec)
-+ ap = getvec( &((*argtable) [n]), NULL, 0, ap );
++ (*argtable) [n].vectorarg = va_arg (ap, VECTORTYPE);
+ break;
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
case TP_CHAR:
(*argtable) [n].pchararg = va_arg (ap, char *);
break;
--- vfwprintf.c.orig 2004-11-25 11:38:36.000000000 -0800
-+++ vfwprintf.c 2005-02-24 15:17:14.000000000 -0800
++++ vfwprintf.c 2005-11-08 22:46:07.000000000 -0800
@@ -42,6 +42,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/lib/libc/stdio/vfwprintf.c,v 1.23 2004/08/26 06:25:28 des Exp $");
/*
* Actual wprintf innards.
*
-@@ -63,12 +65,19 @@
+@@ -63,12 +65,20 @@
#include <string.h>
#include <wchar.h>
#include <wctype.h>
#include "local.h"
#include "fvwrite.h"
-+#ifdef ALTIVEC
-+#include <machine/cpu_capabilities.h>
-+
-+#define VECTORTYPE vector unsigned char
-+#endif /* ALTIVEC */
++#ifdef VECTORS
++typedef __attribute__ ((vector_size(16))) unsigned char VECTORTYPE;
++#ifdef __SSE2__
++#define V64TYPE
++#endif /* __SSE2__ */
++#endif /* VECTORS */
+
union arg {
int intarg;
u_int uintarg;
-@@ -96,6 +105,16 @@
+@@ -96,6 +106,21 @@
#endif
wint_t wintarg;
wchar_t *pwchararg;
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ VECTORTYPE vectorarg;
+ unsigned char vuchararg[16];
+ signed char vchararg[16];
+ unsigned int vuintarg[4];
+ signed int vintarg[4];
+ float vfloatarg[4];
-+#endif /* ALTIVEC */
++#ifdef V64TYPE
++ double vdoublearg[2];
++ unsigned long long vulonglongarg[2];
++ long long vlonglongarg[2];
++#endif /* V64TYPE */
++#endif /* VECTORS */
};
/*
-@@ -106,26 +125,63 @@
+@@ -106,16 +131,20 @@
T_LONG, T_U_LONG, TP_LONG, T_LLONG, T_U_LLONG, TP_LLONG,
T_PTRDIFFT, TP_PTRDIFFT, T_SIZET, TP_SIZET,
T_INTMAXT, T_UINTMAXT, TP_INTMAXT, TP_VOID, TP_CHAR, TP_SCHAR,
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR, T_VECTOR
-+#else /* ! ALTIVEC */
++#else /* ! VECTORS */
T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
};
-static int __sbprintf(FILE *, const wchar_t *, va_list);
static void __find_arguments(const wchar_t *, va_list, union arg **);
static void __grow_type_table(int, enum typeid **, int *);
-+ /*
-+ * Get the argument indexed by nextarg. If the argument table is
-+ * built, use it to get the argument. If its not, get the next
-+ * argument (and arguments must be gotten sequentially).
-+ */
-+#define GETARG(type) \
-+ ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
-+ (nextarg++, va_arg(ap, type)))
-+
-+#ifdef ALTIVEC
-+#define hasAltivec (_cpu_capabilities & kHasAltivec)
-+/*-----------------------------------------------------------------------
-+ * getvec() must be a real subroutine. If it is a #define, then __vfprintf()
-+ * would have its calling sequence changed by Altivec so that a non-Altivec
-+ * processor would crash on illegal instruction. By isolating the calling
-+ * sequence in getvec(), __vprintf() is callable by a non-Altivec processor.
-+ *-----------------------------------------------------------------------*/
-+static va_list getvec(union arg *, const union arg *, int, va_list) __attribute__((noinline));
-+
-+static va_list
-+getvec(union arg *dst, const union arg *argtable, int nextarg, va_list ap)
-+{
-+ dst->vectorarg = GETARG(VECTORTYPE);
-+ return ap;
-+}
-+
-+#define SETVEC(dst) \
-+{ \
-+ ap = getvec(&dst, argtable, nextarg, ap); \
-+ nextarg++; \
-+}
-+#endif /* ALTIVEC */
-+
- /*
- * Helper function for `fprintf to unbuffered unix file': creates a
- * temporary buffer. We only work on write-only files; this avoids
+@@ -125,7 +154,7 @@
* worries about ungetc buffers and so forth.
*/
static int
{
int ret;
FILE fake;
-@@ -144,7 +200,7 @@
+@@ -144,7 +173,7 @@
fake._lbfsize = 0; /* not actually used, but Just In Case */
/* do the work, then copy any error status */
if (ret >= 0 && __fflush(&fake))
ret = WEOF;
if (fake._flags & __SERR)
-@@ -157,7 +213,7 @@
+@@ -157,7 +186,7 @@
* File must already be locked.
*/
static wint_t
{
static const mbstate_t initial;
mbstate_t mbs;
-@@ -167,10 +223,10 @@
+@@ -167,10 +196,10 @@
size_t len;
if ((fp->_flags & __SSTR) == 0)
fp->_flags |= __SERR;
return (WEOF);
}
-@@ -350,13 +406,14 @@
+@@ -350,13 +379,14 @@
* that the multibyte char. string ends in a null character.
*/
static wchar_t *
if (mbsarg == NULL)
return (NULL);
-@@ -374,7 +431,7 @@
+@@ -374,7 +404,7 @@
insize = nchars = 0;
mbs = initial;
while (nchars != (size_t)prec) {
if (nconv == 0 || nconv == (size_t)-1 ||
nconv == (size_t)-2)
break;
-@@ -399,7 +456,7 @@
+@@ -399,7 +429,7 @@
p = mbsarg;
mbs = initial;
while (insize != 0) {
if (nconv == 0 || nconv == (size_t)-1 || nconv == (size_t)-2)
break;
wcp++;
-@@ -425,7 +482,21 @@
+@@ -425,7 +455,21 @@
int ret;
FLOCKFILE(fp);
FUNLOCKFILE(fp);
return (ret);
}
-@@ -474,12 +545,15 @@
+@@ -474,12 +518,15 @@
#define PTRDIFFT 0x800 /* ptrdiff_t */
#define INTMAXT 0x1000 /* intmax_t */
#define CHARINT 0x2000 /* print char using int format */
-+#ifdef ALTIVEC
-+#define VECTOR 0x4000 /* Altivec vector */
-+#endif /* ALTIVEC */
++#ifdef VECTORS
++#define VECTOR 0x4000 /* Altivec or SSE vector */
++#endif /* VECTORS */
/*
* Non-MT-safe version
{
wchar_t *fmt; /* format string */
wchar_t ch; /* character from fmt */
-@@ -524,6 +598,11 @@
+@@ -524,6 +571,11 @@
int nseps; /* number of group separators with ' */
int nrepeats; /* number of repeats of the last group */
#endif
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ union arg vval; /* Vector argument. */
+ wchar_t *pct; /* Pointer to '%' at beginning of specifier. */
+ wchar_t vsep; /* Vector separator character. */
u_long ulval; /* integer arguments %[diouxX] */
uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */
int base; /* base for [diouxX] conversion */
-@@ -560,7 +639,7 @@
+@@ -560,7 +612,7 @@
*/
#define PRINT(ptr, len) do { \
for (n3 = 0; n3 < (len); n3++) \
} while (0)
#define PAD(howmany, with) do { \
if ((n = (howmany)) > 0) { \
-@@ -581,15 +660,6 @@
- } while(0)
-
- /*
-- * Get the argument indexed by nextarg. If the argument table is
-- * built, use it to get the argument. If its not, get the next
-- * argument (and arguments must be gotten sequentially).
-- */
--#define GETARG(type) \
-- ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
-- (nextarg++, va_arg(ap, type)))
--
-- /*
- * To extend shorts properly, we need both signed and unsigned
- * argument extraction methods.
- */
-@@ -640,21 +710,22 @@
+@@ -640,21 +692,22 @@
val = GETARG (int); \
}
fmt = (wchar_t *)fmt0;
argtable = NULL;
-@@ -678,6 +749,9 @@
+@@ -678,6 +731,9 @@
}
if (ch == '\0')
goto done;
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ pct = fmt;
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
fmt++; /* skip over '%' */
flags = 0;
-@@ -686,6 +760,9 @@
+@@ -686,6 +742,9 @@
prec = -1;
sign = '\0';
ox[1] = '\0';
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ vsep = 'X'; /* Illegal value, changed to defaults later. */
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
rflag: ch = *fmt++;
reswitch: switch (ch) {
-@@ -701,6 +778,11 @@
+@@ -701,6 +760,11 @@
case '#':
flags |= ALT;
goto rflag;
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ case ',': case ';': case ':': case '_':
+ vsep = ch;
+ goto rflag;
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
case '*':
/*-
* ``A negative field width argument is taken as a
-@@ -721,8 +803,8 @@
+@@ -721,8 +785,8 @@
goto rflag;
case '\'':
flags |= GROUPING;
goto rflag;
case '.':
if ((ch = *fmt++) == '*') {
-@@ -796,10 +878,16 @@
+@@ -796,10 +860,14 @@
flags |= LONGINT;
/*FALLTHROUGH*/
case 'c':
-+#ifdef ALTIVEC
-+ if (flags & VECTOR) {
-+ SETVEC(vval);
++#ifdef VECTORS
++ if (flags & VECTOR)
+ break;
-+ }
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
if (flags & LONGINT)
*(cp = buf) = (wchar_t)GETARG(wint_t);
else
size = 1;
sign = '\0';
break;
-@@ -808,6 +896,12 @@
+@@ -808,6 +876,10 @@
/*FALLTHROUGH*/
case 'd':
case 'i':
-+#ifdef ALTIVEC
-+ if (flags & VECTOR) {
-+ SETVEC(vval);
++#ifdef VECTORS
++ if (flags & VECTOR)
+ break;
-+ }
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
if (flags & INTMAX_SIZE) {
ujval = SJARG();
if ((intmax_t)ujval < 0) {
-@@ -837,6 +931,12 @@
+@@ -826,6 +898,12 @@
+ #ifndef NO_FLOATING_POINT
+ case 'a':
+ case 'A':
++#ifdef VECTORS
++ if (flags & VECTOR) {
++ flags |= FPT;
++ break;
++ }
++#endif /* VECTORS */
+ if (ch == 'a') {
+ ox[1] = 'x';
+ xdigs = xdigs_lower;
+@@ -837,6 +915,12 @@
}
if (prec >= 0)
prec++;
if (flags & LONGDBL) {
fparg.ldbl = GETARG(long double);
dtoaresult =
-@@ -848,6 +948,7 @@
+@@ -848,6 +932,7 @@
__hdtoa(fparg.dbl, xdigs, prec,
&expt, &signflag, &dtoaend);
}
if (prec < 0)
prec = dtoaend - dtoaresult;
if (expt == INT_MAX)
-@@ -855,7 +956,7 @@
+@@ -855,11 +940,17 @@
if (convbuf != NULL)
free(convbuf);
ndig = dtoaend - dtoaresult;
freedtoa(dtoaresult);
goto fp_common;
case 'e':
-@@ -868,10 +969,24 @@
+ case 'E':
++#ifdef VECTORS
++ if (flags & VECTOR) {
++ flags |= FPT;
++ break;
++ }
++#endif /* VECTORS */
+ expchar = ch;
+ if (prec < 0) /* account for digit before decpt */
+ prec = DEFPREC + 1;
+@@ -868,10 +959,22 @@
goto fp_begin;
case 'f':
case 'F':
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ if (flags & VECTOR) {
+ flags |= FPT;
-+ SETVEC(vval);
+ break;
+ }
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
expchar = '\0';
goto fp_begin;
case 'g':
case 'G':
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ if (flags & VECTOR) {
+ flags |= FPT;
-+ SETVEC(vval);
+ break;
+ }
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
expchar = ch - ('g' - 'e');
if (prec == 0)
prec = 1;
-@@ -880,6 +995,14 @@
+@@ -880,6 +983,14 @@
prec = DEFPREC;
if (convbuf != NULL)
free(convbuf);
if (flags & LONGDBL) {
fparg.ldbl = GETARG(long double);
dtoaresult =
-@@ -893,8 +1016,9 @@
+@@ -893,8 +1004,9 @@
if (expt == 9999)
expt = INT_MAX;
}
freedtoa(dtoaresult);
fp_common:
if (signflag)
-@@ -989,6 +1113,12 @@
+@@ -989,6 +1101,10 @@
flags |= LONGINT;
/*FALLTHROUGH*/
case 'o':
-+#ifdef ALTIVEC
-+ if (flags & VECTOR) {
-+ SETVEC(vval);
++#ifdef VECTORS
++ if (flags & VECTOR)
+ break;
-+ }
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
if (flags & INTMAX_SIZE)
ujval = UJARG();
else
-@@ -1003,6 +1133,12 @@
+@@ -1003,6 +1119,10 @@
* defined manner.''
* -- ANSI X3J11
*/
-+#ifdef ALTIVEC
-+ if (flags & VECTOR) {
-+ SETVEC(vval);
++#ifdef VECTORS
++ if (flags & VECTOR)
+ break;
-+ }
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
ujval = (uintmax_t)(uintptr_t)GETARG(void *);
base = 16;
xdigs = xdigs_lower;
-@@ -1024,7 +1160,7 @@
+@@ -1024,7 +1144,7 @@
if ((mbp = GETARG(char *)) == NULL)
cp = L"(null)";
else {
if (convbuf == NULL) {
fp->_flags |= __SERR;
goto error;
-@@ -1055,6 +1191,12 @@
+@@ -1055,6 +1175,10 @@
flags |= LONGINT;
/*FALLTHROUGH*/
case 'u':
-+#ifdef ALTIVEC
-+ if (flags & VECTOR) {
-+ SETVEC(vval);
++#ifdef VECTORS
++ if (flags & VECTOR)
+ break;
-+ }
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
if (flags & INTMAX_SIZE)
ujval = UJARG();
else
-@@ -1067,6 +1209,12 @@
+@@ -1067,6 +1191,10 @@
case 'x':
xdigs = xdigs_lower;
hex:
-+#ifdef ALTIVEC
-+ if (flags & VECTOR) {
-+ SETVEC(vval);
++#ifdef VECTORS
++ if (flags & VECTOR)
+ break;
-+ }
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
if (flags & INTMAX_SIZE)
ujval = UJARG();
else
-@@ -1111,6 +1259,14 @@
+@@ -1111,6 +1239,11 @@
if (size > BUF) /* should never happen */
abort();
break;
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ case 'v':
-+ if (hasAltivec) {
-+ flags |= VECTOR;
-+ goto rflag;
-+ }
-+ /* drop through */
-+#endif /* ALTIVEC */
++ flags |= VECTOR;
++ goto rflag;
++#endif /* VECTORS */
default: /* "%?" prints ?, unless ? is NUL */
if (ch == '\0')
goto done;
-@@ -1122,6 +1278,183 @@
+@@ -1122,6 +1255,288 @@
break;
}
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ if (flags & VECTOR) {
+ /*
+ * Do the minimum amount of work necessary to construct
+ int i, j; /* Counter. */
+ int vcnt; /* Number of elements in vector. */
+ char *vfmt; /* Pointer to format specifier. */
-+ char vfmt_buf[32]; /* Static buffer for format spec. */
++#define EXTRAHH 2
++ char vfmt_buf[32 + EXTRAHH]; /* Static buffer for format spec. */
+ int vwidth = 0; /* Width specified via '*'. */
+ int vprec = 0; /* Precision specified via '*'. */
-+ union { /* Element. */
-+ int i;
-+ float f;
-+ } velm;
+ char *vstr; /* Used for asprintf(). */
+ int vlen; /* Length returned by asprintf(). */
++ enum {
++ V_CHAR, V_SHORT, V_INT,
++ V_PCHAR, V_PSHORT, V_PINT,
++ V_FLOAT,
++#ifdef V64TYPE
++ V_LONGLONG, V_PLONGLONG,
++ V_DOUBLE,
++#endif /* V64TYPE */
++ } vtype;
+
++ vval.vectorarg = GETARG(VECTORTYPE);
+ /*
+ * Set vfmt. If vfmt_buf may not be big enough,
+ * malloc() space, taking care to free it later.
++ * (EXTRAHH is for possible extra "hh")
+ */
-+ if (&fmt[-1] - pct < sizeof(vfmt_buf))
++ if (&fmt[-1] - pct + EXTRAHH < sizeof(vfmt_buf))
+ vfmt = vfmt_buf;
+ else
-+ vfmt = (char *)malloc(&fmt[-1] - pct + 1);
++ vfmt = (char *)malloc(&fmt[-1] - pct + EXTRAHH + 1);
+
+ /* Set the separator character, if not specified. */
+ if (vsep == 'X') {
+ * finish up the format specifier.
+ */
+ if (flags & SHORTINT) {
-+ if (ch != 'c')
++ switch (ch) {
++ case 'c':
++ vtype = V_SHORT;
++ break;
++ case 'p':
++ vtype = V_PSHORT;
++ break;
++ default:
+ vfmt[j++] = 'h';
++ vtype = V_SHORT;
++ break;
++ }
+ vcnt = 8;
+ } else if (flags & LONGINT) {
-+ if (ch != 'c')
-+ vfmt[j++] = 'l';
+ vcnt = 4;
++ vtype = (ch == 'p') ? V_PINT : V_INT;
++#ifdef V64TYPE
++ } else if (flags & LLONGINT) {
++ switch (ch) {
++ case 'a':
++ case 'A':
++ case 'e':
++ case 'E':
++ case 'f':
++ case 'g':
++ case 'G':
++ vcnt = 2;
++ vtype = V_DOUBLE;
++ break;
++ case 'd':
++ case 'i':
++ case 'u':
++ case 'o':
++ case 'p':
++ case 'x':
++ case 'X':
++ vfmt[j++] = 'l';
++ vfmt[j++] = 'l';
++ vcnt = 2;
++ vtype = (ch == 'p') ? V_PLONGLONG : V_LONGLONG;
++ break;
++ default:
++ /*
++ * The default case should never
++ * happen.
++ */
++ case 'c':
++ vcnt = 16;
++ vtype = V_CHAR;
++ }
++#endif /* V64TYPE */
+ } else {
+ switch (ch) {
+ case 'a':
+ case 'g':
+ case 'G':
+ vcnt = 4;
++ vtype = V_FLOAT;
+ break;
+ default:
+ /*
+ * The default case should never
+ * happen.
+ */
-+ case 'c':
+ case 'd':
+ case 'i':
+ case 'u':
+ case 'o':
-+ case 'p':
+ case 'x':
+ case 'X':
++ vfmt[j++] = 'h';
++ vfmt[j++] = 'h';
++ /* drop through */
++ case 'p':
++ case 'c':
+ vcnt = 16;
++ vtype = (ch == 'p') ? V_PCHAR : V_CHAR;
+ }
+ }
+ vfmt[j++] = ch;
+ vfmt[j++] = '\0';
+
+/* Get a vector element. */
-+#define VPRINT(cnt, ind, args...) do { \
-+ if (flags & FPT) { \
-+ velm.f = vval.vfloatarg[ind]; \
-+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, velm.f); \
-+ } else { \
-+ switch (cnt) { \
-+ default: \
-+ /* The default case should never happen. */ \
-+ case 4: \
-+ velm.i = (unsigned)vval.vintarg[ind]; \
-+ break; \
-+ case 8: \
-+ velm.i = (unsigned short)vval.vshortarg[ind]; \
-+ break; \
-+ case 16: \
-+ velm.i = (unsigned char)vval.vchararg[ind]; \
-+ break; \
-+ } \
-+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, velm.i); \
++#ifdef V64TYPE
++#define VPRINT(type, ind, args...) do { \
++ switch (type) { \
++ case V_CHAR: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
++ break; \
++ case V_PCHAR: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuchararg[ind]); \
++ break; \
++ case V_SHORT: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
++ break; \
++ case V_PSHORT: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vushortarg[ind]); \
++ break; \
++ case V_INT: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
++ break; \
++ case V_PINT: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuintarg[ind]); \
++ break; \
++ case V_LONGLONG: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vulonglongarg[ind]); \
++ break; \
++ case V_PLONGLONG: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vulonglongarg[ind]); \
++ break; \
++ case V_FLOAT: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
++ break; \
++ case V_DOUBLE: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vdoublearg[ind]); \
++ break; \
++ } \
++ ret += vlen; \
++ PRINT(vstr, vlen); \
++ free(vstr); \
++} while (0)
++#else /* !V64TYPE */
++#define VPRINT(type, ind, args...) do { \
++ switch (type) { \
++ case V_CHAR: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
++ break; \
++ case V_PCHAR: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuchararg[ind]); \
++ break; \
++ case V_SHORT: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
++ break; \
++ case V_PSHORT: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vushortarg[ind]); \
++ break; \
++ case V_INT: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
++ break; \
++ case V_PINT: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuintarg[ind]); \
++ break; \
++ case V_FLOAT: \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
++ break; \
+ } \
+ ret += vlen; \
+ PRINT(vstr, vlen); \
+ free(vstr); \
+} while (0)
++#endif /* V64TYPE */
+
+ /* Actually print. */
+ if (vwidth == 0) {
+ if (vprec == 0) {
+ /* First element. */
-+ VPRINT(vcnt, 0);
++ VPRINT(vtype, 0);
+ for (i = 1; i < vcnt; i++) {
+ /* Separator. */
-+ PRINT(&vsep, 1);
++ if(vsep)
++ PRINT(&vsep, 1);
+
+ /* Element. */
-+ VPRINT(vcnt, i);
++ VPRINT(vtype, i);
+ }
+ } else {
+ /* First element. */
-+ VPRINT(vcnt, 0, prec);
++ VPRINT(vtype, 0, prec);
+ for (i = 1; i < vcnt; i++) {
+ /* Separator. */
-+ PRINT(&vsep, 1);
++ if(vsep)
++ PRINT(&vsep, 1);
+
+ /* Element. */
-+ VPRINT(vcnt, i, prec);
++ VPRINT(vtype, i, prec);
+ }
+ }
+ } else {
+ if (vprec == 0) {
+ /* First element. */
-+ VPRINT(vcnt, 0, width);
++ VPRINT(vtype, 0, width);
+ for (i = 1; i < vcnt; i++) {
+ /* Separator. */
-+ PRINT(&vsep, 1);
++ if(vsep)
++ PRINT(&vsep, 1);
+
+ /* Element. */
-+ VPRINT(vcnt, i, width);
++ VPRINT(vtype, i, width);
+ }
+ } else {
+ /* First element. */
-+ VPRINT(vcnt, 0, width, prec);
++ VPRINT(vtype, 0, width, prec);
+ for (i = 1; i < vcnt; i++) {
+ /* Separator. */
-+ PRINT(&vsep, 1);
++ if(vsep)
++ PRINT(&vsep, 1);
+
+ /* Element. */
-+ VPRINT(vcnt, i, width, prec);
++ VPRINT(vtype, i, width, prec);
+ }
+ }
+ }
+
+ continue;
+ }
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
/*
* All reasonable formats wind up here. At this point, `cp'
* points to a string which (if not flags&LADJUST) should be
-@@ -1401,6 +1734,11 @@
+@@ -1401,6 +1816,11 @@
if (flags & LONGINT)
ADDTYPE(T_WINT);
else
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ if (flags & VECTOR)
+ ADDTYPE(T_VECTOR);
+ else
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
ADDTYPE(T_INT);
break;
case 'D':
-@@ -1418,6 +1756,11 @@
+@@ -1408,6 +1828,11 @@
+ /*FALLTHROUGH*/
+ case 'd':
+ case 'i':
++#ifdef VECTORS
++ if (flags & VECTOR)
++ ADDTYPE(T_VECTOR);
++ else
++#endif /* VECTORS */
+ ADDSARG();
+ break;
+ #ifndef NO_FLOATING_POINT
+@@ -1418,6 +1843,11 @@
case 'f':
case 'g':
case 'G':
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ if (flags & VECTOR)
+ ADDTYPE(T_VECTOR);
+ else
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
if (flags & LONGDBL)
ADDTYPE(T_LONG_DOUBLE);
else
-@@ -1446,9 +1789,19 @@
+@@ -1446,9 +1876,19 @@
flags |= LONGINT;
/*FALLTHROUGH*/
case 'o':
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ if (flags & VECTOR)
+ ADDTYPE(T_VECTOR);
+ else
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
ADDUARG();
break;
case 'p':
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ if (flags & VECTOR)
+ ADDTYPE(T_VECTOR);
+ else
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
ADDTYPE(TP_VOID);
break;
case 'S':
-@@ -1466,6 +1819,11 @@
+@@ -1466,6 +1906,11 @@
case 'u':
case 'X':
case 'x':
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ if (flags & VECTOR)
+ ADDTYPE(T_VECTOR);
+ else
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
ADDUARG();
break;
default: /* "%?" prints ?, unless ? is NUL */
-@@ -1532,7 +1890,7 @@
+@@ -1532,7 +1977,7 @@
(*argtable) [n].sizearg = va_arg (ap, size_t);
break;
case TP_SIZET:
break;
case T_INTMAXT:
(*argtable) [n].intmaxarg = va_arg (ap, intmax_t);
-@@ -1551,6 +1909,12 @@
+@@ -1551,6 +1996,11 @@
(*argtable) [n].longdoublearg = va_arg (ap, long double);
break;
#endif
-+#ifdef ALTIVEC
++#ifdef VECTORS
+ case T_VECTOR:
-+ if (hasAltivec)
-+ ap = getvec( &((*argtable) [n]), NULL, 0, ap );
++ (*argtable) [n].vectorarg = va_arg (ap, VECTORTYPE);
+ break;
-+#endif /* ALTIVEC */
++#endif /* VECTORS */
case TP_CHAR:
(*argtable) [n].pchararg = va_arg (ap, char *);
break;
vswscanf.c vwprintf.c vwscanf.c wprintf.c wscanf.c
.for _src in vfprintf-fbsd.c vfwprintf-fbsd.c
-CFLAGS-${_src} += -fshort-enums
-# add altivec options on per file basis, since it now disables inlining
-.if (${MACHINE_ARCH} == ppc) || (${MACHINE_ARCH} == ppc64)
-CFLAGS-${_src} += -faltivec -DALTIVEC
-.endif
+CFLAGS-${_src} += -fshort-enums -DVECTORS
.endfor
UNIX03SRCS+= freopen.c fwrite.c
---- grantpt.c.orig 2006-04-21 22:41:31.000000000 -0700
-+++ grantpt.c 2006-04-21 22:43:03.000000000 -0700
+--- grantpt.c.orig 2004-09-14 19:06:46.000000000 -0700
++++ grantpt.c 2004-09-14 19:11:31.000000000 -0700
@@ -54,18 +54,16 @@
#include <unistd.h>
#include "un-namespace.h"
minor((x).st_rdev) >= 0 && \
minor((x).st_rdev) < PT_MAX)
-@@ -100,50 +119,53 @@
- serrno = errno;
-
- if ((slave = ptsname(fildes)) != NULL) {
-- /*
-- * Block SIGCHLD.
-- */
-- (void)sigemptyset(&nblock);
-- (void)sigaddset(&nblock, SIGCHLD);
-- (void)_sigprocmask(SIG_BLOCK, &nblock, &oblock);
--
-- switch (pid = fork()) {
-- case -1:
-- break;
-- case 0: /* child */
-+ /* 4430299: if we are root, we don't need to fork/exec */
-+ if (geteuid() != 0) {
- /*
-- * pt_chown expects the master pseudo TTY to be its
-- * standard input.
-+ * Block SIGCHLD.
- */
-- (void)_dup2(fildes, STDIN_FILENO);
-- (void)_sigprocmask(SIG_SETMASK, &oblock, NULL);
-- execl(_PATH_PTCHOWN, _PATH_PTCHOWN, (char *)NULL);
-- _exit(EX_UNAVAILABLE);
-- /* NOTREACHED */
-- default: /* parent */
-+ (void)sigemptyset(&nblock);
-+ (void)sigaddset(&nblock, SIGCHLD);
-+ (void)_sigprocmask(SIG_BLOCK, &nblock, &oblock);
-+
-+ switch (pid = fork()) {
-+ case -1:
-+ break;
-+ case 0: /* child */
-+ /*
-+ * pt_chown expects the master pseudo TTY to be its
-+ * standard input.
-+ */
-+ (void)_dup2(fildes, STDIN_FILENO);
-+ (void)_sigprocmask(SIG_SETMASK, &oblock, NULL);
-+ execl(_PATH_PTCHOWN, _PATH_PTCHOWN, (char *)NULL);
-+ _exit(EX_UNAVAILABLE);
-+ /* NOTREACHED */
-+ default: /* parent */
-+ /*
-+ * Just wait for the process. Error checking is
-+ * done below.
-+ */
-+ while ((spid = _waitpid(pid, &status, 0)) == -1 &&
-+ (errno == EINTR))
-+ ;
-+ if (spid != -1 && WIFEXITED(status) &&
-+ WEXITSTATUS(status) == EX_OK)
-+ retval = 0;
-+ else
-+ errno = EACCES;
-+ break;
-+ }
-+
- /*
-- * Just wait for the process. Error checking is
-- * done below.
-+ * Restore process's signal mask.
- */
-- while ((spid = _waitpid(pid, &status, 0)) == -1 &&
-- (errno == EINTR))
-- ;
-- if (spid != -1 && WIFEXITED(status) &&
-- WEXITSTATUS(status) == EX_OK)
-- retval = 0;
-- else
-- errno = EACCES;
-- break;
-+ (void)_sigprocmask(SIG_SETMASK, &oblock, NULL);
- }
-
-- /*
-- * Restore process's signal mask.
-- */
-- (void)_sigprocmask(SIG_SETMASK, &oblock, NULL);
--
- if (retval) {
- /*
-- * pt_chown failed. Try to manually change the
-+ * pt_chown failed (or we're root). Try to manually change the
- * permissions for the slave.
- */
- gid = (grp = getgrnam("tty")) ? grp->gr_gid : -1;
-@@ -227,8 +249,8 @@
+@@ -227,8 +246,8 @@
errno = EINVAL;
else {
(void)sprintf(slave, _PATH_DEV PTS_PREFIX "%c%c",
CFLAGS-${_src} += -D__APPLE_PR3375657_HACK__
.endfor
+.include "Makefile.obsd_begin"
+OBSDMISRCS= stack_protector.c
+.include "Makefile.obsd_end"
+
UNIX03SRCS += mmap.c mprotect.c msgctl.c msync.c munmap.c semctl.c shmctl.c
# Add machine dependent asm sources:
--- /dev/null
+/*
+ * Copyright (c) 2002 Hiroaki Etoh, Federico G. Schwindt, and Miodrag Vallat.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#if defined(LIBC_SCCS) && !defined(list)
+static char rcsid[] = "$OpenBSD: stack_protector.c,v 1.3 2002/12/10 08:53:42 etoh Exp $";
+#endif
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <syslog.h>
+
+long __guard[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+static void __guard_setup(void) __attribute__ ((constructor));
+void __stack_smash_handler(char func[], int damaged __attribute__((unused)));
+
+static void
+__guard_setup(void)
+{
+ int fd;
+ if (__guard[0]!=0) return;
+ fd = open ("/dev/urandom", 0);
+ if (fd != -1) {
+ ssize_t size = read (fd, (char*)&__guard, sizeof(__guard));
+ close (fd) ;
+ if (size == sizeof(__guard)) return;
+ }
+ /* If a random generator can't be used, the protector switches the guard
+ to the "terminator canary" */
+ ((char*)__guard)[0] = 0; ((char*)__guard)[1] = 0;
+ ((char*)__guard)[2] = '\n'; ((char*)__guard)[3] = 255;
+}
+
+void
+__stack_smash_handler(char func[], int damaged)
+{
+ const char message[] = "stack overflow in function %s";
+ struct sigaction sa;
+
+ /* this may fail on a chroot jail, though luck */
+ syslog(LOG_CRIT, message, func);
+
+ bzero(&sa, sizeof(struct sigaction));
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ sa.sa_handler = SIG_DFL;
+ sigaction(SIGABRT, &sa, NULL);
+
+ kill(getpid(), SIGABRT);
+
+ _exit(127);
+}
/*
- * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2003-2005 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
int gettimeofday (struct timeval *tp, struct timezone *tzp)
{
+ extern int __gettimeofday(struct timeval *, struct timezone *);
+ extern int __commpage_gettimeofday(struct timeval *);
static int validtz = 0;
static struct timezone cached_tz = {0};
- struct timeval localtv;
+ struct timeval atv;
if (tp == NULL) {
if (tzp == NULL)
return (0);
- tp = &localtv;
+ tp = &atv;
}
-#if defined(__ppc__) || defined(__ppc64__)
- {
- extern int __ppc_gettimeofday(struct timeval *, struct timezone *);
- extern int __commpage_gettimeofday(struct timeval *);
-
- if (__commpage_gettimeofday(tp)) { /* first try commpage */
- if (__ppc_gettimeofday(tp,tzp)) { /* if it fails, use syscall */
- return (-1);
- }
- }
- }
-#else
- if (syscall (SYS_gettimeofday, tp, tzp) < 0) {
- return (-1);
- }
-#endif
+ if (__commpage_gettimeofday(tp)) { /* first try commpage */
+ if (__gettimeofday(tp, tzp) < 0) { /* if it fails, use syscall */
+ return (-1);
+ }
+ }
+
if (tzp) {
if (validtz == 0) {
struct tm *localtm = localtime ((time_t *)&tp->tv_sec);
/* These defn should match the kernel one */
#define UC_TRAD 1
+#define UC_FLAVOR 30
#if defined(__ppc__) || defined(__ppc64__)
#define UC_TRAD64 20
#define UC_TRAD64_VEC 25
-#define UC_FLAVOR 30
#define UC_FLAVOR_VEC 35
#define UC_FLAVOR64 40
#define UC_FLAVOR64_VEC 45
siginfo_t *sinfo,
ucontext_t *uctx
) {
-#if defined(__ppc__) || defined(__ppc64__)
int ctxstyle = UC_FLAVOR;
-#endif
+#if defined(__ppc__) || defined(__ppc64__)
mcontext_t mctx;
mcontext64_t mctx64;
+#endif
#if defined(__DYNAMIC__)
__in_sigtramp++;
#ifdef __i386__
if (sigstyle == UC_TRAD)
sa_handler(sig);
+ else {
+ sa_sigaction(sig, sinfo, uctx);
+ }
#elif defined(__ppc__) || defined(__ppc64__)
if ((sigstyle == UC_TRAD) || (sigstyle == UC_TRAD64) || (sigstyle == UC_TRAD64_VEC))
sa_handler(sig);
#if defined(__DYNAMIC__)
__in_sigtramp--;
#endif
-#if defined(__ppc__) || defined(__ppc64__)
- {
/* sigreturn(uctx, ctxstyle); */
/* syscall (SYS_SIGRETURN, uctx, ctxstyle); */
syscall (184, uctx, ctxstyle);
- }
-#else
- sigreturn(uctx);
-#endif /* __ppc__ || __ppc64__ */
}