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