|
Packit |
0021fb |
/*
|
|
Packit |
0021fb |
* This file is part of ltrace.
|
|
Packit |
0021fb |
* Copyright (C) 2010,2011,2012,2013 Petr Machata, Red Hat Inc.
|
|
Packit |
0021fb |
* Copyright (C) 2010 Joe Damato
|
|
Packit |
0021fb |
* Copyright (C) 1998,2001,2008,2009 Juan Cespedes
|
|
Packit |
0021fb |
*
|
|
Packit |
0021fb |
* This program is free software; you can redistribute it and/or
|
|
Packit |
0021fb |
* modify it under the terms of the GNU General Public License as
|
|
Packit |
0021fb |
* published by the Free Software Foundation; either version 2 of the
|
|
Packit |
0021fb |
* License, or (at your option) any later version.
|
|
Packit |
0021fb |
*
|
|
Packit |
0021fb |
* This program is distributed in the hope that it will be useful, but
|
|
Packit |
0021fb |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
0021fb |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
0021fb |
* General Public License for more details.
|
|
Packit |
0021fb |
*
|
|
Packit |
0021fb |
* You should have received a copy of the GNU General Public License
|
|
Packit |
0021fb |
* along with this program; if not, write to the Free Software
|
|
Packit |
0021fb |
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
|
Packit |
0021fb |
* 02110-1301 USA
|
|
Packit |
0021fb |
*/
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
#ifndef _PROC_H_
|
|
Packit |
0021fb |
#define _PROC_H_
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
#include "config.h"
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
#include <sys/time.h>
|
|
Packit |
0021fb |
#include <stdint.h>
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
#if defined(HAVE_LIBUNWIND)
|
|
Packit |
0021fb |
# include <libunwind.h>
|
|
Packit |
0021fb |
#endif /* defined(HAVE_LIBUNWIND) */
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
#include "ltrace.h"
|
|
Packit |
0021fb |
#include "dict.h"
|
|
Packit |
0021fb |
#include "sysdep.h"
|
|
Packit |
0021fb |
#include "callback.h"
|
|
Packit |
0021fb |
#include "forward.h"
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
struct event_handler {
|
|
Packit |
0021fb |
/* Event handler that overrides the default one. Should
|
|
Packit |
0021fb |
* return NULL if the event was handled, otherwise the
|
|
Packit |
0021fb |
* returned event is passed to the default handler. */
|
|
Packit |
0021fb |
Event *(*on_event)(struct event_handler *self, Event *event);
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* Called when the event handler removal is requested. */
|
|
Packit |
0021fb |
void (*destroy)(struct event_handler *self);
|
|
Packit |
0021fb |
};
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
enum process_state {
|
|
Packit |
0021fb |
STATE_ATTACHED = 0,
|
|
Packit |
0021fb |
STATE_BEING_CREATED,
|
|
Packit |
0021fb |
STATE_IGNORED /* ignore this process (it's a fork and no -f was used) */
|
|
Packit |
0021fb |
};
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
struct output_state {
|
|
Packit |
0021fb |
size_t params_left;
|
|
Packit |
0021fb |
int need_delim;
|
|
Packit |
0021fb |
};
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
struct callstack_element {
|
|
Packit |
0021fb |
union {
|
|
Packit |
0021fb |
int syscall;
|
|
Packit |
0021fb |
struct library_symbol * libfunc;
|
|
Packit |
0021fb |
} c_un;
|
|
Packit |
0021fb |
int is_syscall;
|
|
Packit |
0021fb |
arch_addr_t return_addr;
|
|
Packit |
0021fb |
struct timeval time_spent;
|
|
Packit |
0021fb |
struct fetch_context *fetch_context;
|
|
Packit |
0021fb |
struct value_dict *arguments;
|
|
Packit |
0021fb |
struct output_state out;
|
|
Packit |
0021fb |
};
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* XXX We should get rid of this. */
|
|
Packit |
0021fb |
#define MAX_CALLDEPTH 64
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* XXX We would rather have this all organized a little differently,
|
|
Packit |
0021fb |
* have struct process for the whole group and struct task (or struct
|
|
Packit |
0021fb |
* lwp, struct thread) for what's there for per-thread stuff. But for
|
|
Packit |
0021fb |
* now this is the less invasive way of structuring it. */
|
|
Packit |
0021fb |
struct process {
|
|
Packit |
0021fb |
enum process_state state;
|
|
Packit |
0021fb |
struct process *parent; /* needed by STATE_BEING_CREATED */
|
|
Packit |
0021fb |
char * filename;
|
|
Packit |
0021fb |
pid_t pid;
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* Dictionary of breakpoints (which is a mapping
|
|
Packit |
0021fb |
* address->breakpoint). This is NULL for non-leader
|
|
Packit |
0021fb |
* processes. */
|
|
Packit |
0021fb |
struct dict *breakpoints;
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
int mask_32bit; /* 1 if 64-bit ltrace is tracing 32-bit process */
|
|
Packit |
0021fb |
unsigned int personality;
|
|
Packit |
0021fb |
int tracesysgood; /* signal indicating a PTRACE_SYSCALL trap */
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
size_t callstack_depth;
|
|
Packit |
0021fb |
struct callstack_element callstack[MAX_CALLDEPTH];
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* Linked list of libraries in backwards order of mapping.
|
|
Packit |
0021fb |
* The last element is the executed binary itself. */
|
|
Packit |
0021fb |
struct library *libraries;
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* Arch-dependent: */
|
|
Packit |
0021fb |
void * instruction_pointer;
|
|
Packit |
0021fb |
void * stack_pointer; /* To get return addr, args... */
|
|
Packit |
0021fb |
void * arch_ptr;
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* XXX We would like to replace this with a pointer to ABI
|
|
Packit |
0021fb |
* object that would provide the relevant services, instead of
|
|
Packit |
0021fb |
* checking the necessary flags in the back end ad
|
|
Packit |
0021fb |
* nauseam. */
|
|
Packit |
0021fb |
short e_machine;
|
|
Packit |
0021fb |
char e_class;
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
#if defined(HAVE_LIBUNWIND)
|
|
Packit |
0021fb |
/* libunwind address space */
|
|
Packit |
0021fb |
unw_addr_space_t unwind_as;
|
|
Packit |
0021fb |
void *unwind_priv;
|
|
Packit |
0021fb |
#endif /* defined(HAVE_LIBUNWIND) */
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* Set in leader. */
|
|
Packit |
0021fb |
struct event_handler *event_handler;
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/**
|
|
Packit |
0021fb |
* Process chaining.
|
|
Packit |
0021fb |
**/
|
|
Packit |
0021fb |
struct process *next;
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* LEADER points to the leader thread of the POSIX.1 process.
|
|
Packit |
0021fb |
If X->LEADER == X, then X is the leader thread and the
|
|
Packit |
0021fb |
process structures chained by NEXT represent other threads,
|
|
Packit |
0021fb |
up until, but not including, the next leader thread.
|
|
Packit |
0021fb |
LEADER may be NULL after the leader has already exited. In
|
|
Packit |
0021fb |
that case this process is waiting to be collected. */
|
|
Packit |
0021fb |
struct process *leader;
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
struct os_process_data os;
|
|
Packit |
0021fb |
struct arch_process_data arch;
|
|
Packit |
0021fb |
};
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* Initialize a process given a path to binary FILENAME, with a PID,
|
|
Packit |
0021fb |
* and add the process to an internal chain of traced processes. */
|
|
Packit |
0021fb |
int process_init(struct process *proc, const char *filename, pid_t pid);
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* PROC underwent an exec. This is a bit like process_destroy
|
|
Packit |
0021fb |
* followed by process_init, except that some state is kept and the
|
|
Packit |
0021fb |
* process doesn't lose it's place in the list of processes. */
|
|
Packit |
0021fb |
int process_exec(struct process *proc);
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* Release any memory allocated for PROC (but not PROC itself). Does
|
|
Packit |
0021fb |
* NOT remove PROC from internal chain.
|
|
Packit |
0021fb |
*
|
|
Packit |
0021fb |
* XXX clearly this init/destroy pair is different than others and
|
|
Packit |
0021fb |
* should be fixed. process_init should presumably be separate from
|
|
Packit |
0021fb |
* process_add. */
|
|
Packit |
0021fb |
void process_destroy(struct process *proc);
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
struct process *open_program(const char *filename, pid_t pid);
|
|
Packit |
0021fb |
void open_pid(pid_t pid);
|
|
Packit |
0021fb |
struct process *pid2proc(pid_t pid);
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* Clone the contents of PROC into the memory referenced by RETP.
|
|
Packit |
0021fb |
* Returns 0 on success or a negative value on failure. */
|
|
Packit |
0021fb |
int process_clone(struct process *retp, struct process *proc, pid_t pid);
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* Iterate through the processes that ltrace currently traces. Tasks
|
|
Packit |
0021fb |
* are considered to be processes for the purpose of this iterator.
|
|
Packit |
0021fb |
* See callback.h for notes on iteration interfaces. */
|
|
Packit |
0021fb |
struct process *each_process(struct process *start_after,
|
|
Packit |
0021fb |
enum callback_status (*cb)(struct process *proc,
|
|
Packit |
0021fb |
void *data),
|
|
Packit |
0021fb |
void *data);
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* Iterate through list of tasks of given process PROC. See
|
|
Packit |
0021fb |
* callback.h for notes on iteration interfaces. */
|
|
Packit |
0021fb |
struct process *each_task(struct process *proc, struct process *start_after,
|
|
Packit |
0021fb |
enum callback_status (*cb)(struct process *proc,
|
|
Packit |
0021fb |
void *data),
|
|
Packit |
0021fb |
void *data);
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
void change_process_leader(struct process *proc, struct process *leader);
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* Prepare those parts of process initialization that need to be done
|
|
Packit |
0021fb |
* after _start is hit (i.e. after dynamic linking was done). */
|
|
Packit |
0021fb |
void process_hit_start(struct process *proc);
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* Remove process from the list of traced processes, drop any events
|
|
Packit |
0021fb |
* in the event queue, destroy it and free memory. */
|
|
Packit |
0021fb |
void remove_process(struct process *proc);
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
void install_event_handler(struct process *proc, struct event_handler *handler);
|
|
Packit |
0021fb |
void destroy_event_handler(struct process *proc);
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* Add a library LIB to the list of PROC's libraries. */
|
|
Packit |
0021fb |
void proc_add_library(struct process *proc, struct library *lib);
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* Remove LIB from list of PROC's libraries. Returns 0 if the library
|
|
Packit |
0021fb |
* was found and unlinked, otherwise returns a negative value. */
|
|
Packit |
0021fb |
int proc_remove_library(struct process *proc, struct library *lib);
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* Clear a delayed flag. If a symbol is neither latent, nor delayed,
|
|
Packit |
0021fb |
* a breakpoint is inserted for it. Returns 0 if the activation was
|
|
Packit |
0021fb |
* successful or a negative value if it failed. Note that if a symbol
|
|
Packit |
0021fb |
* is both latent and delayed, this will not enable the corresponding
|
|
Packit |
0021fb |
* breakpoint. */
|
|
Packit |
0021fb |
int proc_activate_delayed_symbol(struct process *proc,
|
|
Packit |
0021fb |
struct library_symbol *libsym);
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* Iterate through the libraries of PROC. See callback.h for notes on
|
|
Packit |
0021fb |
* iteration interfaces. */
|
|
Packit |
0021fb |
struct library *proc_each_library(struct process *proc,
|
|
Packit |
0021fb |
struct library *start_after,
|
|
Packit |
0021fb |
enum callback_status (*cb)(struct process *p,
|
|
Packit |
0021fb |
struct library *l,
|
|
Packit |
0021fb |
void *data),
|
|
Packit |
0021fb |
void *data);
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* Insert BP into PROC. */
|
|
Packit |
0021fb |
int proc_add_breakpoint(struct process *proc, struct breakpoint *bp);
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* Remove BP from PROC. This has no reason to fail in runtime. If it
|
|
Packit |
0021fb |
* does not find BP in PROC, it's hard error guarded by assertion. */
|
|
Packit |
0021fb |
void proc_remove_breakpoint(struct process *proc, struct breakpoint *bp);
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* Iterate through the breakpoints of PROC. See callback.h for notes
|
|
Packit |
0021fb |
* on iteration interfaces. */
|
|
Packit |
0021fb |
void *proc_each_breakpoint(struct process *proc, void *start,
|
|
Packit |
0021fb |
enum callback_status (*cb)(struct process *proc,
|
|
Packit |
0021fb |
struct breakpoint *bp,
|
|
Packit |
0021fb |
void *data),
|
|
Packit |
0021fb |
void *data);
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* Iterate through the dynamic section at src_addr looking for D_TAG.
|
|
Packit |
0021fb |
* If tag is found, fill it's value in RET and return 0.
|
|
Packit |
0021fb |
* If tag is not found, return a negative value. */
|
|
Packit |
0021fb |
int proc_find_dynamic_entry_addr(struct process *proc, arch_addr_t src_addr,
|
|
Packit |
0021fb |
int d_tag, arch_addr_t *ret);
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* Finds a symbol corresponding to LIBSYM in a process PROC. Returns
|
|
Packit |
0021fb |
* 0 and sets *RETLIB and *RETSYM if the corresponding pointer is
|
|
Packit |
0021fb |
* non-NULL. Returns a negative value when the symbols couldn't be
|
|
Packit |
0021fb |
* found. */
|
|
Packit |
0021fb |
int proc_find_symbol(struct process *proc, struct library_symbol *sym,
|
|
Packit |
0021fb |
struct library **retlib, struct library_symbol **retsym);
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* Iterate through all symbols in all libraries of PROC. See
|
|
Packit |
0021fb |
* callback.h for notes on this interface. */
|
|
Packit |
0021fb |
struct library_symbol *proc_each_symbol
|
|
Packit |
0021fb |
(struct process *proc, struct library_symbol *start_after,
|
|
Packit |
0021fb |
enum callback_status (*cb)(struct library_symbol *, void *),
|
|
Packit |
0021fb |
void *data);
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* Read 8, 16, 32 or 64-bit quantity located at ADDR in PROC. The
|
|
Packit |
0021fb |
* resulting value is stored in *LP. 0 is returned on success or a
|
|
Packit |
0021fb |
* negative value on failure. This uses umovebytes under the hood
|
|
Packit |
0021fb |
* (see backend.h). */
|
|
Packit |
0021fb |
int proc_read_8(struct process *proc, arch_addr_t addr, uint8_t *lp);
|
|
Packit |
0021fb |
int proc_read_16(struct process *proc, arch_addr_t addr, uint16_t *lp);
|
|
Packit |
0021fb |
int proc_read_32(struct process *proc, arch_addr_t addr, uint32_t *lp);
|
|
Packit |
0021fb |
int proc_read_64(struct process *proc, arch_addr_t addr, uint64_t *lp);
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
#endif /* _PROC_H_ */
|