Skip site navigation (1)Skip section navigation (2)

  
 
  

home | help
LIBUNWIND-PTRACE(3libunwind)  Programming Library   LIBUNWIND-PTRACE(3libunwind)

NAME
     libunwind-ptrace -- ptrace() support in libunwind

SYNOPSIS
     #include <libunwind-ptrace.h>

     unw_accessors_t _UPT_accessors;

     void *_UPT_create(pid_t);
     void _UPT_destroy(void *);

     int  _UPT_find_proc_info(unw_addr_space_t,  unw_word_t,  unw_proc_info_t *,
     int, void *);
     void _UPT_put_unwind_info(unw_addr_space_t, unw_proc_info_t *, void *);
     int _UPT_get_dyn_info_list_addr(unw_addr_space_t, unw_word_t *, void *);
     int _UPT_access_mem(unw_addr_space_t, unw_word_t, unw_word_t *,  int,  void
     *);
     int _UPT_access_reg(unw_addr_space_t, unw_regnum_t, unw_word_t *, int, void
     *);
     int  _UPT_access_fpreg(unw_addr_space_t,  unw_regnum_t, unw_fpreg_t *, int,
     void *);
     int  _UPT_get_proc_name(unw_addr_space_t,	unw_word_t,  char   *,	 size_t,
     unw_word_t *, void *);
     int _UPT_resume(unw_addr_space_t, unw_cursor_t *, void *);

DESCRIPTION
     The ptrace(2) system call makes it possible for a process to gain access to
     the machine state and virtual memory of another process. With the right set
     of  callback routines, it is therefore possible to hook up libunwind to an-
     other process via ptrace(2).  While it's not very difficult to  do  so  di-
     rectly,  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''.

     An application that wants to use the libunwind ptrace remote needs to  take
     the folowing steps.

     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.

     2.     Turn on ptrace mode on the target process, either by forking  a  new
	    process,  invoking PTRACE_TRACEME, and then starting the target pro-
	    gram (via execve(2)), or by directly attaching to an already running
	    process (via PTRACE_ATTACH).

     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.

     4.     The  opaque  pointer returned then needs to be passed as the ``argu-
	    ment'' pointer (third argument) to unw_init_remote().

     In special circumstances, an application may prefer to use only portions of
     the libunwind ptrace remote. For this reason, the individual callback  rou-
     tines (_UPT_find_proc_info(), _UPT_put_unwind_info(), etc.) are also avail-
     able  for direct use. Of course, the addresses of these routines could also
     be picked up from _UPT_accessors, but doing so would  prevent  static  ini-
     tialization.  Also,  when	using  _UPT_accessors, all the callback routines
     will be linked into the  application,  even  if  they  are  never	actually
     called.

     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.

     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.

AVAILABILITY
     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.

THREAD SAFETY
     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.

RETURN VALUE
     _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.

FILES
     libunwind-ptrace.h
	     Header file to include when using the interface defined by this li-
	    brary.

     -lunwind-ptrace -lunwind-generic
	     Linker  switches to add when building a program that uses the func-
	    tions defined by this library.

EXAMPLE
	 #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);
	 }

SEE ALSO
     execve(2), libunwind(3libunwind), ptrace(2)

AUTHOR
     David Mosberger-Tang
     Email: dmosberger@gmail.com
     WWW: http://www.nongnu.org/libunwind/.

Programming Library		 29 August 2023     LIBUNWIND-PTRACE(3libunwind)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=libunwind-ptrace&sektion=3&manpath=FreeBSD+Ports+15.1.quarterly>

home | help