19351ac6dSMark Johnston /*- 2*1bdc41d2SMark 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 689351ac6dSMark Johnston error = proc_create(argv[0], argv, 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 { 1089351ac6dSMark Johnston char mapbname[MAXPATHLEN], *name; 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); 1509351ac6dSMark Johnston basename_r(map->pr_mapname, mapbname); 1519351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(strcmp(mapname, mapbname), 0, 1529351ac6dSMark Johnston "expected map name '%s' doesn't match '%s'", mapname, mapbname); 1539351ac6dSMark Johnston } 1549351ac6dSMark Johnston 1559351ac6dSMark Johnston ATF_TC(map_alias_name2map); 1569351ac6dSMark Johnston ATF_TC_HEAD(map_alias_name2map, tc) 1579351ac6dSMark Johnston { 1589351ac6dSMark Johnston atf_tc_set_md_var(tc, "descr", 1599351ac6dSMark Johnston "Callers are supposed to be able to use \"a.out\" as an alias for " 1609351ac6dSMark Johnston "the program executable. Make sure that proc_name2map() handles " 1619351ac6dSMark Johnston "this properly."); 1629351ac6dSMark Johnston } 1639351ac6dSMark Johnston ATF_TC_BODY(map_alias_name2map, tc) 1649351ac6dSMark Johnston { 1659351ac6dSMark Johnston struct proc_handle *phdl; 1669351ac6dSMark Johnston prmap_t *map1, *map2; 1679351ac6dSMark Johnston 1689351ac6dSMark Johnston phdl = start_prog(tc, false); 1699351ac6dSMark Johnston 1709351ac6dSMark Johnston /* Initialize the rtld_db handle. */ 1719351ac6dSMark Johnston (void)proc_rdagent(phdl); 1729351ac6dSMark Johnston 1739351ac6dSMark Johnston /* Ensure that "target_prog" and "a.out" return the same map. */ 1749351ac6dSMark Johnston map1 = proc_name2map(phdl, target_prog_file); 1759351ac6dSMark Johnston ATF_REQUIRE_MSG(map1 != NULL, "failed to look up map for '%s'", 1769351ac6dSMark Johnston target_prog_file); 1779351ac6dSMark Johnston map2 = proc_name2map(phdl, aout_object); 1789351ac6dSMark Johnston ATF_REQUIRE_MSG(map2 != NULL, "failed to look up map for '%s'", 1799351ac6dSMark Johnston aout_object); 1809351ac6dSMark Johnston ATF_CHECK_EQ(strcmp(map1->pr_mapname, map2->pr_mapname), 0); 1819351ac6dSMark Johnston 1829351ac6dSMark Johnston ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); 1839351ac6dSMark Johnston 1849351ac6dSMark Johnston proc_free(phdl); 1859351ac6dSMark Johnston } 1869351ac6dSMark Johnston 187d42df2a4SMark Johnston ATF_TC(map_prefix_name2map); 188d42df2a4SMark Johnston ATF_TC_HEAD(map_prefix_name2map, tc) 189d42df2a4SMark Johnston { 190d42df2a4SMark Johnston atf_tc_set_md_var(tc, "descr", 191d42df2a4SMark Johnston "Verify that proc_name2map() returns prefix matches of the " 192d42df2a4SMark Johnston "basename of loaded objects if no full matches are found."); 193d42df2a4SMark Johnston } 194d42df2a4SMark Johnston ATF_TC_BODY(map_prefix_name2map, tc) 195d42df2a4SMark Johnston { 196d42df2a4SMark Johnston struct proc_handle *phdl; 197d42df2a4SMark Johnston prmap_t *map1, *map2; 198d42df2a4SMark Johnston 199d42df2a4SMark Johnston phdl = start_prog(tc, false); 200d42df2a4SMark Johnston 201d42df2a4SMark Johnston /* Initialize the rtld_db handle. */ 202d42df2a4SMark Johnston (void)proc_rdagent(phdl); 203d42df2a4SMark Johnston 204d42df2a4SMark Johnston /* Make sure that "ld-elf" and "ld-elf.so" return the same map. */ 205d42df2a4SMark Johnston map1 = proc_name2map(phdl, "ld-elf"); 206d42df2a4SMark Johnston ATF_REQUIRE_MSG(map1 != NULL, "failed to look up map for 'ld-elf'"); 207d42df2a4SMark Johnston map2 = proc_name2map(phdl, "ld-elf.so"); 208d42df2a4SMark Johnston ATF_REQUIRE_MSG(map2 != NULL, "failed to look up map for 'ld-elf.so'"); 209d42df2a4SMark Johnston ATF_CHECK_EQ(strcmp(map1->pr_mapname, map2->pr_mapname), 0); 210d42df2a4SMark Johnston 211d42df2a4SMark Johnston ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); 212d42df2a4SMark Johnston 213d42df2a4SMark Johnston proc_free(phdl); 214d42df2a4SMark Johnston } 215d42df2a4SMark Johnston 2169351ac6dSMark Johnston ATF_TC(map_alias_name2sym); 2179351ac6dSMark Johnston ATF_TC_HEAD(map_alias_name2sym, tc) 2189351ac6dSMark Johnston { 2199351ac6dSMark Johnston atf_tc_set_md_var(tc, "descr", 2209351ac6dSMark Johnston "Callers are supposed to be able to use \"a.out\" as an alias for " 2219351ac6dSMark Johnston "the program executable. Make sure that proc_name2sym() handles " 2229351ac6dSMark Johnston "this properly."); 2239351ac6dSMark Johnston } 2249351ac6dSMark Johnston ATF_TC_BODY(map_alias_name2sym, tc) 2259351ac6dSMark Johnston { 2269351ac6dSMark Johnston GElf_Sym sym1, sym2; 22741da933cSMark Johnston prsyminfo_t si1, si2; 2289351ac6dSMark Johnston struct proc_handle *phdl; 2299351ac6dSMark Johnston int error; 2309351ac6dSMark Johnston 2319351ac6dSMark Johnston phdl = start_prog(tc, false); 2329351ac6dSMark Johnston 2339351ac6dSMark Johnston /* Initialize the rtld_db handle. */ 2349351ac6dSMark Johnston (void)proc_rdagent(phdl); 2359351ac6dSMark Johnston 2369351ac6dSMark Johnston /* 2379351ac6dSMark Johnston * Make sure that "target_prog:main" and "a.out:main" return the same 2389351ac6dSMark Johnston * symbol. 2399351ac6dSMark Johnston */ 24041da933cSMark Johnston error = proc_name2sym(phdl, target_prog_file, "main", &sym1, &si1); 2419351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'main' via %s", 2429351ac6dSMark Johnston target_prog_file); 24341da933cSMark Johnston error = proc_name2sym(phdl, aout_object, "main", &sym2, &si2); 2449351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'main' via %s", 2459351ac6dSMark Johnston aout_object); 2469351ac6dSMark Johnston 2479351ac6dSMark Johnston ATF_CHECK_EQ(memcmp(&sym1, &sym2, sizeof(sym1)), 0); 24841da933cSMark Johnston ATF_CHECK_EQ(si1.prs_id, si2.prs_id); 2499351ac6dSMark Johnston 2509351ac6dSMark Johnston ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); 2519351ac6dSMark Johnston 2529351ac6dSMark Johnston proc_free(phdl); 2539351ac6dSMark Johnston } 2549351ac6dSMark Johnston 2559351ac6dSMark Johnston ATF_TC(symbol_lookup); 2569351ac6dSMark Johnston ATF_TC_HEAD(symbol_lookup, tc) 2579351ac6dSMark Johnston { 2589351ac6dSMark Johnston atf_tc_set_md_var(tc, "descr", 2599351ac6dSMark Johnston "Look up a couple of well-known symbols in the test program, place " 2609351ac6dSMark Johnston "breakpoints on them, and verify that we hit the breakpoints. Also " 2619351ac6dSMark Johnston "make sure that we can use the breakpoint address to look up the " 2629351ac6dSMark Johnston "corresponding symbol."); 2639351ac6dSMark Johnston } 2649351ac6dSMark Johnston ATF_TC_BODY(symbol_lookup, tc) 2659351ac6dSMark Johnston { 2669351ac6dSMark Johnston GElf_Sym main_sym, r_debug_state_sym; 2679351ac6dSMark Johnston struct proc_handle *phdl; 2689351ac6dSMark Johnston u_long saved; 2699351ac6dSMark Johnston int error; 2709351ac6dSMark Johnston 2719351ac6dSMark Johnston phdl = start_prog(tc, false); 2729351ac6dSMark Johnston 27341da933cSMark Johnston error = proc_name2sym(phdl, target_prog_file, "main", &main_sym, NULL); 2749351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'main'"); 2759351ac6dSMark Johnston 2769351ac6dSMark Johnston error = proc_name2sym(phdl, ldelf_object, "r_debug_state", 27741da933cSMark Johnston &r_debug_state_sym, NULL); 2789351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'r_debug_state'"); 2799351ac6dSMark Johnston 2809351ac6dSMark Johnston set_bkpt(phdl, r_debug_state_sym.st_value, &saved); 2819351ac6dSMark Johnston ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); 2829351ac6dSMark Johnston verify_bkpt(phdl, &r_debug_state_sym, "r_debug_state", ldelf_object); 2839351ac6dSMark Johnston remove_bkpt(phdl, r_debug_state_sym.st_value, saved); 2849351ac6dSMark Johnston 2859351ac6dSMark Johnston set_bkpt(phdl, main_sym.st_value, &saved); 2869351ac6dSMark Johnston ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); 2879351ac6dSMark Johnston verify_bkpt(phdl, &main_sym, "main", target_prog_file); 2889351ac6dSMark Johnston remove_bkpt(phdl, main_sym.st_value, saved); 2899351ac6dSMark Johnston 2909351ac6dSMark Johnston ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); 2919351ac6dSMark Johnston 2929351ac6dSMark Johnston proc_free(phdl); 2939351ac6dSMark Johnston } 2949351ac6dSMark Johnston 295cd9c9939SMark Johnston ATF_TC(symbol_lookup_fail); 296cd9c9939SMark Johnston ATF_TC_HEAD(symbol_lookup_fail, tc) 297cd9c9939SMark Johnston { 298cd9c9939SMark Johnston atf_tc_set_md_var(tc, "descr", 299cd9c9939SMark Johnston "Verify that proc_addr2sym() returns an error when given an offset " 300cd9c9939SMark Johnston "that it cannot resolve."); 301cd9c9939SMark Johnston } 302cd9c9939SMark Johnston ATF_TC_BODY(symbol_lookup_fail, tc) 303cd9c9939SMark Johnston { 304cd9c9939SMark Johnston char symname[32]; 305cd9c9939SMark Johnston GElf_Sym sym; 306cd9c9939SMark Johnston struct proc_handle *phdl; 307cd9c9939SMark Johnston prmap_t *map; 308cd9c9939SMark Johnston int error; 309cd9c9939SMark Johnston 310cd9c9939SMark Johnston phdl = start_prog(tc, false); 311cd9c9939SMark Johnston 312cd9c9939SMark Johnston /* Initialize the rtld_db handle. */ 313cd9c9939SMark Johnston (void)proc_rdagent(phdl); 314cd9c9939SMark Johnston 315d42df2a4SMark Johnston map = proc_name2map(phdl, target_prog_file); 316cd9c9939SMark Johnston ATF_REQUIRE_MSG(map != NULL, "failed to look up map for '%s'", 317cd9c9939SMark Johnston target_prog_file); 318cd9c9939SMark Johnston 319cd9c9939SMark Johnston /* 320cd9c9939SMark Johnston * We shouldn't be able to find symbols at the beginning of a mapped 321cd9c9939SMark Johnston * file. 322cd9c9939SMark Johnston */ 323cd9c9939SMark Johnston error = proc_addr2sym(phdl, map->pr_vaddr, symname, sizeof(symname), 324cd9c9939SMark Johnston &sym); 325cd9c9939SMark Johnston ATF_REQUIRE_MSG(error != 0, "unexpectedly found a symbol"); 326cd9c9939SMark Johnston 327cd9c9939SMark Johnston ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); 328cd9c9939SMark Johnston 329cd9c9939SMark Johnston proc_free(phdl); 330cd9c9939SMark Johnston } 331cd9c9939SMark Johnston 3329351ac6dSMark Johnston ATF_TC(signal_forward); 3339351ac6dSMark Johnston ATF_TC_HEAD(signal_forward, tc) 3349351ac6dSMark Johnston { 3359351ac6dSMark Johnston atf_tc_set_md_var(tc, "descr", 3369351ac6dSMark Johnston "Run the test program in a mode which causes it to send a signal " 3379351ac6dSMark Johnston "to itself. Make sure that we intercept the signal and that " 3389351ac6dSMark Johnston "proc_continue() forwards it to the process."); 3399351ac6dSMark Johnston } 3409351ac6dSMark Johnston ATF_TC_BODY(signal_forward, tc) 3419351ac6dSMark Johnston { 3429351ac6dSMark Johnston struct proc_handle *phdl; 3439351ac6dSMark Johnston int state, status; 3449351ac6dSMark Johnston 3459351ac6dSMark Johnston phdl = start_prog(tc, true); 3469351ac6dSMark Johnston ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); 3479351ac6dSMark Johnston 3489351ac6dSMark Johnston /* The process should have been interrupted by a signal. */ 3499351ac6dSMark Johnston state = proc_wstatus(phdl); 3509351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(state, PS_STOP, "process has unexpected state %d", 3519351ac6dSMark Johnston state); 3529351ac6dSMark Johnston 3539351ac6dSMark Johnston /* Continue execution and allow the signal to be delivered. */ 3549351ac6dSMark Johnston ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); 3559351ac6dSMark Johnston 3569351ac6dSMark Johnston /* 3579351ac6dSMark Johnston * Make sure the process exited with status 0. If it didn't receive the 3589351ac6dSMark Johnston * SIGUSR1 that it sent to itself, it'll exit with a non-zero exit 3599351ac6dSMark Johnston * status, causing the test to fail. 3609351ac6dSMark Johnston */ 3619351ac6dSMark Johnston state = proc_wstatus(phdl); 3629351ac6dSMark Johnston ATF_REQUIRE_EQ_MSG(state, PS_UNDEAD, "process has unexpected state %d", 3639351ac6dSMark Johnston state); 3649351ac6dSMark Johnston 3659351ac6dSMark Johnston status = proc_getwstat(phdl); 3669351ac6dSMark Johnston ATF_REQUIRE(status >= 0); 3679351ac6dSMark Johnston ATF_REQUIRE(WIFEXITED(status)); 3689351ac6dSMark Johnston ATF_REQUIRE_EQ(WEXITSTATUS(status), 0); 3699351ac6dSMark Johnston 3709351ac6dSMark Johnston proc_free(phdl); 3719351ac6dSMark Johnston } 3729351ac6dSMark Johnston 373*1bdc41d2SMark Johnston ATF_TC(symbol_sort_local); 374*1bdc41d2SMark Johnston ATF_TC_HEAD(symbol_sort_local, tc) 375*1bdc41d2SMark Johnston { 376*1bdc41d2SMark Johnston atf_tc_set_md_var(tc, "descr", 377*1bdc41d2SMark Johnston "Ensure that proc_addr2sym() returns the non-local alias when " 378*1bdc41d2SMark Johnston "the address resolves to multiple symbols."); 379*1bdc41d2SMark Johnston } 380*1bdc41d2SMark Johnston ATF_TC_BODY(symbol_sort_local, tc) 381*1bdc41d2SMark Johnston { 382*1bdc41d2SMark Johnston char symname[32]; 383*1bdc41d2SMark Johnston GElf_Sym bar_sym; 384*1bdc41d2SMark Johnston struct proc_handle *phdl; 385*1bdc41d2SMark Johnston int error; 386*1bdc41d2SMark Johnston 387*1bdc41d2SMark Johnston phdl = start_prog(tc, true); 388*1bdc41d2SMark Johnston 389*1bdc41d2SMark Johnston error = proc_name2sym(phdl, target_prog_file, "bar", &bar_sym, NULL); 390*1bdc41d2SMark Johnston ATF_REQUIRE_MSG(error == 0, "failed to look up 'bar' in %s", 391*1bdc41d2SMark Johnston target_prog_file); 392*1bdc41d2SMark Johnston ATF_REQUIRE(GELF_ST_BIND(bar_sym.st_info) == STB_LOCAL); 393*1bdc41d2SMark Johnston 394*1bdc41d2SMark Johnston error = proc_addr2sym(phdl, bar_sym.st_value, symname, sizeof(symname), 395*1bdc41d2SMark Johnston &bar_sym); 396*1bdc41d2SMark Johnston ATF_REQUIRE_MSG(error == 0, "failed to resolve 'bar' by addr"); 397*1bdc41d2SMark Johnston 398*1bdc41d2SMark Johnston ATF_REQUIRE_MSG(strcmp(symname, "baz") == 0, 399*1bdc41d2SMark Johnston "unexpected symbol name '%s'", symname); 400*1bdc41d2SMark Johnston ATF_REQUIRE(GELF_ST_BIND(bar_sym.st_info) == STB_GLOBAL); 401*1bdc41d2SMark Johnston } 402*1bdc41d2SMark Johnston 403*1bdc41d2SMark Johnston ATF_TC(symbol_sort_prefix); 404*1bdc41d2SMark Johnston ATF_TC_HEAD(symbol_sort_prefix, tc) 405*1bdc41d2SMark Johnston { 406*1bdc41d2SMark Johnston atf_tc_set_md_var(tc, "descr", 407*1bdc41d2SMark Johnston "Ensure that proc_addr2sym() returns the alias whose name is not " 408*1bdc41d2SMark Johnston "prefixed with '$' if one exists."); 409*1bdc41d2SMark Johnston } 410*1bdc41d2SMark Johnston ATF_TC_BODY(symbol_sort_prefix, tc) 411*1bdc41d2SMark Johnston { 412*1bdc41d2SMark Johnston char symname[32]; 413*1bdc41d2SMark Johnston GElf_Sym qux_sym; 414*1bdc41d2SMark Johnston struct proc_handle *phdl; 415*1bdc41d2SMark Johnston int error; 416*1bdc41d2SMark Johnston 417*1bdc41d2SMark Johnston phdl = start_prog(tc, true); 418*1bdc41d2SMark Johnston 419*1bdc41d2SMark Johnston error = proc_name2sym(phdl, target_prog_file, "$qux", &qux_sym, NULL); 420*1bdc41d2SMark Johnston ATF_REQUIRE_MSG(error == 0, "failed to look up '$qux' in %s", 421*1bdc41d2SMark Johnston target_prog_file); 422*1bdc41d2SMark Johnston 423*1bdc41d2SMark Johnston error = proc_addr2sym(phdl, qux_sym.st_value, symname, sizeof(symname), 424*1bdc41d2SMark Johnston &qux_sym); 425*1bdc41d2SMark Johnston ATF_REQUIRE_MSG(error == 0, "failed to resolve 'qux' by addr"); 426*1bdc41d2SMark Johnston 427*1bdc41d2SMark Johnston ATF_REQUIRE_MSG(strcmp(symname, "qux") == 0, 428*1bdc41d2SMark Johnston "unexpected symbol name '%s'", symname); 429*1bdc41d2SMark Johnston } 430*1bdc41d2SMark Johnston 431*1bdc41d2SMark Johnston ATF_TC(symbol_sort_underscore); 432*1bdc41d2SMark Johnston ATF_TC_HEAD(symbol_sort_underscore, tc) 433*1bdc41d2SMark Johnston { 434*1bdc41d2SMark Johnston atf_tc_set_md_var(tc, "descr", 435*1bdc41d2SMark Johnston "Ensure that proc_addr2sym() returns the alias with fewest leading " 436*1bdc41d2SMark Johnston "underscores in the name when the address resolves to multiple " 437*1bdc41d2SMark Johnston "symbols."); 438*1bdc41d2SMark Johnston } 439*1bdc41d2SMark Johnston ATF_TC_BODY(symbol_sort_underscore, tc) 440*1bdc41d2SMark Johnston { 441*1bdc41d2SMark Johnston char symname[32]; 442*1bdc41d2SMark Johnston GElf_Sym foo_sym; 443*1bdc41d2SMark Johnston struct proc_handle *phdl; 444*1bdc41d2SMark Johnston int error; 445*1bdc41d2SMark Johnston 446*1bdc41d2SMark Johnston phdl = start_prog(tc, true); 447*1bdc41d2SMark Johnston 448*1bdc41d2SMark Johnston error = proc_name2sym(phdl, target_prog_file, "foo", &foo_sym, NULL); 449*1bdc41d2SMark Johnston ATF_REQUIRE_MSG(error == 0, "failed to look up 'foo' in %s", 450*1bdc41d2SMark Johnston target_prog_file); 451*1bdc41d2SMark Johnston 452*1bdc41d2SMark Johnston error = proc_addr2sym(phdl, foo_sym.st_value, symname, sizeof(symname), 453*1bdc41d2SMark Johnston &foo_sym); 454*1bdc41d2SMark Johnston ATF_REQUIRE_MSG(error == 0, "failed to resolve 'foo' by addr"); 455*1bdc41d2SMark Johnston 456*1bdc41d2SMark Johnston ATF_REQUIRE_MSG(strcmp(symname, "foo") == 0, 457*1bdc41d2SMark Johnston "unexpected symbol name '%s'", symname); 458*1bdc41d2SMark Johnston } 459*1bdc41d2SMark Johnston 4609351ac6dSMark Johnston ATF_TP_ADD_TCS(tp) 4619351ac6dSMark Johnston { 4629351ac6dSMark Johnston 4639351ac6dSMark Johnston ATF_TP_ADD_TC(tp, map_alias_name2map); 464d42df2a4SMark Johnston ATF_TP_ADD_TC(tp, map_prefix_name2map); 4659351ac6dSMark Johnston ATF_TP_ADD_TC(tp, map_alias_name2sym); 4669351ac6dSMark Johnston ATF_TP_ADD_TC(tp, symbol_lookup); 467cd9c9939SMark Johnston ATF_TP_ADD_TC(tp, symbol_lookup_fail); 4689351ac6dSMark Johnston ATF_TP_ADD_TC(tp, signal_forward); 469*1bdc41d2SMark Johnston ATF_TP_ADD_TC(tp, symbol_sort_local); 470*1bdc41d2SMark Johnston ATF_TP_ADD_TC(tp, symbol_sort_prefix); 471*1bdc41d2SMark Johnston ATF_TP_ADD_TC(tp, symbol_sort_underscore); 4729351ac6dSMark Johnston 4739351ac6dSMark Johnston return (atf_no_error()); 4749351ac6dSMark Johnston } 475