This is databreak.m in view mode; [Download] [Up]
#import <gdb.h> #import "../breakpoint.h" extern RegionManager *regionManager; #import <string.h> const static char breakpoint_insn[] = BREAKPOINT; typedef struct _Safety { const char *name; CORE_ADDR address; char shadow[sizeof(breakpoint_insn)]; } Safety; static Safety safeties[] = { {"accept"}, {"adjtime"}, {"bind"}, {"connect"}, {"fcntl"}, {"fstat"}, {"fstatfs"}, {"setjmp"}, {"getdents"}, {"getdirentries"}, {"getdomainname"}, {"getfh"}, {"getgroups"}, {"gethostname"}, {"getitimer"}, {"getpeername"}, {"getrlimit"}, {"getrusage"}, {"getsockname"}, {"getsockopt"}, {"ioctl"}, {"lstat"}, {"mmap"}, {"pipe"}, {"read"}, {"readlink"}, {"readv"}, {"recv"}, {"recvfrom"}, {"recvmsg"}, {"select"}, {"setitimer"}, {"setquota"}, {"sigstack"}, {"socketpair"}, {"stat"}, {"statfs"}, {"syscall"}, {"table"}, {"ustat"}, {"wait"}, {"wait3"}, {"wait4"}, {"msg_receive"}, {"msg_rpc"} }; BOOL safetiesInserted = NO; static BOOL safetiesInitialized = NO; static const int numSafeties = sizeof(safeties) / sizeof(*safeties); static void initializeSafeties() { if (!safetiesInitialized) { int i; Safety *safety; for (i = 0, safety = safeties; i < numSafeties; i++, safety++) { struct minimal_symbol *minSym = lookup_minimal_symbol(safety->name, NULL, NULL); if (minSym) { safety->address = SYMBOL_VALUE_ADDRESS(minSym); read_memory(safety->address, safety->shadow, sizeof(safety->shadow)); } } safetiesInitialized = YES; } } BOOL isSafetyBreakpoint(CORE_ADDR address) { if (safetiesInserted) { int i; Safety *safety; for (i = 0, safety = safeties; i < numSafeties; i++, safety++) if (address == safety->address) return YES; } return NO; } void insertSafetyBreakpoints() { if (!safetiesInserted) { int i; Safety *safety; for (i = 0, safety = safeties; i < numSafeties; i++, safety++) { [regionManager putDataAt: (void *)safety->address for: sizeof(breakpoint_insn) from: (void *)breakpoint_insn markOnly: YES]; } safetiesInserted = YES; } } void removeSafetyBreakpoints() { if (safetiesInserted) { int i; Safety *safety; for (i = 0, safety = safeties; i < numSafeties; i++, safety++) { [regionManager putDataAt: (void *)safety->address for: sizeof(breakpoint_insn) from: (void *)safety->shadow markOnly: YES]; } safetiesInserted = NO; } } void insertDataBreakpoint(struct breakpoint *b) { kern_return_t r; r = vm_protect(inferior_task, b->start_page, b->end_page - b->start_page, NO, VM_PROT_READ); if (r != KERN_SUCCESS) { mach_error("error inserting data breakpoint",r); } else { b->inserted = YES; } } void removeDataBreakpoint(struct breakpoint *b) { vm_protect(inferior_task, b->start_page, b->end_page - b->start_page, NO, VM_PROT_READ | VM_PROT_WRITE); b->inserted = NO; // removeSafetyBreakpoints(); } static void dbCommand(char *args, int from_tty) { char *address, *bytes; void *newAddress; int newLength; value_ptr val; CORE_ADDR startPage; int sizePage; vm_address_t offset; vm_address_t s; initializeSafeties(); if (address = args) { if (bytes = index(address, ' ')) { *bytes = '\0'; bytes++; newAddress = (void *)parse_and_eval_address(address); newLength = value_as_long(parse_and_eval(bytes)); } else { val = parse_and_eval(address); if (val->lval != lval_memory) error("Can't insert databreakpoint. %s is %s.", address, val->lval == lval_register ? "in a register" : "not a memory location"); newAddress = (void *)(VALUE_ADDRESS(val) + VALUE_OFFSET(val)); if (newAddress) newLength = TYPE_LENGTH(VALUE_TYPE(val)); else { newAddress = (void *)value_as_long(val); newLength = 1; } } offset = ((vm_address_t)newAddress % vm_page_size); s = newLength + offset; startPage = (vm_address_t)newAddress - offset; sizePage = (s - (s % vm_page_size)) + vm_page_size; set_data_breakpoint(newAddress, newLength, startPage, sizePage); } } void _initialize_db() { add_com("data-break", class_breakpoint, dbCommand, "break if data specified changes\n"); add_com_alias("db", "data-break", class_breakpoint, 1); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.