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