 A.Olokhtonov
					
					4 years ago
						A.Olokhtonov
					
					4 years ago
					
				
				 10 changed files with 274 additions and 14 deletions
			
			
		| @ -0,0 +1,33 @@ | |||||||
|  | #!/bin/bash | ||||||
|  | 
 | ||||||
|  | set -e | ||||||
|  | set -x | ||||||
|  | 
 | ||||||
|  | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" | ||||||
|  | pushd $SCRIPT_DIR | ||||||
|  | 
 | ||||||
|  | if [[ $# = 0 ]]; then | ||||||
|  | 	pushd src | ||||||
|  | 	mkdir -p ../build | ||||||
|  | 	gcc main.c -g -O0 -o ../build/trace -Wall -Wextra -Wno-unused-variable -Wno-unused-function -Wno-switch  # -fsanitize=address | ||||||
|  | 	popd | ||||||
|  | elif [[ $1 = "examples" ]]; then | ||||||
|  | 	pushd res | ||||||
|  | 	gcc -g -o 001-simple 001-simple.c | ||||||
|  | 	gcc -g -o 002-compilation-units 002-compilation-units.c 002-compilation-units-impl.c | ||||||
|  | 	gcc -g -o 003-recursion 003-recursion.c | ||||||
|  | 	gcc -g -o 004-scoped-variables 004-scoped-variables.c | ||||||
|  | 	gcc -g -o 005-base-types 005-base-types.c | ||||||
|  | 	gcc -g -o 006-composite-types 006-composite-types.c | ||||||
|  | 	popd | ||||||
|  | elif [[ $1 = "tests" ]]; then | ||||||
|  | 	pushd test/ | ||||||
|  | 	gcc test_main.c -g -o ../build/test -Wall -Wextra -Wno-unused-function -Wno-unused-variable | ||||||
|  | 	popd | ||||||
|  | elif [[ $1 = "clean" ]]; then | ||||||
|  | 	rm build/* | ||||||
|  | else | ||||||
|  | 	echo "No such target '$1'" | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | popd | ||||||
| @ -1,7 +0,0 @@ | |||||||
| all: |  | ||||||
| 	gcc -g -o 001-simple 001-simple.c |  | ||||||
| 	gcc -g -o 002-compilation-units 002-compilation-units.c 002-compilation-units-impl.c |  | ||||||
| 	gcc -g -o 003-recursion 003-recursion.c |  | ||||||
| 	gcc -g -o 004-scoped-variables 004-scoped-variables.c |  | ||||||
| 	gcc -g -o 005-base-types 005-base-types.c |  | ||||||
| 	gcc -g -o 006-composite-types 006-composite-types.c |  | ||||||
									
										Binary file not shown.
									
								
							
						| @ -1,2 +0,0 @@ | |||||||
| debug: |  | ||||||
| 	gcc main.c -g -O0 -o ../build/trace -Wall -Wextra -Wno-unused-variable -Wno-unused-function -Wno-switch  # -fsanitize=address |  | ||||||
| @ -0,0 +1,211 @@ | |||||||
|  | #include "../src/common.h" | ||||||
|  | 
 | ||||||
|  | #include "../src/dwarf.c" | ||||||
|  | #include "../src/eh_frame.c" | ||||||
|  | #include "../src/util.c" | ||||||
|  | #include "../src/command.c" | ||||||
|  | 
 | ||||||
|  | #define DO_TEST(title, call) do { \ | ||||||
|  | int rt = call; \ | ||||||
|  | if (rt == 0) { \ | ||||||
|  | fprintf(stderr, "Test '%s' \033[1m\033[32msuccess\033[0m...\n", title); \ | ||||||
|  | } else { \ | ||||||
|  | fprintf(stderr, "Test '%s' \033[1m\033[31mfail\033[0m\n", title); \ | ||||||
|  | exit(1); \ | ||||||
|  | } \ | ||||||
|  | } while(0) | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | test_start(char *path) | ||||||
|  | { | ||||||
|  |     struct mi_process proc = process_create(path); | ||||||
|  |     waitpid(proc.pid, 0, 0); | ||||||
|  |     parse_debug_info(proc.elf, &proc.debug); | ||||||
|  |     proc.main_address = get_address_of_subroutine(proc, "main"); | ||||||
|  |     command_start(proc); | ||||||
|  |     struct mi_registers regs = get_process_registers(proc); | ||||||
|  |      | ||||||
|  |     int result = 1; | ||||||
|  |      | ||||||
|  |     if (proc.main_address == regs.rip - proc.base_address) { | ||||||
|  |         result = 0; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     command_kill(proc); | ||||||
|  |     waitpid(proc.pid, 0, 0); | ||||||
|  |      | ||||||
|  |     return(result); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | test_regs(char *path) | ||||||
|  | { | ||||||
|  |     struct mi_process proc = process_create(path); | ||||||
|  |     waitpid(proc.pid, 0, 0); | ||||||
|  |     parse_debug_info(proc.elf, &proc.debug); | ||||||
|  |     proc.main_address = get_address_of_subroutine(proc, "main"); | ||||||
|  |     command_start(proc); | ||||||
|  |     struct mi_registers regs = get_process_registers(proc); | ||||||
|  |      | ||||||
|  |     int result = 1; | ||||||
|  |     if (regs.rbp > 0 && regs.rsp > 0 && regs.rip > 0) { | ||||||
|  |         result = 0; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     command_kill(proc); | ||||||
|  |     waitpid(proc.pid, 0, 0); | ||||||
|  |      | ||||||
|  |     return(result); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | test_step(char *path, int steps, u64 pc) | ||||||
|  | { | ||||||
|  |     struct mi_process proc = process_create(path); | ||||||
|  |     waitpid(proc.pid, 0, 0); | ||||||
|  |     parse_debug_info(proc.elf, &proc.debug); | ||||||
|  |     parse_debug_line(proc.elf, &proc.debug); | ||||||
|  |     proc.main_address = get_address_of_subroutine(proc, "main"); | ||||||
|  |     command_start(proc); | ||||||
|  |     for (int i = 0; i < steps; ++i) { | ||||||
|  |         command_step(proc); | ||||||
|  |     } | ||||||
|  |     struct mi_registers regs = get_process_registers(proc); | ||||||
|  |     int result = 1; | ||||||
|  |     if ((regs.rip - proc.base_address) == pc) { | ||||||
|  |         result = 0; | ||||||
|  |     } | ||||||
|  |     command_kill(proc); | ||||||
|  |     waitpid(proc.pid, 0, 0); | ||||||
|  |     return(result); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | test_next(char *path, int nexts, u64 pc) | ||||||
|  | { | ||||||
|  |     struct mi_process proc = process_create(path); | ||||||
|  |     waitpid(proc.pid, 0, 0); | ||||||
|  |     parse_debug_info(proc.elf, &proc.debug); | ||||||
|  |     parse_debug_line(proc.elf, &proc.debug); | ||||||
|  |     proc.main_address = get_address_of_subroutine(proc, "main"); | ||||||
|  |     command_start(proc); | ||||||
|  |     for (int i = 0; i < nexts; ++i) { | ||||||
|  |         command_next(proc); | ||||||
|  |     } | ||||||
|  |     struct mi_registers regs = get_process_registers(proc); | ||||||
|  |     int result = 1; | ||||||
|  |     if ((regs.rip - proc.base_address) == pc) { | ||||||
|  |         result = 0; | ||||||
|  |     } | ||||||
|  |     command_kill(proc); | ||||||
|  |     waitpid(proc.pid, 0, 0); | ||||||
|  |     return(result); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | test_list(char *path, int steps, int line, int column) | ||||||
|  | { | ||||||
|  |     struct mi_process proc = process_create(path); | ||||||
|  |     waitpid(proc.pid, 0, 0); | ||||||
|  |     parse_debug_info(proc.elf, &proc.debug); | ||||||
|  |     parse_debug_line(proc.elf, &proc.debug); | ||||||
|  |     proc.main_address = get_address_of_subroutine(proc, "main"); | ||||||
|  |     command_start(proc); | ||||||
|  |     for (int i = 0; i < steps; ++i) { | ||||||
|  |         command_step(proc); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     int comp_unit; | ||||||
|  |     struct mi_registers regs = get_process_registers(proc); | ||||||
|  |     struct mi_sourcepoint *sp = pc_to_sourcepoint(proc, regs.rip - proc.base_address, &comp_unit); | ||||||
|  |      | ||||||
|  |     int result = 1; | ||||||
|  |     if (sp->line == line && sp->column == column) { | ||||||
|  |         result = 0; | ||||||
|  |     } | ||||||
|  |     command_kill(proc); | ||||||
|  |     waitpid(proc.pid, 0, 0); | ||||||
|  |     return(result); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | test_print(char *path, int steps, char *name, char *type, int location) | ||||||
|  | { | ||||||
|  |     struct mi_process proc = process_create(path); | ||||||
|  |     waitpid(proc.pid, 0, 0); | ||||||
|  |     parse_debug_info(proc.elf, &proc.debug); | ||||||
|  |     parse_debug_line(proc.elf, &proc.debug); | ||||||
|  |     proc.main_address = get_address_of_subroutine(proc, "main"); | ||||||
|  |     command_start(proc); | ||||||
|  |     for (int i = 0; i < steps; ++i) { | ||||||
|  |         command_step(proc); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     struct mi_registers regs = get_process_registers(proc); | ||||||
|  |     u64 pc = regs.rip - proc.base_address; | ||||||
|  |     u64 cfa = get_cfa_at_pc(proc, pc); | ||||||
|  |      | ||||||
|  |     struct mi_variable *variable = get_variable(proc, name, strlen(name), pc); | ||||||
|  |     struct mi_type real_type = proc.debug.types[variable->type]; | ||||||
|  |      | ||||||
|  |     int result = 1; | ||||||
|  |     int type_length = strlen(type); | ||||||
|  |     if (0 == strncmp(type, real_type.name, type_length) && variable->location == location) { | ||||||
|  |         result = 0; | ||||||
|  |     } | ||||||
|  |     command_kill(proc); | ||||||
|  |     waitpid(proc.pid, 0, 0); | ||||||
|  |     return(result); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | main(void) | ||||||
|  | { | ||||||
|  |     DO_TEST("start 001-simple", test_start("res/001-simple")); | ||||||
|  |     DO_TEST("start 002-compilation-units", test_start("res/002-compilation-units")); | ||||||
|  |     DO_TEST("start 003-recursion", test_start("res/003-recursion")); | ||||||
|  |     DO_TEST("start 004-scoped-variables", test_start("res/004-scoped-variables")); | ||||||
|  |     DO_TEST("start 005-base-types", test_start("res/005-base-types")); | ||||||
|  |     DO_TEST("start 006-composite-types", test_start("res/006-composite-types")); | ||||||
|  |      | ||||||
|  |     DO_TEST("regs 001-simple", test_regs("res/001-simple")); | ||||||
|  |     DO_TEST("regs 002-compilation-units", test_regs("res/002-compilation-units")); | ||||||
|  |     DO_TEST("regs 003-recursion", test_regs("res/003-recursion")); | ||||||
|  |     DO_TEST("regs 004-scoped-variables", test_regs("res/004-scoped-variables")); | ||||||
|  |     DO_TEST("regs 005-base-types", test_regs("res/005-base-types")); | ||||||
|  |     DO_TEST("regs 006-composite-types", test_regs("res/006-composite-types")); | ||||||
|  |      | ||||||
|  |     DO_TEST("step 001-simple", test_step("res/001-simple", 4, 0x1166)); | ||||||
|  |     DO_TEST("step 002-compilation-units", test_step("res/002-compilation-units", 4, 0x114f)); | ||||||
|  |     DO_TEST("step 003-recursion", test_step("res/003-recursion", 9, 0x1130)); | ||||||
|  |     DO_TEST("step 004-scoped-variables", test_step("res/004-scoped-variables", 7, 0x1145)); | ||||||
|  |     DO_TEST("step 005-base-types", test_step("res/005-base-types", 3, 0x113e)); | ||||||
|  |     DO_TEST("step 006-composite-types", test_step("res/006-composite-types", 5, 0x114c)); | ||||||
|  |      | ||||||
|  |     DO_TEST("next 001-simple", test_next("res/001-simple", 4, 0x1166)); | ||||||
|  |     DO_TEST("next 002-compilation-units", test_next("res/002-compilation-units", 4, 0x1146)); | ||||||
|  |     DO_TEST("next 003-recursion", test_next("res/003-recursion", 2, 0x116b)); | ||||||
|  |     DO_TEST("next 004-scoped-variables", test_next("res/004-scoped-variables", 4, 0x11a3)); | ||||||
|  |     DO_TEST("next 005-base-types", test_next("res/005-base-types", 3, 0x113e)); | ||||||
|  |     DO_TEST("next 006-composite-types", test_next("res/006-composite-types", 5, 0x114c)); | ||||||
|  |      | ||||||
|  |     DO_TEST("list 001-simple", test_list("res/001-simple", 4, 12, 20)); | ||||||
|  |     DO_TEST("list 002-compilation-units", test_list("res/002-compilation-units", 4, 5, 6)); | ||||||
|  |     DO_TEST("list 003-recursion", test_list("res/003-recursion", 9, 4, 5)); | ||||||
|  |     DO_TEST("list 004-scoped-variables", test_list("res/004-scoped-variables", 7, 15, 6)); | ||||||
|  |     DO_TEST("list 005-base-types", test_list("res/005-base-types", 3, 6, 7)); | ||||||
|  |     DO_TEST("list 006-composite-types", test_list("res/006-composite-types", 5, 18, 14)); | ||||||
|  |      | ||||||
|  |     DO_TEST("print 001-simple", test_print("res/001-simple", 4, "i", "int", -28)); | ||||||
|  |     DO_TEST("print 002-compilation-units", test_print("res/002-compilation-units", 5, "sq", "int", -20)); | ||||||
|  |     DO_TEST("print 003-recursion", test_print("res/003-recursion", 28, "result", "int", -20)); | ||||||
|  |     DO_TEST("print 004-scoped-variables", test_print("res/004-scoped-variables", 9, "b_f2", "int", -24)); | ||||||
|  |     DO_TEST("print 005-base-types long", test_print("res/005-base-types", 5, "var_unsigned_long", "long unsigned int", -40)); | ||||||
|  |     DO_TEST("print 005-base-types char", test_print("res/005-base-types", 4, "var_char", "char", -41)); | ||||||
|  |     DO_TEST("print 005-base-types float", test_print("res/005-base-types", 8, "var_float", "float", -48)); | ||||||
|  |     DO_TEST("print 005-base-types double", test_print("res/005-base-types", 9, "var_double", "double", -56)); | ||||||
|  |      | ||||||
|  |     fprintf(stderr, "\033[1m\033[32mAll tests succeeded!\033[0m\n"); | ||||||
|  |      | ||||||
|  |     return(0); | ||||||
|  | } | ||||||
					Loading…
					
					
				
		Reference in new issue