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