libunwind-nto

QNX SDP8.0C Library ReferenceAPIDeveloper

QNX OS support in the remote unwinder (libunwind)

Syntax:

#include libunwind-nto.h

unw_accessors_t unw_nto_accessors;

void *unw_nto_create(pid_t, pthread_t);

void unw_nto_destroy(void *);

int unw_nto_find_proc_info(unw_addr_space_t, unw_word_t,
                           unw_proc_info_t *, int, void *);

void unw_nto_put_unwind_info(unw_addr_space_t,
                             unw_proc_info_t *, void *);

int unw_nto_get_dyn_info_list_addr(unw_addr_space_t,
                                   unw_word_t *, void *);

int unw_nto_access_mem(unw_addr_space_t, unw_word_t,
                       unw_word_t *, int, void *);

int unw_nto_access_reg(unw_addr_space_t, unw_regnum_t,
                       unw_word_t *, int, void *);

int unw_nto_access_fpreg(unw_addr_space_t, unw_regnum_t,
                         unw_fpreg_t *, int, void *);

int unw_nto_get_proc_name(unw_addr_space_t, unw_word_t,
                          char *, size_t, unw_word_t *, void *);

int unw_nto_resume(unw_addr_space_t, unw_cursor_t *, void *);

Runs on:

QNX

Description:

The QNX operating system allows a process to gain access to the machine state and virtual memory of another process, or to a different thread within the same process. To accommodate this access, the libunwind-nto library connects to another process using callback routines. These callback routines and variables use the unw_nto name prefix, which stands for "unwind via nto."

Using the unw_nto library:

To incorporate the unwind library into your application, use the following steps:
  1. Create a new libunwind address space to represent the target process. To do so, call the unw_create_addr_space() routine, and:
    • If the application passes the address of the unw_nto_accessors code as the first argument, then the target process unwinds properly.
    • If the application uses only portions of the unw_nto library, then use the individual callback routines such as unw_nto_find_proc_info(), or unw_nto_put_unwind_info(). The addresses of these routines get picked up from the unw_nto_accessors command; this prevents static initialization and links the callback routines to the application without having to call them separately.
  2. Locate the ID of the target process (pid). To unwind only one thread at a given time, locate the ID of that thread (tid).
  3. Create a unw_nto-info structure by calling the unw_nto_create() function and passing the pid and tid as the arguments. The application returns an opaque pointer.
    Note:
    By specifying the tid of the target process thread, you ensure that only one thread uses the unw_nto-info structure at any given time, making the unwinding thread-safe.
  4. Call unw_init_remote(), passing the opaque pointer returned by unw_nto_create() as the third argument.
  5. When unwinding is complete, call unw_nto_destroy(), again passing the opaque pointer returned by unw_nto_create() as the argument, to ensure that all memory and other resources are freed up.

Application Programming Interface (API) for libunwind-nto:

unw_nto_create()
Creates a unw_nto-info structure when you pass the pid and tid of the target process thread as the arguments. Doing this stops the target thread.

Returns an opaque pointer. May return NULL if the function fails to create the unw_nto-info structure.

unw_nto_destroy()
Frees up memory and other resources after the application runs the libunwind command on the target process.
unw_nto_resume()
Doesn't perform any action. May be called through unw_resume().

Library:

libc

Use the -l c option to qcc to link against this library. This library is usually included automatically.

Example:

#include <libunwind-nto.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 (&unw_nto_accessors, 0);
    if (!as) {
        fprintf (stderr, "unw_create_addr_space() failed");
        exit (EXIT_FAILURE);
    }
    
    void *ui = unw_nto_create (target_pid, (thread_t)1);
    if (!ui) {
        fprintf (stderr, "unw_nto_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);
    }
    
    unw_nto_destroy (ui);
    unw_destroy_addr_space (as);
    exit (EXIT_SUCCESS);
}
    
Page updated: