breakpoints.c revision 02a796e5e49c147982020c78b0066930e979f3e4
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 88/*****************************************************************************/ 89 90struct breakpoint * 91address2bpstruct(struct process *proc, arch_addr_t addr) 92{ 93 assert(proc != NULL); 94 assert(proc->breakpoints != NULL); 95 assert(proc->leader == proc); 96 debug(DEBUG_FUNCTION, "address2bpstruct(pid=%d, addr=%p)", proc->pid, addr); 97 98 struct breakpoint *found; 99 if (DICT_FIND_VAL(proc->breakpoints, &addr, &found) < 0) 100 return NULL; 101 return found; 102} 103 104#ifndef ARCH_HAVE_BREAKPOINT_DATA 105int 106arch_breakpoint_init(struct process *proc, struct breakpoint *sbp) 107{ 108 return 0; 109} 110 111void 112arch_breakpoint_destroy(struct breakpoint *sbp) 113{ 114} 115 116int 117arch_breakpoint_clone(struct breakpoint *retp, struct breakpoint *sbp) 118{ 119 return 0; 120} 121#endif 122 123static void 124breakpoint_init_base(struct breakpoint *bp, 125 arch_addr_t addr, struct library_symbol *libsym) 126{ 127 bp->cbs = NULL; 128 bp->addr = addr; 129 memset(bp->orig_value, 0, sizeof(bp->orig_value)); 130 bp->enabled = 0; 131 bp->libsym = libsym; 132} 133 134/* On second thought, I don't think we need PROC. All the translation 135 * (arch_translate_address in particular) should be doable using 136 * static lookups of various sections in the ELF file. We shouldn't 137 * need process for anything. */ 138int 139breakpoint_init(struct breakpoint *bp, struct process *proc, 140 arch_addr_t addr, struct library_symbol *libsym) 141{ 142 breakpoint_init_base(bp, addr, libsym); 143 return arch_breakpoint_init(proc, bp); 144} 145 146void 147breakpoint_set_callbacks(struct breakpoint *bp, struct bp_callbacks *cbs) 148{ 149 if (bp->cbs != NULL) 150 assert(bp->cbs == NULL); 151 bp->cbs = cbs; 152} 153 154void 155breakpoint_destroy(struct breakpoint *bp) 156{ 157 if (bp == NULL) 158 return; 159 arch_breakpoint_destroy(bp); 160} 161 162int 163breakpoint_clone(struct breakpoint *retp, struct process *new_proc, 164 struct breakpoint *bp) 165{ 166 struct library_symbol *libsym = NULL; 167 if (bp->libsym != NULL) { 168 int rc = proc_find_symbol(new_proc, bp->libsym, NULL, &libsym); 169 assert(rc == 0); 170 } 171 172 breakpoint_init_base(retp, bp->addr, libsym); 173 memcpy(retp->orig_value, bp->orig_value, sizeof(bp->orig_value)); 174 retp->enabled = bp->enabled; 175 if (arch_breakpoint_clone(retp, bp) < 0) 176 return -1; 177 breakpoint_set_callbacks(retp, bp->cbs); 178 return 0; 179} 180 181int 182breakpoint_turn_on(struct breakpoint *bp, struct process *proc) 183{ 184 bp->enabled++; 185 if (bp->enabled == 1) { 186 assert(proc->pid != 0); 187 enable_breakpoint(proc, bp); 188 } 189 return 0; 190} 191 192int 193breakpoint_turn_off(struct breakpoint *bp, struct process *proc) 194{ 195 bp->enabled--; 196 if (bp->enabled == 0) 197 disable_breakpoint(proc, bp); 198 assert(bp->enabled >= 0); 199 return 0; 200} 201 202struct breakpoint * 203insert_breakpoint_at(struct process *proc, arch_addr_t addr, 204 struct library_symbol *libsym) 205{ 206 struct process *leader = proc->leader; 207 208 /* Only the group leader should be getting the breakpoints and 209 * thus have ->breakpoint initialized. */ 210 assert(leader != NULL); 211 assert(leader->breakpoints != NULL); 212 213 debug(DEBUG_FUNCTION, 214 "insert_breakpoint_at(pid=%d, addr=%p, symbol=%s)", 215 proc->pid, addr, libsym ? libsym->name : "NULL"); 216 217 assert(addr != 0); 218 219 /* We first create the breakpoint to find out what it's real 220 * address is. This makes a difference on ARM. 221 * 222 * XXX The real problem here is that to create a return 223 * breakpoint ltrace calls get_return_addr and then 224 * insert_breakpoint_at. So get_return_addr needs to encode 225 * all the information necessary for breakpoint_init into the 226 * address itself, so ADDR is potentially mangled. We filter 227 * the noise out by first creating the breakpoint on stack, 228 * and then looking at the address of the created breakpoint. 229 * Replacing get_return_addr with get_return_breakpoint might 230 * be a better solution. */ 231 struct breakpoint bp; 232 if (breakpoint_init(&bp, proc, addr, libsym) < 0) 233 return NULL; 234 235 /* XXX what we need to do instead is have a list of 236 * breakpoints that are enabled at this address. The 237 * following works if every breakpoint is the same and there's 238 * no extra data, but that doesn't hold anymore. For now it 239 * will suffice, about the only realistic case where we need 240 * to have more than one breakpoint per address is return from 241 * a recursive library call. */ 242 struct breakpoint *sbp; 243 if (DICT_FIND_VAL(leader->breakpoints, &bp.addr, &sbp) >= 0) { 244 breakpoint_destroy(&bp); 245 } else { 246 sbp = malloc(sizeof(*sbp)); 247 if (sbp == NULL 248 || breakpoint_init(sbp, proc, addr, libsym) < 0) { 249 free(sbp); 250 return NULL; 251 } 252 if (proc_add_breakpoint(leader, sbp) < 0) { 253 fail: 254 free(sbp); 255 breakpoint_destroy(&bp); 256 return NULL; 257 } 258 memcpy(sbp, &bp, sizeof(*sbp)); 259 } 260 261 if (breakpoint_turn_on(sbp, proc) < 0) { 262 proc_remove_breakpoint(leader, sbp); 263 goto fail; 264 } 265 266 return sbp; 267} 268 269void 270delete_breakpoint(struct process *proc, arch_addr_t addr) 271{ 272 debug(DEBUG_FUNCTION, "delete_breakpoint(pid=%d, addr=%p)", proc->pid, addr); 273 274 struct process *leader = proc->leader; 275 assert(leader != NULL); 276 277 struct breakpoint *sbp = NULL; 278 DICT_FIND_VAL(leader->breakpoints, &addr, &sbp); 279 assert(sbp != NULL); 280 281 if (breakpoint_turn_off(sbp, proc) < 0) { 282 fprintf(stderr, "Couldn't turn off the breakpoint %s@%p\n", 283 breakpoint_name(sbp), sbp->addr); 284 return; 285 } 286 if (sbp->enabled == 0) { 287 proc_remove_breakpoint(leader, sbp); 288 breakpoint_destroy(sbp); 289 free(sbp); 290 } 291} 292 293const char * 294breakpoint_name(const struct breakpoint *bp) 295{ 296 assert(bp != NULL); 297 return bp->libsym != NULL ? bp->libsym->name : NULL; 298} 299 300struct library * 301breakpoint_library(const struct breakpoint *bp) 302{ 303 assert(bp != NULL); 304 return bp->libsym != NULL ? bp->libsym->lib : NULL; 305} 306 307static enum callback_status 308enable_bp_cb(arch_addr_t *addr, struct breakpoint **bpp, void *data) 309{ 310 struct process *proc = data; 311 debug(DEBUG_FUNCTION, "enable_bp_cb(pid=%d)", proc->pid); 312 if ((*bpp)->enabled) 313 enable_breakpoint(proc, *bpp); 314 return CBS_CONT; 315} 316 317void 318enable_all_breakpoints(struct process *proc) 319{ 320 debug(DEBUG_FUNCTION, "enable_all_breakpoints(pid=%d)", proc->pid); 321 322 debug(1, "Enabling breakpoints for pid %u...", proc->pid); 323 if (proc->breakpoints != NULL) 324 DICT_EACH(proc->breakpoints, arch_addr_t, struct breakpoint *, 325 NULL, enable_bp_cb, proc); 326} 327 328static enum callback_status 329disable_bp_cb(arch_addr_t *addr, struct breakpoint **bpp, void *data) 330{ 331 struct process *proc = data; 332 debug(DEBUG_FUNCTION, "disable_bp_cb(pid=%d)", proc->pid); 333 if ((*bpp)->enabled) 334 disable_breakpoint(proc, *bpp); 335 return CBS_CONT; 336} 337 338void 339disable_all_breakpoints(struct process *proc) 340{ 341 debug(DEBUG_FUNCTION, "disable_all_breakpoints(pid=%d)", proc->pid); 342 assert(proc->leader == proc); 343 DICT_EACH(proc->breakpoints, arch_addr_t, struct breakpoint *, 344 NULL, disable_bp_cb, proc); 345} 346 347static void 348entry_breakpoint_on_hit(struct breakpoint *bp, struct process *proc) 349{ 350 if (proc == NULL || proc->leader == NULL) 351 return; 352 delete_breakpoint(proc, bp->addr); 353 process_hit_start(proc); 354} 355 356int 357entry_breakpoint_init(struct process *proc, 358 struct breakpoint *bp, arch_addr_t addr, 359 struct library *lib) 360{ 361 assert(addr != 0); 362 int err = breakpoint_init(bp, proc, addr, NULL); 363 if (err < 0) 364 return err; 365 366 static struct bp_callbacks entry_callbacks = { 367 .on_hit = entry_breakpoint_on_hit, 368 }; 369 bp->cbs = &entry_callbacks; 370 return 0; 371} 372 373int 374breakpoints_init(struct process *proc) 375{ 376 debug(DEBUG_FUNCTION, "breakpoints_init(pid=%d)", proc->pid); 377 378 /* XXX breakpoint dictionary should be initialized 379 * outside. Here we just put in breakpoints. */ 380 assert(proc->breakpoints != NULL); 381 382 /* Only the thread group leader should hold the breakpoints. */ 383 assert(proc->leader == proc); 384 385 /* N.B. the following used to be conditional on this, and 386 * maybe it still needs to be. */ 387 assert(proc->filename != NULL); 388 389 struct library *lib = ltelf_read_main_binary(proc, proc->filename); 390 struct breakpoint *entry_bp = NULL; 391 int bp_state = 0; 392 int result = -1; 393 switch ((int)(lib != NULL)) { 394 fail: 395 switch (bp_state) { 396 case 2: 397 proc_remove_library(proc, lib); 398 proc_remove_breakpoint(proc, entry_bp); 399 case 1: 400 breakpoint_destroy(entry_bp); 401 } 402 library_destroy(lib); 403 free(entry_bp); 404 case 0: 405 return result; 406 } 407 408 entry_bp = malloc(sizeof(*entry_bp)); 409 if (entry_bp == NULL 410 || (entry_breakpoint_init(proc, entry_bp, 411 lib->entry, lib)) < 0) { 412 fprintf(stderr, 413 "Couldn't initialize entry breakpoint for PID %d.\n" 414 "Some tracing events may be missed.\n", proc->pid); 415 free(entry_bp); 416 417 } else { 418 ++bp_state; 419 420 if ((result = proc_add_breakpoint(proc, entry_bp)) < 0) 421 goto fail; 422 ++bp_state; 423 424 if ((result = breakpoint_turn_on(entry_bp, proc)) < 0) 425 goto fail; 426 } 427 proc_add_library(proc, lib); 428 429 proc->callstack_depth = 0; 430 return 0; 431} 432