From dccb83bb7595af99458935b0c81581e5d4de4707 Mon Sep 17 00:00:00 2001 From: markj Date: Sun, 21 Sep 2014 21:25:41 +0000 Subject: Add some ATF tests for libproc. Differential Revision: D710 Reviewed by: jmmv, ngie, rpaulo --- lib/libproc/Makefile | 4 + lib/libproc/test/Makefile | 5 - lib/libproc/test/t1-bkpt/Makefile | 12 - lib/libproc/test/t1-bkpt/t1-bkpt.c | 71 ------ lib/libproc/test/t2-name2map/Makefile | 12 - lib/libproc/test/t2-name2map/t2-name2map.c | 46 ---- lib/libproc/test/t3-name2sym/Makefile | 12 - lib/libproc/test/t3-name2sym/t3-name2sym.c | 51 ----- lib/libproc/tests/Makefile | 21 ++ lib/libproc/tests/proc_test.c | 347 +++++++++++++++++++++++++++++ lib/libproc/tests/target_prog.c | 59 +++++ 11 files changed, 431 insertions(+), 209 deletions(-) delete mode 100644 lib/libproc/test/Makefile delete mode 100644 lib/libproc/test/t1-bkpt/Makefile delete mode 100644 lib/libproc/test/t1-bkpt/t1-bkpt.c delete mode 100644 lib/libproc/test/t2-name2map/Makefile delete mode 100644 lib/libproc/test/t2-name2map/t2-name2map.c delete mode 100644 lib/libproc/test/t3-name2sym/Makefile delete mode 100644 lib/libproc/test/t3-name2sym/t3-name2sym.c create mode 100644 lib/libproc/tests/Makefile create mode 100644 lib/libproc/tests/proc_test.c create mode 100644 lib/libproc/tests/target_prog.c diff --git a/lib/libproc/Makefile b/lib/libproc/Makefile index dafe10d..d665dc4 100644 --- a/lib/libproc/Makefile +++ b/lib/libproc/Makefile @@ -29,4 +29,8 @@ SHLIB_MAJOR= 2 MAN= +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + .include diff --git a/lib/libproc/test/Makefile b/lib/libproc/test/Makefile deleted file mode 100644 index e4d33f8..0000000 --- a/lib/libproc/test/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# $FreeBSD$ - -SUBDIR= t1-bkpt t2-name2map t3-name2sym - -.include diff --git a/lib/libproc/test/t1-bkpt/Makefile b/lib/libproc/test/t1-bkpt/Makefile deleted file mode 100644 index eb5b37f..0000000 --- a/lib/libproc/test/t1-bkpt/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# $FreeBSD$ - -PROG= t1-bkpt - -SRCS= t1-bkpt.c - -LDADD= -lproc -lelf -lrtld_db -lutil -DPADD= ${LIBPROC} ${LIBELF} - -MAN= - -.include diff --git a/lib/libproc/test/t1-bkpt/t1-bkpt.c b/lib/libproc/test/t1-bkpt/t1-bkpt.c deleted file mode 100644 index 1cd4d17..0000000 --- a/lib/libproc/test/t1-bkpt/t1-bkpt.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2010 The FreeBSD Foundation - * All rights reserved. - * - * This software was developed by Rui Paulo under sponsorship from the - * FreeBSD Foundation. - * - * 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 AUTHOR AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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. - * - * $FreeBSD$ - */ -#include -#include - -#include -#include -#include -#include - -int __noinline -t1_bkpt_t() -{ - printf("TEST OK\n"); -} - -int -t1_bkpt_d() -{ - struct proc_handle *phdl; - char *targv[] = { "t1-bkpt-t", NULL}; - unsigned long saved; - - proc_create("./t1-bkpt", targv, NULL, NULL, &phdl); - assert(proc_bkptset(phdl, (uintptr_t)t1_bkpt_t, &saved) == 0); - proc_continue(phdl); - assert(proc_wstatus(phdl) == PS_STOP); - proc_bkptexec(phdl, saved); - proc_continue(phdl); - proc_wstatus(phdl); - proc_free(phdl); -} - - -int -main(int argc, char **argv) -{ - if (!strcmp(argv[0], "t1-bkpt-t")) - t1_bkpt_t(); - else - t1_bkpt_d(); -} - diff --git a/lib/libproc/test/t2-name2map/Makefile b/lib/libproc/test/t2-name2map/Makefile deleted file mode 100644 index 9002acc..0000000 --- a/lib/libproc/test/t2-name2map/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# $FreeBSD$ - -PROG= t2-name2map - -SRCS= t2-name2map.c - -LDADD= -lproc -lelf -lrtld_db -lutil -DPADD= ${LIBPROC} ${LIBELF} - -MAN= - -.include diff --git a/lib/libproc/test/t2-name2map/t2-name2map.c b/lib/libproc/test/t2-name2map/t2-name2map.c deleted file mode 100644 index 825963d..0000000 --- a/lib/libproc/test/t2-name2map/t2-name2map.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2010 The FreeBSD Foundation - * All rights reserved. - * - * This software was developed by Rui Paulo under sponsorship from the - * FreeBSD Foundation. - * - * 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 AUTHOR AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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. - * - * $FreeBSD$ - */ - -#include -#include -#include -#include - -int -main(int argc, char *argv[]) -{ - prmap_t *map = NULL; - struct proc_handle *phdl; - - proc_create("./t2-name2map", argv, NULL, NULL, &phdl); - map = proc_name2map(phdl, "ld-elf.so.1"); - assert(map); -} diff --git a/lib/libproc/test/t3-name2sym/Makefile b/lib/libproc/test/t3-name2sym/Makefile deleted file mode 100644 index 68e23c6..0000000 --- a/lib/libproc/test/t3-name2sym/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# $FreeBSD$ - -PROG= t3-name2sym - -SRCS= t3-name2sym.c - -LDADD= -lproc -lelf -lrtld_db -lutil -DPADD= ${LIBPROC} ${LIBELF} - -MAN= - -.include diff --git a/lib/libproc/test/t3-name2sym/t3-name2sym.c b/lib/libproc/test/t3-name2sym/t3-name2sym.c deleted file mode 100644 index 0be8653..0000000 --- a/lib/libproc/test/t3-name2sym/t3-name2sym.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2010 The FreeBSD Foundation - * All rights reserved. - * - * This software was developed by Rui Paulo under sponsorship from the - * FreeBSD Foundation. - * - * 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 AUTHOR AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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. - * - * $FreeBSD$ - */ -#include -#include -#include -#include -#include -#include - -int -main(int argc, char *argv[]) -{ - prmap_t *map = NULL; - struct proc_handle *phdl; - GElf_Sym sym; - - proc_create("./t3-name2sym", argv, NULL, NULL, &phdl); - memset(&sym, 0, sizeof(sym)); - assert(proc_name2sym(phdl, "ld-elf.so.1", "r_debug_state", &sym) == 0); - printf("0x%lx\n", sym.st_value); - assert(proc_name2sym(phdl, "t3-name2sym", "main", &sym) == 0); - printf("0x%lx\n", sym.st_value); -} diff --git a/lib/libproc/tests/Makefile b/lib/libproc/tests/Makefile new file mode 100644 index 0000000..1f98467 --- /dev/null +++ b/lib/libproc/tests/Makefile @@ -0,0 +1,21 @@ +# $FreeBSD$ + +TESTSDIR= ${TESTSBASE}/lib/libproc + +ATF_TESTS_C+= proc_test + +PROGS= target_prog +SRCS_target_prog= target_prog.c +BINDIR_target_prog= ${TESTSDIR} + +LDADD+= -lelf -lproc -lrtld_db -lutil +DPADD+= ${LIBELF} ${LIBPROC} ${LIBRTLD_DB} ${LIBUTIL} + +# Ensure that symbols aren't stripped from the test program, as they're needed +# for testing symbol lookup. +STRIP= + +MAN= +WARNS?= 6 + +.include diff --git a/lib/libproc/tests/proc_test.c b/lib/libproc/tests/proc_test.c new file mode 100644 index 0000000..60f1f04 --- /dev/null +++ b/lib/libproc/tests/proc_test.c @@ -0,0 +1,347 @@ +/*- + * Copyright (c) 2014 Mark Johnston + * 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 AUTHOR AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +static const char *aout_object = "a.out"; +static const char *ldelf_object = "ld-elf.so.1"; +static const char *target_prog_file = "target_prog"; + +/* + * Run the test program. If the sig parameter is set to true, the test program + * will deliver SIGUSR1 to itself during execution. + */ +static struct proc_handle * +start_prog(const struct atf_tc *tc, bool sig) +{ + char *argv[3]; + struct proc_handle *phdl; + int error; + + asprintf(&argv[0], "%s/%s", atf_tc_get_config_var(tc, "srcdir"), + target_prog_file); + ATF_REQUIRE(argv[0] != NULL); + + if (sig) { + argv[1] = strdup("-s"); + argv[2] = NULL; + } else { + argv[1] = NULL; + } + + error = proc_create(argv[0], argv, NULL, NULL, &phdl); + ATF_REQUIRE_EQ_MSG(error, 0, "failed to run '%s'", target_prog_file); + ATF_REQUIRE(phdl != NULL); + + free(argv[0]); + free(argv[1]); + + return (phdl); +} + +static void +set_bkpt(struct proc_handle *phdl, uintptr_t addr, u_long *saved) +{ + int error; + + error = proc_bkptset(phdl, addr, saved); + ATF_REQUIRE_EQ_MSG(error, 0, "failed to set breakpoint at 0x%jx", + (uintmax_t)addr); +} + +static void +remove_bkpt(struct proc_handle *phdl, uintptr_t addr, u_long val) +{ + int error; + + error = proc_bkptdel(phdl, addr, val); + ATF_REQUIRE_EQ_MSG(error, 0, + "failed to delete breakpoint at 0x%jx", (uintmax_t)addr); + + error = proc_regset(phdl, REG_PC, addr); + ATF_REQUIRE_EQ_MSG(error, 0, "failed to reset program counter"); +} + +/* + * Wait for the specified process to hit a breakpoint at the specified symbol. + */ +static void +verify_bkpt(struct proc_handle *phdl, GElf_Sym *sym, const char *symname, + const char *mapname) +{ + char mapbname[MAXPATHLEN], *name; + GElf_Sym tsym; + prmap_t *map; + size_t namesz; + u_long addr; + int error, state; + + state = proc_wstatus(phdl); + ATF_REQUIRE_EQ_MSG(state, PS_STOP, "process has state %d", state); + + /* Get the program counter and decrement it. */ + error = proc_regget(phdl, REG_PC, &addr); + ATF_REQUIRE_EQ_MSG(error, 0, "failed to obtain PC for '%s'", + target_prog_file); + proc_bkptregadj(&addr); + + /* + * Make sure the PC matches the expected value obtained from the symbol + * definition we looked up earlier. + */ + ATF_CHECK_EQ_MSG(addr, sym->st_value, + "program counter 0x%lx doesn't match expected value 0x%jx", + addr, (uintmax_t)sym->st_value); + + /* + * Ensure we can look up the r_debug_state symbol using its starting + * address and that the resulting symbol matches the one we found using + * a name lookup. + */ + namesz = strlen(symname) + 1; + name = malloc(namesz); + ATF_REQUIRE(name != NULL); + + error = proc_addr2sym(phdl, addr, name, namesz, &tsym); + ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up symbol at 0x%lx", addr); + ATF_REQUIRE_EQ(memcmp(sym, &tsym, sizeof(*sym)), 0); + ATF_REQUIRE_EQ(strcmp(symname, name), 0); + free(name); + + map = proc_addr2map(phdl, addr); + ATF_REQUIRE_MSG(map != NULL, "failed to look up map for address 0x%lx", + addr); + basename_r(map->pr_mapname, mapbname); + ATF_REQUIRE_EQ_MSG(strcmp(mapname, mapbname), 0, + "expected map name '%s' doesn't match '%s'", mapname, mapbname); +} + +ATF_TC(map_alias_obj2map); +ATF_TC_HEAD(map_alias_obj2map, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Callers are supposed to be able to use \"a.out\" as an alias for " + "the program executable. Make sure that proc_obj2map() handles " + "this properly."); +} +ATF_TC_BODY(map_alias_obj2map, tc) +{ + struct proc_handle *phdl; + prmap_t *map1, *map2; + + phdl = start_prog(tc, false); + + /* Initialize the rtld_db handle. */ + (void)proc_rdagent(phdl); + + /* Ensure that "target_prog" and "a.out" return the same map. */ + map1 = proc_obj2map(phdl, target_prog_file); + ATF_REQUIRE_MSG(map1 != NULL, "failed to look up map for '%s'", + target_prog_file); + map2 = proc_obj2map(phdl, aout_object); + ATF_REQUIRE_MSG(map2 != NULL, "failed to look up map for '%s'", + aout_object); + ATF_CHECK_EQ(strcmp(map1->pr_mapname, map2->pr_mapname), 0); + + ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); + + proc_free(phdl); +} + +ATF_TC(map_alias_name2map); +ATF_TC_HEAD(map_alias_name2map, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Callers are supposed to be able to use \"a.out\" as an alias for " + "the program executable. Make sure that proc_name2map() handles " + "this properly."); +} +ATF_TC_BODY(map_alias_name2map, tc) +{ + struct proc_handle *phdl; + prmap_t *map1, *map2; + + phdl = start_prog(tc, false); + + /* Initialize the rtld_db handle. */ + (void)proc_rdagent(phdl); + + /* Ensure that "target_prog" and "a.out" return the same map. */ + map1 = proc_name2map(phdl, target_prog_file); + ATF_REQUIRE_MSG(map1 != NULL, "failed to look up map for '%s'", + target_prog_file); + map2 = proc_name2map(phdl, aout_object); + ATF_REQUIRE_MSG(map2 != NULL, "failed to look up map for '%s'", + aout_object); + ATF_CHECK_EQ(strcmp(map1->pr_mapname, map2->pr_mapname), 0); + + ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); + + proc_free(phdl); +} + +ATF_TC(map_alias_name2sym); +ATF_TC_HEAD(map_alias_name2sym, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Callers are supposed to be able to use \"a.out\" as an alias for " + "the program executable. Make sure that proc_name2sym() handles " + "this properly."); +} +ATF_TC_BODY(map_alias_name2sym, tc) +{ + GElf_Sym sym1, sym2; + struct proc_handle *phdl; + int error; + + phdl = start_prog(tc, false); + + /* Initialize the rtld_db handle. */ + (void)proc_rdagent(phdl); + + /* + * Make sure that "target_prog:main" and "a.out:main" return the same + * symbol. + */ + error = proc_name2sym(phdl, target_prog_file, "main", &sym1); + ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'main' via %s", + target_prog_file); + error = proc_name2sym(phdl, aout_object, "main", &sym2); + ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'main' via %s", + aout_object); + + ATF_CHECK_EQ(memcmp(&sym1, &sym2, sizeof(sym1)), 0); + + ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); + + proc_free(phdl); +} + +ATF_TC(symbol_lookup); +ATF_TC_HEAD(symbol_lookup, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Look up a couple of well-known symbols in the test program, place " + "breakpoints on them, and verify that we hit the breakpoints. Also " + "make sure that we can use the breakpoint address to look up the " + "corresponding symbol."); +} +ATF_TC_BODY(symbol_lookup, tc) +{ + GElf_Sym main_sym, r_debug_state_sym; + struct proc_handle *phdl; + u_long saved; + int error; + + phdl = start_prog(tc, false); + + error = proc_name2sym(phdl, target_prog_file, "main", &main_sym); + ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'main'"); + + error = proc_name2sym(phdl, ldelf_object, "r_debug_state", + &r_debug_state_sym); + ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'r_debug_state'"); + + set_bkpt(phdl, r_debug_state_sym.st_value, &saved); + ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); + verify_bkpt(phdl, &r_debug_state_sym, "r_debug_state", ldelf_object); + remove_bkpt(phdl, r_debug_state_sym.st_value, saved); + + set_bkpt(phdl, main_sym.st_value, &saved); + ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); + verify_bkpt(phdl, &main_sym, "main", target_prog_file); + remove_bkpt(phdl, main_sym.st_value, saved); + + ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); + + proc_free(phdl); +} + +ATF_TC(signal_forward); +ATF_TC_HEAD(signal_forward, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Run the test program in a mode which causes it to send a signal " + "to itself. Make sure that we intercept the signal and that " + "proc_continue() forwards it to the process."); +} +ATF_TC_BODY(signal_forward, tc) +{ + struct proc_handle *phdl; + int state, status; + + phdl = start_prog(tc, true); + ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); + + /* The process should have been interrupted by a signal. */ + state = proc_wstatus(phdl); + ATF_REQUIRE_EQ_MSG(state, PS_STOP, "process has unexpected state %d", + state); + + /* Continue execution and allow the signal to be delivered. */ + ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); + + /* + * Make sure the process exited with status 0. If it didn't receive the + * SIGUSR1 that it sent to itself, it'll exit with a non-zero exit + * status, causing the test to fail. + */ + state = proc_wstatus(phdl); + ATF_REQUIRE_EQ_MSG(state, PS_UNDEAD, "process has unexpected state %d", + state); + + status = proc_getwstat(phdl); + ATF_REQUIRE(status >= 0); + ATF_REQUIRE(WIFEXITED(status)); + ATF_REQUIRE_EQ(WEXITSTATUS(status), 0); + + proc_free(phdl); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, map_alias_obj2map); + ATF_TP_ADD_TC(tp, map_alias_name2map); + ATF_TP_ADD_TC(tp, map_alias_name2sym); + ATF_TP_ADD_TC(tp, symbol_lookup); + ATF_TP_ADD_TC(tp, signal_forward); + + return (atf_no_error()); +} diff --git a/lib/libproc/tests/target_prog.c b/lib/libproc/tests/target_prog.c new file mode 100644 index 0000000..1edf0de --- /dev/null +++ b/lib/libproc/tests/target_prog.c @@ -0,0 +1,59 @@ +/*- + * Copyright (c) 2014 Mark Johnston + * 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 AUTHOR AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +static volatile sig_atomic_t saw; + +static void +usr1(int sig __unused) +{ + + saw = 1; +} + +int +main(int argc, char **argv) +{ + + if (argc == 1) + return (EXIT_SUCCESS); + if (argc == 2 && strcmp(argv[1], "-s") == 0) { + if (signal(SIGUSR1, usr1) == SIG_ERR) + err(1, "signal"); + if (kill(getpid(), SIGUSR1) != 0) + err(1, "kill"); + return (saw == 1 ? EXIT_SUCCESS : EXIT_FAILURE); + } + return (EXIT_FAILURE); +} -- cgit v1.1