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_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, NULL); ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'main'"); error = proc_name2sym(phdl, ldelf_object, "r_debug_state", &r_debug_state_sym, NULL); 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_BODY(symbol_lookup_fail, tc) { char symname[32]; GElf_Sym sym; struct proc_handle *phdl; prmap_t *map; int error; phdl = start_prog(tc, false); /* Initialize the rtld_db handle. */ (void)proc_rdagent(phdl); map = proc_name2map(phdl, target_prog_file); ATF_REQUIRE_MSG(map != NULL, "failed to look up map for '%s'", target_prog_file); /* * We shouldn't be able to find symbols at the beginning of a mapped * file. */ error = proc_addr2sym(phdl, map->pr_vaddr, symname, sizeof(symname), &sym); ATF_REQUIRE_MSG(error != 0, "unexpectedly found a symbol"); ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); proc_free(phdl); }
ATF_TC_BODY(symbol_lookup, tc) { GElf_Sym main_sym, r_debug_state_sym; struct proc_handle *phdl; proc_breakpoint_t saved; int error; phdl = start_prog(tc, false); error = proc_name2sym(phdl, target_prog_file, "main", &main_sym, NULL); ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'main'"); error = proc_name2sym(phdl, ldelf_object, r_debug_state, &r_debug_state_sym, NULL); ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up '%s'", r_debug_state); set_bkpt(phdl, (uintptr_t)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, (uintptr_t)r_debug_state_sym.st_value, &saved); set_bkpt(phdl, (uintptr_t)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, (uintptr_t)main_sym.st_value, &saved); ATF_CHECK_EQ_MSG(proc_detach(phdl, PRELEASE_HANG), 0, "failed to detach"); proc_free(phdl); }
ATF_TC_BODY(map_alias_name2sym, tc) { GElf_Sym sym1, sym2; prsyminfo_t si1, si2; 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, &si1); ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'main' via %s", target_prog_file); error = proc_name2sym(phdl, aout_object, "main", &sym2, &si2); 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(si1.prs_id, si2.prs_id); ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); proc_free(phdl); }
ATF_TC_BODY(symbol_sort_underscore, tc) { char symname[32]; GElf_Sym foo_sym; struct proc_handle *phdl; int error; phdl = start_prog(tc, true); error = proc_name2sym(phdl, target_prog_file, "foo", &foo_sym, NULL); ATF_REQUIRE_MSG(error == 0, "failed to look up 'foo' in %s", target_prog_file); error = proc_addr2sym(phdl, foo_sym.st_value, symname, sizeof(symname), &foo_sym); ATF_REQUIRE_MSG(error == 0, "failed to resolve 'foo' by addr"); ATF_REQUIRE_MSG(strcmp(symname, "foo") == 0, "unexpected symbol name '%s'", symname); }
ATF_TC_BODY(map_prefix_name2map, tc) { struct proc_handle *phdl; prmap_t *map1, *map2; phdl = start_prog(tc, false); /* Initialize the rtld_db handle. */ (void)proc_rdagent(phdl); /* Make sure that "ld-elf" and "ld-elf.so" return the same map. */ map1 = proc_name2map(phdl, "ld-elf"); ATF_REQUIRE_MSG(map1 != NULL, "failed to look up map for 'ld-elf'"); map2 = proc_name2map(phdl, "ld-elf.so"); ATF_REQUIRE_MSG(map2 != NULL, "failed to look up map for 'ld-elf.so'"); 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_BODY(symbol_sort_local, tc) { char symname[32]; GElf_Sym bar_sym; struct proc_handle *phdl; int error; phdl = start_prog(tc, true); error = proc_name2sym(phdl, target_prog_file, "bar", &bar_sym, NULL); ATF_REQUIRE_MSG(error == 0, "failed to look up 'bar' in %s", target_prog_file); ATF_REQUIRE(GELF_ST_BIND(bar_sym.st_info) == STB_LOCAL); error = proc_addr2sym(phdl, bar_sym.st_value, symname, sizeof(symname), &bar_sym); ATF_REQUIRE_MSG(error == 0, "failed to resolve 'bar' by addr"); ATF_REQUIRE_MSG(strcmp(symname, "baz") == 0, "unexpected symbol name '%s'", symname); ATF_REQUIRE(GELF_ST_BIND(bar_sym.st_info) == STB_GLOBAL); }
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); }
int run_test(int argc, char **argv, unsigned int test_num, Test *test, char **fifos) { char *in_file = NULL; int in_fd = -1; char **out_files = NULL; int *out_fds = NULL; int fifo_fds[MAX_READERS]; pid_t child = 0; int i, res = 0, wres; /* Write some information about the test to the log */ print_test_info(test_num, test); assert(test->npipes <= MAX_READERS); for (i = 0; i < MAX_READERS; i++) fifo_fds[i] = -1; /* Open any output files needed */ if (test->nfiles > 0) { if (0 != get_output_files(test, &out_files, &out_fds)) goto BAIL; } /* Create an input file if the test needs one */ if (test->in_type == IN_FILE) { if (NULL == (in_file = get_input_file(test))) goto BAIL; } /* Start the program under test */ child = start_prog(argc, argv, test, &in_fd, in_file, fifos, out_files); if (child < 0) goto BAIL; /* Open any named pipes required */ if (test->npipes > 0) { if (0 != open_fifos(test->npipes, fifos, fifo_fds)) goto BAIL; } if (test->npipes) { /* reading from pipes, run the full poll loop */ res = run_poll_loop(test, in_fd, fifo_fds, fifos); /* Close any pipes that are still open */ if (0 != close_fifos(test->npipes, fifos, fifo_fds)) { res = -1; } } else if (test->in_type == IN_PIPE || test->in_type == IN_SLOW_PIPE) { /* only sending to a pipe, so just shove the data down it */ size_t offset = 0; if (gen_data("pipe", in_fd, test->in_len, &offset, 0, 0) != test->in_len) { res = -1; } if (0 != close(in_fd)) { perror("Closing pipe"); res = -1; } } /* Wait for the program to finish and check the exit status */ wres = wait_child(child); if (-99 == wres) goto BAIL; if (wres < 0) res = -1; /* Check the contents of any regular files that were created */ if (test->nfiles > 0) { if (0 != check_output_files(test, out_fds, out_files)) res = -1; } /* Clean up */ if (NULL != in_file) remove_files(&in_file, 1); if (test->nfiles > 0) { remove_files(out_files, test->nfiles); } return res; BAIL: /* Something went wrong, clean up and return 99 */ if (NULL != in_file) remove_files(&in_file, 1); if (test->nfiles > 0 && NULL != out_files) { remove_files(out_files, test->nfiles); } if (test->npipes > 0) { close_fifos(test->npipes, fifos, fifo_fds); } return 99; }