mirror of
https://github.com/libunwind/libunwind.git
synced 2026-01-12 00:04:03 +08:00
282 lines
6.6 KiB
Groff
282 lines
6.6 KiB
Groff
.\" *********************************** start of \input{common.tex}
|
|
.\" *********************************** end of \input{common.tex}
|
|
'\" t
|
|
.\" Manual page created with latex2man on Tue Aug 29 10:53:41 2023
|
|
.\" NOTE: This file is generated, DO NOT EDIT.
|
|
.de Vb
|
|
.ft CW
|
|
.nf
|
|
..
|
|
.de Ve
|
|
.ft R
|
|
|
|
.fi
|
|
..
|
|
.TH "LIBUNWIND\-PTRACE" "3libunwind" "29 August 2023" "Programming Library " "Programming Library "
|
|
.SH NAME
|
|
libunwind\-ptrace
|
|
\-\- ptrace() support in libunwind
|
|
.PP
|
|
.SH SYNOPSIS
|
|
|
|
.PP
|
|
#include <libunwind\-ptrace.h>
|
|
.br
|
|
.PP
|
|
unw_accessors_t
|
|
_UPT_accessors;
|
|
.br
|
|
.PP
|
|
void *_UPT_create(pid_t);
|
|
.br
|
|
void _UPT_destroy(void *);
|
|
.br
|
|
.PP
|
|
int _UPT_find_proc_info(unw_addr_space_t,
|
|
unw_word_t,
|
|
unw_proc_info_t *,
|
|
int,
|
|
void *);
|
|
.br
|
|
void _UPT_put_unwind_info(unw_addr_space_t,
|
|
unw_proc_info_t *,
|
|
void *);
|
|
.br
|
|
int _UPT_get_dyn_info_list_addr(unw_addr_space_t,
|
|
unw_word_t *,
|
|
void *);
|
|
.br
|
|
int _UPT_access_mem(unw_addr_space_t,
|
|
unw_word_t,
|
|
unw_word_t *,
|
|
int,
|
|
void *);
|
|
.br
|
|
int _UPT_access_reg(unw_addr_space_t,
|
|
unw_regnum_t,
|
|
unw_word_t *,
|
|
int,
|
|
void *);
|
|
.br
|
|
int _UPT_access_fpreg(unw_addr_space_t,
|
|
unw_regnum_t,
|
|
unw_fpreg_t *,
|
|
int,
|
|
void *);
|
|
.br
|
|
int _UPT_get_proc_name(unw_addr_space_t,
|
|
unw_word_t,
|
|
char *,
|
|
size_t,
|
|
unw_word_t *,
|
|
void *);
|
|
.br
|
|
int _UPT_resume(unw_addr_space_t,
|
|
unw_cursor_t *,
|
|
void *);
|
|
.br
|
|
.PP
|
|
.SH DESCRIPTION
|
|
|
|
.PP
|
|
The ptrace(2)
|
|
system call makes it possible for a process to
|
|
gain access to the machine state and virtual memory of \fIanother\fP
|
|
process. With the right set of callback routines, it is therefore
|
|
possible to hook up libunwind
|
|
to another process via
|
|
ptrace(2).
|
|
While it\&'s not very difficult to do so directly,
|
|
libunwind
|
|
further facilitates this task by providing
|
|
ready\-to\-use callbacks for this purpose. The routines and variables
|
|
implementing this facility use a name prefix of _UPT,
|
|
which is
|
|
stands for ``unwind via ptrace\&''\&.
|
|
.PP
|
|
An application that wants to use the libunwind
|
|
ptrace remote needs to
|
|
take the following steps.
|
|
.PP
|
|
.TP
|
|
1.
|
|
Create a new libunwind address space that represents the target
|
|
process. This is done by calling unw_create_addr_space().
|
|
In
|
|
many cases, the application will simply want to pass the address of
|
|
_UPT_accessors
|
|
as the first argument to this routine. Doing so
|
|
will ensure that libunwind
|
|
will be able to properly unwind the
|
|
target process.
|
|
.PP
|
|
.TP
|
|
2.
|
|
Turn on ptrace mode on the target process, either by forking a new
|
|
process, invoking PTRACE_TRACEME,
|
|
and then starting the target
|
|
program (via execve(2)),
|
|
or by directly attaching to an already
|
|
running process (via PTRACE_ATTACH).
|
|
.PP
|
|
.TP
|
|
3.
|
|
Once the process\-ID (pid) of the target process is known, a
|
|
UPT info structure can be created by calling
|
|
_UPT_create(),
|
|
passing the pid of the target process as the
|
|
only argument.
|
|
.PP
|
|
.TP
|
|
4.
|
|
The opaque pointer returned then needs to be passed as the
|
|
``argument\&'' pointer (third argument) to unw_init_remote().
|
|
.PP
|
|
In special circumstances, an application may prefer to use only
|
|
portions of the libunwind
|
|
ptrace remote. For this reason, the individual
|
|
callback routines (_UPT_find_proc_info(),
|
|
_UPT_put_unwind_info(),
|
|
etc.) are also available for direct use. Of
|
|
course, the addresses of these routines could also be picked up from
|
|
_UPT_accessors,
|
|
but doing so would prevent static initialization. Also,
|
|
when using _UPT_accessors,
|
|
\fIall\fP
|
|
the callback routines will be
|
|
linked into the application, even if they are never actually called.
|
|
.PP
|
|
The _UPT_resume()
|
|
routine can be used to resume execution of the target
|
|
process. It simply invokes ptrace(2)
|
|
with a command value of
|
|
PTRACE_CONT\&.
|
|
.PP
|
|
When the application is done using libunwind
|
|
on the target process,
|
|
_UPT_destroy()
|
|
needs to be called, passing it the opaque pointer that
|
|
was returned by the call to _UPT_create().
|
|
This ensures that all
|
|
memory and other resources are freed up.
|
|
.PP
|
|
.SH AVAILABILITY
|
|
|
|
.PP
|
|
Since ptrace(2)
|
|
works within a single machine only, the libunwind ptrace
|
|
remote by definition is not available in libunwind
|
|
versions configured
|
|
for cross\-unwinding.
|
|
.PP
|
|
.SH THREAD SAFETY
|
|
|
|
.PP
|
|
The libunwind
|
|
ptrace remote assumes that a single UPT info structure is
|
|
never shared between threads. Because of this, no explicit locking is used. As
|
|
long as only one thread uses a UPT info structure at any given time, this
|
|
facility is thread\-safe.
|
|
.PP
|
|
.SH RETURN VALUE
|
|
|
|
.PP
|
|
_UPT_create()
|
|
may return a NULL
|
|
pointer if it fails to create
|
|
the UPT info structure for any reason. For the current implementation, the only
|
|
reason this call may fail is when the system is out of memory.
|
|
.PP
|
|
.SH FILES
|
|
|
|
.PP
|
|
.TP
|
|
libunwind\-ptrace.h
|
|
Header file to include when using the
|
|
interface defined by this library.
|
|
.TP
|
|
\fB\-l\fPunwind\-ptrace \fB\-l\fPunwind\-generic
|
|
Linker switches to add when building a program that uses the
|
|
functions defined by this library.
|
|
.PP
|
|
.SH EXAMPLE
|
|
|
|
.Vb
|
|
#include <libunwind\-ptrace.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
int
|
|
main (int argc, char **argv)
|
|
{
|
|
if (argc != 2) {
|
|
fprintf (stderr, "usage: %s PID\\n", argv[0]);
|
|
exit (EXIT_FAILURE);
|
|
}
|
|
|
|
char *endptr;
|
|
pid_t target_pid = strtoul (argv[1], &endptr, 10);
|
|
if (target_pid == 0 && argv[1] == endptr) {
|
|
fprintf (stderr, "usage: %s PID\\n", argv[0]);
|
|
exit (EXIT_FAILURE);
|
|
}
|
|
|
|
unw_addr_space_t as = unw_create_addr_space (&_UPT_accessors, 0);
|
|
if (!as) {
|
|
fprintf (stderr, "unw_create_addr_space() failed");
|
|
exit (EXIT_FAILURE);
|
|
}
|
|
|
|
void *ui = _UPT_create (target_pid);
|
|
if (!ui) {
|
|
fprintf (stderr, "_UPT_create() failed");
|
|
exit (EXIT_FAILURE);
|
|
}
|
|
|
|
unw_cursor_t cursor;
|
|
int ret = unw_init_remote (&cursor, as, ui);
|
|
if (ret < 0) {
|
|
fprintf (stderr, "unw_init_remote() failed: ret=%d\\n", ret);
|
|
exit (EXIT_FAILURE);
|
|
}
|
|
|
|
do {
|
|
unw_proc_info_t pi;
|
|
ret = unw_get_proc_info (&cursor, &pi);
|
|
if (ret == \-UNW_ENOINFO) {
|
|
fprintf (stdout, "no info\\n");
|
|
} else if (ret >= 0) {
|
|
printf ("\\tproc=%#016lx\-%#016lx\\thandler=%#016lx lsda=%#016lx",
|
|
(long) pi.start_ip, (long) pi.end_ip,
|
|
(long) pi.handler, (long) pi.lsda);
|
|
}
|
|
ret = unw_step (&cursor);
|
|
} while (ret > 0);
|
|
if (ret < 0) {
|
|
fprintf (stderr, "unwind failed with ret=%d\\n", ret);
|
|
exit (EXIT_FAILURE);
|
|
}
|
|
|
|
_UPT_destroy (ui);
|
|
unw_destroy_addr_space (as);
|
|
exit (EXIT_SUCCESS);
|
|
}
|
|
.Ve
|
|
.PP
|
|
.SH SEE ALSO
|
|
|
|
.PP
|
|
execve(2),
|
|
libunwind(3libunwind),
|
|
ptrace(2)
|
|
.PP
|
|
.SH AUTHOR
|
|
|
|
.PP
|
|
David Mosberger\-Tang
|
|
.br
|
|
Email: \fBdmosberger@gmail.com\fP
|
|
.br
|
|
WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
|
|
.\" NOTE: This file is generated, DO NOT EDIT.
|