1tnfctl_pid_open(3TNF)        TNF Library Functions       tnfctl_pid_open(3TNF)
2
3
4

NAME

6       tnfctl_pid_open,  tnfctl_exec_open,  tnfctl_continue  -  interfaces for
7       direct probe and process control for another process
8

SYNOPSIS

10       cc [ flag ... ] file ... -ltnfctl [ library ... ]
11       #include <tnf/tnfctl.h>
12
13       tnfctl_errcode_t tnfctl_pid_open(pid_t pid, tnfctl_handle_t **ret_val);
14
15
16       tnfctl_errcode_t tnfctl_exec_open(const char *pgm_name,
17            char * const *argv, char * const *envp,
18            const char *libnfprobe_path, const char *ld_preload,
19            tnfctl_handle_t **ret_val);
20
21
22       tnfctl_errcode_t tnfctl_continue(tnfctl_handle_t *hndl,
23            tnfctl_event_t *evt, tnfctl_handle_t **child_hndl);
24
25

DESCRIPTION

27       The tnfctl_pid_open(), tnfctl_exec_open(), and tnfctl_continue()  func‐
28       tions  create  handles  to  control  probes in another  process (direct
29       process probe control). Either tnfctl_pid_open() or  tnfctl_exec_open()
30       will  return a handle in ret_val that can be used for probe control. On
31       return of these calls, the process is stopped. tnfctl_continue() allows
32       the process specified by hndl to continue execution.
33
34
35       The  tnfctl_pid_open()  function  attaches  to  a  running process with
36       process id of  pid. The process is stopped on return of this call.  The
37       tnfctl_pid_open()  function returns an error message if pid is the same
38       as the calling process. See tnfctl_internal_open(3TNF) for  information
39       on  internal  process  probe  control. A pointer to an opaque handle is
40       returned in  ret_val, which can be used to control the process and  the
41       probes  in  the process. The target process must have  libtnfprobe.so.1
42       (defined in <tnf/tnfctl.h> as macro TNFCTL_LIBTNFPROBE) linked  in  for
43       probe control to work.
44
45
46       The tnfctl_exec_open() function is used to exec(2) a program and obtain
47       a probe control handle. For probe control to work, the process image to
48       be   exec'd must load libtnfprobe.so.1. The tnfctl_exec_open() function
49       makes it simple for the library to be loaded at process start up  time.
50       The  pgm_name  argument  is  the command to exec. If pgm_name is not an
51       absolute path, then the  $PATH environment variable is used to find the
52       pgm_name.  argv is a null-terminated argument pointer, that is, it is a
53       null-terminated array of pointers  to  null-terminated  strings.  These
54       strings  constitute  the  argument  list   available to the new process
55       image. The argv argument must have at least one member, and  it  should
56       point to a string that is the same as pgm_name. See execve(2). The lib‐
57       nfprobe_path argument is an optional argument, and if set, it should be
58       the  path  to the directory that contains libtnfprobe.so.1. There is no
59       need for a trailing "/" in this argument.  This argument is  useful  if
60       libtnfprobe.so.1  is not installed in  /usr/lib. ld_preload is a space-
61       separated list of libraries to preload into the  target  program.  This
62       string  should  follow the syntax guidelines of the LD_PRELOAD environ‐
63       ment variable.  See ld.so.1(1). The following illustrates  how  strings
64       are concatenated to form the LD_PRELOAD environment variable in the new
65       process image:
66
67         <current value of $LD_PRELOAD> + <space> +
68         libtnfprobe_path + "/libtnfprobe.so.1" +<space> +
69         ld_preload
70
71
72
73       This option is useful for preloading interposition libraries that  have
74       probes in them.
75
76
77       envp  is  an optional argument, and if set, it is used for the environ‐
78       ment of the target program.  It is a null-terminated array of  pointers
79       to   null-terminated  strings. These strings constitute the environment
80       of the new process image. See execve(2). If envp is set,  it  overrides
81       ld_preload.  In  this case, it is the caller's responsibility to ensure
82       that  libtnfprobe.so.1 is loaded into the target program.  If  envp  is
83       not set, the new process image inherits the environment of the  calling
84       process, except for LD_PRELOAD.
85
86
87       The ret_val argument is the handle that can  be  used  to  control  the
88       process and the probes within the process.  Upon return, the process is
89       stopped before any user code, including .init sections, has  been  exe‐
90       cuted.
91
92
93       The  tnfctl_continue()  function is a blocking call and lets the target
94       process referenced by hndl continue running.  It can only  be  used  on
95       handles  returned  by  tnfctl_pid_open() and tnfctl_exec_open() (direct
96       process probe control). It returns when the target  stops;  the  reason
97       that  the  process stopped  is returned in evt. This call is interrupt‐
98       ible by signals.  If it is interrupted, the  process  is  stopped,  and
99       TNFCTL_EVENT_EINTR  is returned in evt. The client of this library will
100       have to decide which signal implies a  stop to  the  target  and  catch
101       that  signal.  Since  a  signal  interrupts  tnfctl_continue(), it will
102       return, and the caller can decide whether or not  to  call  tnfctl_con‐
103       tinue() again.
104
105
106       tnfctl_continue()   returns   with  an  event  of  TNFCTL_EVENT_DLOPEN,
107       TNFCTL_EVENT_DLCLOSE,       TNFCTL_EVENT_EXEC,       TNFCTL_EVENT_FORK,
108       TNFCTL_EVENT_EXIT,  or  TNFCTL_EVENT_TARGGONE,  respectively,  when the
109       target program calls dlopen(3C), dlclose(3C), any flavor  of   exec(2),
110       fork(2) (or fork1(2)), exit(2), or terminates unexpectedly. If the tar‐
111       get  program  called  exec(2),  the   client   then   needs   to   call
112       tnfctl_close(3TNF)  on  the  current handle leaving the target resumed,
113       suspended, or killed (second argument to  tnfctl_close(3TNF)). No other
114       libtnfctl  interface  call  can  be used on the existing handle. If the
115       client wants to control the exec'ed image, it should leave the old han‐
116       dle  suspended,  and  use  tnfctl_pid_open()  to  reattach  to the same
117       process.  This new handle can then  be  used  to  control  the  exec'ed
118       image.   See EXAMPLES below for sample code.  If the target process did
119       a  fork(2) or fork1(2), and if control of  the  child  process  is  not
120       needed,  then  child_hndl  should  be   NULL.  If  control of the child
121       process is needed, then child_hndl should be set.   If  it  is  set,  a
122       pointer  to  a  handle that can be used to control the child process is
123       returned in child_hndl. The child process is stopped at the end of  the
124       fork() system call. See EXAMPLES for an example of this event.
125

RETURN VALUES

127       The tnfctl_pid_open(), tnfctl_exec_open(), and  tnfctl_continue() func‐
128       tions return TNFCTL_ERR_NONE upon success.
129

ERRORS

131       The following error codes apply to tnfctl_pid_open():
132
133       TNFCTL_ERR_BADARG           The  pid specified  is  the  same  process.
134                                   Use tnfctl_internal_open(3TNF) instead.
135
136
137       TNFCTL_ERR_ACCES            Permission  denied. No privilege to connect
138                                   to a setuid  process.
139
140
141       TNFCTL_ERR_ALLOCFAIL        A memory allocation failure occurred.
142
143
144       TNFCTL_ERR_BUSY             Another client is already using   /proc  to
145                                   control this process or internal tracing is
146                                   being used.
147
148
149       TNFCTL_ERR_NOTDYNAMIC       The process is not a dynamic executable.
150
151
152       TNFCTL_ERR_NOPROCESS        No such target process exists.
153
154
155       TNFCTL_ERR_NOLIBTNFPROBE    libtnfprobe.so.1 is not linked in the  tar‐
156                                   get process.
157
158
159       TNFCTL_ERR_INTERNAL         An internal error occurred.
160
161
162
163       The following error codes apply to  tnfctl_exec_open():
164
165       TNFCTL_ERR_ACCES            Permission denied.
166
167
168       TNFCTL_ERR_ALLOCFAIL        A memory allocation failure occurred.
169
170
171       TNFCTL_ERR_NOTDYNAMIC       The target is not a dynamic executable.
172
173
174       TNFCTL_ERR_NOLIBTNFPROBE    libtnfprobe.so.1  is not linked in the tar‐
175                                   get process.
176
177
178       TNFCTL_ERR_FILENOTFOUND     The program is not found.
179
180
181       TNFCTL_ERR_INTERNAL         An internal error occurred.
182
183
184
185       The following error codes apply to  tnfctl_continue():
186
187       TNFCTL_ERR_BADARG       Bad  input  argument.  hndl  is  not  a  direct
188                               process probe control handle.
189
190
191       TNFCTL_ERR_INTERNAL     An internal error occurred.
192
193
194       TNFCTL_ERR_NOPROCESS    No such target process exists.
195
196

EXAMPLES

198       Example 1 Using tnfctl_pid_open()
199
200
201       These  examples  do not include any error-handling code.  Only the ini‐
202       tial  example includes the declaration of the variables that  are  used
203       in all  of the examples.
204
205
206
207       The  following  example shows how to preload  libtnfprobe.so.1 from the
208       normal location and inherit the parent's environment.
209
210
211         const char        *pgm;
212         char * const      *argv;
213         tnfctl_handle_t   *hndl, *new_hndl, *child_hndl;
214         tnfctl_errcode_t  err;
215         char * const      *envptr;
216         extern char       **environ;
217         tnfctl_event_t    evt;
218         int               pid;
219
220         /* assuming argv has been allocated */
221         argv[0] = pgm;
222         /* set up rest of argument vector here */
223         err = tnfctl_exec_open(pgm, argv, NULL, NULL, NULL, &hndl);
224
225
226
227       This  example  shows  how  to  preload  two   user-supplied   libraries
228       libc_probe.so.1  and libthread_probe.so.1. They interpose on the corre‐
229       sponding libc.so and libthread.so interfaces and have probes for  func‐
230       tion  entry  and  exit.  libtnfprobe.so.1  is preloaded from the normal
231       location and the parent's environment is inherited.
232
233
234         /* assuming argv has been allocated */
235         argv[0] = pgm;
236         /* set up rest of argument vector here */
237         err = tnfctl_exec_open(pgm, argv, NULL, NULL,
238               "libc_probe.so.1 libthread_probe.so.1", &hndl);
239
240
241
242       This example preloads an  interposition  library  libc_probe.so.1,  and
243       specifies a different location from which to preload libtnfprobe.so.1.
244
245
246         /* assuming argv has been allocated */
247         argv[0] = pgm;
248         /* set up rest of argument vector here */
249         err = tnfctl_exec_open(pgm, argv, NULL, "/opt/SUNWXXX/lib",
250               "libc_probe.so.1", &hndl);
251
252
253
254       To  set  up  the  environment explicitly for probe control to work, the
255       target process must link  libtnfprobe.so.1. If using  envp, it  is  the
256       caller's responsibility to do so.
257
258
259         /* assuming argv has been allocated */
260         argv[0] = pgm;
261         /* set up rest of argument vector here */
262         /* envptr set up to caller's needs */
263         err = tnfctl_exec_open(pgm, argv, envptr, NULL, NULL, &hndl);
264
265
266
267       Use this example to resume a process that does an  exec(2) without con‐
268       trolling it.
269
270
271         err = tnfctl_continue(hndl, &evt, NULL);
272         switch (evt) {
273         case TNFCTL_EVENT_EXEC:
274              /* let target process continue without control */
275              err = tnfctl_close(hndl, TNFCTL_TARG_RESUME);
276              ...
277              break;
278         }
279
280
281
282       Alternatively, use the next example to control a process that  does  an
283       exec(2).
284
285
286         /*
287          * assume the pid variable has been set by calling
288          * tnfctl_trace_attrs_get()
289         */
290         err = tnfctl_continue(hndl, &evt, NULL);
291         switch (evt) {
292         case TNFCTL_EVENT_EXEC:
293              /* suspend the target process */
294              err = tnfctl_close(hndl, TNFCTL_TARG_SUSPEND);
295              /* re-open the exec'ed image */
296              err = tnfctl_pid_open(pid, &new_hndl);
297              /* new_hndl now controls the exec'ed image */
298              ...
299              break;
300         }
301
302
303
304       To let  fork'ed children continue without control, use NULL as the last
305       argument to tnfctl_continue().
306
307
308         err = tnfctl_continue(hndl, &evt, NULL);
309
310
311
312       The next example is how to control  child  processes  that  fork(2)  or
313       fork1(2) create.
314
315
316         err = tnfctl_continue(hndl, &evt, &child_hndl);
317         switch (evt) {
318         case TNFCTL_EVENT_FORK:
319              /* spawn a new thread or process to control child_hndl */
320              ...
321              break;
322         }
323
324

ATTRIBUTES

326       See attributes(5) for descriptions of the following attributes:
327
328
329
330
331       ┌─────────────────────────────┬─────────────────────────────┐
332       │      ATTRIBUTE TYPE         │      ATTRIBUTE VALUE        │
333       ├─────────────────────────────┼─────────────────────────────┤
334       │Availability                 │SUNWtnfc                     │
335       ├─────────────────────────────┼─────────────────────────────┤
336       │MT Level                     │MT-Safe                      │
337       └─────────────────────────────┴─────────────────────────────┘
338

SEE ALSO

340       ld(1),   prex(1),   proc(1),   exec(2),  execve(2),  exit(2),  fork(2),
341       TNF_PROBE(3TNF),     dlclose(3C),     dlopen(3C),      libtnfctl(3TNF),
342       tnfctl_close(3TNF),      tnfctl_internal_open(3TNF),      tracing(3TNF)
343       attributes(5)
344
345
346       Linker and Libraries Guide
347

NOTES

349       After  a  call  to  tnfctl_continue()  returns,  a  client  should  use
350       tnfctl_trace_attrs_get(3TNF) to check the trace_buf_state member of the
351       trace attributes and make sure that there is no internal error  in  the
352       target.
353
354
355
356SunOS 5.11                        1 Mar 2004             tnfctl_pid_open(3TNF)
Impressum