breakpoints.c 11.3 KB
Newer Older
1 2
/*
 * This file is part of ltrace.
3
 * Copyright (C) 2006,2007,2011,2012,2013,2014 Petr Machata, Red Hat Inc.
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 * Copyright (C) 2009 Juan Cespedes
 * Copyright (C) 1998,2001,2002,2003,2007,2008,2009 Juan Cespedes
 * Copyright (C) 2006 Ian Wienand
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 */

Juan Cespedes's avatar
Juan Cespedes committed
24 25
#include "config.h"

Juan Cespedes's avatar
Juan Cespedes committed
26
#include <assert.h>
27
#include <errno.h>
Petr Machata's avatar
Petr Machata committed
28 29 30
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Juan Cespedes's avatar
Juan Cespedes committed
31

Juan Cespedes's avatar
Juan Cespedes committed
32 33 34 35
#ifdef __powerpc__
#include <sys/ptrace.h>
#endif

Petr Machata's avatar
Petr Machata committed
36
#include "backend.h"
37
#include "breakpoint.h"
Petr Machata's avatar
Petr Machata committed
38
#include "debug.h"
39
#include "library.h"
Petr Machata's avatar
Petr Machata committed
40 41
#include "ltrace-elf.h"
#include "proc.h"
Juan Cespedes's avatar
Juan Cespedes committed
42

43 44
#ifndef ARCH_HAVE_TRANSLATE_ADDRESS
int
45
arch_translate_address_dyn(struct process *proc,
46
		       arch_addr_t addr, arch_addr_t *ret)
47 48 49 50 51 52 53 54
{
	*ret = addr;
	return 0;
}

struct ltelf;
int
arch_translate_address(struct ltelf *lte,
55
		       arch_addr_t addr, arch_addr_t *ret)
56 57 58 59 60 61
{
	*ret = addr;
	return 0;
}
#endif

Petr Machata's avatar
Petr Machata committed
62
void
63
breakpoint_on_hit(struct breakpoint *bp, struct process *proc)
Petr Machata's avatar
Petr Machata committed
64 65 66
{
	assert(bp != NULL);
	if (bp->cbs != NULL && bp->cbs->on_hit != NULL)
67 68 69 70
		(bp->cbs->on_hit)(bp, proc);
}

void
71
breakpoint_on_continue(struct breakpoint *bp, struct process *proc)
72 73 74 75 76 77
{
	assert(bp != NULL);
	if (bp->cbs != NULL && bp->cbs->on_continue != NULL)
		(bp->cbs->on_continue)(bp, proc);
	else
		continue_after_breakpoint(proc, bp);
Petr Machata's avatar
Petr Machata committed
78 79
}

80
void
81
breakpoint_on_retract(struct breakpoint *bp, struct process *proc)
82 83 84 85 86 87
{
	assert(bp != NULL);
	if (bp->cbs != NULL && bp->cbs->on_retract != NULL)
		(bp->cbs->on_retract)(bp, proc);
}

88 89 90 91 92 93 94 95
void
breakpoint_on_install(struct breakpoint *bp, struct process *proc)
{
	assert(bp != NULL);
	if (bp->cbs != NULL && bp->cbs->on_install != NULL)
		(bp->cbs->on_install)(bp, proc);
}

96 97 98 99 100 101 102 103 104 105 106 107 108 109
int
breakpoint_get_return_bp(struct breakpoint **ret,
			 struct breakpoint *bp, struct process *proc)
{
	assert(bp != NULL);
	if (bp->cbs != NULL && bp->cbs->get_return_bp != NULL)
		return (bp->cbs->get_return_bp)(ret, bp, proc);

	if ((*ret = create_default_return_bp(proc)) == NULL)
		return -1;

	return 0;
}

Juan Cespedes's avatar
Juan Cespedes committed
110 111
/*****************************************************************************/

112
struct breakpoint *
113
address2bpstruct(struct process *proc, arch_addr_t addr)
Petr Machata's avatar
Petr Machata committed
114
{
Petr Machata's avatar
Petr Machata committed
115 116
	assert(proc != NULL);
	assert(proc->breakpoints != NULL);
117
	assert(proc->leader == proc);
118
	debug(DEBUG_FUNCTION, "address2bpstruct(pid=%d, addr=%p)", proc->pid, addr);
119

120 121
	struct breakpoint *found;
	if (DICT_FIND_VAL(proc->breakpoints, &addr, &found) < 0)
122
		return NULL;
123
	return found;
Juan Cespedes's avatar
Juan Cespedes committed
124 125
}

126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
#ifndef OS_HAVE_BREAKPOINT_DATA
int
os_breakpoint_init(struct process *proc, struct breakpoint *sbp)
{
	return 0;
}

void
os_breakpoint_destroy(struct breakpoint *sbp)
{
}

int
os_breakpoint_clone(struct breakpoint *retp, struct breakpoint *sbp)
{
	return 0;
}
#endif

145
#ifndef ARCH_HAVE_BREAKPOINT_DATA
146
int
147
arch_breakpoint_init(struct process *proc, struct breakpoint *sbp)
148 149 150
{
	return 0;
}
151 152 153 154 155

void
arch_breakpoint_destroy(struct breakpoint *sbp)
{
}
Petr Machata's avatar
Petr Machata committed
156 157 158 159 160 161

int
arch_breakpoint_clone(struct breakpoint *retp, struct breakpoint *sbp)
{
	return 0;
}
162 163
#endif

Petr Machata's avatar
Petr Machata committed
164
static void
165
breakpoint_init_base(struct breakpoint *bp,
166
		     arch_addr_t addr, struct library_symbol *libsym)
Petr Machata's avatar
Petr Machata committed
167 168 169 170 171 172 173 174
{
	bp->cbs = NULL;
	bp->addr = addr;
	memset(bp->orig_value, 0, sizeof(bp->orig_value));
	bp->enabled = 0;
	bp->libsym = libsym;
}

175 176 177 178
/* On second thought, I don't think we need PROC.  All the translation
 * (arch_translate_address in particular) should be doable using
 * static lookups of various sections in the ELF file.  We shouldn't
 * need process for anything.  */
179
int
180
breakpoint_init(struct breakpoint *bp, struct process *proc,
181
		arch_addr_t addr, struct library_symbol *libsym)
182
{
183
	breakpoint_init_base(bp, addr, libsym);
184 185 186 187 188 189 190
	if (os_breakpoint_init(proc, bp) < 0)
		return -1;
	if (arch_breakpoint_init(proc, bp) < 0) {
		os_breakpoint_destroy(bp);
		return -1;
	}
	return 0;
191 192
}

193 194 195 196 197 198 199 200
void
breakpoint_set_callbacks(struct breakpoint *bp, struct bp_callbacks *cbs)
{
	if (bp->cbs != NULL)
		assert(bp->cbs == NULL);
	bp->cbs = cbs;
}

201 202 203 204 205
void
breakpoint_destroy(struct breakpoint *bp)
{
	if (bp == NULL)
		return;
Petr Machata's avatar
Petr Machata committed
206
	arch_breakpoint_destroy(bp);
207
	os_breakpoint_destroy(bp);
Petr Machata's avatar
Petr Machata committed
208
}
209

Petr Machata's avatar
Petr Machata committed
210
int
211
breakpoint_clone(struct breakpoint *retp, struct process *new_proc,
212
		 struct breakpoint *bp)
Petr Machata's avatar
Petr Machata committed
213
{
214 215 216 217
	struct library_symbol *libsym = NULL;
	if (bp->libsym != NULL) {
		int rc = proc_find_symbol(new_proc, bp->libsym, NULL, &libsym);
		assert(rc == 0);
Petr Machata's avatar
Petr Machata committed
218 219
	}

220
	breakpoint_init_base(retp, bp->addr, libsym);
Petr Machata's avatar
Petr Machata committed
221 222
	memcpy(retp->orig_value, bp->orig_value, sizeof(bp->orig_value));
	retp->enabled = bp->enabled;
223
	if (os_breakpoint_clone(retp, bp) < 0)
Petr Machata's avatar
Petr Machata committed
224
		return -1;
225 226 227 228
	if (arch_breakpoint_clone(retp, bp) < 0) {
		os_breakpoint_destroy(retp);
		return -1;
	}
Petr Machata's avatar
Petr Machata committed
229 230
	breakpoint_set_callbacks(retp, bp->cbs);
	return 0;
231 232
}

233
int
234
breakpoint_turn_on(struct breakpoint *bp, struct process *proc)
235 236 237
{
	bp->enabled++;
	if (bp->enabled == 1) {
Petr Machata's avatar
Petr Machata committed
238 239
		assert(proc->pid != 0);
		enable_breakpoint(proc, bp);
240
		breakpoint_on_install(bp, proc);
241 242 243 244 245
	}
	return 0;
}

int
246
breakpoint_turn_off(struct breakpoint *bp, struct process *proc)
247 248 249
{
	bp->enabled--;
	if (bp->enabled == 0)
Petr Machata's avatar
Petr Machata committed
250
		disable_breakpoint(proc, bp);
251 252 253 254
	assert(bp->enabled >= 0);
	return 0;
}

255 256 257 258 259 260 261 262 263 264 265 266 267
struct breakpoint *
create_default_return_bp(struct process *proc)
{
	struct breakpoint *bp = malloc(sizeof *bp);
	arch_addr_t return_addr = get_return_addr(proc, proc->stack_pointer);
	if (return_addr == 0 || bp == NULL
	    || breakpoint_init(bp, proc, return_addr, NULL) < 0) {
		free(bp);
		return NULL;
	}
	return bp;
}

268
struct breakpoint *
269 270
insert_breakpoint_at(struct process *proc, arch_addr_t addr,
		     struct library_symbol *libsym)
Petr Machata's avatar
Petr Machata committed
271
{
272 273
	debug(DEBUG_FUNCTION,
	      "insert_breakpoint_at(pid=%d, addr=%p, symbol=%s)",
Petr Machata's avatar
Petr Machata committed
274
	      proc->pid, addr, libsym ? libsym->name : "NULL");
Juan Cespedes's avatar
Juan Cespedes committed
275

Petr Machata's avatar
Nits  
Petr Machata committed
276
	assert(addr != 0);
277

278 279 280
	struct breakpoint *bp = malloc(sizeof *bp);
	if (bp == NULL || breakpoint_init(bp, proc, addr, libsym) < 0) {
		free(bp);
Petr Machata's avatar
Petr Machata committed
281
		return NULL;
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307
	}

	/* N.B. (and XXX): BP->addr might differ from ADDR.  On ARM
	 * this is a real possibility.  The problem here is that to
	 * create a return breakpoint ltrace calls get_return_addr and
	 * then insert_breakpoint_at.  So get_return_addr needs to
	 * encode all the information necessary for breakpoint_init
	 * into the address itself, so ADDR is potentially
	 * mangled.  */

	struct breakpoint *tmp = insert_breakpoint(proc, bp);
	if (tmp != bp) {
		breakpoint_destroy(bp);
		free(bp);
	}
	return tmp;
}

struct breakpoint *
insert_breakpoint(struct process *proc, struct breakpoint *bp)
{
	/* Only the group leader should be getting the breakpoints and
	 * thus have ->breakpoint initialized.  */
	struct process *leader = proc->leader;
	assert(leader != NULL);
	assert(leader->breakpoints != NULL);
Petr Machata's avatar
Petr Machata committed
308

309 310 311 312 313 314 315
	/* XXX what we need to do instead is have a list of
	 * breakpoints that are enabled at this address.  The
	 * following works if every breakpoint is the same and there's
	 * no extra data, but that doesn't hold anymore.  For now it
	 * will suffice, about the only realistic case where we need
	 * to have more than one breakpoint per address is return from
	 * a recursive library call.  */
316 317 318
	struct breakpoint *ext_bp = bp;
	if (DICT_FIND_VAL(leader->breakpoints, &bp->addr, &ext_bp) != 0) {
		if (proc_add_breakpoint(leader, bp) < 0)
319
			return NULL;
320
		ext_bp = bp;
Juan Cespedes's avatar
Juan Cespedes committed
321
	}
322

323 324 325 326
	if (breakpoint_turn_on(ext_bp, proc) < 0) {
		if (ext_bp != bp)
			proc_remove_breakpoint(leader, bp);
		return NULL;
327
	}
328

329
	return ext_bp;
Juan Cespedes's avatar
Juan Cespedes committed
330 331
}

332
void
333
delete_breakpoint_at(struct process *proc, arch_addr_t addr)
Petr Machata's avatar
Petr Machata committed
334
{
335 336
	debug(DEBUG_FUNCTION, "delete_breakpoint_at(pid=%d, addr=%p)",
	      proc->pid, addr);
337

338
	struct process *leader = proc->leader;
339 340
	assert(leader != NULL);

341 342 343
	struct breakpoint *bp = NULL;
	DICT_FIND_VAL(leader->breakpoints, &addr, &bp);
	assert(bp != NULL);
Juan Cespedes's avatar
Juan Cespedes committed
344

345
	if (delete_breakpoint(proc, bp) < 0) {
346
		fprintf(stderr, "Couldn't turn off the breakpoint %[email protected]%p\n",
347
			breakpoint_name(bp), bp->addr);
348
	}
349 350 351 352 353 354 355 356 357 358 359 360 361 362 363
}

int
delete_breakpoint(struct process *proc, struct breakpoint *bp)
{
	struct process *leader = proc->leader;
	assert(leader != NULL);

	if (breakpoint_turn_off(bp, proc) < 0)
		return -1;

	if (bp->enabled == 0) {
		proc_remove_breakpoint(leader, bp);
		breakpoint_destroy(bp);
		free(bp);
364
	}
365 366

	return 0;
Juan Cespedes's avatar
Juan Cespedes committed
367 368
}

Petr Machata's avatar
Petr Machata committed
369 370 371 372 373 374 375
const char *
breakpoint_name(const struct breakpoint *bp)
{
	assert(bp != NULL);
	return bp->libsym != NULL ? bp->libsym->name : NULL;
}

376 377 378 379 380 381 382
struct library *
breakpoint_library(const struct breakpoint *bp)
{
	assert(bp != NULL);
	return bp->libsym != NULL ? bp->libsym->lib : NULL;
}

383 384
static enum callback_status
disable_bp_cb(arch_addr_t *addr, struct breakpoint **bpp, void *data)
Petr Machata's avatar
Petr Machata committed
385
{
386 387 388 389 390
	struct process *proc = data;
	debug(DEBUG_FUNCTION, "disable_bp_cb(pid=%d)", proc->pid);
	if ((*bpp)->enabled)
		disable_breakpoint(proc, *bpp);
	return CBS_CONT;
Juan Cespedes's avatar
Juan Cespedes committed
391 392
}

393
void
394 395
disable_all_breakpoints(struct process *proc)
{
396
	debug(DEBUG_FUNCTION, "disable_all_breakpoints(pid=%d)", proc->pid);
397
	assert(proc->leader == proc);
398 399
	DICT_EACH(proc->breakpoints, arch_addr_t, struct breakpoint *,
		  NULL, disable_bp_cb, proc);
Juan Cespedes's avatar
Juan Cespedes committed
400
}
Juan Cespedes's avatar
Juan Cespedes committed
401

402
static void
403
entry_breakpoint_on_hit(struct breakpoint *bp, struct process *proc)
404 405 406
{
	if (proc == NULL || proc->leader == NULL)
		return;
407
	delete_breakpoint_at(proc, bp->addr);
408
	process_hit_start(proc);
409 410 411
}

int
412
entry_breakpoint_init(struct process *proc,
413
		      struct breakpoint *bp, arch_addr_t addr,
414
		      struct library *lib)
415
{
416
	assert(addr != 0);
417
	int err = breakpoint_init(bp, proc, addr, NULL);
418
	if (err < 0)
419 420 421
		return err;

	static struct bp_callbacks entry_callbacks = {
422
		.on_hit = entry_breakpoint_on_hit,
423
	};
424
	bp->cbs = &entry_callbacks;
425
	return 0;
426 427
}

428
int
429
breakpoints_init(struct process *proc)
430
{
431
	debug(DEBUG_FUNCTION, "breakpoints_init(pid=%d)", proc->pid);
Petr Machata's avatar
Petr Machata committed
432

433 434 435
	/* XXX breakpoint dictionary should be initialized
	 * outside.  Here we just put in breakpoints.  */
	assert(proc->breakpoints != NULL);
Juan Cespedes's avatar
Juan Cespedes committed
436

437 438
	/* Only the thread group leader should hold the breakpoints.  */
	assert(proc->leader == proc);
439

440 441 442 443 444
	/* N.B. the following used to be conditional on this, and
	 * maybe it still needs to be.  */
	assert(proc->filename != NULL);

	struct library *lib = ltelf_read_main_binary(proc, proc->filename);
445
	struct breakpoint *entry_bp = NULL;
446 447
	int bp_state = 0;
	int result = -1;
448
	switch ((int)(lib != NULL)) {
449 450 451
	fail:
		switch (bp_state) {
		case 2:
452
			proc_remove_library(proc, lib);
453
			proc_remove_breakpoint(proc, entry_bp);
454
		case 1:
455
			breakpoint_destroy(entry_bp);
456
		}
457
		library_destroy(lib);
458 459 460 461
		free(entry_bp);
	case 0:
		return result;
	}
462

463 464
	entry_bp = malloc(sizeof(*entry_bp));
	if (entry_bp == NULL
465 466 467 468 469 470
	    || (entry_breakpoint_init(proc, entry_bp,
				      lib->entry, lib)) < 0) {
		fprintf(stderr,
			"Couldn't initialize entry breakpoint for PID %d.\n"
			"Some tracing events may be missed.\n", proc->pid);
		free(entry_bp);
471

472 473
	} else {
		++bp_state;
474

475
		if ((result = proc_add_breakpoint(proc, entry_bp)) < 0)
476 477 478
			goto fail;
		++bp_state;

479
		if ((result = breakpoint_turn_on(entry_bp, proc)) < 0)
480 481
			goto fail;
	}
482 483
	proc_add_library(proc, lib);

Juan Cespedes's avatar
Juan Cespedes committed
484
	proc->callstack_depth = 0;
485
	return 0;
Juan Cespedes's avatar
Juan Cespedes committed
486
}