summaryrefslogtreecommitdiff
path: root/usr/src/lib/libsaveargs/tests
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libsaveargs/tests')
-rw-r--r--usr/src/lib/libsaveargs/tests/README14
-rw-r--r--usr/src/lib/libsaveargs/tests/dump/Makefile39
-rw-r--r--usr/src/lib/libsaveargs/tests/dump/dump.c167
-rw-r--r--usr/src/lib/libsaveargs/tests/functional/Makefile45
-rw-r--r--usr/src/lib/libsaveargs/tests/functional/align.c32
-rw-r--r--usr/src/lib/libsaveargs/tests/functional/basic.c32
-rw-r--r--usr/src/lib/libsaveargs/tests/functional/big-struct-ret-and-spill.c38
-rw-r--r--usr/src/lib/libsaveargs/tests/functional/big-struct-ret.c38
-rw-r--r--usr/src/lib/libsaveargs/tests/functional/small-struct-ret-and-spill.c37
-rw-r--r--usr/src/lib/libsaveargs/tests/functional/small-struct-ret.c37
-rw-r--r--usr/src/lib/libsaveargs/tests/functional/stack-spill.c32
-rw-r--r--usr/src/lib/libsaveargs/tests/functional/test.sh37
-rw-r--r--usr/src/lib/libsaveargs/tests/testmatch/Makefile40
-rw-r--r--usr/src/lib/libsaveargs/tests/testmatch/data.s468
-rw-r--r--usr/src/lib/libsaveargs/tests/testmatch/testmatch.c175
15 files changed, 1231 insertions, 0 deletions
diff --git a/usr/src/lib/libsaveargs/tests/README b/usr/src/lib/libsaveargs/tests/README
new file mode 100644
index 0000000000..b3d833faa1
--- /dev/null
+++ b/usr/src/lib/libsaveargs/tests/README
@@ -0,0 +1,14 @@
+testmatch:
+
+ A stub program that tests the saveargs matcher against a variety of
+ function prologues (assembled from data.s)
+
+functional:
+
+ Actually test the full chunk of the (libproc) side of the code, running
+ pstack on the range of test apps.
+
+dump:
+
+ Display each function in a given object we believe to have saved
+ arguments.
diff --git a/usr/src/lib/libsaveargs/tests/dump/Makefile b/usr/src/lib/libsaveargs/tests/dump/Makefile
new file mode 100644
index 0000000000..41c2f51cd9
--- /dev/null
+++ b/usr/src/lib/libsaveargs/tests/dump/Makefile
@@ -0,0 +1,39 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2012, Richard Lowe.
+#
+
+include $(SRC)/Makefile.master
+include $(SRC)/Makefile.master.64
+
+.KEEP_STATE:
+
+OBJECTS = dump.o
+PROG = dump
+
+CFLAGS += -m64
+
+LDLIBS64 += -lctf -lelf -lsaveargs
+
+C99MODE = $(C99_ENABLE)
+
+$(PROG): $(OBJECTS)
+ $(LINK.c) -o $@ $(OBJECTS) $(LDLIBS64)
+clean:
+ $(RM) $(OBJECTS) $(PROG)
+
+clobber: clean
+
+all: $(PROG)
+
+install: all
diff --git a/usr/src/lib/libsaveargs/tests/dump/dump.c b/usr/src/lib/libsaveargs/tests/dump/dump.c
new file mode 100644
index 0000000000..7b4a628d4a
--- /dev/null
+++ b/usr/src/lib/libsaveargs/tests/dump/dump.c
@@ -0,0 +1,167 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2011, Robert Mustacchi, Inc. All rights reserved.
+ * Copyright 2013, Richard Lowe.
+ */
+
+#include <err.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <libctf.h>
+#include <saveargs.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <unistd.h>
+
+extern const char *__progname;
+
+typedef struct symtab_sym {
+ GElf_Sym ss_sym;
+ char *ss_name;
+ ctf_funcinfo_t ss_finfo;
+ uint8_t *ss_data;
+ size_t ss_size;
+} symtab_sym_t;
+
+static void
+walk_symtab(Elf *elf, char *fname, ctf_file_t *fp,
+ void (*callback)(ctf_file_t *, symtab_sym_t *))
+{
+ Elf_Scn *stab = NULL;
+ Elf_Scn *text = NULL;
+ Elf_Data *stabdata = NULL;
+ Elf_Data *textdata = NULL;
+ GElf_Ehdr ehdr;
+ GElf_Shdr stabshdr;
+ GElf_Shdr textshdr;
+ int foundtext = 0, foundstab = 0;
+ symtab_sym_t ss;
+
+ if ((gelf_getehdr(elf, &ehdr)) == NULL)
+ errx(1, "could not read ELF header from %s\n",
+ fname);
+
+ while ((stab = elf_nextscn(elf, stab)) != NULL) {
+ (void) gelf_getshdr(stab, &stabshdr);
+
+ if (stabshdr.sh_type == SHT_SYMTAB) {
+ foundstab = 1;
+ break;
+ }
+ }
+
+ while ((text = elf_nextscn(elf, text)) != NULL) {
+ (void) gelf_getshdr(text, &textshdr);
+
+ if (strcmp(".text", elf_strptr(elf,
+ ehdr.e_shstrndx, (size_t)textshdr.sh_name)) == 0) {
+ foundtext = 1;
+ break;
+ }
+ }
+
+ if (!foundstab || !foundtext)
+ return;
+
+ stabdata = elf_getdata(stab, NULL);
+ textdata = elf_rawdata(text, NULL);
+ for (unsigned symdx = 0;
+ symdx < (stabshdr.sh_size / stabshdr.sh_entsize);
+ symdx++) {
+ (void) gelf_getsym(stabdata, symdx, &ss.ss_sym);
+
+ if ((GELF_ST_TYPE(ss.ss_sym.st_info) != STT_FUNC) ||
+ (ss.ss_sym.st_shndx == SHN_UNDEF))
+ continue;
+
+ ss.ss_name = elf_strptr(elf, stabshdr.sh_link,
+ ss.ss_sym.st_name);
+ ss.ss_data = ((uint8_t *)(textdata->d_buf)) +
+ (ss.ss_sym.st_value - textshdr.sh_addr);
+
+ if (ctf_func_info(fp, symdx, &ss.ss_finfo) == CTF_ERR) {
+ fprintf(stderr, "failed to get funcinfo for: %s\n",
+ ss.ss_name);
+ continue;
+ }
+
+ (void) callback(fp, &ss);
+ }
+}
+
+void
+check_sym(ctf_file_t *ctfp, symtab_sym_t *ss)
+{
+ int rettype = ctf_type_kind(ctfp, ss->ss_finfo.ctc_return);
+ int start_index = 0;
+
+ if (ss->ss_finfo.ctc_argc == 0) /* No arguments, no point */
+ return;
+
+ if (((rettype == CTF_K_STRUCT) || (rettype == CTF_K_UNION)) &&
+ ctf_type_size(ctfp, ss->ss_finfo.ctc_return) > 16)
+ start_index = 1;
+
+ if (saveargs_has_args(ss->ss_data, ss->ss_sym.st_size,
+ ss->ss_finfo.ctc_argc, start_index) != SAVEARGS_NO_ARGS)
+ printf("%s has %d saved args\n", ss->ss_name,
+ ss->ss_finfo.ctc_argc);
+}
+
+int
+main(int argc, char **argv)
+{
+ Elf *elf;
+ ctf_file_t *ctfp;
+ int errp, fd;
+
+ if (ctf_version(CTF_VERSION) == -1)
+ errx(1, "mismatched libctf versions\n");
+
+ if (elf_version(EV_CURRENT) == EV_NONE)
+ errx(1, "mismatched libelf versions\n");
+
+ if (argc != 2)
+ errx(2, "usage: %s <file>\n", __progname);
+
+ if ((ctfp = ctf_open(argv[1], &errp)) == NULL)
+ errx(1, "failed to ctf_open file: %s: %s\n", argv[1],
+ ctf_errmsg(errp));
+
+ if ((fd = open(argv[1], O_RDONLY)) == -1)
+ errx(1, "could not open %s\n", argv[1]);
+
+ if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL)
+ errx(1, "could not interpret ELF from %s\n",
+ argv[1]);
+
+ walk_symtab(elf, argv[1], ctfp, check_sym);
+
+ (void) elf_end(elf);
+ (void) close(fd);
+
+ return (0);
+}
diff --git a/usr/src/lib/libsaveargs/tests/functional/Makefile b/usr/src/lib/libsaveargs/tests/functional/Makefile
new file mode 100644
index 0000000000..d8810eb49a
--- /dev/null
+++ b/usr/src/lib/libsaveargs/tests/functional/Makefile
@@ -0,0 +1,45 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2012, Richard Lowe.
+#
+
+include $(SRC)/Makefile.master
+include $(SRC)/Makefile.master.64
+
+.KEEP_STATE:
+
+PROGS = align \
+ basic \
+ big-struct-ret \
+ big-struct-ret-and-spill \
+ small-struct-ret \
+ small-struct-ret-and-spill \
+ stack-spill
+
+CFLAGS += $(CTF_FLAGS)
+CFLAGS64 += $(CTF_FLAGS)
+
+%: %.c
+ $(LINK.c) -o $@ $< -lc
+ $(CTFCONVERT) -L VERSION $@
+
+all: $(PROGS)
+
+install: all
+
+clean:
+ $(RM) $(PROGS)
+
+clobber: clean
+
+FRC:
diff --git a/usr/src/lib/libsaveargs/tests/functional/align.c b/usr/src/lib/libsaveargs/tests/functional/align.c
new file mode 100644
index 0000000000..731ca5eccb
--- /dev/null
+++ b/usr/src/lib/libsaveargs/tests/functional/align.c
@@ -0,0 +1,32 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2012, Richard Lowe.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+
+int
+test(long a, long b, long c, long d, long e)
+{
+ printf("%ld %ld %ld %ld %ld\n", a, b, c, d, e);
+ for (;;)
+ sleep(60);
+}
+
+int
+main(int argc, char **argv)
+{
+ test(1, 2, 3, 4, 5);
+ return (0);
+}
diff --git a/usr/src/lib/libsaveargs/tests/functional/basic.c b/usr/src/lib/libsaveargs/tests/functional/basic.c
new file mode 100644
index 0000000000..4a6a3819a6
--- /dev/null
+++ b/usr/src/lib/libsaveargs/tests/functional/basic.c
@@ -0,0 +1,32 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2012, Richard Lowe.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+
+int
+test(long a, long b, long c, long d)
+{
+ printf("%ld %ld %ld %ld\n", a, b, c, d);
+ for (;;)
+ sleep(60);
+}
+
+int
+main(int argc, char **argv)
+{
+ test(1, 2, 3, 4);
+ return (0);
+}
diff --git a/usr/src/lib/libsaveargs/tests/functional/big-struct-ret-and-spill.c b/usr/src/lib/libsaveargs/tests/functional/big-struct-ret-and-spill.c
new file mode 100644
index 0000000000..4823346299
--- /dev/null
+++ b/usr/src/lib/libsaveargs/tests/functional/big-struct-ret-and-spill.c
@@ -0,0 +1,38 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2012, Richard Lowe.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+
+struct foo {
+ long a;
+ long b;
+ long c;
+};
+
+struct foo
+test(long a, long b, long c, long d, long e, long f, long g, long h)
+{
+ printf("%ld %ld %ld %ld %ld %ld %ld %ld\n", a, b, c, d, e, f, g, h);
+ for (;;)
+ sleep(60);
+}
+
+int
+main(int argc, char **argv)
+{
+ test(1, 2, 3, 4, 5, 6, 7, 8);
+ return (0);
+}
diff --git a/usr/src/lib/libsaveargs/tests/functional/big-struct-ret.c b/usr/src/lib/libsaveargs/tests/functional/big-struct-ret.c
new file mode 100644
index 0000000000..0953622f0d
--- /dev/null
+++ b/usr/src/lib/libsaveargs/tests/functional/big-struct-ret.c
@@ -0,0 +1,38 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2012, Richard Lowe.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+
+struct foo {
+ long a;
+ long b;
+ long c;
+};
+
+struct foo
+test(long a, long b, long c, long d)
+{
+ printf("%ld %ld %ld %ld\n", a, b, c, d);
+ for (;;)
+ sleep(60);
+}
+
+int
+main(int argc, char **argv)
+{
+ test(1, 2, 3, 4);
+ return (0);
+}
diff --git a/usr/src/lib/libsaveargs/tests/functional/small-struct-ret-and-spill.c b/usr/src/lib/libsaveargs/tests/functional/small-struct-ret-and-spill.c
new file mode 100644
index 0000000000..6cbc0cde47
--- /dev/null
+++ b/usr/src/lib/libsaveargs/tests/functional/small-struct-ret-and-spill.c
@@ -0,0 +1,37 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2012, Richard Lowe.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+
+struct foo {
+ long a;
+ long b;
+};
+
+struct foo
+test(long a, long b, long c, long d, long e, long f, long g, long h)
+{
+ printf("%ld %ld %ld %ld %ld %ld %ld %ld\n", a, b, c, d, e, f, g, h);
+ for (;;)
+ sleep(60);
+}
+
+int
+main(int argc, char **argv)
+{
+ test(1, 2, 3, 4, 5, 6, 7, 8);
+ return (0);
+}
diff --git a/usr/src/lib/libsaveargs/tests/functional/small-struct-ret.c b/usr/src/lib/libsaveargs/tests/functional/small-struct-ret.c
new file mode 100644
index 0000000000..3731365f11
--- /dev/null
+++ b/usr/src/lib/libsaveargs/tests/functional/small-struct-ret.c
@@ -0,0 +1,37 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2012, Richard Lowe.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+
+struct foo {
+ long a;
+ long b;
+};
+
+struct foo
+test(long a, long b, long c, long d)
+{
+ printf("%ld %ld %ld %ld\n", a, b, c, d);
+ for (;;)
+ sleep(60);
+}
+
+int
+main(int argc, char **argv)
+{
+ test(1, 2, 3, 4);
+ return (0);
+}
diff --git a/usr/src/lib/libsaveargs/tests/functional/stack-spill.c b/usr/src/lib/libsaveargs/tests/functional/stack-spill.c
new file mode 100644
index 0000000000..4324d60c27
--- /dev/null
+++ b/usr/src/lib/libsaveargs/tests/functional/stack-spill.c
@@ -0,0 +1,32 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2012, Richard Lowe.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+
+int
+test(long a, long b, long c, long d, long e, long f, long g, long h)
+{
+ printf("%ld %ld %ld %ld %ld %ld %ld %ld\n", a, b, c, d, e, f, g, h);
+ for (;;)
+ sleep(60);
+}
+
+int
+main(int argc, char **argv)
+{
+ test(1, 2, 3, 4, 5, 6, 7, 8);
+ return (0);
+}
diff --git a/usr/src/lib/libsaveargs/tests/functional/test.sh b/usr/src/lib/libsaveargs/tests/functional/test.sh
new file mode 100644
index 0000000000..dea1059b2c
--- /dev/null
+++ b/usr/src/lib/libsaveargs/tests/functional/test.sh
@@ -0,0 +1,37 @@
+#! /usr/bin/ksh
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2012, Richard Lowe.
+#
+
+function tester {
+ prog=${1}
+ pattern=${2}
+
+ ./$prog >/dev/null &
+ pid=$!
+ if (/usr/bin/amd64/pstack $pid | /usr/xpg4/bin/grep -q "${pattern}"); then
+ echo "pass: ${prog}"
+ else
+ echo "FAIL: ${prog}"
+ fi
+ kill $pid
+}
+
+tester align "test (1, 2, 3, 4, 5)"
+tester basic "test (1, 2, 3, 4)"
+tester big-struct-ret "test (1, 2, 3, 4)"
+tester big-struct-ret-and-spill "test (1, 2, 3, 4, 5, 6, 7, 8)"
+tester small-struct-ret "test (1, 2, 3, 4)"
+tester small-struct-ret-and-spill "test (1, 2, 3, 4, 5, 6, 7, 8)"
+tester stack-spill "test (1, 2, 3, 4, 5, 6, 7, 8)"
diff --git a/usr/src/lib/libsaveargs/tests/testmatch/Makefile b/usr/src/lib/libsaveargs/tests/testmatch/Makefile
new file mode 100644
index 0000000000..0bea0f4d87
--- /dev/null
+++ b/usr/src/lib/libsaveargs/tests/testmatch/Makefile
@@ -0,0 +1,40 @@
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2012, Richard Lowe.
+#
+
+include $(SRC)/Makefile.master
+include $(SRC)/Makefile.master.64
+
+.KEEP_STATE:
+
+OBJECTS = testmatch.o data.o
+PROG = testmatch
+
+LDLIBS64 += -lsaveargs
+
+ASFLAGS += -P
+AS_CPPFLAGS += -D_ASM
+
+$(PROG): $(OBJECTS)
+ $(LINK.c) -o $@ $(OBJECTS) $(LDLIBS64)
+
+clean:
+ $(RM) $(OBJECTS) $(PROG)
+
+clobber: clean
+
+all: $(PROG)
+
+install: all
diff --git a/usr/src/lib/libsaveargs/tests/testmatch/data.s b/usr/src/lib/libsaveargs/tests/testmatch/data.s
new file mode 100644
index 0000000000..77a5b30394
--- /dev/null
+++ b/usr/src/lib/libsaveargs/tests/testmatch/data.s
@@ -0,0 +1,468 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2012, Richard Lowe.
+ */
+
+#define FUNC(x) \
+ .text; \
+ .align 16; \
+ .globl x; \
+ .type x, @function; \
+x:
+
+#define SET_SIZE(x, x_size) \
+ .size x, [.-x]; \
+ .globl x_size; \
+ .type x_size, @object; \
+x_size:
+
+/*
+ * Extracted versions of the functional tests
+ *
+ * Named of the form <compiler>-<prologue style>-<nature of test>
+ * basic -- A regular function
+ * align -- odd number of arguments needing save-area
+ * alignment
+ * big-struct-ret -- returns a > 16byte structure by value
+ * big-struct-ret-and-spill -- returns a > 16byte structure by value and
+ * spills args to the stack
+ * small-struct-ret -- returns a < 16byte structure by value
+ * small-struct-ret-and-spill -- returns a < 16byte structure by value and
+ * spills args to the stack
+ * stack-spill -- spills arguments to the stack
+ */
+FUNC(gcc_mov_align)
+pushq %rbp
+movq %rsp, %rbp
+movq %rbx, -0x38(%rbp)
+movq %r8, -0x28(%rbp)
+movq %rcx, -0x20(%rbp)
+movq %rdx, -0x18(%rbp)
+movq %rsi, -0x10(%rbp)
+movq %rdi, -0x8(%rbp)
+subq $0x70, %rsp
+SET_SIZE(gcc_mov_align, gcc_mov_align_end)
+
+FUNC(gcc_mov_basic)
+pushq %rbp
+movq %rsp, %rbp
+movq %rbx,-0x28(%rbp)
+movq %rcx,-0x20(%rbp)
+movq %rdx,-0x18(%rbp)
+movq %rsi,-0x10(%rbp)
+movq %rdi,-0x8(%rbp)
+subq $0x50,%rsp
+SET_SIZE(gcc_mov_basic, gcc_mov_basic_end)
+
+FUNC(gcc_mov_noorder)
+pushq %rbp
+movq %rsp, %rbp
+movq %rcx,-0x20(%rbp)
+movq %rbx,-0x28(%rbp)
+movq %rdi,-0x8(%rbp)
+movq %rdx,-0x18(%rbp)
+movq %rsi,-0x10(%rbp)
+subq $0x50,%rsp
+SET_SIZE(gcc_mov_noorder, gcc_mov_noorder_end)
+
+FUNC(gcc_mov_big_struct_ret)
+pushq %rbp
+movq %rsp,%rbp
+movq %rbx,-0x28(%rbp)
+movq %r8,-0x20(%rbp)
+movq %rcx,-0x18(%rbp)
+movq %rdx,-0x10(%rbp)
+movq %rsi,-0x8(%rbp)
+subq $0x50,%rsp
+SET_SIZE(gcc_mov_big_struct_ret, gcc_mov_big_struct_ret_end)
+
+FUNC(gcc_mov_struct_noorder)
+pushq %rbp
+movq %rsp,%rbp
+movq %rcx,-0x18(%rbp)
+movq %r8,-0x20(%rbp)
+movq %rsi,-0x8(%rbp)
+movq %rdx,-0x10(%rbp)
+movq %rbx,-0x28(%rbp)
+subq $0x50,%rsp
+SET_SIZE(gcc_mov_struct_noorder, gcc_mov_struct_noorder_end)
+
+FUNC(gcc_mov_big_struct_ret_and_spill)
+pushq %rbp
+movq %rsp,%rbp
+movq %rbx,-0x38(%rbp)
+movq %r9,-0x28(%rbp)
+movq %r8,-0x20(%rbp)
+movq %rcx,-0x18(%rbp)
+movq %rdx,-0x10(%rbp)
+movq %rsi,-0x8(%rbp)
+subq $0x90,%rsp
+SET_SIZE(gcc_mov_big_struct_ret_and_spill, gcc_mov_big_struct_ret_and_spill_end)
+
+FUNC(gcc_mov_small_struct_ret)
+pushq %rbp
+movq %rsp,%rbp
+movq %rbx,-0x28(%rbp)
+movq %rcx,-0x20(%rbp)
+movq %rdx,-0x18(%rbp)
+movq %rsi,-0x10(%rbp)
+movq %rdi,-0x8(%rbp)
+subq $0x50,%rsp
+SET_SIZE(gcc_mov_small_struct_ret, gcc_mov_small_struct_ret_end)
+
+FUNC(gcc_mov_small_struct_ret_and_spill)
+pushq %rbp
+movq %rsp,%rbp
+movq %rbx,-0x38(%rbp)
+movq %r9,-0x30(%rbp)
+movq %r8,-0x28(%rbp)
+movq %rcx,-0x20(%rbp)
+movq %rdx,-0x18(%rbp)
+movq %rsi,-0x10(%rbp)
+movq %rdi,-0x8(%rbp)
+subq $0x90,%rsp
+SET_SIZE(gcc_mov_small_struct_ret_and_spill, gcc_mov_small_struct_ret_and_spill_end)
+
+FUNC(gcc_mov_stack_spill)
+pushq %rbp
+movq %rsp,%rbp
+movq %rbx,-0x38(%rbp)
+movq %r9,-0x30(%rbp)
+movq %r8,-0x28(%rbp)
+movq %rcx,-0x20(%rbp)
+movq %rdx,-0x18(%rbp)
+movq %rsi,-0x10(%rbp)
+movq %rdi,-0x8(%rbp)
+subq $0x90,%rsp
+SET_SIZE(gcc_mov_stack_spill, gcc_mov_stack_spill_end)
+
+FUNC(gcc_push_align)
+pushq %rbp
+movq %rsp,%rbp
+pushq %rdi
+pushq %rsi
+pushq %rdx
+pushq %rcx
+pushq %r8
+subq $0x8,%rsp
+subq $0x30,%rsp
+SET_SIZE(gcc_push_align, gcc_push_align_end)
+
+FUNC(gcc_push_basic)
+pushq %rbp
+movq %rsp,%rbp
+pushq %rdi
+pushq %rsi
+pushq %rdx
+pushq %rcx
+subq $0x20,%rsp
+SET_SIZE(gcc_push_basic, gcc_push_basic_end)
+
+FUNC(gcc_push_noorder)
+pushq %rbp
+movq %rsp,%rbp
+pushq %rsi
+pushq %rdi
+pushq %rcx
+pushq %rdx
+subq $0x20,%rsp
+SET_SIZE(gcc_push_noorder, gcc_push_noorder_end)
+
+FUNC(gcc_push_big_struct_ret)
+pushq %rbp
+movq %rsp,%rbp
+pushq %rsi
+pushq %rdx
+pushq %rcx
+pushq %r8
+subq $0x30,%rsp
+SET_SIZE(gcc_push_big_struct_ret, gcc_push_big_struct_ret_end)
+
+FUNC(gcc_push_struct_noorder)
+pushq %rbp
+movq %rsp,%rbp
+pushq %rdx
+pushq %rsi
+pushq %r8
+pushq %rcx
+subq $0x30,%rsp
+SET_SIZE(gcc_push_struct_noorder, gcc_push_struct_noorder_end)
+
+FUNC(gcc_push_big_struct_ret_and_spill)
+pushq %rbp
+movq %rsp,%rbp
+pushq %rsi
+pushq %rdx
+pushq %rcx
+pushq %r8
+pushq %r9
+subq $0x8,%rsp
+subq $0x50,%rsp
+SET_SIZE(gcc_push_big_struct_ret_and_spill, gcc_push_big_struct_ret_and_spill_end)
+
+FUNC(gcc_push_small_struct_ret)
+pushq %rbp
+movq %rsp,%rbp
+pushq %rdi
+pushq %rsi
+pushq %rdx
+pushq %rcx
+subq $0x20,%rsp
+SET_SIZE(gcc_push_small_struct_ret, gcc_push_small_struct_ret_end)
+
+FUNC(gcc_push_small_struct_ret_and_spill)
+pushq %rbp
+movq %rsp,%rbp
+pushq %rdi
+pushq %rsi
+pushq %rdx
+pushq %rcx
+pushq %r8
+pushq %r9
+subq $0x50,%rsp
+SET_SIZE(gcc_push_small_struct_ret_and_spill, gcc_push_small_struct_ret_and_spill_end)
+
+FUNC(gcc_push_stack_spill)
+pushq %rbp
+movq %rsp,%rbp
+pushq %rdi
+pushq %rsi
+pushq %rdx
+pushq %rcx
+pushq %r8
+pushq %r9
+subq $0x50,%rsp
+SET_SIZE(gcc_push_stack_spill, gcc_push_stack_spill_end)
+
+FUNC(ss_mov_align)
+pushq %rbp
+movq %rsp,%rbp
+subq $0x30,%rsp
+movq %rdi,-0x8(%rbp)
+movq %rsi,-0x10(%rbp)
+movq %rdx,-0x18(%rbp)
+movq %rcx,-0x20(%rbp)
+movq %r8,-0x28(%rbp)
+SET_SIZE(ss_mov_align, ss_mov_align_end)
+
+FUNC(ss_mov_basic)
+pushq %rbp
+movq %rsp,%rbp
+subq $0x20,%rsp
+movq %rdi,-0x8(%rbp)
+movq %rsi,-0x10(%rbp)
+movq %rdx,-0x18(%rbp)
+movq %rcx,-0x20(%rbp)
+SET_SIZE(ss_mov_basic, ss_mov_basic_end)
+
+FUNC(ss_mov_big_struct_ret)
+pushq %rbp
+movq %rsp,%rbp
+subq $0x30,%rsp
+movq %rdi,-0x8(%rbp)
+movq %rsi,-0x10(%rbp)
+movq %rdx,-0x18(%rbp)
+movq %rcx,-0x20(%rbp)
+movq %r8,-0x28(%rbp)
+SET_SIZE(ss_mov_big_struct_ret, ss_mov_big_struct_ret_end)
+
+FUNC(ss_mov_big_struct_ret_and_spill)
+pushq %rbp
+movq %rsp,%rbp
+subq $0x50,%rsp
+movq %rdi,-0x8(%rbp)
+movq %rsi,-0x10(%rbp)
+movq %rdx,-0x18(%rbp)
+movq %rcx,-0x20(%rbp)
+movq %r8,-0x28(%rbp)
+movq %r9,-0x30(%rbp)
+SET_SIZE(ss_mov_big_struct_ret_and_spill, ss_mov_big_struct_ret_and_spill_end)
+
+FUNC(ss_mov_small_struct_ret)
+pushq %rbp
+movq %rsp,%rbp
+subq $0x20,%rsp
+movq %rdi,-0x8(%rbp)
+movq %rsi,-0x10(%rbp)
+movq %rdx,-0x18(%rbp)
+movq %rcx,-0x20(%rbp)
+SET_SIZE(ss_mov_small_struct_ret, ss_mov_small_struct_ret_end)
+
+FUNC(ss_mov_small_struct_ret_and_spill)
+pushq %rbp
+movq %rsp,%rbp
+subq $0x50,%rsp
+movq %rdi,-0x8(%rbp)
+movq %rsi,-0x10(%rbp)
+movq %rdx,-0x18(%rbp)
+movq %rcx,-0x20(%rbp)
+movq %r8,-0x28(%rbp)
+movq %r9,-0x30(%rbp)
+SET_SIZE(ss_mov_small_struct_ret_and_spill, ss_mov_small_struct_ret_and_spill_end)
+
+FUNC(ss_mov_stack_spill)
+pushq %rbp
+movq %rsp,%rbp
+subq $0x50,%rsp
+movq %rdi,-0x8(%rbp)
+movq %rsi,-0x10(%rbp)
+movq %rdx,-0x18(%rbp)
+movq %rcx,-0x20(%rbp)
+movq %r8,-0x28(%rbp)
+movq %r9,-0x30(%rbp)
+SET_SIZE(ss_mov_stack_spill, ss_mov_stack_spill_end)
+
+/* DTrace instrumentation */
+FUNC(dtrace_instrumented)
+int $0x3
+movq %rsp, %rbp
+movq %rbx,-0x28(%rbp)
+movq %rcx,-0x20(%rbp)
+movq %rdx,-0x18(%rbp)
+movq %rsi,-0x10(%rbp)
+movq %rdi,-0x8(%rbp)
+subq $0x50,%rsp
+SET_SIZE(dtrace_instrumented, dtrace_instrumented_end)
+
+/*
+ * System functions with special characteristics, be they non-initial FP save,
+ * gaps between FP save and argument saving, or gaps between saved arguments.
+ */
+FUNC(kmem_alloc)
+leaq -0x1(%rdi),%rax
+pushq %rbp
+movq %rax,%rdx
+movq %rsp,%rbp
+subq $0x30,%rsp
+shrq $0x3,%rdx
+movq %r12,-0x28(%rbp)
+movq %rbx,-0x30(%rbp)
+cmpq $0x1ff,%rdx
+movq %r13,-0x20(%rbp)
+movq %r14,-0x18(%rbp)
+movq %rsi,-0x10(%rbp)
+movq %rdi,-0x8(%rbp)
+movq %rdi,%r12
+SET_SIZE(kmem_alloc, kmem_alloc_end)
+
+FUNC(uts_kill)
+pushq %rbp
+movq %rsp,%rbp
+subq $0x50,%rsp
+movq %rbx,-0x28(%rbp)
+leaq -0x50(%rbp),%rbx
+movq %r12,-0x20(%rbp)
+movq %r13,-0x18(%rbp)
+movq %rsi,-0x10(%rbp)
+movl %edi,%r12d
+movq %rdi,-0x8(%rbp)
+SET_SIZE(uts_kill, uts_kill_end)
+
+FUNC(av1394_ic_bitreverse)
+movq %rdi,%rdx
+movq $0x5555555555555555,%rax
+movq $0x3333333333333333,%rcx
+shrq $0x1,%rdx
+pushq %rbp
+andq %rax,%rdx
+andq %rdi,%rax
+addq %rax,%rax
+movq %rsp,%rbp
+subq $0x10,%rsp
+orq %rdx,%rax
+movq %rdi,-0x8(%rbp)
+SET_SIZE(av1394_ic_bitreverse, av1394_ic_bitreverse_end)
+
+/* Problematic functions which should not match */
+
+FUNC(no_fp) /* No frame pointer */
+movq %rdi, %rsi
+movq %rsi, %rdi
+movq %rbx,-0x28(%rbp)
+movq %rcx,-0x20(%rbp)
+movq %rdx,-0x18(%rbp)
+movq %rsi,-0x10(%rbp)
+movq %rdi,-0x8(%rbp)
+subq $0x50,%rsp
+SET_SIZE(no_fp, no_fp_end)
+
+/* Small structure return, but with an SSE type (thus forcing it to the stack) */
+FUNC(small_struct_ret_w_float)
+pushq %rbp
+movq %rsp,%rbp
+movq %rdi,-0x8(%rbp)
+subq $0x30,%rsp
+SET_SIZE(small_struct_ret_w_float, small_struct_ret_w_float_end)
+
+/* Big structure return, but with an SSE type */
+FUNC(big_struct_ret_w_float)
+pushq %rbp
+movq %rsp,%rbp
+movq %rsi,-0x8(%rbp)
+subq $0x50,%rsp
+movq %rsi,-0x48(%rbp)
+movq -0x48(%rbp),%rax
+movq %rax,%rsi
+movl $0x400f60,%edi
+movl $0x0,%eax
+movl $0x1770,%edi
+movl $0x0,%eax
+leave
+ret
+SET_SIZE(big_struct_ret_w_float, big_struct_ret_w_float_end)
+
+FUNC(big_struct_arg_by_value)
+pushq %rbp
+movq %rsp,%rbp
+movq %rdi,-0x8(%rbp)
+subq $0x40,%rsp
+SET_SIZE(big_struct_arg_by_value, big_struct_arg_by_value_end)
+
+FUNC(small_struct_arg_by_value)
+pushq %rbp
+movq %rsp,%rbp
+movq %rdx,-0x18(%rbp)
+movq %rsi,-0x10(%rbp)
+movq %rdi,-0x8(%rbp)
+subq $0x50,%rsp
+SET_SIZE(small_struct_arg_by_value, small_struct_arg_by_value_end)
+
+FUNC(interleaved_argument_saves)
+pushq %rbp
+movq %rdi,%rax
+shlq $0x21,%rax
+movq %rsp,%rbp
+shrq $0x29,%rax
+subq $0x30,%rsp
+movq %rdi,-0x8(%rbp)
+movq %rbx,-0x28(%rbp)
+movzbl %dil,%edi
+movq %rcx,-0x20(%rbp)
+movq %rdx,-0x18(%rbp)
+movq %rsi,-0x10(%rbp)
+movq 0x0(,%rax,8),%rax
+SET_SIZE(interleaved_argument_saves, interleaved_argument_saves_end)
+
+FUNC(jmp_table)
+pushq %rbp
+movq %rsp,%rbp
+.word 0x9afe
+.word 0xffff
+.word 0xffff
+.word 0xa8ff
+.word 0xffff
+.word 0xffff
+.word 0x7cff
+.word 0xffff
+.word 0xffff
+SET_SIZE(jmp_table, jmp_table_end)
diff --git a/usr/src/lib/libsaveargs/tests/testmatch/testmatch.c b/usr/src/lib/libsaveargs/tests/testmatch/testmatch.c
new file mode 100644
index 0000000000..0af4a1cb78
--- /dev/null
+++ b/usr/src/lib/libsaveargs/tests/testmatch/testmatch.c
@@ -0,0 +1,175 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2012, Richard Lowe.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <saveargs.h>
+
+#define DEF_TEST(name) \
+ extern uint8_t name[]; \
+ extern int name##_end
+
+#define SIZE_OF(name) ((caddr_t)&name##_end - (caddr_t)&name)
+
+#define TEST_GOOD(name, argc) \
+ if (saveargs_has_args(name, SIZE_OF(name), argc, 0) == \
+ SAVEARGS_TRAD_ARGS) \
+ printf("Pass: %s\n", #name); \
+ else \
+ printf("FAIL: %s\n", #name);
+
+#define TEST_GOOD_STRUCT(name, argc) \
+ if (saveargs_has_args(name, SIZE_OF(name), argc, 1) == \
+ SAVEARGS_STRUCT_ARGS) \
+ printf("Pass: %s\n", #name); \
+ else \
+ printf("FAIL: %s\n", #name);
+
+/*
+ * GCC deals with structures differently, so TRAD args is actually correct for
+ * this
+ */
+#define TEST_GOOD_GSTRUCT(name, argc) \
+ if (saveargs_has_args(name, SIZE_OF(name), argc, 1) == \
+ SAVEARGS_TRAD_ARGS) \
+ printf("Pass: %s\n", #name); \
+ else \
+ printf("FAIL: %s\n", #name);
+
+#define TEST_BAD(name, argc) \
+ if (saveargs_has_args(name, SIZE_OF(name), argc, 0) == \
+ SAVEARGS_NO_ARGS) \
+ printf("Pass: %s\n", #name); \
+ else \
+ printf("FAIL: %s\n", #name);
+
+#define TEST_BAD_STRUCT(name, argc) \
+ if (saveargs_has_args(name, SIZE_OF(name), argc, 1) == \
+ SAVEARGS_NO_ARGS) \
+ printf("Pass: %s\n", #name); \
+ else \
+ printf("FAIL: %s\n", #name);
+
+#define TEST_BAD_GSTRUCT(name, argc) \
+ if (saveargs_has_args(name, SIZE_OF(name), argc, 1) == \
+ SAVEARGS_NO_ARGS) \
+ printf("Pass: %s\n", #name); \
+ else \
+ printf("FAIL: %s\n", #name);
+
+DEF_TEST(gcc_mov_align);
+DEF_TEST(gcc_mov_basic);
+DEF_TEST(gcc_mov_noorder);
+DEF_TEST(gcc_mov_struct_noorder);
+DEF_TEST(gcc_mov_big_struct_ret);
+DEF_TEST(gcc_mov_big_struct_ret_and_spill);
+DEF_TEST(gcc_mov_small_struct_ret);
+DEF_TEST(gcc_mov_small_struct_ret_and_spill);
+DEF_TEST(gcc_mov_stack_spill);
+
+DEF_TEST(gcc_push_align);
+DEF_TEST(gcc_push_basic);
+DEF_TEST(gcc_push_noorder);
+DEF_TEST(gcc_push_struct_noorder);
+DEF_TEST(gcc_push_big_struct_ret);
+DEF_TEST(gcc_push_big_struct_ret_and_spill);
+DEF_TEST(gcc_push_small_struct_ret);
+DEF_TEST(gcc_push_small_struct_ret_and_spill);
+DEF_TEST(gcc_push_stack_spill);
+
+DEF_TEST(ss_mov_align);
+DEF_TEST(ss_mov_basic);
+DEF_TEST(ss_mov_big_struct_ret);
+DEF_TEST(ss_mov_big_struct_ret_and_spill);
+DEF_TEST(ss_mov_small_struct_ret);
+DEF_TEST(ss_mov_small_struct_ret_and_spill);
+DEF_TEST(ss_mov_stack_spill);
+
+DEF_TEST(dtrace_instrumented);
+DEF_TEST(kmem_alloc);
+DEF_TEST(uts_kill);
+DEF_TEST(av1394_ic_bitreverse);
+
+DEF_TEST(small_struct_ret_w_float);
+DEF_TEST(big_struct_ret_w_float);
+
+DEF_TEST(interleaved_argument_saves);
+DEF_TEST(jmp_table);
+
+/*
+ * Functions which should not match
+ *
+ * no_fp -- valid save-args sequence with no saved FP
+ * big_struct_arg_by_value -- function with big struct passed by value
+ * small_struct_arg_by_value -- function with small struct passed by value
+ */
+DEF_TEST(no_fp);
+DEF_TEST(big_struct_arg_by_value);
+DEF_TEST(small_struct_arg_by_value);
+
+int
+main(int argc, char **argv)
+{
+ TEST_GOOD(kmem_alloc, 2);
+ TEST_GOOD(uts_kill, 2);
+ TEST_GOOD(av1394_ic_bitreverse, 1);
+ TEST_GOOD(dtrace_instrumented, 4);
+ TEST_GOOD_GSTRUCT(big_struct_ret_w_float, 1);
+ TEST_BAD(no_fp, 5);
+
+ TEST_GOOD(gcc_mov_align, 5);
+ TEST_GOOD(gcc_push_align, 5);
+ TEST_GOOD(ss_mov_align, 5);
+
+ TEST_GOOD(gcc_mov_basic, 4);
+ TEST_GOOD(gcc_push_basic, 4);
+ TEST_GOOD(ss_mov_basic, 4);
+
+ TEST_GOOD(gcc_mov_noorder, 4);
+ TEST_GOOD(gcc_push_noorder, 4);
+
+ TEST_GOOD_GSTRUCT(gcc_mov_big_struct_ret, 4);
+ TEST_GOOD_GSTRUCT(gcc_push_big_struct_ret, 4);
+ TEST_GOOD_STRUCT(ss_mov_big_struct_ret, 4);
+
+ TEST_GOOD_GSTRUCT(gcc_mov_struct_noorder, 4);
+ TEST_GOOD_GSTRUCT(gcc_push_struct_noorder, 4);
+
+ TEST_GOOD_GSTRUCT(gcc_mov_big_struct_ret_and_spill, 8);
+ TEST_GOOD_GSTRUCT(gcc_push_big_struct_ret_and_spill, 8);
+ TEST_GOOD_STRUCT(ss_mov_big_struct_ret_and_spill, 8);
+
+ TEST_GOOD(gcc_mov_small_struct_ret, 4);
+ TEST_GOOD(gcc_push_small_struct_ret, 4);
+ TEST_GOOD(ss_mov_small_struct_ret, 4);
+
+ TEST_GOOD(gcc_mov_small_struct_ret_and_spill, 8);
+ TEST_GOOD(gcc_push_small_struct_ret_and_spill, 8);
+ TEST_GOOD(ss_mov_small_struct_ret_and_spill, 8);
+
+ TEST_GOOD(gcc_mov_stack_spill, 8);
+ TEST_GOOD(gcc_push_stack_spill, 8);
+ TEST_GOOD(ss_mov_stack_spill, 8);
+
+ TEST_BAD(big_struct_arg_by_value, 2);
+ TEST_BAD(small_struct_arg_by_value, 2);
+
+ TEST_BAD(small_struct_ret_w_float, 1);
+
+ TEST_GOOD(interleaved_argument_saves, 4);
+ TEST_BAD(jmp_table, 1);
+
+ return (0);
+}