breakpoints.c revision 5ee368270823922ee2a11f0637a355641f6af457
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 debug(DEBUG_FUNCTION, "delete_breakpoint(pid=%d, addr=%p)", proc->pid, addr); 232 233 Process * leader = proc->leader; 234 assert(leader != NULL); 235 236 struct breakpoint *sbp = dict_find_entry(leader->breakpoints, addr); 237 assert(sbp != NULL); 238 /* This should only happen on out-of-memory conditions. */ 239 if (sbp == NULL) 240 return; 241 242 if (breakpoint_turn_off(sbp, proc) < 0) { 243 fprintf(stderr, "Couldn't turn off the breakpoint %s@%p\n", 244 breakpoint_name(sbp), sbp->addr); 245 return; 246 } 247 if (sbp->enabled == 0) { 248 proc_remove_breakpoint(leader, sbp); 249 breakpoint_destroy(sbp); 250 free(sbp); 251 } 252} 253 254const char * 255breakpoint_name(const struct breakpoint *bp) 256{ 257 assert(bp != NULL); 258 return bp->libsym != NULL ? bp->libsym->name : NULL; 259} 260 261struct library * 262breakpoint_library(const struct breakpoint *bp) 263{ 264 assert(bp != NULL); 265 return bp->libsym != NULL ? bp->libsym->lib : NULL; 266} 267 268static void 269enable_bp_cb(void *addr, void *sbp, void *proc) 270{ 271 debug(DEBUG_FUNCTION, "enable_bp_cb(pid=%d)", ((Process *)proc)->pid); 272 if (((struct breakpoint *)sbp)->enabled) 273 enable_breakpoint(proc, sbp); 274} 275 276void 277enable_all_breakpoints(Process *proc) 278{ 279 debug(DEBUG_FUNCTION, "enable_all_breakpoints(pid=%d)", proc->pid); 280 281 debug(1, "Enabling breakpoints for pid %u...", proc->pid); 282 if (proc->breakpoints) { 283 dict_apply_to_all(proc->breakpoints, enable_bp_cb, 284 proc); 285 } 286#ifdef __mips__ 287 { 288 /* 289 * I'm sure there is a nicer way to do this. We need to 290 * insert breakpoints _after_ the child has been started. 291 */ 292 struct library_symbol *sym; 293 struct library_symbol *new_sym; 294 sym=proc->list_of_symbols; 295 while(sym){ 296 void *addr= sym2addr(proc,sym); 297 if(!addr){ 298 sym=sym->next; 299 continue; 300 } 301 if(dict_find_entry(proc->breakpoints,addr)){ 302 sym=sym->next; 303 continue; 304 } 305 debug(2,"inserting bp %p %s",addr,sym->name); 306 new_sym=malloc(sizeof(*new_sym) + strlen(sym->name) + 1); 307 memcpy(new_sym,sym,sizeof(*new_sym) + strlen(sym->name) + 1); 308 new_sym->next=proc->list_of_symbols; 309 proc->list_of_symbols=new_sym; 310 insert_breakpoint(proc, addr, new_sym); 311 sym=sym->next; 312 } 313 } 314#endif 315} 316 317static void 318disable_bp_cb(void *addr, void *sbp, void *proc) 319{ 320 debug(DEBUG_FUNCTION, "disable_bp_cb(pid=%d)", ((Process *)proc)->pid); 321 if (((struct breakpoint *)sbp)->enabled) 322 disable_breakpoint(proc, sbp); 323} 324 325void 326disable_all_breakpoints(Process *proc) { 327 debug(DEBUG_FUNCTION, "disable_all_breakpoints(pid=%d)", proc->pid); 328 assert(proc->leader == proc); 329 dict_apply_to_all(proc->breakpoints, disable_bp_cb, proc); 330} 331 332/* XXX This is not currently properly supported. On clone, this is 333 * just sliced. Hopefully at the point that clone is done, this 334 * breakpoint is not necessary anymore. If this use case ends up 335 * being important, we need to add a clone and destroy callbacks to 336 * breakpoints, and we should also probably drop arch_breakpoint_data 337 * so that we don't end up with two different customization mechanisms 338 * for one structure. */ 339struct entry_breakpoint { 340 struct breakpoint super; 341 target_address_t dyn_addr; 342}; 343 344static void 345entry_breakpoint_on_hit(struct breakpoint *a, struct Process *proc) 346{ 347 fprintf(stderr, "entry_breakpoint_on_hit\n"); 348 struct entry_breakpoint *bp = (void *)a; 349 if (proc == NULL || proc->leader == NULL) 350 return; 351 target_address_t dyn_addr = bp->dyn_addr; 352 delete_breakpoint(proc, bp->super.addr); 353 linkmap_init(proc, dyn_addr); 354 arch_dynlink_done(proc); 355} 356 357int 358entry_breakpoint_init(struct Process *proc, 359 struct entry_breakpoint *bp, target_address_t addr, 360 struct library *lib) 361{ 362 int err; 363 if ((err = breakpoint_init(&bp->super, proc, addr, NULL)) < 0) 364 return err; 365 366 static struct bp_callbacks entry_callbacks = { 367 .on_hit = entry_breakpoint_on_hit, 368 }; 369 bp->super.cbs = &entry_callbacks; 370 bp->dyn_addr = lib->dyn_addr; 371 return 0; 372} 373 374int 375breakpoints_init(Process *proc) 376{ 377 debug(DEBUG_FUNCTION, "breakpoints_init(pid=%d)", proc->pid); 378 379 /* XXX breakpoint dictionary should be initialized 380 * outside. Here we just put in breakpoints. */ 381 assert(proc->breakpoints != NULL); 382 383 /* Only the thread group leader should hold the breakpoints. */ 384 assert(proc->leader == proc); 385 386 /* N.B. the following used to be conditional on this, and 387 * maybe it still needs to be. */ 388 assert(proc->filename != NULL); 389 390 struct library *lib = ltelf_read_main_binary(proc, proc->filename); 391 struct entry_breakpoint *entry_bp = NULL; 392 int bp_state = 0; 393 int result = -1; 394 switch (lib != NULL) { 395 fail: 396 switch (bp_state) { 397 case 2: 398 proc_remove_library(proc, lib); 399 proc_remove_breakpoint(proc, &entry_bp->super); 400 case 1: 401 breakpoint_destroy(&entry_bp->super); 402 } 403 library_destroy(lib); 404 free(entry_bp); 405 case 0: 406 return result; 407 } 408 409 entry_bp = malloc(sizeof(*entry_bp)); 410 if (entry_bp == NULL 411 || (result = entry_breakpoint_init(proc, entry_bp, 412 lib->entry, lib)) < 0) 413 goto fail; 414 ++bp_state; 415 416 if ((result = proc_add_breakpoint(proc, &entry_bp->super)) < 0) 417 goto fail; 418 ++bp_state; 419 420 if ((result = breakpoint_turn_on(&entry_bp->super, proc)) < 0) 421 goto fail; 422 proc_add_library(proc, lib); 423 424 proc->callstack_depth = 0; 425 return 0; 426} 427