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