diff options
Diffstat (limited to 'usr/src/lib/libsaveargs/tests')
-rw-r--r-- | usr/src/lib/libsaveargs/tests/README | 14 | ||||
-rw-r--r-- | usr/src/lib/libsaveargs/tests/dump/Makefile | 39 | ||||
-rw-r--r-- | usr/src/lib/libsaveargs/tests/dump/dump.c | 167 | ||||
-rw-r--r-- | usr/src/lib/libsaveargs/tests/functional/Makefile | 45 | ||||
-rw-r--r-- | usr/src/lib/libsaveargs/tests/functional/align.c | 32 | ||||
-rw-r--r-- | usr/src/lib/libsaveargs/tests/functional/basic.c | 32 | ||||
-rw-r--r-- | usr/src/lib/libsaveargs/tests/functional/big-struct-ret-and-spill.c | 38 | ||||
-rw-r--r-- | usr/src/lib/libsaveargs/tests/functional/big-struct-ret.c | 38 | ||||
-rw-r--r-- | usr/src/lib/libsaveargs/tests/functional/small-struct-ret-and-spill.c | 37 | ||||
-rw-r--r-- | usr/src/lib/libsaveargs/tests/functional/small-struct-ret.c | 37 | ||||
-rw-r--r-- | usr/src/lib/libsaveargs/tests/functional/stack-spill.c | 32 | ||||
-rw-r--r-- | usr/src/lib/libsaveargs/tests/functional/test.sh | 37 | ||||
-rw-r--r-- | usr/src/lib/libsaveargs/tests/testmatch/Makefile | 40 | ||||
-rw-r--r-- | usr/src/lib/libsaveargs/tests/testmatch/data.s | 468 | ||||
-rw-r--r-- | usr/src/lib/libsaveargs/tests/testmatch/testmatch.c | 175 |
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); +} |