19351ac6dSMark Johnston /*-
21bdc41d2SMark Johnston * Copyright (c) 2014-2017 Mark Johnston <markj@FreeBSD.org>
39351ac6dSMark Johnston * All rights reserved.
49351ac6dSMark Johnston *
59351ac6dSMark Johnston * Redistribution and use in source and binary forms, with or without
69351ac6dSMark Johnston * modification, are permitted provided that the following conditions
79351ac6dSMark Johnston * are met:
89351ac6dSMark Johnston * 1. Redistributions of source code must retain the above copyright
99351ac6dSMark Johnston * notice, this list of conditions and the following disclaimer.
109351ac6dSMark Johnston * 2. Redistributions in binary form must reproduce the above copyright
119351ac6dSMark Johnston * notice, this list of conditions and the following disclaimer in the
129351ac6dSMark Johnston * documentation and/or other materials provided with the distribution.
139351ac6dSMark Johnston *
149351ac6dSMark Johnston * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
159351ac6dSMark Johnston * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
169351ac6dSMark Johnston * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
179351ac6dSMark Johnston * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
189351ac6dSMark Johnston * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
199351ac6dSMark Johnston * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
209351ac6dSMark Johnston * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
219351ac6dSMark Johnston * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
229351ac6dSMark Johnston * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
239351ac6dSMark Johnston * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
249351ac6dSMark Johnston * SUCH DAMAGE.
259351ac6dSMark Johnston */
269351ac6dSMark Johnston
279351ac6dSMark Johnston #include <sys/types.h>
289351ac6dSMark Johnston #include <sys/wait.h>
299351ac6dSMark Johnston
309351ac6dSMark Johnston #include <libgen.h>
319351ac6dSMark Johnston #include <stdio.h>
329351ac6dSMark Johnston #include <stdint.h>
339351ac6dSMark Johnston #include <stdlib.h>
349351ac6dSMark Johnston #include <string.h>
359351ac6dSMark Johnston #include <atf-c.h>
369351ac6dSMark Johnston #include <libelf.h>
379351ac6dSMark Johnston #include <libproc.h>
389351ac6dSMark Johnston
399351ac6dSMark Johnston static const char *aout_object = "a.out";
409351ac6dSMark Johnston static const char *ldelf_object = "ld-elf.so.1";
419351ac6dSMark Johnston static const char *target_prog_file = "target_prog";
429351ac6dSMark Johnston
439351ac6dSMark Johnston /*
449351ac6dSMark Johnston * Run the test program. If the sig parameter is set to true, the test program
459351ac6dSMark Johnston * will deliver SIGUSR1 to itself during execution.
469351ac6dSMark Johnston */
479351ac6dSMark Johnston static struct proc_handle *
start_prog(const struct atf_tc * tc,bool sig)489351ac6dSMark Johnston start_prog(const struct atf_tc *tc, bool sig)
499351ac6dSMark Johnston {
509351ac6dSMark Johnston char *argv[3];
519351ac6dSMark Johnston struct proc_handle *phdl;
529351ac6dSMark Johnston int error;
539351ac6dSMark Johnston
549351ac6dSMark Johnston asprintf(&argv[0], "%s/%s", atf_tc_get_config_var(tc, "srcdir"),
559351ac6dSMark Johnston target_prog_file);
569351ac6dSMark Johnston ATF_REQUIRE(argv[0] != NULL);
579351ac6dSMark Johnston
589351ac6dSMark Johnston if (sig) {
599351ac6dSMark Johnston argv[1] = strdup("-s");
609351ac6dSMark Johnston argv[2] = NULL;
619351ac6dSMark Johnston } else {
629351ac6dSMark Johnston argv[1] = NULL;
639351ac6dSMark Johnston }
649351ac6dSMark Johnston
655577b8a7SMark Johnston error = proc_create(argv[0], argv, NULL, NULL, NULL, &phdl);
669351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(error, 0, "failed to run '%s'", target_prog_file);
679351ac6dSMark Johnston ATF_REQUIRE(phdl != NULL);
689351ac6dSMark Johnston
699351ac6dSMark Johnston free(argv[0]);
709351ac6dSMark Johnston free(argv[1]);
719351ac6dSMark Johnston
729351ac6dSMark Johnston return (phdl);
739351ac6dSMark Johnston }
749351ac6dSMark Johnston
759351ac6dSMark Johnston static void
set_bkpt(struct proc_handle * phdl,uintptr_t addr,u_long * saved)769351ac6dSMark Johnston set_bkpt(struct proc_handle *phdl, uintptr_t addr, u_long *saved)
779351ac6dSMark Johnston {
789351ac6dSMark Johnston int error;
799351ac6dSMark Johnston
809351ac6dSMark Johnston error = proc_bkptset(phdl, addr, saved);
819351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(error, 0, "failed to set breakpoint at 0x%jx",
829351ac6dSMark Johnston (uintmax_t)addr);
839351ac6dSMark Johnston }
849351ac6dSMark Johnston
859351ac6dSMark Johnston static void
remove_bkpt(struct proc_handle * phdl,uintptr_t addr,u_long val)869351ac6dSMark Johnston remove_bkpt(struct proc_handle *phdl, uintptr_t addr, u_long val)
879351ac6dSMark Johnston {
889351ac6dSMark Johnston int error;
899351ac6dSMark Johnston
909351ac6dSMark Johnston error = proc_bkptdel(phdl, addr, val);
919351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(error, 0,
929351ac6dSMark Johnston "failed to delete breakpoint at 0x%jx", (uintmax_t)addr);
939351ac6dSMark Johnston
949351ac6dSMark Johnston error = proc_regset(phdl, REG_PC, addr);
959351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(error, 0, "failed to reset program counter");
969351ac6dSMark Johnston }
979351ac6dSMark Johnston
989351ac6dSMark Johnston /*
999351ac6dSMark Johnston * Wait for the specified process to hit a breakpoint at the specified symbol.
1009351ac6dSMark Johnston */
1019351ac6dSMark Johnston static void
verify_bkpt(struct proc_handle * phdl,GElf_Sym * sym,const char * symname,const char * mapname)1029351ac6dSMark Johnston verify_bkpt(struct proc_handle *phdl, GElf_Sym *sym, const char *symname,
1039351ac6dSMark Johnston const char *mapname)
1049351ac6dSMark Johnston {
1051bf4012cSEd Schouten char *name, *mapname_copy, *mapbname;
1069351ac6dSMark Johnston GElf_Sym tsym;
1079351ac6dSMark Johnston prmap_t *map;
1089351ac6dSMark Johnston size_t namesz;
1099351ac6dSMark Johnston u_long addr;
1109351ac6dSMark Johnston int error, state;
1119351ac6dSMark Johnston
1129351ac6dSMark Johnston state = proc_wstatus(phdl);
1139351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(state, PS_STOP, "process has state %d", state);
1149351ac6dSMark Johnston
1159351ac6dSMark Johnston /* Get the program counter and decrement it. */
1169351ac6dSMark Johnston error = proc_regget(phdl, REG_PC, &addr);
1179351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(error, 0, "failed to obtain PC for '%s'",
1189351ac6dSMark Johnston target_prog_file);
1199351ac6dSMark Johnston proc_bkptregadj(&addr);
1209351ac6dSMark Johnston
1219351ac6dSMark Johnston /*
1229351ac6dSMark Johnston * Make sure the PC matches the expected value obtained from the symbol
1239351ac6dSMark Johnston * definition we looked up earlier.
1249351ac6dSMark Johnston */
1259351ac6dSMark Johnston ATF_CHECK_EQ_MSG(addr, sym->st_value,
1269351ac6dSMark Johnston "program counter 0x%lx doesn't match expected value 0x%jx",
1279351ac6dSMark Johnston addr, (uintmax_t)sym->st_value);
1289351ac6dSMark Johnston
1299351ac6dSMark Johnston /*
1309351ac6dSMark Johnston * Ensure we can look up the r_debug_state symbol using its starting
1319351ac6dSMark Johnston * address and that the resulting symbol matches the one we found using
1329351ac6dSMark Johnston * a name lookup.
1339351ac6dSMark Johnston */
1349351ac6dSMark Johnston namesz = strlen(symname) + 1;
1359351ac6dSMark Johnston name = malloc(namesz);
1369351ac6dSMark Johnston ATF_REQUIRE(name != NULL);
1379351ac6dSMark Johnston
1389351ac6dSMark Johnston error = proc_addr2sym(phdl, addr, name, namesz, &tsym);
1399351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up symbol at 0x%lx", addr);
1409351ac6dSMark Johnston ATF_REQUIRE_EQ(memcmp(sym, &tsym, sizeof(*sym)), 0);
1419351ac6dSMark Johnston ATF_REQUIRE_EQ(strcmp(symname, name), 0);
1429351ac6dSMark Johnston free(name);
1439351ac6dSMark Johnston
1449351ac6dSMark Johnston map = proc_addr2map(phdl, addr);
1459351ac6dSMark Johnston ATF_REQUIRE_MSG(map != NULL, "failed to look up map for address 0x%lx",
1469351ac6dSMark Johnston addr);
1471bf4012cSEd Schouten mapname_copy = strdup(map->pr_mapname);
1481bf4012cSEd Schouten mapbname = basename(mapname_copy);
1499351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(strcmp(mapname, mapbname), 0,
1509351ac6dSMark Johnston "expected map name '%s' doesn't match '%s'", mapname, mapbname);
1511bf4012cSEd Schouten free(mapname_copy);
1529351ac6dSMark Johnston }
1539351ac6dSMark Johnston
1549351ac6dSMark Johnston ATF_TC(map_alias_name2map);
ATF_TC_HEAD(map_alias_name2map,tc)1559351ac6dSMark Johnston ATF_TC_HEAD(map_alias_name2map, tc)
1569351ac6dSMark Johnston {
1579351ac6dSMark Johnston atf_tc_set_md_var(tc, "descr",
1589351ac6dSMark Johnston "Callers are supposed to be able to use \"a.out\" as an alias for "
1599351ac6dSMark Johnston "the program executable. Make sure that proc_name2map() handles "
1609351ac6dSMark Johnston "this properly.");
1619351ac6dSMark Johnston }
ATF_TC_BODY(map_alias_name2map,tc)1629351ac6dSMark Johnston ATF_TC_BODY(map_alias_name2map, tc)
1639351ac6dSMark Johnston {
1649351ac6dSMark Johnston struct proc_handle *phdl;
1659351ac6dSMark Johnston prmap_t *map1, *map2;
1669351ac6dSMark Johnston
1679351ac6dSMark Johnston phdl = start_prog(tc, false);
1689351ac6dSMark Johnston
1699351ac6dSMark Johnston /* Initialize the rtld_db handle. */
1709351ac6dSMark Johnston (void)proc_rdagent(phdl);
1719351ac6dSMark Johnston
1729351ac6dSMark Johnston /* Ensure that "target_prog" and "a.out" return the same map. */
1739351ac6dSMark Johnston map1 = proc_name2map(phdl, target_prog_file);
1749351ac6dSMark Johnston ATF_REQUIRE_MSG(map1 != NULL, "failed to look up map for '%s'",
1759351ac6dSMark Johnston target_prog_file);
1769351ac6dSMark Johnston map2 = proc_name2map(phdl, aout_object);
1779351ac6dSMark Johnston ATF_REQUIRE_MSG(map2 != NULL, "failed to look up map for '%s'",
1789351ac6dSMark Johnston aout_object);
1799351ac6dSMark Johnston ATF_CHECK_EQ(strcmp(map1->pr_mapname, map2->pr_mapname), 0);
1809351ac6dSMark Johnston
1819351ac6dSMark Johnston ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");
1829351ac6dSMark Johnston
183*520c80f1SMark Johnston proc_detach(phdl, 0);
1849351ac6dSMark Johnston }
1859351ac6dSMark Johnston
186d42df2a4SMark Johnston ATF_TC(map_prefix_name2map);
ATF_TC_HEAD(map_prefix_name2map,tc)187d42df2a4SMark Johnston ATF_TC_HEAD(map_prefix_name2map, tc)
188d42df2a4SMark Johnston {
189d42df2a4SMark Johnston atf_tc_set_md_var(tc, "descr",
190d42df2a4SMark Johnston "Verify that proc_name2map() returns prefix matches of the "
191d42df2a4SMark Johnston "basename of loaded objects if no full matches are found.");
192d42df2a4SMark Johnston }
ATF_TC_BODY(map_prefix_name2map,tc)193d42df2a4SMark Johnston ATF_TC_BODY(map_prefix_name2map, tc)
194d42df2a4SMark Johnston {
195d42df2a4SMark Johnston struct proc_handle *phdl;
196d42df2a4SMark Johnston prmap_t *map1, *map2;
197d42df2a4SMark Johnston
198d42df2a4SMark Johnston phdl = start_prog(tc, false);
199d42df2a4SMark Johnston
200d42df2a4SMark Johnston /* Initialize the rtld_db handle. */
201d42df2a4SMark Johnston (void)proc_rdagent(phdl);
202d42df2a4SMark Johnston
203d42df2a4SMark Johnston /* Make sure that "ld-elf" and "ld-elf.so" return the same map. */
204d42df2a4SMark Johnston map1 = proc_name2map(phdl, "ld-elf");
205d42df2a4SMark Johnston ATF_REQUIRE_MSG(map1 != NULL, "failed to look up map for 'ld-elf'");
206d42df2a4SMark Johnston map2 = proc_name2map(phdl, "ld-elf.so");
207d42df2a4SMark Johnston ATF_REQUIRE_MSG(map2 != NULL, "failed to look up map for 'ld-elf.so'");
208d42df2a4SMark Johnston ATF_CHECK_EQ(strcmp(map1->pr_mapname, map2->pr_mapname), 0);
209d42df2a4SMark Johnston
210d42df2a4SMark Johnston ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");
211d42df2a4SMark Johnston
212*520c80f1SMark Johnston proc_detach(phdl, 0);
213d42df2a4SMark Johnston }
214d42df2a4SMark Johnston
2159351ac6dSMark Johnston ATF_TC(map_alias_name2sym);
ATF_TC_HEAD(map_alias_name2sym,tc)2169351ac6dSMark Johnston ATF_TC_HEAD(map_alias_name2sym, tc)
2179351ac6dSMark Johnston {
2189351ac6dSMark Johnston atf_tc_set_md_var(tc, "descr",
2199351ac6dSMark Johnston "Callers are supposed to be able to use \"a.out\" as an alias for "
2209351ac6dSMark Johnston "the program executable. Make sure that proc_name2sym() handles "
2219351ac6dSMark Johnston "this properly.");
2229351ac6dSMark Johnston }
ATF_TC_BODY(map_alias_name2sym,tc)2239351ac6dSMark Johnston ATF_TC_BODY(map_alias_name2sym, tc)
2249351ac6dSMark Johnston {
2259351ac6dSMark Johnston GElf_Sym sym1, sym2;
22641da933cSMark Johnston prsyminfo_t si1, si2;
2279351ac6dSMark Johnston struct proc_handle *phdl;
2289351ac6dSMark Johnston int error;
2299351ac6dSMark Johnston
2309351ac6dSMark Johnston phdl = start_prog(tc, false);
2319351ac6dSMark Johnston
2329351ac6dSMark Johnston /* Initialize the rtld_db handle. */
2339351ac6dSMark Johnston (void)proc_rdagent(phdl);
2349351ac6dSMark Johnston
2359351ac6dSMark Johnston /*
2369351ac6dSMark Johnston * Make sure that "target_prog:main" and "a.out:main" return the same
2379351ac6dSMark Johnston * symbol.
2389351ac6dSMark Johnston */
23941da933cSMark Johnston error = proc_name2sym(phdl, target_prog_file, "main", &sym1, &si1);
2409351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'main' via %s",
2419351ac6dSMark Johnston target_prog_file);
24241da933cSMark Johnston error = proc_name2sym(phdl, aout_object, "main", &sym2, &si2);
2439351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'main' via %s",
2449351ac6dSMark Johnston aout_object);
2459351ac6dSMark Johnston
2469351ac6dSMark Johnston ATF_CHECK_EQ(memcmp(&sym1, &sym2, sizeof(sym1)), 0);
24741da933cSMark Johnston ATF_CHECK_EQ(si1.prs_id, si2.prs_id);
2489351ac6dSMark Johnston
2499351ac6dSMark Johnston ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");
2509351ac6dSMark Johnston
251*520c80f1SMark Johnston proc_detach(phdl, 0);
2529351ac6dSMark Johnston }
2539351ac6dSMark Johnston
2549351ac6dSMark Johnston ATF_TC(symbol_lookup);
ATF_TC_HEAD(symbol_lookup,tc)2559351ac6dSMark Johnston ATF_TC_HEAD(symbol_lookup, tc)
2569351ac6dSMark Johnston {
2579351ac6dSMark Johnston atf_tc_set_md_var(tc, "descr",
2589351ac6dSMark Johnston "Look up a couple of well-known symbols in the test program, place "
2599351ac6dSMark Johnston "breakpoints on them, and verify that we hit the breakpoints. Also "
2609351ac6dSMark Johnston "make sure that we can use the breakpoint address to look up the "
2619351ac6dSMark Johnston "corresponding symbol.");
2629351ac6dSMark Johnston }
ATF_TC_BODY(symbol_lookup,tc)2639351ac6dSMark Johnston ATF_TC_BODY(symbol_lookup, tc)
2649351ac6dSMark Johnston {
2659351ac6dSMark Johnston GElf_Sym main_sym, r_debug_state_sym;
2669351ac6dSMark Johnston struct proc_handle *phdl;
2679351ac6dSMark Johnston u_long saved;
2689351ac6dSMark Johnston int error;
2699351ac6dSMark Johnston
2709351ac6dSMark Johnston phdl = start_prog(tc, false);
2719351ac6dSMark Johnston
27241da933cSMark Johnston error = proc_name2sym(phdl, target_prog_file, "main", &main_sym, NULL);
2739351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'main'");
2749351ac6dSMark Johnston
2759351ac6dSMark Johnston error = proc_name2sym(phdl, ldelf_object, "r_debug_state",
27641da933cSMark Johnston &r_debug_state_sym, NULL);
2779351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'r_debug_state'");
2789351ac6dSMark Johnston
2799351ac6dSMark Johnston set_bkpt(phdl, r_debug_state_sym.st_value, &saved);
2809351ac6dSMark Johnston ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");
2819351ac6dSMark Johnston verify_bkpt(phdl, &r_debug_state_sym, "r_debug_state", ldelf_object);
2829351ac6dSMark Johnston remove_bkpt(phdl, r_debug_state_sym.st_value, saved);
2839351ac6dSMark Johnston
2849351ac6dSMark Johnston set_bkpt(phdl, main_sym.st_value, &saved);
2859351ac6dSMark Johnston ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");
2869351ac6dSMark Johnston verify_bkpt(phdl, &main_sym, "main", target_prog_file);
2879351ac6dSMark Johnston remove_bkpt(phdl, main_sym.st_value, saved);
2889351ac6dSMark Johnston
2899351ac6dSMark Johnston ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");
2909351ac6dSMark Johnston
291*520c80f1SMark Johnston proc_detach(phdl, 0);
2929351ac6dSMark Johnston }
2939351ac6dSMark Johnston
294cd9c9939SMark Johnston ATF_TC(symbol_lookup_fail);
ATF_TC_HEAD(symbol_lookup_fail,tc)295cd9c9939SMark Johnston ATF_TC_HEAD(symbol_lookup_fail, tc)
296cd9c9939SMark Johnston {
297cd9c9939SMark Johnston atf_tc_set_md_var(tc, "descr",
298cd9c9939SMark Johnston "Verify that proc_addr2sym() returns an error when given an offset "
299cd9c9939SMark Johnston "that it cannot resolve.");
300cd9c9939SMark Johnston }
ATF_TC_BODY(symbol_lookup_fail,tc)301cd9c9939SMark Johnston ATF_TC_BODY(symbol_lookup_fail, tc)
302cd9c9939SMark Johnston {
303cd9c9939SMark Johnston char symname[32];
304cd9c9939SMark Johnston GElf_Sym sym;
305cd9c9939SMark Johnston struct proc_handle *phdl;
306cd9c9939SMark Johnston prmap_t *map;
307cd9c9939SMark Johnston int error;
308cd9c9939SMark Johnston
309cd9c9939SMark Johnston phdl = start_prog(tc, false);
310cd9c9939SMark Johnston
311cd9c9939SMark Johnston /* Initialize the rtld_db handle. */
312cd9c9939SMark Johnston (void)proc_rdagent(phdl);
313cd9c9939SMark Johnston
314d42df2a4SMark Johnston map = proc_name2map(phdl, target_prog_file);
315cd9c9939SMark Johnston ATF_REQUIRE_MSG(map != NULL, "failed to look up map for '%s'",
316cd9c9939SMark Johnston target_prog_file);
317cd9c9939SMark Johnston
318cd9c9939SMark Johnston /*
319cd9c9939SMark Johnston * We shouldn't be able to find symbols at the beginning of a mapped
320cd9c9939SMark Johnston * file.
321cd9c9939SMark Johnston */
322cd9c9939SMark Johnston error = proc_addr2sym(phdl, map->pr_vaddr, symname, sizeof(symname),
323cd9c9939SMark Johnston &sym);
324cd9c9939SMark Johnston ATF_REQUIRE_MSG(error != 0, "unexpectedly found a symbol");
325cd9c9939SMark Johnston
326cd9c9939SMark Johnston ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");
327cd9c9939SMark Johnston
328*520c80f1SMark Johnston proc_detach(phdl, 0);
329cd9c9939SMark Johnston }
330cd9c9939SMark Johnston
3319351ac6dSMark Johnston ATF_TC(signal_forward);
ATF_TC_HEAD(signal_forward,tc)3329351ac6dSMark Johnston ATF_TC_HEAD(signal_forward, tc)
3339351ac6dSMark Johnston {
3349351ac6dSMark Johnston atf_tc_set_md_var(tc, "descr",
3359351ac6dSMark Johnston "Run the test program in a mode which causes it to send a signal "
3369351ac6dSMark Johnston "to itself. Make sure that we intercept the signal and that "
3379351ac6dSMark Johnston "proc_continue() forwards it to the process.");
3389351ac6dSMark Johnston }
ATF_TC_BODY(signal_forward,tc)3399351ac6dSMark Johnston ATF_TC_BODY(signal_forward, tc)
3409351ac6dSMark Johnston {
3419351ac6dSMark Johnston struct proc_handle *phdl;
3429351ac6dSMark Johnston int state, status;
3439351ac6dSMark Johnston
3449351ac6dSMark Johnston phdl = start_prog(tc, true);
3459351ac6dSMark Johnston ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");
3469351ac6dSMark Johnston
3479351ac6dSMark Johnston /* The process should have been interrupted by a signal. */
3489351ac6dSMark Johnston state = proc_wstatus(phdl);
3499351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(state, PS_STOP, "process has unexpected state %d",
3509351ac6dSMark Johnston state);
3519351ac6dSMark Johnston
3529351ac6dSMark Johnston /* Continue execution and allow the signal to be delivered. */
3539351ac6dSMark Johnston ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");
3549351ac6dSMark Johnston
3559351ac6dSMark Johnston /*
3569351ac6dSMark Johnston * Make sure the process exited with status 0. If it didn't receive the
3579351ac6dSMark Johnston * SIGUSR1 that it sent to itself, it'll exit with a non-zero exit
3589351ac6dSMark Johnston * status, causing the test to fail.
3599351ac6dSMark Johnston */
3609351ac6dSMark Johnston state = proc_wstatus(phdl);
3619351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(state, PS_UNDEAD, "process has unexpected state %d",
3629351ac6dSMark Johnston state);
3639351ac6dSMark Johnston
3649351ac6dSMark Johnston status = proc_getwstat(phdl);
3659351ac6dSMark Johnston ATF_REQUIRE(status >= 0);
3669351ac6dSMark Johnston ATF_REQUIRE(WIFEXITED(status));
3679351ac6dSMark Johnston ATF_REQUIRE_EQ(WEXITSTATUS(status), 0);
3689351ac6dSMark Johnston
369*520c80f1SMark Johnston proc_detach(phdl, 0);
3709351ac6dSMark Johnston }
3719351ac6dSMark Johnston
3721bdc41d2SMark Johnston ATF_TC(symbol_sort_local);
ATF_TC_HEAD(symbol_sort_local,tc)3731bdc41d2SMark Johnston ATF_TC_HEAD(symbol_sort_local, tc)
3741bdc41d2SMark Johnston {
3751bdc41d2SMark Johnston atf_tc_set_md_var(tc, "descr",
3761bdc41d2SMark Johnston "Ensure that proc_addr2sym() returns the non-local alias when "
3771bdc41d2SMark Johnston "the address resolves to multiple symbols.");
3781bdc41d2SMark Johnston }
ATF_TC_BODY(symbol_sort_local,tc)3791bdc41d2SMark Johnston ATF_TC_BODY(symbol_sort_local, tc)
3801bdc41d2SMark Johnston {
3811bdc41d2SMark Johnston char symname[32];
3821bdc41d2SMark Johnston GElf_Sym bar_sym;
3831bdc41d2SMark Johnston struct proc_handle *phdl;
3841bdc41d2SMark Johnston int error;
3851bdc41d2SMark Johnston
3861bdc41d2SMark Johnston phdl = start_prog(tc, true);
3871bdc41d2SMark Johnston
3881bdc41d2SMark Johnston error = proc_name2sym(phdl, target_prog_file, "bar", &bar_sym, NULL);
3891bdc41d2SMark Johnston ATF_REQUIRE_MSG(error == 0, "failed to look up 'bar' in %s",
3901bdc41d2SMark Johnston target_prog_file);
3911bdc41d2SMark Johnston ATF_REQUIRE(GELF_ST_BIND(bar_sym.st_info) == STB_LOCAL);
3921bdc41d2SMark Johnston
3931bdc41d2SMark Johnston error = proc_addr2sym(phdl, bar_sym.st_value, symname, sizeof(symname),
3941bdc41d2SMark Johnston &bar_sym);
3951bdc41d2SMark Johnston ATF_REQUIRE_MSG(error == 0, "failed to resolve 'bar' by addr");
3961bdc41d2SMark Johnston
3971bdc41d2SMark Johnston ATF_REQUIRE_MSG(strcmp(symname, "baz") == 0,
3981bdc41d2SMark Johnston "unexpected symbol name '%s'", symname);
3991bdc41d2SMark Johnston ATF_REQUIRE(GELF_ST_BIND(bar_sym.st_info) == STB_GLOBAL);
400*520c80f1SMark Johnston
401*520c80f1SMark Johnston proc_detach(phdl, 0);
4021bdc41d2SMark Johnston }
4031bdc41d2SMark Johnston
4041bdc41d2SMark Johnston ATF_TC(symbol_sort_prefix);
ATF_TC_HEAD(symbol_sort_prefix,tc)4051bdc41d2SMark Johnston ATF_TC_HEAD(symbol_sort_prefix, tc)
4061bdc41d2SMark Johnston {
4071bdc41d2SMark Johnston atf_tc_set_md_var(tc, "descr",
4081bdc41d2SMark Johnston "Ensure that proc_addr2sym() returns the alias whose name is not "
4091bdc41d2SMark Johnston "prefixed with '$' if one exists.");
4101bdc41d2SMark Johnston }
ATF_TC_BODY(symbol_sort_prefix,tc)4111bdc41d2SMark Johnston ATF_TC_BODY(symbol_sort_prefix, tc)
4121bdc41d2SMark Johnston {
4131bdc41d2SMark Johnston char symname[32];
4141bdc41d2SMark Johnston GElf_Sym qux_sym;
4151bdc41d2SMark Johnston struct proc_handle *phdl;
4161bdc41d2SMark Johnston int error;
4171bdc41d2SMark Johnston
4181bdc41d2SMark Johnston phdl = start_prog(tc, true);
4191bdc41d2SMark Johnston
4201bdc41d2SMark Johnston error = proc_name2sym(phdl, target_prog_file, "$qux", &qux_sym, NULL);
4211bdc41d2SMark Johnston ATF_REQUIRE_MSG(error == 0, "failed to look up '$qux' in %s",
4221bdc41d2SMark Johnston target_prog_file);
4231bdc41d2SMark Johnston
4241bdc41d2SMark Johnston error = proc_addr2sym(phdl, qux_sym.st_value, symname, sizeof(symname),
4251bdc41d2SMark Johnston &qux_sym);
4261bdc41d2SMark Johnston ATF_REQUIRE_MSG(error == 0, "failed to resolve 'qux' by addr");
4271bdc41d2SMark Johnston
4281bdc41d2SMark Johnston ATF_REQUIRE_MSG(strcmp(symname, "qux") == 0,
4291bdc41d2SMark Johnston "unexpected symbol name '%s'", symname);
430*520c80f1SMark Johnston
431*520c80f1SMark Johnston proc_detach(phdl, 0);
4321bdc41d2SMark Johnston }
4331bdc41d2SMark Johnston
4341bdc41d2SMark Johnston ATF_TC(symbol_sort_underscore);
ATF_TC_HEAD(symbol_sort_underscore,tc)4351bdc41d2SMark Johnston ATF_TC_HEAD(symbol_sort_underscore, tc)
4361bdc41d2SMark Johnston {
4371bdc41d2SMark Johnston atf_tc_set_md_var(tc, "descr",
4381bdc41d2SMark Johnston "Ensure that proc_addr2sym() returns the alias with fewest leading "
4391bdc41d2SMark Johnston "underscores in the name when the address resolves to multiple "
4401bdc41d2SMark Johnston "symbols.");
4411bdc41d2SMark Johnston }
ATF_TC_BODY(symbol_sort_underscore,tc)4421bdc41d2SMark Johnston ATF_TC_BODY(symbol_sort_underscore, tc)
4431bdc41d2SMark Johnston {
4441bdc41d2SMark Johnston char symname[32];
4451bdc41d2SMark Johnston GElf_Sym foo_sym;
4461bdc41d2SMark Johnston struct proc_handle *phdl;
4471bdc41d2SMark Johnston int error;
4481bdc41d2SMark Johnston
4491bdc41d2SMark Johnston phdl = start_prog(tc, true);
4501bdc41d2SMark Johnston
4511bdc41d2SMark Johnston error = proc_name2sym(phdl, target_prog_file, "foo", &foo_sym, NULL);
4521bdc41d2SMark Johnston ATF_REQUIRE_MSG(error == 0, "failed to look up 'foo' in %s",
4531bdc41d2SMark Johnston target_prog_file);
4541bdc41d2SMark Johnston
4551bdc41d2SMark Johnston error = proc_addr2sym(phdl, foo_sym.st_value, symname, sizeof(symname),
4561bdc41d2SMark Johnston &foo_sym);
4571bdc41d2SMark Johnston ATF_REQUIRE_MSG(error == 0, "failed to resolve 'foo' by addr");
4581bdc41d2SMark Johnston
4591bdc41d2SMark Johnston ATF_REQUIRE_MSG(strcmp(symname, "foo") == 0,
4601bdc41d2SMark Johnston "unexpected symbol name '%s'", symname);
461*520c80f1SMark Johnston
462*520c80f1SMark Johnston proc_detach(phdl, 0);
4631bdc41d2SMark Johnston }
4641bdc41d2SMark Johnston
ATF_TP_ADD_TCS(tp)4659351ac6dSMark Johnston ATF_TP_ADD_TCS(tp)
4669351ac6dSMark Johnston {
4679351ac6dSMark Johnston
4689351ac6dSMark Johnston ATF_TP_ADD_TC(tp, map_alias_name2map);
469d42df2a4SMark Johnston ATF_TP_ADD_TC(tp, map_prefix_name2map);
4709351ac6dSMark Johnston ATF_TP_ADD_TC(tp, map_alias_name2sym);
4719351ac6dSMark Johnston ATF_TP_ADD_TC(tp, symbol_lookup);
472cd9c9939SMark Johnston ATF_TP_ADD_TC(tp, symbol_lookup_fail);
4739351ac6dSMark Johnston ATF_TP_ADD_TC(tp, signal_forward);
4741bdc41d2SMark Johnston ATF_TP_ADD_TC(tp, symbol_sort_local);
4751bdc41d2SMark Johnston ATF_TP_ADD_TC(tp, symbol_sort_prefix);
4761bdc41d2SMark Johnston ATF_TP_ADD_TC(tp, symbol_sort_underscore);
4779351ac6dSMark Johnston
4789351ac6dSMark Johnston return (atf_no_error());
4799351ac6dSMark Johnston }
480