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/cdefs.h> 289351ac6dSMark Johnston __FBSDID("$FreeBSD$"); 299351ac6dSMark Johnston 309351ac6dSMark Johnston #include <sys/types.h> 319351ac6dSMark Johnston #include <sys/wait.h> 329351ac6dSMark Johnston 339351ac6dSMark Johnston #include <libgen.h> 349351ac6dSMark Johnston #include <stdio.h> 359351ac6dSMark Johnston #include <stdint.h> 369351ac6dSMark Johnston #include <stdlib.h> 379351ac6dSMark Johnston #include <string.h> 389351ac6dSMark Johnston #include <atf-c.h> 399351ac6dSMark Johnston #include <libelf.h> 409351ac6dSMark Johnston #include <libproc.h> 419351ac6dSMark Johnston 429351ac6dSMark Johnston static const char *aout_object = "a.out"; 439351ac6dSMark Johnston static const char *ldelf_object = "ld-elf.so.1"; 449351ac6dSMark Johnston static const char *target_prog_file = "target_prog"; 459351ac6dSMark Johnston 469351ac6dSMark Johnston /* 479351ac6dSMark Johnston * Run the test program. If the sig parameter is set to true, the test program 489351ac6dSMark Johnston * will deliver SIGUSR1 to itself during execution. 499351ac6dSMark Johnston */ 509351ac6dSMark Johnston static struct proc_handle * 519351ac6dSMark Johnston start_prog(const struct atf_tc *tc, bool sig) 529351ac6dSMark Johnston { 539351ac6dSMark Johnston char *argv[3]; 549351ac6dSMark Johnston struct proc_handle *phdl; 559351ac6dSMark Johnston int error; 569351ac6dSMark Johnston 579351ac6dSMark Johnston asprintf(&argv[0], "%s/%s", atf_tc_get_config_var(tc, "srcdir"), 589351ac6dSMark Johnston target_prog_file); 599351ac6dSMark Johnston ATF_REQUIRE(argv[0] != NULL); 609351ac6dSMark Johnston 619351ac6dSMark Johnston if (sig) { 629351ac6dSMark Johnston argv[1] = strdup("-s"); 639351ac6dSMark Johnston argv[2] = NULL; 649351ac6dSMark Johnston } else { 659351ac6dSMark Johnston argv[1] = NULL; 669351ac6dSMark Johnston } 679351ac6dSMark Johnston 68*5577b8a7SMark Johnston error = proc_create(argv[0], argv, NULL, NULL, NULL, &phdl); 699351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(error, 0, "failed to run '%s'", target_prog_file); 709351ac6dSMark Johnston ATF_REQUIRE(phdl != NULL); 719351ac6dSMark Johnston 729351ac6dSMark Johnston free(argv[0]); 739351ac6dSMark Johnston free(argv[1]); 749351ac6dSMark Johnston 759351ac6dSMark Johnston return (phdl); 769351ac6dSMark Johnston } 779351ac6dSMark Johnston 789351ac6dSMark Johnston static void 799351ac6dSMark Johnston set_bkpt(struct proc_handle *phdl, uintptr_t addr, u_long *saved) 809351ac6dSMark Johnston { 819351ac6dSMark Johnston int error; 829351ac6dSMark Johnston 839351ac6dSMark Johnston error = proc_bkptset(phdl, addr, saved); 849351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(error, 0, "failed to set breakpoint at 0x%jx", 859351ac6dSMark Johnston (uintmax_t)addr); 869351ac6dSMark Johnston } 879351ac6dSMark Johnston 889351ac6dSMark Johnston static void 899351ac6dSMark Johnston remove_bkpt(struct proc_handle *phdl, uintptr_t addr, u_long val) 909351ac6dSMark Johnston { 919351ac6dSMark Johnston int error; 929351ac6dSMark Johnston 939351ac6dSMark Johnston error = proc_bkptdel(phdl, addr, val); 949351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(error, 0, 959351ac6dSMark Johnston "failed to delete breakpoint at 0x%jx", (uintmax_t)addr); 969351ac6dSMark Johnston 979351ac6dSMark Johnston error = proc_regset(phdl, REG_PC, addr); 989351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(error, 0, "failed to reset program counter"); 999351ac6dSMark Johnston } 1009351ac6dSMark Johnston 1019351ac6dSMark Johnston /* 1029351ac6dSMark Johnston * Wait for the specified process to hit a breakpoint at the specified symbol. 1039351ac6dSMark Johnston */ 1049351ac6dSMark Johnston static void 1059351ac6dSMark Johnston verify_bkpt(struct proc_handle *phdl, GElf_Sym *sym, const char *symname, 1069351ac6dSMark Johnston const char *mapname) 1079351ac6dSMark Johnston { 1081bf4012cSEd Schouten char *name, *mapname_copy, *mapbname; 1099351ac6dSMark Johnston GElf_Sym tsym; 1109351ac6dSMark Johnston prmap_t *map; 1119351ac6dSMark Johnston size_t namesz; 1129351ac6dSMark Johnston u_long addr; 1139351ac6dSMark Johnston int error, state; 1149351ac6dSMark Johnston 1159351ac6dSMark Johnston state = proc_wstatus(phdl); 1169351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(state, PS_STOP, "process has state %d", state); 1179351ac6dSMark Johnston 1189351ac6dSMark Johnston /* Get the program counter and decrement it. */ 1199351ac6dSMark Johnston error = proc_regget(phdl, REG_PC, &addr); 1209351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(error, 0, "failed to obtain PC for '%s'", 1219351ac6dSMark Johnston target_prog_file); 1229351ac6dSMark Johnston proc_bkptregadj(&addr); 1239351ac6dSMark Johnston 1249351ac6dSMark Johnston /* 1259351ac6dSMark Johnston * Make sure the PC matches the expected value obtained from the symbol 1269351ac6dSMark Johnston * definition we looked up earlier. 1279351ac6dSMark Johnston */ 1289351ac6dSMark Johnston ATF_CHECK_EQ_MSG(addr, sym->st_value, 1299351ac6dSMark Johnston "program counter 0x%lx doesn't match expected value 0x%jx", 1309351ac6dSMark Johnston addr, (uintmax_t)sym->st_value); 1319351ac6dSMark Johnston 1329351ac6dSMark Johnston /* 1339351ac6dSMark Johnston * Ensure we can look up the r_debug_state symbol using its starting 1349351ac6dSMark Johnston * address and that the resulting symbol matches the one we found using 1359351ac6dSMark Johnston * a name lookup. 1369351ac6dSMark Johnston */ 1379351ac6dSMark Johnston namesz = strlen(symname) + 1; 1389351ac6dSMark Johnston name = malloc(namesz); 1399351ac6dSMark Johnston ATF_REQUIRE(name != NULL); 1409351ac6dSMark Johnston 1419351ac6dSMark Johnston error = proc_addr2sym(phdl, addr, name, namesz, &tsym); 1429351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up symbol at 0x%lx", addr); 1439351ac6dSMark Johnston ATF_REQUIRE_EQ(memcmp(sym, &tsym, sizeof(*sym)), 0); 1449351ac6dSMark Johnston ATF_REQUIRE_EQ(strcmp(symname, name), 0); 1459351ac6dSMark Johnston free(name); 1469351ac6dSMark Johnston 1479351ac6dSMark Johnston map = proc_addr2map(phdl, addr); 1489351ac6dSMark Johnston ATF_REQUIRE_MSG(map != NULL, "failed to look up map for address 0x%lx", 1499351ac6dSMark Johnston addr); 1501bf4012cSEd Schouten mapname_copy = strdup(map->pr_mapname); 1511bf4012cSEd Schouten mapbname = basename(mapname_copy); 1529351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(strcmp(mapname, mapbname), 0, 1539351ac6dSMark Johnston "expected map name '%s' doesn't match '%s'", mapname, mapbname); 1541bf4012cSEd Schouten free(mapname_copy); 1559351ac6dSMark Johnston } 1569351ac6dSMark Johnston 1579351ac6dSMark Johnston ATF_TC(map_alias_name2map); 1589351ac6dSMark Johnston ATF_TC_HEAD(map_alias_name2map, tc) 1599351ac6dSMark Johnston { 1609351ac6dSMark Johnston atf_tc_set_md_var(tc, "descr", 1619351ac6dSMark Johnston "Callers are supposed to be able to use \"a.out\" as an alias for " 1629351ac6dSMark Johnston "the program executable. Make sure that proc_name2map() handles " 1639351ac6dSMark Johnston "this properly."); 1649351ac6dSMark Johnston } 1659351ac6dSMark Johnston ATF_TC_BODY(map_alias_name2map, tc) 1669351ac6dSMark Johnston { 1679351ac6dSMark Johnston struct proc_handle *phdl; 1689351ac6dSMark Johnston prmap_t *map1, *map2; 1699351ac6dSMark Johnston 1709351ac6dSMark Johnston phdl = start_prog(tc, false); 1719351ac6dSMark Johnston 1729351ac6dSMark Johnston /* Initialize the rtld_db handle. */ 1739351ac6dSMark Johnston (void)proc_rdagent(phdl); 1749351ac6dSMark Johnston 1759351ac6dSMark Johnston /* Ensure that "target_prog" and "a.out" return the same map. */ 1769351ac6dSMark Johnston map1 = proc_name2map(phdl, target_prog_file); 1779351ac6dSMark Johnston ATF_REQUIRE_MSG(map1 != NULL, "failed to look up map for '%s'", 1789351ac6dSMark Johnston target_prog_file); 1799351ac6dSMark Johnston map2 = proc_name2map(phdl, aout_object); 1809351ac6dSMark Johnston ATF_REQUIRE_MSG(map2 != NULL, "failed to look up map for '%s'", 1819351ac6dSMark Johnston aout_object); 1829351ac6dSMark Johnston ATF_CHECK_EQ(strcmp(map1->pr_mapname, map2->pr_mapname), 0); 1839351ac6dSMark Johnston 1849351ac6dSMark Johnston ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); 1859351ac6dSMark Johnston 1869351ac6dSMark Johnston proc_free(phdl); 1879351ac6dSMark Johnston } 1889351ac6dSMark Johnston 189d42df2a4SMark Johnston ATF_TC(map_prefix_name2map); 190d42df2a4SMark Johnston ATF_TC_HEAD(map_prefix_name2map, tc) 191d42df2a4SMark Johnston { 192d42df2a4SMark Johnston atf_tc_set_md_var(tc, "descr", 193d42df2a4SMark Johnston "Verify that proc_name2map() returns prefix matches of the " 194d42df2a4SMark Johnston "basename of loaded objects if no full matches are found."); 195d42df2a4SMark Johnston } 196d42df2a4SMark Johnston ATF_TC_BODY(map_prefix_name2map, tc) 197d42df2a4SMark Johnston { 198d42df2a4SMark Johnston struct proc_handle *phdl; 199d42df2a4SMark Johnston prmap_t *map1, *map2; 200d42df2a4SMark Johnston 201d42df2a4SMark Johnston phdl = start_prog(tc, false); 202d42df2a4SMark Johnston 203d42df2a4SMark Johnston /* Initialize the rtld_db handle. */ 204d42df2a4SMark Johnston (void)proc_rdagent(phdl); 205d42df2a4SMark Johnston 206d42df2a4SMark Johnston /* Make sure that "ld-elf" and "ld-elf.so" return the same map. */ 207d42df2a4SMark Johnston map1 = proc_name2map(phdl, "ld-elf"); 208d42df2a4SMark Johnston ATF_REQUIRE_MSG(map1 != NULL, "failed to look up map for 'ld-elf'"); 209d42df2a4SMark Johnston map2 = proc_name2map(phdl, "ld-elf.so"); 210d42df2a4SMark Johnston ATF_REQUIRE_MSG(map2 != NULL, "failed to look up map for 'ld-elf.so'"); 211d42df2a4SMark Johnston ATF_CHECK_EQ(strcmp(map1->pr_mapname, map2->pr_mapname), 0); 212d42df2a4SMark Johnston 213d42df2a4SMark Johnston ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); 214d42df2a4SMark Johnston 215d42df2a4SMark Johnston proc_free(phdl); 216d42df2a4SMark Johnston } 217d42df2a4SMark Johnston 2189351ac6dSMark Johnston ATF_TC(map_alias_name2sym); 2199351ac6dSMark Johnston ATF_TC_HEAD(map_alias_name2sym, tc) 2209351ac6dSMark Johnston { 2219351ac6dSMark Johnston atf_tc_set_md_var(tc, "descr", 2229351ac6dSMark Johnston "Callers are supposed to be able to use \"a.out\" as an alias for " 2239351ac6dSMark Johnston "the program executable. Make sure that proc_name2sym() handles " 2249351ac6dSMark Johnston "this properly."); 2259351ac6dSMark Johnston } 2269351ac6dSMark Johnston ATF_TC_BODY(map_alias_name2sym, tc) 2279351ac6dSMark Johnston { 2289351ac6dSMark Johnston GElf_Sym sym1, sym2; 22941da933cSMark Johnston prsyminfo_t si1, si2; 2309351ac6dSMark Johnston struct proc_handle *phdl; 2319351ac6dSMark Johnston int error; 2329351ac6dSMark Johnston 2339351ac6dSMark Johnston phdl = start_prog(tc, false); 2349351ac6dSMark Johnston 2359351ac6dSMark Johnston /* Initialize the rtld_db handle. */ 2369351ac6dSMark Johnston (void)proc_rdagent(phdl); 2379351ac6dSMark Johnston 2389351ac6dSMark Johnston /* 2399351ac6dSMark Johnston * Make sure that "target_prog:main" and "a.out:main" return the same 2409351ac6dSMark Johnston * symbol. 2419351ac6dSMark Johnston */ 24241da933cSMark Johnston error = proc_name2sym(phdl, target_prog_file, "main", &sym1, &si1); 2439351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'main' via %s", 2449351ac6dSMark Johnston target_prog_file); 24541da933cSMark Johnston error = proc_name2sym(phdl, aout_object, "main", &sym2, &si2); 2469351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'main' via %s", 2479351ac6dSMark Johnston aout_object); 2489351ac6dSMark Johnston 2499351ac6dSMark Johnston ATF_CHECK_EQ(memcmp(&sym1, &sym2, sizeof(sym1)), 0); 25041da933cSMark Johnston ATF_CHECK_EQ(si1.prs_id, si2.prs_id); 2519351ac6dSMark Johnston 2529351ac6dSMark Johnston ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); 2539351ac6dSMark Johnston 2549351ac6dSMark Johnston proc_free(phdl); 2559351ac6dSMark Johnston } 2569351ac6dSMark Johnston 2579351ac6dSMark Johnston ATF_TC(symbol_lookup); 2589351ac6dSMark Johnston ATF_TC_HEAD(symbol_lookup, tc) 2599351ac6dSMark Johnston { 2609351ac6dSMark Johnston atf_tc_set_md_var(tc, "descr", 2619351ac6dSMark Johnston "Look up a couple of well-known symbols in the test program, place " 2629351ac6dSMark Johnston "breakpoints on them, and verify that we hit the breakpoints. Also " 2639351ac6dSMark Johnston "make sure that we can use the breakpoint address to look up the " 2649351ac6dSMark Johnston "corresponding symbol."); 2659351ac6dSMark Johnston } 2669351ac6dSMark Johnston ATF_TC_BODY(symbol_lookup, tc) 2679351ac6dSMark Johnston { 2689351ac6dSMark Johnston GElf_Sym main_sym, r_debug_state_sym; 2699351ac6dSMark Johnston struct proc_handle *phdl; 2709351ac6dSMark Johnston u_long saved; 2719351ac6dSMark Johnston int error; 2729351ac6dSMark Johnston 2739351ac6dSMark Johnston phdl = start_prog(tc, false); 2749351ac6dSMark Johnston 27541da933cSMark Johnston error = proc_name2sym(phdl, target_prog_file, "main", &main_sym, NULL); 2769351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'main'"); 2779351ac6dSMark Johnston 2789351ac6dSMark Johnston error = proc_name2sym(phdl, ldelf_object, "r_debug_state", 27941da933cSMark Johnston &r_debug_state_sym, NULL); 2809351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'r_debug_state'"); 2819351ac6dSMark Johnston 2829351ac6dSMark Johnston set_bkpt(phdl, r_debug_state_sym.st_value, &saved); 2839351ac6dSMark Johnston ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); 2849351ac6dSMark Johnston verify_bkpt(phdl, &r_debug_state_sym, "r_debug_state", ldelf_object); 2859351ac6dSMark Johnston remove_bkpt(phdl, r_debug_state_sym.st_value, saved); 2869351ac6dSMark Johnston 2879351ac6dSMark Johnston set_bkpt(phdl, main_sym.st_value, &saved); 2889351ac6dSMark Johnston ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); 2899351ac6dSMark Johnston verify_bkpt(phdl, &main_sym, "main", target_prog_file); 2909351ac6dSMark Johnston remove_bkpt(phdl, main_sym.st_value, saved); 2919351ac6dSMark Johnston 2929351ac6dSMark Johnston ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); 2939351ac6dSMark Johnston 2949351ac6dSMark Johnston proc_free(phdl); 2959351ac6dSMark Johnston } 2969351ac6dSMark Johnston 297cd9c9939SMark Johnston ATF_TC(symbol_lookup_fail); 298cd9c9939SMark Johnston ATF_TC_HEAD(symbol_lookup_fail, tc) 299cd9c9939SMark Johnston { 300cd9c9939SMark Johnston atf_tc_set_md_var(tc, "descr", 301cd9c9939SMark Johnston "Verify that proc_addr2sym() returns an error when given an offset " 302cd9c9939SMark Johnston "that it cannot resolve."); 303cd9c9939SMark Johnston } 304cd9c9939SMark Johnston ATF_TC_BODY(symbol_lookup_fail, tc) 305cd9c9939SMark Johnston { 306cd9c9939SMark Johnston char symname[32]; 307cd9c9939SMark Johnston GElf_Sym sym; 308cd9c9939SMark Johnston struct proc_handle *phdl; 309cd9c9939SMark Johnston prmap_t *map; 310cd9c9939SMark Johnston int error; 311cd9c9939SMark Johnston 312cd9c9939SMark Johnston phdl = start_prog(tc, false); 313cd9c9939SMark Johnston 314cd9c9939SMark Johnston /* Initialize the rtld_db handle. */ 315cd9c9939SMark Johnston (void)proc_rdagent(phdl); 316cd9c9939SMark Johnston 317d42df2a4SMark Johnston map = proc_name2map(phdl, target_prog_file); 318cd9c9939SMark Johnston ATF_REQUIRE_MSG(map != NULL, "failed to look up map for '%s'", 319cd9c9939SMark Johnston target_prog_file); 320cd9c9939SMark Johnston 321cd9c9939SMark Johnston /* 322cd9c9939SMark Johnston * We shouldn't be able to find symbols at the beginning of a mapped 323cd9c9939SMark Johnston * file. 324cd9c9939SMark Johnston */ 325cd9c9939SMark Johnston error = proc_addr2sym(phdl, map->pr_vaddr, symname, sizeof(symname), 326cd9c9939SMark Johnston &sym); 327cd9c9939SMark Johnston ATF_REQUIRE_MSG(error != 0, "unexpectedly found a symbol"); 328cd9c9939SMark Johnston 329cd9c9939SMark Johnston ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); 330cd9c9939SMark Johnston 331cd9c9939SMark Johnston proc_free(phdl); 332cd9c9939SMark Johnston } 333cd9c9939SMark Johnston 3349351ac6dSMark Johnston ATF_TC(signal_forward); 3359351ac6dSMark Johnston ATF_TC_HEAD(signal_forward, tc) 3369351ac6dSMark Johnston { 3379351ac6dSMark Johnston atf_tc_set_md_var(tc, "descr", 3389351ac6dSMark Johnston "Run the test program in a mode which causes it to send a signal " 3399351ac6dSMark Johnston "to itself. Make sure that we intercept the signal and that " 3409351ac6dSMark Johnston "proc_continue() forwards it to the process."); 3419351ac6dSMark Johnston } 3429351ac6dSMark Johnston ATF_TC_BODY(signal_forward, tc) 3439351ac6dSMark Johnston { 3449351ac6dSMark Johnston struct proc_handle *phdl; 3459351ac6dSMark Johnston int state, status; 3469351ac6dSMark Johnston 3479351ac6dSMark Johnston phdl = start_prog(tc, true); 3489351ac6dSMark Johnston ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); 3499351ac6dSMark Johnston 3509351ac6dSMark Johnston /* The process should have been interrupted by a signal. */ 3519351ac6dSMark Johnston state = proc_wstatus(phdl); 3529351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(state, PS_STOP, "process has unexpected state %d", 3539351ac6dSMark Johnston state); 3549351ac6dSMark Johnston 3559351ac6dSMark Johnston /* Continue execution and allow the signal to be delivered. */ 3569351ac6dSMark Johnston ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); 3579351ac6dSMark Johnston 3589351ac6dSMark Johnston /* 3599351ac6dSMark Johnston * Make sure the process exited with status 0. If it didn't receive the 3609351ac6dSMark Johnston * SIGUSR1 that it sent to itself, it'll exit with a non-zero exit 3619351ac6dSMark Johnston * status, causing the test to fail. 3629351ac6dSMark Johnston */ 3639351ac6dSMark Johnston state = proc_wstatus(phdl); 3649351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(state, PS_UNDEAD, "process has unexpected state %d", 3659351ac6dSMark Johnston state); 3669351ac6dSMark Johnston 3679351ac6dSMark Johnston status = proc_getwstat(phdl); 3689351ac6dSMark Johnston ATF_REQUIRE(status >= 0); 3699351ac6dSMark Johnston ATF_REQUIRE(WIFEXITED(status)); 3709351ac6dSMark Johnston ATF_REQUIRE_EQ(WEXITSTATUS(status), 0); 3719351ac6dSMark Johnston 3729351ac6dSMark Johnston proc_free(phdl); 3739351ac6dSMark Johnston } 3749351ac6dSMark Johnston 3751bdc41d2SMark Johnston ATF_TC(symbol_sort_local); 3761bdc41d2SMark Johnston ATF_TC_HEAD(symbol_sort_local, tc) 3771bdc41d2SMark Johnston { 3781bdc41d2SMark Johnston atf_tc_set_md_var(tc, "descr", 3791bdc41d2SMark Johnston "Ensure that proc_addr2sym() returns the non-local alias when " 3801bdc41d2SMark Johnston "the address resolves to multiple symbols."); 3811bdc41d2SMark Johnston } 3821bdc41d2SMark Johnston ATF_TC_BODY(symbol_sort_local, tc) 3831bdc41d2SMark Johnston { 3841bdc41d2SMark Johnston char symname[32]; 3851bdc41d2SMark Johnston GElf_Sym bar_sym; 3861bdc41d2SMark Johnston struct proc_handle *phdl; 3871bdc41d2SMark Johnston int error; 3881bdc41d2SMark Johnston 3891bdc41d2SMark Johnston phdl = start_prog(tc, true); 3901bdc41d2SMark Johnston 3911bdc41d2SMark Johnston error = proc_name2sym(phdl, target_prog_file, "bar", &bar_sym, NULL); 3921bdc41d2SMark Johnston ATF_REQUIRE_MSG(error == 0, "failed to look up 'bar' in %s", 3931bdc41d2SMark Johnston target_prog_file); 3941bdc41d2SMark Johnston ATF_REQUIRE(GELF_ST_BIND(bar_sym.st_info) == STB_LOCAL); 3951bdc41d2SMark Johnston 3961bdc41d2SMark Johnston error = proc_addr2sym(phdl, bar_sym.st_value, symname, sizeof(symname), 3971bdc41d2SMark Johnston &bar_sym); 3981bdc41d2SMark Johnston ATF_REQUIRE_MSG(error == 0, "failed to resolve 'bar' by addr"); 3991bdc41d2SMark Johnston 4001bdc41d2SMark Johnston ATF_REQUIRE_MSG(strcmp(symname, "baz") == 0, 4011bdc41d2SMark Johnston "unexpected symbol name '%s'", symname); 4021bdc41d2SMark Johnston ATF_REQUIRE(GELF_ST_BIND(bar_sym.st_info) == STB_GLOBAL); 4031bdc41d2SMark Johnston } 4041bdc41d2SMark Johnston 4051bdc41d2SMark Johnston ATF_TC(symbol_sort_prefix); 4061bdc41d2SMark Johnston ATF_TC_HEAD(symbol_sort_prefix, tc) 4071bdc41d2SMark Johnston { 4081bdc41d2SMark Johnston atf_tc_set_md_var(tc, "descr", 4091bdc41d2SMark Johnston "Ensure that proc_addr2sym() returns the alias whose name is not " 4101bdc41d2SMark Johnston "prefixed with '$' if one exists."); 4111bdc41d2SMark Johnston } 4121bdc41d2SMark Johnston ATF_TC_BODY(symbol_sort_prefix, tc) 4131bdc41d2SMark Johnston { 4141bdc41d2SMark Johnston char symname[32]; 4151bdc41d2SMark Johnston GElf_Sym qux_sym; 4161bdc41d2SMark Johnston struct proc_handle *phdl; 4171bdc41d2SMark Johnston int error; 4181bdc41d2SMark Johnston 4191bdc41d2SMark Johnston phdl = start_prog(tc, true); 4201bdc41d2SMark Johnston 4211bdc41d2SMark Johnston error = proc_name2sym(phdl, target_prog_file, "$qux", &qux_sym, NULL); 4221bdc41d2SMark Johnston ATF_REQUIRE_MSG(error == 0, "failed to look up '$qux' in %s", 4231bdc41d2SMark Johnston target_prog_file); 4241bdc41d2SMark Johnston 4251bdc41d2SMark Johnston error = proc_addr2sym(phdl, qux_sym.st_value, symname, sizeof(symname), 4261bdc41d2SMark Johnston &qux_sym); 4271bdc41d2SMark Johnston ATF_REQUIRE_MSG(error == 0, "failed to resolve 'qux' by addr"); 4281bdc41d2SMark Johnston 4291bdc41d2SMark Johnston ATF_REQUIRE_MSG(strcmp(symname, "qux") == 0, 4301bdc41d2SMark Johnston "unexpected symbol name '%s'", symname); 4311bdc41d2SMark Johnston } 4321bdc41d2SMark Johnston 4331bdc41d2SMark Johnston ATF_TC(symbol_sort_underscore); 4341bdc41d2SMark Johnston ATF_TC_HEAD(symbol_sort_underscore, tc) 4351bdc41d2SMark Johnston { 4361bdc41d2SMark Johnston atf_tc_set_md_var(tc, "descr", 4371bdc41d2SMark Johnston "Ensure that proc_addr2sym() returns the alias with fewest leading " 4381bdc41d2SMark Johnston "underscores in the name when the address resolves to multiple " 4391bdc41d2SMark Johnston "symbols."); 4401bdc41d2SMark Johnston } 4411bdc41d2SMark Johnston ATF_TC_BODY(symbol_sort_underscore, tc) 4421bdc41d2SMark Johnston { 4431bdc41d2SMark Johnston char symname[32]; 4441bdc41d2SMark Johnston GElf_Sym foo_sym; 4451bdc41d2SMark Johnston struct proc_handle *phdl; 4461bdc41d2SMark Johnston int error; 4471bdc41d2SMark Johnston 4481bdc41d2SMark Johnston phdl = start_prog(tc, true); 4491bdc41d2SMark Johnston 4501bdc41d2SMark Johnston error = proc_name2sym(phdl, target_prog_file, "foo", &foo_sym, NULL); 4511bdc41d2SMark Johnston ATF_REQUIRE_MSG(error == 0, "failed to look up 'foo' in %s", 4521bdc41d2SMark Johnston target_prog_file); 4531bdc41d2SMark Johnston 4541bdc41d2SMark Johnston error = proc_addr2sym(phdl, foo_sym.st_value, symname, sizeof(symname), 4551bdc41d2SMark Johnston &foo_sym); 4561bdc41d2SMark Johnston ATF_REQUIRE_MSG(error == 0, "failed to resolve 'foo' by addr"); 4571bdc41d2SMark Johnston 4581bdc41d2SMark Johnston ATF_REQUIRE_MSG(strcmp(symname, "foo") == 0, 4591bdc41d2SMark Johnston "unexpected symbol name '%s'", symname); 4601bdc41d2SMark Johnston } 4611bdc41d2SMark Johnston 4629351ac6dSMark Johnston ATF_TP_ADD_TCS(tp) 4639351ac6dSMark Johnston { 4649351ac6dSMark Johnston 4659351ac6dSMark Johnston ATF_TP_ADD_TC(tp, map_alias_name2map); 466d42df2a4SMark Johnston ATF_TP_ADD_TC(tp, map_prefix_name2map); 4679351ac6dSMark Johnston ATF_TP_ADD_TC(tp, map_alias_name2sym); 4689351ac6dSMark Johnston ATF_TP_ADD_TC(tp, symbol_lookup); 469cd9c9939SMark Johnston ATF_TP_ADD_TC(tp, symbol_lookup_fail); 4709351ac6dSMark Johnston ATF_TP_ADD_TC(tp, signal_forward); 4711bdc41d2SMark Johnston ATF_TP_ADD_TC(tp, symbol_sort_local); 4721bdc41d2SMark Johnston ATF_TP_ADD_TC(tp, symbol_sort_prefix); 4731bdc41d2SMark Johnston ATF_TP_ADD_TC(tp, symbol_sort_underscore); 4749351ac6dSMark Johnston 4759351ac6dSMark Johnston return (atf_no_error()); 4769351ac6dSMark Johnston } 477