breakpoints.c revision cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3
1#include "config.h" 2 3#include <stdlib.h> 4#include <string.h> 5#include <assert.h> 6#include <errno.h> 7 8#ifdef __powerpc__ 9#include <sys/ptrace.h> 10#endif 11 12#include "breakpoint.h" 13#include "common.h" 14#include "proc.h" 15#include "library.h" 16 17#ifndef ARCH_HAVE_TRANSLATE_ADDRESS 18int 19arch_translate_address(struct Process *proc, 20 target_address_t addr, target_address_t *ret) 21{ 22 *ret = addr; 23 return 0; 24} 25#endif 26 27void 28breakpoint_on_hit(struct breakpoint *bp, struct Process *proc) 29{ 30 assert(bp != NULL); 31 if (bp->cbs != NULL && bp->cbs->on_hit != NULL) 32 (bp->cbs->on_hit)(bp, proc); 33} 34 35void 36breakpoint_on_continue(struct breakpoint *bp, struct Process *proc) 37{ 38 assert(bp != NULL); 39 if (bp->cbs != NULL && bp->cbs->on_continue != NULL) 40 (bp->cbs->on_continue)(bp, proc); 41 else 42 continue_after_breakpoint(proc, bp); 43} 44 45void 46breakpoint_on_retract(struct breakpoint *bp, struct Process *proc) 47{ 48 assert(bp != NULL); 49 if (bp->cbs != NULL && bp->cbs->on_retract != NULL) 50 (bp->cbs->on_retract)(bp, proc); 51} 52 53/*****************************************************************************/ 54 55struct breakpoint * 56address2bpstruct(Process *proc, void *addr) 57{ 58 assert(proc != NULL); 59 assert(proc->breakpoints != NULL); 60 assert(proc->leader == proc); 61 debug(DEBUG_FUNCTION, "address2bpstruct(pid=%d, addr=%p)", proc->pid, addr); 62 return dict_find_entry(proc->breakpoints, addr); 63} 64 65#ifndef ARCH_HAVE_BREAKPOINT_DATA 66int 67arch_breakpoint_init(struct Process *proc, struct breakpoint *sbp) 68{ 69 return 0; 70} 71 72void 73arch_breakpoint_destroy(struct breakpoint *sbp) 74{ 75} 76 77int 78arch_breakpoint_clone(struct breakpoint *retp, struct breakpoint *sbp) 79{ 80 return 0; 81} 82#endif 83 84static void 85breakpoint_init_base(struct breakpoint *bp, struct Process *proc, 86 target_address_t addr, struct library_symbol *libsym) 87{ 88 bp->cbs = NULL; 89 bp->addr = addr; 90 memset(bp->orig_value, 0, sizeof(bp->orig_value)); 91 bp->enabled = 0; 92 bp->libsym = libsym; 93} 94 95/* On second thought, I don't think we need PROC. All the translation 96 * (arch_translate_address in particular) should be doable using 97 * static lookups of various sections in the ELF file. We shouldn't 98 * need process for anything. */ 99int 100breakpoint_init(struct breakpoint *bp, struct Process *proc, 101 target_address_t addr, struct library_symbol *libsym) 102{ 103 breakpoint_init_base(bp, proc, addr, libsym); 104 return arch_breakpoint_init(proc, bp); 105} 106 107void 108breakpoint_set_callbacks(struct breakpoint *bp, struct bp_callbacks *cbs) 109{ 110 if (bp->cbs != NULL) 111 assert(bp->cbs == NULL); 112 bp->cbs = cbs; 113} 114 115void 116breakpoint_destroy(struct breakpoint *bp) 117{ 118 if (bp == NULL) 119 return; 120 arch_breakpoint_destroy(bp); 121} 122 123struct find_symbol_data { 124 struct library_symbol *old_libsym; 125 struct library_symbol *found_libsym; 126}; 127 128static enum callback_status 129find_sym_in_lib(struct Process *proc, struct library *lib, void *u) 130{ 131 struct find_symbol_data *fs = u; 132 fs->found_libsym 133 = library_each_symbol(lib, NULL, library_symbol_equal_cb, 134 fs->old_libsym); 135 return fs->found_libsym != NULL ? CBS_STOP : CBS_CONT; 136} 137 138int 139breakpoint_clone(struct breakpoint *retp, struct Process *new_proc, 140 struct breakpoint *bp, struct Process *old_proc) 141{ 142 /* Find library and symbol that this breakpoint was linked to. */ 143 struct library_symbol *libsym = bp->libsym; 144 struct library *lib = NULL; 145 if (libsym != NULL) { 146 struct find_symbol_data f_data = { 147 .old_libsym = libsym, 148 }; 149 lib = proc_each_library(old_proc, NULL, 150 find_sym_in_lib, &f_data); 151 assert(lib != NULL); 152 libsym = f_data.found_libsym; 153 } 154 155 /* LIB and LIBSYM now hold the new library and symbol that 156 * correspond to the original breakpoint. Now we can do the 157 * clone itself. */ 158 breakpoint_init_base(retp, new_proc, bp->addr, libsym); 159 memcpy(retp->orig_value, bp->orig_value, sizeof(bp->orig_value)); 160 retp->enabled = bp->enabled; 161 if (arch_breakpoint_clone(retp, bp) < 0) 162 return -1; 163 breakpoint_set_callbacks(retp, bp->cbs); 164 return 0; 165} 166 167int 168breakpoint_turn_on(struct breakpoint *bp, struct Process *proc) 169{ 170 bp->enabled++; 171 if (bp->enabled == 1) { 172 assert(proc->pid != 0); 173 enable_breakpoint(proc, bp); 174 } 175 return 0; 176} 177 178int 179breakpoint_turn_off(struct breakpoint *bp, struct Process *proc) 180{ 181 bp->enabled--; 182 if (bp->enabled == 0) 183 disable_breakpoint(proc, bp); 184 assert(bp->enabled >= 0); 185 return 0; 186} 187 188struct breakpoint * 189insert_breakpoint(struct Process *proc, void *addr, 190 struct library_symbol *libsym) 191{ 192 Process *leader = proc->leader; 193 194 /* Only the group leader should be getting the breakpoints and 195 * thus have ->breakpoint initialized. */ 196 assert(leader != NULL); 197 assert(leader->breakpoints != NULL); 198 199 debug(DEBUG_FUNCTION, "insert_breakpoint(pid=%d, addr=%p, symbol=%s)", 200 proc->pid, addr, libsym ? libsym->name : "NULL"); 201 202 assert(addr != 0); 203 204 /* XXX what we need to do instead is have a list of 205 * breakpoints that are enabled at this address. The 206 * following works if every breakpoint is the same and there's 207 * no extra data, but that doesn't hold anymore. For now it 208 * will suffice, about the only realistic case where we need 209 * to have more than one breakpoint per address is return from 210 * a recursive library call. */ 211 struct breakpoint *sbp = dict_find_entry(leader->breakpoints, addr); 212 if (sbp == NULL) { 213 sbp = malloc(sizeof(*sbp)); 214 if (sbp == NULL 215 || breakpoint_init(sbp, proc, addr, libsym) < 0) { 216 free(sbp); 217 return NULL; 218 } 219 if (proc_add_breakpoint(leader, sbp) < 0) { 220 fail: 221 breakpoint_destroy(sbp); 222 free(sbp); 223 return NULL; 224 } 225 } 226 227 if (breakpoint_turn_on(sbp, proc) < 0) { 228 proc_remove_breakpoint(leader, sbp); 229 goto fail; 230 } 231 232 return sbp; 233} 234 235void 236delete_breakpoint(Process *proc, void *addr) 237{ 238 debug(DEBUG_FUNCTION, "delete_breakpoint(pid=%d, addr=%p)", proc->pid, addr); 239 240 Process * leader = proc->leader; 241 assert(leader != NULL); 242 243 struct breakpoint *sbp = dict_find_entry(leader->breakpoints, addr); 244 assert(sbp != NULL); 245 /* This should only happen on out-of-memory conditions. */ 246 if (sbp == NULL) 247 return; 248 249 if (breakpoint_turn_off(sbp, proc) < 0) { 250 fprintf(stderr, "Couldn't turn off the breakpoint %s@%p\n", 251 breakpoint_name(sbp), sbp->addr); 252 return; 253 } 254 if (sbp->enabled == 0) { 255 proc_remove_breakpoint(leader, sbp); 256 breakpoint_destroy(sbp); 257 free(sbp); 258 } 259} 260 261const char * 262breakpoint_name(const struct breakpoint *bp) 263{ 264 assert(bp != NULL); 265 return bp->libsym != NULL ? bp->libsym->name : NULL; 266} 267 268struct library * 269breakpoint_library(const struct breakpoint *bp) 270{ 271 assert(bp != NULL); 272 return bp->libsym != NULL ? bp->libsym->lib : NULL; 273} 274 275static void 276enable_bp_cb(void *addr, void *sbp, void *proc) 277{ 278 debug(DEBUG_FUNCTION, "enable_bp_cb(pid=%d)", ((Process *)proc)->pid); 279 if (((struct breakpoint *)sbp)->enabled) 280 enable_breakpoint(proc, sbp); 281} 282 283void 284enable_all_breakpoints(Process *proc) 285{ 286 debug(DEBUG_FUNCTION, "enable_all_breakpoints(pid=%d)", proc->pid); 287 288 debug(1, "Enabling breakpoints for pid %u...", proc->pid); 289 if (proc->breakpoints) { 290 dict_apply_to_all(proc->breakpoints, enable_bp_cb, 291 proc); 292 } 293#ifdef __mips__ 294 { 295 /* 296 * I'm sure there is a nicer way to do this. We need to 297 * insert breakpoints _after_ the child has been started. 298 */ 299 struct library_symbol *sym; 300 struct library_symbol *new_sym; 301 sym=proc->list_of_symbols; 302 while(sym){ 303 void *addr= sym2addr(proc,sym); 304 if(!addr){ 305 sym=sym->next; 306 continue; 307 } 308 if(dict_find_entry(proc->breakpoints,addr)){ 309 sym=sym->next; 310 continue; 311 } 312 debug(2,"inserting bp %p %s",addr,sym->name); 313 new_sym=malloc(sizeof(*new_sym) + strlen(sym->name) + 1); 314 memcpy(new_sym,sym,sizeof(*new_sym) + strlen(sym->name) + 1); 315 new_sym->next=proc->list_of_symbols; 316 proc->list_of_symbols=new_sym; 317 insert_breakpoint(proc, addr, new_sym); 318 sym=sym->next; 319 } 320 } 321#endif 322} 323 324static void 325disable_bp_cb(void *addr, void *sbp, void *proc) 326{ 327 debug(DEBUG_FUNCTION, "disable_bp_cb(pid=%d)", ((Process *)proc)->pid); 328 if (((struct breakpoint *)sbp)->enabled) 329 disable_breakpoint(proc, sbp); 330} 331 332void 333disable_all_breakpoints(Process *proc) { 334 debug(DEBUG_FUNCTION, "disable_all_breakpoints(pid=%d)", proc->pid); 335 assert(proc->leader == proc); 336 dict_apply_to_all(proc->breakpoints, disable_bp_cb, proc); 337} 338 339/* XXX This is not currently properly supported. On clone, this is 340 * just sliced. Hopefully at the point that clone is done, this 341 * breakpoint is not necessary anymore. If this use case ends up 342 * being important, we need to add a clone and destroy callbacks to 343 * breakpoints, and we should also probably drop arch_breakpoint_data 344 * so that we don't end up with two different customization mechanisms 345 * for one structure. */ 346struct entry_breakpoint { 347 struct breakpoint super; 348 target_address_t dyn_addr; 349}; 350 351static void 352entry_breakpoint_on_hit(struct breakpoint *a, struct Process *proc) 353{ 354 struct entry_breakpoint *bp = (void *)a; 355 if (proc == NULL || proc->leader == NULL) 356 return; 357 target_address_t dyn_addr = bp->dyn_addr; 358 delete_breakpoint(proc, bp->super.addr); 359 linkmap_init(proc, dyn_addr); 360 arch_dynlink_done(proc); 361} 362 363int 364entry_breakpoint_init(struct Process *proc, 365 struct entry_breakpoint *bp, target_address_t addr, 366 struct library *lib) 367{ 368 int err; 369 if ((err = breakpoint_init(&bp->super, proc, addr, NULL)) < 0) 370 return err; 371 372 static struct bp_callbacks entry_callbacks = { 373 .on_hit = entry_breakpoint_on_hit, 374 }; 375 bp->super.cbs = &entry_callbacks; 376 bp->dyn_addr = lib->dyn_addr; 377 return 0; 378} 379 380int 381breakpoints_init(Process *proc) 382{ 383 debug(DEBUG_FUNCTION, "breakpoints_init(pid=%d)", proc->pid); 384 385 /* XXX breakpoint dictionary should be initialized 386 * outside. Here we just put in breakpoints. */ 387 assert(proc->breakpoints != NULL); 388 389 /* Only the thread group leader should hold the breakpoints. */ 390 assert(proc->leader == proc); 391 392 /* N.B. the following used to be conditional on this, and 393 * maybe it still needs to be. */ 394 assert(proc->filename != NULL); 395 396 struct library *lib = ltelf_read_main_binary(proc, proc->filename); 397 struct entry_breakpoint *entry_bp = NULL; 398 int bp_state = 0; 399 int result = -1; 400 switch (lib != NULL) { 401 fail: 402 switch (bp_state) { 403 case 2: 404 proc_remove_library(proc, lib); 405 proc_remove_breakpoint(proc, &entry_bp->super); 406 case 1: 407 breakpoint_destroy(&entry_bp->super); 408 } 409 library_destroy(lib); 410 free(entry_bp); 411 case 0: 412 return result; 413 } 414 415 entry_bp = malloc(sizeof(*entry_bp)); 416 if (entry_bp == NULL 417 || (result = entry_breakpoint_init(proc, entry_bp, 418 lib->entry, lib)) < 0) 419 goto fail; 420 ++bp_state; 421 422 if ((result = proc_add_breakpoint(proc, &entry_bp->super)) < 0) 423 goto fail; 424 ++bp_state; 425 426 if ((result = breakpoint_turn_on(&entry_bp->super, proc)) < 0) 427 goto fail; 428 proc_add_library(proc, lib); 429 430 proc->callstack_depth = 0; 431 return 0; 432} 433