File: libproc.h

package info (click to toggle)
dtrace 2.0.5-1
  • links: PTS
  • area: main
  • in suites: sid
  • size: 24,408 kB
  • sloc: ansic: 61,247; sh: 17,997; asm: 1,717; lex: 947; awk: 754; yacc: 695; perl: 37; sed: 17; makefile: 15
file content (344 lines) | stat: -rw-r--r-- 12,586 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
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
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
/*
 * Oracle Linux DTrace.
 * Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved.
 * Licensed under the Universal Permissive License v 1.0 as shown at
 * http://oss.oracle.com/licenses/upl.
 */
/*
 * Portions Copyright 2007 Chad Mynhier
 */

/*
 * Interfaces available from the process control library, libproc.
 */

#ifndef	_LIBPROC_H
#define	_LIBPROC_H

#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <setjmp.h>
#include <gelf.h>
#include <sys/statvfs.h>
#include <sys/wait.h>
#include <rtld_db.h>
#include <sys/ctf-api.h>
#include <sys/ptrace.h>
#include <sys/sol_procfs.h>
#include <sys/dtrace_types.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/utsname.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/user.h>

#include <sys/compiler.h>

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * Maximum number of digits needed for a pid so we can properly
 * size strings for /proc/$pid/auxv, /proc/$pid/maps, etc.
 * E.g., if procname[] will be "$procfs/$pid/exe", we size
 *     char procname[PATH_MAX + MAXLEN_PID + strlen("/exe") + 1];
 * The null-terminating char of $procfs is overwritten by a '/',
 * and then we add space for the new terminating char at the end.
 */
#define MAXLEN_PID 9

/*
 * Opaque structure tag reference to a process control structure.
 * Clients of libproc cannot look inside the process control structure.
 * The implementation of struct ps_prochandle can change w/o affecting clients.
 */
struct ps_prochandle;
typedef struct ps_prochandle ps_prochandle;

/* State values returned by Pstate() */
#define	PS_RUN		1	/* process is running */
#define	PS_STOP		2	/* process is stopped by SIGSTOP etc */
#define	PS_TRACESTOP	3	/* process is stopped by ptrace() or bkpts */
#define	PS_DEAD		4	/* process is terminated (core file) */

/* Values for Prelease()'s release_mode argument */
#define PS_RELEASE_NORMAL 0	/* ptrace detach, do not kill */
#define PS_RELEASE_KILL 1	/* ptrace detach and kill */
#define PS_RELEASE_NO_DETACH 2	/* no ptrace detach or lock release */

/*
 * Function prototypes for routines in the process control package.
 */
extern	struct ps_prochandle *Pcreate(const char *, char *const *,
    void *, int *);

extern	struct ps_prochandle *Pgrab(pid_t pid, int noninvasiveness,
	int already_ptraced, void *wrap_arg, int *perr);
extern	int	Ptrace(struct ps_prochandle *, int stopped);
extern	void	Ptrace_set_detached(struct ps_prochandle *, boolean_t);

extern	void	Prelease(struct ps_prochandle *, int);
extern	void	Pfree(struct ps_prochandle *P);
extern	void	Puntrace(struct ps_prochandle *, int stay_stopped);
extern	void	Pclose(struct ps_prochandle *);

extern	int	Pmemfd(struct ps_prochandle *);
extern	long	Pwait(struct ps_prochandle *, boolean_t block,
    int *return_early);
extern	int	Pstate(struct ps_prochandle *);
extern	ssize_t	Pread(struct ps_prochandle *, void *, size_t, uintptr_t);
extern	ssize_t Pread_string(struct ps_prochandle *, char *, size_t, uintptr_t);
extern 	ssize_t	Pread_scalar(struct ps_prochandle *P, void *buf, size_t nbyte,
    size_t nscalar, uintptr_t address);
extern 	ssize_t	Pread_scalar_quietly(struct ps_prochandle *P, void *buf,
    size_t nbyte, size_t nscalar, uintptr_t address, int quietly);
extern	int	Phasfds(struct ps_prochandle *);
extern	void	Pset_procfs_path(const char *);
extern	int	Pdynamically_linked(struct ps_prochandle *);
extern	int	Ptraceable(struct ps_prochandle *);
extern	int	Pelf64(struct ps_prochandle *);
extern	pid_t	Ptracer_pid(pid_t);
extern	pid_t	Ptgid(pid_t);

/*
 * Calls that do not take a process structure.  These are used to determine
 * whether it is sensible to grab a pid at all, before the grab takes place.
 */
extern int Pexists(pid_t pid);
extern int Psystem_daemon(pid_t pid, uid_t useruid, const char *sysslice);

/*
 * Read the first argument of the function at which the process P is
 * halted, which must be a pointer.
 *
 * On error, -1 cast to a uintptr_t is returned, and errno is set.
 */
extern	uintptr_t Pread_first_arg(struct ps_prochandle *P);

/*
 * Hook and wrapper functions.  These functions all get their 'arg' argument
 * from the corresponding argument to Pcreate() and Pgrab().
 *
 * Route all calls to ptrace() via the specified wrapper function.
 *
 * _arg_ is constant for all calls using this prochandle until the next call to
 * Pset_ptrace_wrapper().
 */
typedef long ptrace_fun(enum __ptrace_request request, void *arg, pid_t pid,
    void *addr, void *data);

extern	void	Pset_ptrace_wrapper(struct ps_prochandle *P,
    ptrace_fun *wrapper);

/*
 * Likewise, but for Pwait().
 *
 * A program intending to call libproc functions from threads other than those
 * grabbing the process will typically need to wrap both ptrace() and Pwait().
 */
typedef long pwait_fun(struct ps_prochandle *P, void *arg, boolean_t block,
    int *return_early);

extern	void	Pset_pwait_wrapper(struct ps_prochandle *P, pwait_fun *wrapper);

/*
 * The function that implements the guts of Pwait(), that the Pwait() wrapper
 * function should end up calling (somehow, from some thread or other).  Safe to
 * call only from the thread that did Pgrab() or Pcreate().
 */
extern	long	Pwait_internal(struct ps_prochandle *P, boolean_t block,
    int *return_early);

/*
 * Register a function to be called around the outermost layer of Ptrace()/
 * Puntrace() calls.  This can, e.g., take a mutex to ensure that other threads
 * do not interfere and unbalance the Ptrace()/Puntrace() stack by issuing
 * further Ptrace()/Puntrace() calls while inside at least one Ptrace().
 *
 * Note that on exit from Pgrab()/Pcreate(), we are in a Ptrace(), so the lock
 * will be taken out then.
 *
 * This locking function is *global* and applies to all libproc calls, but P and
 * the arg are not global.
 */
typedef	void	ptrace_lock_hook_fun(struct ps_prochandle *P, void *arg,
    int ptracing);

extern	void	Pset_ptrace_lock_hook(ptrace_lock_hook_fun *hook);

/*
 * Like the ptrace_lock_hook, but of inverse sign: used to possibly release
 * locks around long-running blocking waitpid() calls inside Pwait(), while
 * retaining the lock for the remainder of Pwait() (which may trigger
 * breakpoints, invoke other wrapped functions etc).
 */
typedef	void	waitpid_lock_hook_fun(struct ps_prochandle *P, void *arg,
    int waitpidding);

extern	void	Pset_waitpid_lock_hook(waitpid_lock_hook_fun *hook);

/*
 * Register a function that returns the address of a per-thread pointer-sized
 * area suitable for storing a jmp_buf, to be called on exec() to register a
 * chain of setjmp loci to unwind out of libproc.  Must never return NULL (but
 * can return a pointer to NULL to indicate that no rethrowing is needed at this
 * point, even if an exec() is detected).
 *
 * As with the ptrace lock hook, this is global, for the same reason (it must
 * work during Pcreate() and Pgrab()).
 */
typedef	jmp_buf **libproc_unwinder_pad_fun(struct ps_prochandle *P);
extern	void	Pset_libproc_unwinder_pad(libproc_unwinder_pad_fun *unwinder_pad);

/*
 * Breakpoints.
 *
 * This is not a completely safe interface: it cannot handle breakpoints on
 * signal return.
 */
extern	int	Pbkpt(struct ps_prochandle *P, uintptr_t addr, int after_singlestep,
    int (*bkpt_handler)(uintptr_t addr, void *data),
    void (*bkpt_cleanup)(void *data),
    void *data);
extern	int	Pbkpt_notifier(struct ps_prochandle *P, uintptr_t addr, int after_singlestep,
    void (*bkpt_handler)(uintptr_t addr, void *data),
    void (*bkpt_cleanup)(void *data),
    void *data);
extern	void	Punbkpt(struct ps_prochandle *P, uintptr_t address);
extern	int	Pbkpt_continue(struct ps_prochandle *P);
extern 	uintptr_t Pbkpt_addr(struct ps_prochandle *P);

/*
 * Symbol table interfaces.
 */

/*
 * Pseudo-names passed to Plookup_by_name() for well-known load objects.
 */
#define	PR_OBJ_EXEC	((const char *)0)	/* search the executable file */
#define	PR_OBJ_LDSO	((const char *)1)	/* search ld.so */
#define	PR_OBJ_EVERY	((const char *)-1)	/* search every load object */

/*
 * Special Lmid_t passed to Plookup_by_lmid() to search all link maps.  The
 * special values LM_ID_BASE and LM_ID_LDSO from <link.h> may also be used.
 * If PR_OBJ_EXEC is used as the object name, the lmid must be PR_LMID_EVERY
 * or LM_ID_BASE in order to return a match.  If PR_OBJ_LDSO is used as the
 * object name, the lmid must be PR_LMID_EVERY or LM_ID_LDSO to return a match.
 */
#define	PR_LMID_EVERY	((Lmid_t)-1UL)		/* search every link map */

/*
 * 'object_name' is the name of a load object obtained from an
 * an iteration over the process's mapped objects (Pobject_iter),
 * or else it is one of the special PR_OBJ_* values above.
 */
extern int Plookup_by_addr(struct ps_prochandle *, uintptr_t, const char **,
			   GElf_Sym *);

typedef struct prsyminfo {
	const char	*prs_object;		/* object name */
	const char	*prs_name;		/* symbol name */
	Lmid_t		prs_lmid;		/* link map id */
	uint_t		prs_id;			/* symbol id */
	uint_t		prs_table;		/* symbol table id */
} prsyminfo_t;

extern int Pxlookup_by_name(struct ps_prochandle *,
    Lmid_t, const char *, const char *, GElf_Sym *, prsyminfo_t *);

typedef int proc_map_f(void *, const prmap_t *, const char *);

extern int Pobject_iter(struct ps_prochandle *, proc_map_f *, void *);

extern const prmap_t *Paddr_to_map(struct ps_prochandle *, uintptr_t);
extern const prmap_t *Pname_to_map(struct ps_prochandle *, const char *);
extern const prmap_t *Plmid_to_map(struct ps_prochandle *,
    Lmid_t, const char *);
extern const prmap_file_t *Pinode_to_file_map(struct ps_prochandle *,
    dev_t, ino_t);
extern char *Pmap_mapfile_name(struct ps_prochandle *P, const prmap_t *mapp);

extern char *Pobjname(struct ps_prochandle *, uintptr_t, char *, size_t);
extern int Plmid(struct ps_prochandle *, uintptr_t, Lmid_t *);
extern uint64_t Pgetauxval(struct ps_prochandle *P, int type);

/*
 * Symbol table iteration interface.
 */
typedef int proc_sym_f(void *, const GElf_Sym *, const char *);

extern int Psymbol_iter_by_addr(struct ps_prochandle *,
    const char *, int, int, proc_sym_f *, void *);

/*
 * 'which' selects which symbol table and can be one of the following.
 */
#define	PR_SYMTAB	1
#define	PR_DYNSYM	2
/*
 * 'type' selects the symbols of interest by binding and type.  It is a bit-
 * mask of one or more of the following flags, whose order MUST match the
 * order of STB and STT constants in <sys/elf.h>.
 */
#define	BIND_LOCAL	0x0001
#define	BIND_GLOBAL	0x0002
#define	BIND_WEAK	0x0004
#define	BIND_ANY (BIND_LOCAL|BIND_GLOBAL|BIND_WEAK)
#define	TYPE_NOTYPE	0x0100
#define	TYPE_OBJECT	0x0200
#define	TYPE_FUNC	0x0400
#define	TYPE_SECTION	0x0800
#define	TYPE_FILE	0x1000
#define	TYPE_ANY (TYPE_NOTYPE|TYPE_OBJECT|TYPE_FUNC|TYPE_SECTION|TYPE_FILE)

/*
 * This should be called when an RD_DLACTIVITY event with the
 * RD_CONSISTENT state occurs via librtld_db's event mechanism.
 * This makes libproc's address space mappings and symbol tables current.
 * The variant Pupdate_syms() can be used to preload all symbol tables as well.
 */
extern void Pupdate_maps(struct ps_prochandle *);
extern void Pupdate_syms(struct ps_prochandle *);

/*
 * This must be called after the victim process performs a successful
 * exec() if any of the symbol table interface functions have been called
 * prior to that point.  This is essential because an exec() invalidates
 * all previous symbol table and address space mapping information.
 * It is always safe to call, but if it is called other than after an
 * exec() by the victim process it just causes unnecessary overhead.
 *
 * The rtld_db agent handle obtained from a previous call to Prd_agent() is
 * made invalid by Preset_maps() and Prd_agent() must be called again to get
 * the new handle.
 */
extern void Preset_maps(struct ps_prochandle *);

/*
 * Return 1 if this address is within a valid mapping, file-backed mapping, or
 * writable mapping, respectively.
 */
extern int Pvalid_mapping(struct ps_prochandle *P, uintptr_t addr);
extern int Pfile_mapping(struct ps_prochandle *P, uintptr_t addr);
extern int Pwritable_mapping(struct ps_prochandle *P, uintptr_t addr);

extern pid_t Pgetpid(struct ps_prochandle *);

/*
 * Return the librtld_db agent handle for the victim process.
 * The handle will become invalid at the next successful exec() and the
 * client (caller of proc_rd_agent()) must not use it beyond that point.
 * If the process is already dead, there's nothing we can do.
 */
rd_agent_t *Prd_agent(struct ps_prochandle *);

#ifdef	__cplusplus
}
#endif

#endif	/* _LIBPROC_H */