breakpoints.c revision b94407705ecddffd7820ee61bcad3f0d72ee87c1
1/* 2 * This file is part of ltrace. 3 * Copyright (C) 2006,2007,2011,2012,2013 Petr Machata, Red Hat Inc. 4 * Copyright (C) 2009 Juan Cespedes 5 * Copyright (C) 1998,2001,2002,2003,2007,2008,2009 Juan Cespedes 6 * Copyright (C) 2006 Ian Wienand 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of the 11 * License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, but 14 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 21 * 02110-1301 USA 22 */ 23 24#include "config.h" 25 26#include <assert.h> 27#include <errno.h> 28#include <stdio.h> 29#include <stdlib.h> 30#include <string.h> 31 32#ifdef __powerpc__ 33#include <sys/ptrace.h> 34#endif 35 36#include "backend.h" 37#include "breakpoint.h" 38#include "debug.h" 39#include "library.h" 40#include "ltrace-elf.h" 41#include "proc.h" 42 43#ifndef ARCH_HAVE_TRANSLATE_ADDRESS 44int 45arch_translate_address_dyn(struct process *proc, 46 arch_addr_t addr, arch_addr_t *ret) 47{ 48 *ret = addr; 49 return 0; 50} 51 52struct ltelf; 53int 54arch_translate_address(struct ltelf *lte, 55 arch_addr_t addr, arch_addr_t *ret) 56{ 57 *ret = addr; 58 return 0; 59} 60#endif 61 62void 63breakpoint_on_hit(struct breakpoint *bp, struct process *proc) 64{ 65 assert(bp != NULL); 66 if (bp->cbs != NULL && bp->cbs->on_hit != NULL) 67 (bp->cbs->on_hit)(bp, proc); 68} 69 70void 71breakpoint_on_continue(struct breakpoint *bp, struct process *proc) 72{ 73 assert(bp != NULL); 74 if (bp->cbs != NULL && bp->cbs->on_continue != NULL) 75 (bp->cbs->on_continue)(bp, proc); 76 else 77 continue_after_breakpoint(proc, bp); 78} 79 80void 81breakpoint_on_retract(struct breakpoint *bp, struct process *proc) 82{ 83 assert(bp != NULL); 84 if (bp->cbs != NULL && bp->cbs->on_retract != NULL) 85 (bp->cbs->on_retract)(bp, proc); 86} 87 88int 89breakpoint_get_return_bp(struct breakpoint **ret, 90 struct breakpoint *bp, struct process *proc) 91{ 92 assert(bp != NULL); 93 if (bp->cbs != NULL && bp->cbs->get_return_bp != NULL) 94 return (bp->cbs->get_return_bp)(ret, bp, proc); 95 96 if ((*ret = create_default_return_bp(proc)) == NULL) 97 return -1; 98 99 return 0; 100} 101 102/*****************************************************************************/ 103 104struct breakpoint * 105address2bpstruct(struct process *proc, arch_addr_t addr) 106{ 107 assert(proc != NULL); 108 assert(proc->breakpoints != NULL); 109 assert(proc->leader == proc); 110 debug(DEBUG_FUNCTION, "address2bpstruct(pid=%d, addr=%p)", proc->pid, addr); 111 112 struct breakpoint *found; 113 if (DICT_FIND_VAL(proc->breakpoints, &addr, &found) < 0) 114 return NULL; 115 return found; 116} 117 118#ifndef OS_HAVE_BREAKPOINT_DATA 119int 120os_breakpoint_init(struct process *proc, struct breakpoint *sbp) 121{ 122 return 0; 123} 124 125void 126os_breakpoint_destroy(struct breakpoint *sbp) 127{ 128} 129 130int 131os_breakpoint_clone(struct breakpoint *retp, struct breakpoint *sbp) 132{ 133 return 0; 134} 135#endif 136 137#ifndef ARCH_HAVE_BREAKPOINT_DATA 138int 139arch_breakpoint_init(struct process *proc, struct breakpoint *sbp) 140{ 141 return 0; 142} 143 144void 145arch_breakpoint_destroy(struct breakpoint *sbp) 146{ 147} 148 149int 150arch_breakpoint_clone(struct breakpoint *retp, struct breakpoint *sbp) 151{ 152 return 0; 153} 154#endif 155 156static void 157breakpoint_init_base(struct breakpoint *bp, 158 arch_addr_t addr, struct library_symbol *libsym) 159{ 160 bp->cbs = NULL; 161 bp->addr = addr; 162 memset(bp->orig_value, 0, sizeof(bp->orig_value)); 163 bp->enabled = 0; 164 bp->libsym = libsym; 165} 166 167/* On second thought, I don't think we need PROC. All the translation 168 * (arch_translate_address in particular) should be doable using 169 * static lookups of various sections in the ELF file. We shouldn't 170 * need process for anything. */ 171int 172breakpoint_init(struct breakpoint *bp, struct process *proc, 173 arch_addr_t addr, struct library_symbol *libsym) 174{ 175 breakpoint_init_base(bp, addr, libsym); 176 if (os_breakpoint_init(proc, bp) < 0) 177 return -1; 178 if (arch_breakpoint_init(proc, bp) < 0) { 179 os_breakpoint_destroy(bp); 180 return -1; 181 } 182 return 0; 183} 184 185void 186breakpoint_set_callbacks(struct breakpoint *bp, struct bp_callbacks *cbs) 187{ 188 if (bp->cbs != NULL) 189 assert(bp->cbs == NULL); 190 bp->cbs = cbs; 191} 192 193void 194breakpoint_destroy(struct breakpoint *bp) 195{ 196 if (bp == NULL) 197 return; 198 arch_breakpoint_destroy(bp); 199 os_breakpoint_destroy(bp); 200} 201 202int 203breakpoint_clone(struct breakpoint *retp, struct process *new_proc, 204 struct breakpoint *bp) 205{ 206 struct library_symbol *libsym = NULL; 207 if (bp->libsym != NULL) { 208 int rc = proc_find_symbol(new_proc, bp->libsym, NULL, &libsym); 209 assert(rc == 0); 210 } 211 212 breakpoint_init_base(retp, bp->addr, libsym); 213 memcpy(retp->orig_value, bp->orig_value, sizeof(bp->orig_value)); 214 retp->enabled = bp->enabled; 215 if (os_breakpoint_clone(retp, bp) < 0) 216 return -1; 217 if (arch_breakpoint_clone(retp, bp) < 0) { 218 os_breakpoint_destroy(retp); 219 return -1; 220 } 221 breakpoint_set_callbacks(retp, bp->cbs); 222 return 0; 223} 224 225int 226breakpoint_turn_on(struct breakpoint *bp, struct process *proc) 227{ 228 bp->enabled++; 229 if (bp->enabled == 1) { 230 assert(proc->pid != 0); 231 enable_breakpoint(proc, bp); 232 } 233 return 0; 234} 235 236int 237breakpoint_turn_off(struct breakpoint *bp, struct process *proc) 238{ 239 bp->enabled--; 240 if (bp->enabled == 0) 241 disable_breakpoint(proc, bp); 242 assert(bp->enabled >= 0); 243 return 0; 244} 245 246struct breakpoint * 247create_default_return_bp(struct process *proc) 248{ 249 struct breakpoint *bp = malloc(sizeof *bp); 250 arch_addr_t return_addr = get_return_addr(proc, proc->stack_pointer); 251 if (return_addr == 0 || bp == NULL 252 || breakpoint_init(bp, proc, return_addr, NULL) < 0) { 253 free(bp); 254 return NULL; 255 } 256 return bp; 257} 258 259struct breakpoint * 260insert_breakpoint_at(struct process *proc, arch_addr_t addr, 261 struct library_symbol *libsym) 262{ 263 debug(DEBUG_FUNCTION, 264 "insert_breakpoint_at(pid=%d, addr=%p, symbol=%s)", 265 proc->pid, addr, libsym ? libsym->name : "NULL"); 266 267 assert(addr != 0); 268 269 struct breakpoint *bp = malloc(sizeof *bp); 270 if (bp == NULL || breakpoint_init(bp, proc, addr, libsym) < 0) { 271 free(bp); 272 return NULL; 273 } 274 275 /* N.B. (and XXX): BP->addr might differ from ADDR. On ARM 276 * this is a real possibility. The problem here is that to 277 * create a return breakpoint ltrace calls get_return_addr and 278 * then insert_breakpoint_at. So get_return_addr needs to 279 * encode all the information necessary for breakpoint_init 280 * into the address itself, so ADDR is potentially 281 * mangled. */ 282 283 struct breakpoint *tmp = insert_breakpoint(proc, bp); 284 if (tmp != bp) { 285 breakpoint_destroy(bp); 286 free(bp); 287 } 288 return tmp; 289} 290 291struct breakpoint * 292insert_breakpoint(struct process *proc, struct breakpoint *bp) 293{ 294 /* Only the group leader should be getting the breakpoints and 295 * thus have ->breakpoint initialized. */ 296 struct process *leader = proc->leader; 297 assert(leader != NULL); 298 assert(leader->breakpoints != NULL); 299 300 /* XXX what we need to do instead is have a list of 301 * breakpoints that are enabled at this address. The 302 * following works if every breakpoint is the same and there's 303 * no extra data, but that doesn't hold anymore. For now it 304 * will suffice, about the only realistic case where we need 305 * to have more than one breakpoint per address is return from 306 * a recursive library call. */ 307 struct breakpoint *ext_bp = bp; 308 if (DICT_FIND_VAL(leader->breakpoints, &bp->addr, &ext_bp) != 0) { 309 if (proc_add_breakpoint(leader, bp) < 0) 310 return NULL; 311 ext_bp = bp; 312 } 313 314 if (breakpoint_turn_on(ext_bp, proc) < 0) { 315 if (ext_bp != bp) 316 proc_remove_breakpoint(leader, bp); 317 return NULL; 318 } 319 320 return ext_bp; 321} 322 323void 324delete_breakpoint_at(struct process *proc, arch_addr_t addr) 325{ 326 debug(DEBUG_FUNCTION, "delete_breakpoint_at(pid=%d, addr=%p)", 327 proc->pid, addr); 328 329 struct process *leader = proc->leader; 330 assert(leader != NULL); 331 332 struct breakpoint *bp = NULL; 333 DICT_FIND_VAL(leader->breakpoints, &addr, &bp); 334 assert(bp != NULL); 335 336 if (delete_breakpoint(proc, bp) < 0) { 337 fprintf(stderr, "Couldn't turn off the breakpoint %s@%p\n", 338 breakpoint_name(bp), bp->addr); 339 } 340} 341 342int 343delete_breakpoint(struct process *proc, struct breakpoint *bp) 344{ 345 struct process *leader = proc->leader; 346 assert(leader != NULL); 347 348 if (breakpoint_turn_off(bp, proc) < 0) 349 return -1; 350 351 if (bp->enabled == 0) { 352 proc_remove_breakpoint(leader, bp); 353 breakpoint_destroy(bp); 354 free(bp); 355 } 356 357 return 0; 358} 359 360const char * 361breakpoint_name(const struct breakpoint *bp) 362{ 363 assert(bp != NULL); 364 return bp->libsym != NULL ? bp->libsym->name : NULL; 365} 366 367struct library * 368breakpoint_library(const struct breakpoint *bp) 369{ 370 assert(bp != NULL); 371 return bp->libsym != NULL ? bp->libsym->lib : NULL; 372} 373 374static enum callback_status 375enable_bp_cb(arch_addr_t *addr, struct breakpoint **bpp, void *data) 376{ 377 struct process *proc = data; 378 debug(DEBUG_FUNCTION, "enable_bp_cb(pid=%d)", proc->pid); 379 if ((*bpp)->enabled) 380 enable_breakpoint(proc, *bpp); 381 return CBS_CONT; 382} 383 384void 385enable_all_breakpoints(struct process *proc) 386{ 387 debug(DEBUG_FUNCTION, "enable_all_breakpoints(pid=%d)", proc->pid); 388 389 debug(1, "Enabling breakpoints for pid %u...", proc->pid); 390 if (proc->breakpoints != NULL) 391 DICT_EACH(proc->breakpoints, arch_addr_t, struct breakpoint *, 392 NULL, enable_bp_cb, proc); 393} 394 395static enum callback_status 396disable_bp_cb(arch_addr_t *addr, struct breakpoint **bpp, void *data) 397{ 398 struct process *proc = data; 399 debug(DEBUG_FUNCTION, "disable_bp_cb(pid=%d)", proc->pid); 400 if ((*bpp)->enabled) 401 disable_breakpoint(proc, *bpp); 402 return CBS_CONT; 403} 404 405void 406disable_all_breakpoints(struct process *proc) 407{ 408 debug(DEBUG_FUNCTION, "disable_all_breakpoints(pid=%d)", proc->pid); 409 assert(proc->leader == proc); 410 DICT_EACH(proc->breakpoints, arch_addr_t, struct breakpoint *, 411 NULL, disable_bp_cb, proc); 412} 413 414static void 415entry_breakpoint_on_hit(struct breakpoint *bp, struct process *proc) 416{ 417 if (proc == NULL || proc->leader == NULL) 418 return; 419 delete_breakpoint_at(proc, bp->addr); 420 process_hit_start(proc); 421} 422 423int 424entry_breakpoint_init(struct process *proc, 425 struct breakpoint *bp, arch_addr_t addr, 426 struct library *lib) 427{ 428 assert(addr != 0); 429 int err = breakpoint_init(bp, proc, addr, NULL); 430 if (err < 0) 431 return err; 432 433 static struct bp_callbacks entry_callbacks = { 434 .on_hit = entry_breakpoint_on_hit, 435 }; 436 bp->cbs = &entry_callbacks; 437 return 0; 438} 439 440int 441breakpoints_init(struct process *proc) 442{ 443 debug(DEBUG_FUNCTION, "breakpoints_init(pid=%d)", proc->pid); 444 445 /* XXX breakpoint dictionary should be initialized 446 * outside. Here we just put in breakpoints. */ 447 assert(proc->breakpoints != NULL); 448 449 /* Only the thread group leader should hold the breakpoints. */ 450 assert(proc->leader == proc); 451 452 /* N.B. the following used to be conditional on this, and 453 * maybe it still needs to be. */ 454 assert(proc->filename != NULL); 455 456 struct library *lib = ltelf_read_main_binary(proc, proc->filename); 457 struct breakpoint *entry_bp = NULL; 458 int bp_state = 0; 459 int result = -1; 460 switch ((int)(lib != NULL)) { 461 fail: 462 switch (bp_state) { 463 case 2: 464 proc_remove_library(proc, lib); 465 proc_remove_breakpoint(proc, entry_bp); 466 case 1: 467 breakpoint_destroy(entry_bp); 468 } 469 library_destroy(lib); 470 free(entry_bp); 471 case 0: 472 return result; 473 } 474 475 entry_bp = malloc(sizeof(*entry_bp)); 476 if (entry_bp == NULL 477 || (entry_breakpoint_init(proc, entry_bp, 478 lib->entry, lib)) < 0) { 479 fprintf(stderr, 480 "Couldn't initialize entry breakpoint for PID %d.\n" 481 "Some tracing events may be missed.\n", proc->pid); 482 free(entry_bp); 483 484 } else { 485 ++bp_state; 486 487 if ((result = proc_add_breakpoint(proc, entry_bp)) < 0) 488 goto fail; 489 ++bp_state; 490 491 if ((result = breakpoint_turn_on(entry_bp, proc)) < 0) 492 goto fail; 493 } 494 proc_add_library(proc, lib); 495 496 proc->callstack_depth = 0; 497 return 0; 498} 499