diff options
Diffstat (limited to 'sim/ppc/spa-reporter.c')
-rw-r--r-- | sim/ppc/spa-reporter.c | 772 |
1 files changed, 0 insertions, 772 deletions
diff --git a/sim/ppc/spa-reporter.c b/sim/ppc/spa-reporter.c deleted file mode 100644 index d021b07..0000000 --- a/sim/ppc/spa-reporter.c +++ /dev/null @@ -1,772 +0,0 @@ -/* - * Copyright (C) 1991 Gordon Irlam. All rights reserved. - */ - -/* - * Sparc trace generator. - * - * Generate a Sparc address trace. - * - * Report system calls. - * - * We want to display the system call and the return value at the same time - * (so that other output does not appear between the two) but also want to - * identify system calls that block without having to wait for them to - * return. Whenever a system call is performed we store the name of the - * call and the parameters. If we don't see a return within a certain time - * period we display the call regardless, and assume it has blocked. - */ - - -/* - * Imported declarations. - */ - -#include "config.h" - -#ifdef HAVE_STRING_H -#include <string.h> -#else -#ifdef HAVE_STRINGS_H -#include <strings.h> -#endif -#endif - -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif - -#ifdef HAVE_UNISTD_H -#include <unistd.h> - -#include <fcntl.h> -#include <stdio.h> -#include <malloc.h> -#include <ctype.h> -#include <signal.h> -#include <sys/types.h> -#include <sys/ptrace.h> -#include <sys/syscall.h> -#include <machine/trap.h> - -/* - * sigcleanup is not defined in a system header file. - */ -#define SYS_sigcleanup 139 - -#include "prototype.h" -#include "error.h" -#include "spy.h" -#include "system_calls.h" - - -/* - * Forward declarations. - */ - -PROTOTYPE(void report_trap, - (int pid, void *addr, int trap, int g1, syscall_params *params)); -PROTOTYPE(void report_trap_result, (int pid, int error, int o0, int o1)); -PROTOTYPE(void display_trap_msg, (void)); -PROTOTYPE(void delayed_trap_msg, (void)); -PROTOTYPE(void discard_trap_msg, (void)); -PROTOTYPE(int copy_memory, (int pid, void *addr, int size, char *data)); -PROTOTYPE(char *snarf_string, (int pid, void *addr)); -PROTOTYPE(char *snarf_data, (int pid, void *addr, int size)); -PROTOTYPE(char *format_value, - (int pid, fmt_type format, unsigned long value, int opt)); -PROTOTYPE(int printable_data, (char *data, int size)); -PROTOTYPE(char *print_string, (char *data, int size)); - - -/* - * Global definitions. - */ - -static char *trap_msg = NULL; -static fmt_type result_format; -static int no_return; -static fmt_type post_fmt; -static unsigned long post_value; -static int post_size; - - -/* - * Report the occurence of the specified trap. - */ - -void report_trap(pid, addr, trap, g1, params_addr) - int pid; - void *addr; - int trap; - int g1; - syscall_params *params_addr; -{ - syscall_params params; - call_desc *call; - int i; - fmt_type arg_format; - char *arg_str; - - /* - * Display any previous trap message that is still pending (it might have - * been a trap that did not return a value, and so has not yet been - * displayed). - */ - - display_trap_msg(); - - /* - * Read the parameters, and construct a string describing the system call. - */ - - ensure(ptrace(PTRACE_READDATA, pid, - (char *) params_addr, sizeof(syscall_params), - (char *) params) != -1); - - no_return = 0; - - if (trap != T_SOFTWARE_TRAP) { - - /* - * Not a system call trap. - */ - - no_return = 1; - - ensure((trap_msg = malloc(17 + 20 + 1)) != NULL); - sprintf(trap_msg, "0x%08lx: trap %d", (unsigned long) addr, trap); - - result_format = fmt_unknown; - } if ((g1 < 0) || (g1 >= no_system_calls)) { - - /* - * An unknown system call. - */ - - ensure((trap_msg = malloc(21 + 20 + 1)) != NULL); - sprintf(trap_msg, "0x%08lx: _unknown_%d(", - (unsigned long) addr, g1); - - arg_str = format_value(pid, fmt_unknown, params[0], 0); - ensure((trap_msg = realloc(trap_msg, strlen(trap_msg) - + strlen(arg_str) + 1 + 1)) - != NULL); - sprintf(trap_msg + sizeof(trap_msg), "%s)", arg_str); - free(arg_str); - - result_format = fmt_unknown; - } else { - - /* - * A known system call. - */ - - call = &system_calls[g1]; - switch (g1) { - case SYS_open : - if (!(params[1] & O_CREAT)) { - call = &system_call_open_simple; - } - break; - case SYS_exit : - case SYS_execve : - case SYS_sigcleanup : - no_return = 1; - break; - default : - break; - } - - ensure((trap_msg = malloc(13 + strlen(call->name) + 1 + 1)) - != NULL); - sprintf(trap_msg, "0x%08lx: %s(", - (unsigned long) addr, call->name); - - /* - * Display each of the arguments. - */ - - for (i = 0; i < NO_PARAMS; i++) { - if ((arg_format = call->arg[i]) == fmt_none) { - break; - } - if (i > 0) { - strcat(trap_msg, ", "); - } - if (arg_format == fmt_data) { - assert(((i + 1) < NO_PARAMS) && - (call->arg[i + 1] == fmt_data_size)); - arg_str = format_value(pid, arg_format, - params[i], (int) params[i + 1]); - } else { - arg_str = format_value(pid, arg_format, params[i], 0); - } - ensure((trap_msg = realloc(trap_msg, strlen(trap_msg) + - strlen(arg_str) + 2 + 1)) - != NULL); - strcat(trap_msg, arg_str); - free(arg_str); - } - - strcat(trap_msg, ")"); - - result_format = call->result; - } - - /* - * Set alarm so that name of call will be displayed even if it blocks. - */ - - alarm((unsigned int) 1); -} - - -/* - * Report the value returned as a result of the most recent trap. - */ - -void report_trap_result(pid, error, o0, o1) - int pid; - int error; - int o0; - int o1; -{ - char *result, *eno, *emsg, *addr; - - /* - * Turn off alarm used to ensure we print the call promptly - we are about - * to print it now. - */ - - alarm((unsigned int) 0); - - /* - * See if previous call blocked. - */ - - if (trap_msg == NULL) { - ensure((trap_msg = strdup(" [previous call]")) != NULL); - } - - /* - * Work out error message (if any) to be printed following return value. - */ - - if (error) { - eno = format_value(pid, fmt_error, o0, 0); - ensure((emsg = malloc(9 + strlen(eno) + 1)) != NULL); - sprintf(emsg, " [error %s]", eno); - free(eno); - o0 = -1; - post_fmt = fmt_none; - } else { - ensure((emsg = strdup("")) != NULL); - } - - /* - * Print out all the details of the system call. - */ - - if (result_format == fmt_none) { - ensure(fprintf(msgfile, "%s: %s%s\n", trace_progname, trap_msg, emsg) - != EOF); - } else { - result = format_value(pid, result_format, o0, 0); - ensure(fprintf(msgfile, "%s: %s -> %s%s\n", - trace_progname, trap_msg, result, emsg) != EOF); - free(result); - } - - free(emsg); - - /* - * Display any string or buffer modified by the system call if required. - * And providing it can be displayed as a (non-null) string. - */ - - if (post_fmt != fmt_none) { - result = format_value(pid, post_fmt, post_value, post_size); - if ((result[0] == '"') && (strlen(result) > 2)) { - addr = format_value(pid, fmt_ptr, post_value, 0); - ensure(fprintf(msgfile, "%s: %s: %s\n", - trace_progname, addr, result) != EOF); - free(addr); - } - free(result); - post_fmt = fmt_none; - } - - free(trap_msg); - trap_msg = NULL; -} - - -/* - * Report any trap messages that haven't been reported yet. - */ - -void display_trap_msg() { - - /* - * Clear the alarm - we are about to print the message. - */ - - alarm((unsigned int) 0); - - if (trap_msg != NULL) { - ensure(fprintf(msgfile, "%s: %s\n", trace_progname, trap_msg) != EOF); - free(trap_msg); - trap_msg = NULL; - } -} - - -/* - * Report the completion of a trap message as being delayed. - * - * This routine is invoked when a SIGALRM is received. - */ - -void delayed_trap_msg() { - - assert(trap_msg != NULL); - - /* - * If the call was not expected to return a value, think nothing of it, - * otherwise assume the call has blocked. - */ - - ensure(fprintf(msgfile, "%s: %s%s\n", - trace_progname, trap_msg, (no_return ? "" : " [pending]")) - != EOF); - free(trap_msg); - trap_msg = NULL; -} - - -/* - * Discard any pending trap messages. - * - * This routine is used by the child of a fork to discard the fork system call - * record. - */ - -void discard_trap_msg() { - - trap_msg = NULL; -} - - -/* - * Attempt to copy size bytes from the target process to data. The number of - * bytes successfully copied is returned. - */ - -int copy_memory(pid, addr, size, data) - int pid; - void *addr; - int size; - char *data; -{ - int lo, hi, try; - - assert(size >= 0); - - /* - * Common cases first. - */ - - if (ptrace(PTRACE_READDATA, pid, (char *) addr, size, data) != -1) { - return size; - } else if (ptrace(PTRACE_READDATA, pid, (char *) addr, 1, data) == -1) { - return 0; - } - - /* - * Binary search. - */ - - lo = 1; - hi = size - 1; - - while (lo < hi) { - try = (lo + hi + 1) / 2; - if (ptrace(PTRACE_READDATA, pid, (char *) addr, try, data) != -1) { - lo = try; - } else { - hi = try - 1; - } - } - - ensure(ptrace(PTRACE_READDATA, pid, (char *) addr, lo, data) != -1); - - return lo; -} - - -/* - * Create a string representing the contents of the indicated null termintated - * region of memory. - */ - -char *snarf_string(pid, addr) - int pid; - void *addr; -{ - char data[STRING_SIZE_LIMIT + 1]; - int size, len; - char *result = NULL; - int too_long = 0; - - size = copy_memory(pid, addr, STRING_SIZE_LIMIT, data); - data[size] = '\0'; - len = strlen(data); - too_long = (len == STRING_SIZE_LIMIT); - if ((len < size) || too_long) { - if (printable_data(data, len)) { - result = print_string(data, len); - if (too_long) { - ensure((result = realloc(result, strlen(result) + 2 + 1)) - != NULL); - strcat(result, ".."); - } - } - } - - return result; -} - - -/* - * Create a string representing the contents of the indicated length delimited - * region of memory. - */ - -char *snarf_data(pid, addr, size) - int pid; - void *addr; - int size; -{ - char data[DATA_SIZE_LIMIT]; - char *result = NULL; - int too_long = 0; - - if (size > DATA_SIZE_LIMIT) { - size = DATA_SIZE_LIMIT; - too_long = 1; - } - if ((size >= 0) && (copy_memory(pid, addr, size, data) == size)) { - if (printable_data(data, size)) { - result = print_string(data, size); - if (too_long) { - ensure((result = realloc(result, strlen(result) + 2 + 1)) - != NULL); - strcat(result, ".."); - } - } - } - - return result; -} - - -/* - * Create a string representing the contents of the indicated null termintated - * array of pointers to null terminated regions of memory. - */ - -char *snarf_string_array(pid, addr) - int pid; - void *addr; -{ - char *data[ARRAY_SIZE_LIMIT + 1]; - int size, len, i; - char *result = NULL; - char *s; - int too_long = 0; - - size = copy_memory(pid, addr, ARRAY_SIZE_LIMIT * sizeof(char *), - (char *) data) / sizeof(char *); - data[size] = NULL; - for (len = 0; data[len] != NULL; len++) { - } - too_long = (len == ARRAY_SIZE_LIMIT); - if ((len < size) || too_long) { - ensure((result = strdup("{")) != NULL); - for (i = 0; i < len; i++) { - if (i > 0) { - strcat(result, ", "); - } - s = format_value(pid, fmt_string, (unsigned long) data[i], 0); - ensure((result = realloc(result, - strlen(result) + strlen(s) + 2 + 5 + 1)) - != NULL); - strcat(result, s); - } - if (too_long) { - strcat(result, ", .."); - } - strcat(result, "}"); - } - - return result; -} - - -/* - * Return a string containing a value printed in a specific format. Opt is a - * second optional parameter currently only used to contain the size to be used - * with fmt_data. - */ - -char *format_value(pid, format, value, opt) - int pid; - fmt_type format; - unsigned long value; - int opt; -{ - char *str; - int sig, error; - - /* - * See if we are meant to hang on to the value for later use. - */ - - switch (format) { - - case fmt_post_string : - post_fmt = fmt_string ; - post_value = value; - format = fmt_ptr; - break; - - case fmt_post_data : - post_fmt = fmt_data; - post_value = value; - format = fmt_ptr; - break; - - case fmt_data_size : - format = FMT_SIZE; - break; - - case fmt_post_data_size : - post_size = (int) value; - format = FMT_SIZE; - break; - - default : - break; - } - - /* - * Display the value. - */ - - switch (format) { - - case fmt_dec : - - ensure((str = malloc(20 + 1)) != NULL); - sprintf(str, "%d", (int) value); - break; - - case fmt_hex : - - ensure((str = malloc(2 + 20 + 1)) != NULL); - sprintf(str, "0x%lx", value); - break; - - case fmt_ptr : - - if (value == 0) { - ensure((str = strdup("NULL")) != NULL); - } else { - ensure((str = malloc(10 + 1)) != NULL); - sprintf(str, "0x%08lx", value); - } - break; - - case fmt_fd : - - ensure((str = malloc(2 + 20 + 1)) != NULL); - sprintf(str, "fd%d", (int) value); - break; - - case fmt_signal : - - sig = (int) value; - if ((sig < 0) || (sig >= no_signal_names)) { - ensure((str = malloc(20 + 1)) != NULL); - sprintf(str, "%d", sig); - } else { - ensure((str = strdup(signal_names[sig])) != NULL); - } - break; - - case fmt_error : - - error = (int) value; - if ((error < 0) || (error >= no_error_names)) { - ensure((str = malloc(20 + 1)) != NULL); - sprintf(str, "%d", error); - } else { - ensure((str = strdup(error_names[error])) != NULL); - } - break; - - case fmt_open_flags : - - ensure((str = malloc(8 + 3 + 20 + 1)) != NULL); - switch (value & 3) { - case O_RDONLY : - sprintf(str, "O_RDONLY"); - value -= O_RDONLY; - break; - case O_WRONLY : - sprintf(str, "O_WRONLY"); - value -= O_WRONLY; - break; - case O_RDWR : - sprintf(str, "O_RDWR"); - value -= O_RDWR; - break; - default : - sprintf(str, "0x%lx", value); - value = 0; - break; - } - if (value != 0) { - sprintf(str + strlen(str), "|0x%lx", value); - } - break; - - case fmt_unknown : - - ensure((str = strdup("..")) != NULL); - break; - - case fmt_string : - - if ((str = snarf_string(pid, (void *) value)) == NULL) { - str = format_value(pid, fmt_ptr, value, 0); - } - break; - - case fmt_data : - - if ((str = snarf_data(pid, (void *) value, opt)) == NULL) { - str = format_value(pid, fmt_ptr, value, 0); - } - break; - - case fmt_string_array : - - if ((str = snarf_string_array(pid, (void *) value)) == NULL) { - str = format_value(pid, fmt_ptr, value, 0); - } - break; - - default : - - diagnose("Unexpected display format"); - break; - } - - return str; -} - - -/* - * Determine whether size bytes of data are printable. - */ - -int printable_data(data, size) - char *data; - int size; -{ - int i; - - for (i = 0; i < size; i++) { - - if (!(isprint(data[i]))) { - - switch (data[i]) { - - case '\0' : - case '\t' : - case '\n' : - case '\f' : - case '\r' : - break; - - default : - return 0; - break; - } - } - } - - return 1; -} - - -/* - * Create a string representing size bytes of data. - */ - -char *print_string(data, size) - char *data; - int size; -{ - char *str, *s; - int i; - - assert(size >= 0); - - ensure((str = malloc(1 + size * 2 + 1 + 1)) != NULL); - s = str; - - *(s++) = '"'; - - for (i = 0; i < size; i++) { - - if ((!(isprint(data[i]))) || (data[i] == '"') || (data[i] == '\\')) { - - *(s++) = '\\'; - - switch (data[i]) { - case '\0' : - *(s++) = '0'; - break; - case '\t' : - *(s++) = 't'; - break; - case '\n' : - *(s++) = 'n'; - break; - case '\f' : - *(s++) = 'f'; - break; - case '\r' : - *(s++) = 'r'; - break; - case '"' : - case '\\' : - *(s++) = data[i]; - break; - default : - diagnose("Attempted to display illegal character"); - } - } else { - - *(s++) = data[i]; - } - } - - *(s++) = '"'; - *s = '\0'; - - return str; -} |