Title and Contents

Appendixes

Appendix 1—Debugger Variables

The debugger has the following predefined variables. Conventionally, a Ladebug debugger variable name is an identifier with a leading dollar sign ($).

Variable
Default Setting
Description
$ascii
1
Prints ASCII or all ISO Latin-1.
$beep
1
Beeps on illegal command line editing.
$catchexecs
0
Stops execution on program exec.
$catchforkinfork
0
Notifies you as soon as the forked process is created (otherwise you are notified when the call finishes).
$catchforks
0
Notifies you on program fork and stops child.
$childprocess
0
When the debugger detects a fork, it assigns the child process ID to $childprocess.
$curevent
0
Displays the current breakpoint number.
$curfile
(null)
Displays the current source file.
$curfilepath
(null)
Displays the current source file access path.
$curline
0
Displays the current source line.
$curpc
0
Displays the current point of program execution.
$curprocess
0
Displays the current process ID.
$cursrcline
0
Displays the last source line at end of most recent source listing.
$cursrcpc
0
Displays the PC address at end of most recent machine code listing.
$curthread
0
Displays the current thread ID.
$dbxoutputformat
0
Displays various data structures in dbx format.
$dbxuse
0
Replaces current use paths.
$decints
0
Displays integers in decimal radix.
$doverbosehelp
1
Displays the help menu front page.
$editline
1
Enables command line editing.
$eventecho
1
Echoes events with event numbers.
$exitonterminationofprocesswithpid
None
If set to process ID (pid), when that process terminates, the debugger exits.
$funcsig
1
Displays function signature at breakpoint.
$giveladebughints
1
Displays hints on Ladebug features.
$hasmeta
0
Interprets multibyte characters.
$hexints
0
Displays integers in hex radix.
$historylines
20
Defines the number of commands to show for history.
$indent
1
Prints structures with indentation.
$kdebug_host
localhost
Specifies the node name of the gateway system. The default "localhost" indicates no gateway system.
$kdebug_line
kdebug
Specifies the label of the /etc/remote entry on the gateway system for the kdebug communication port.
$kdebug_dbgtty
(null)
Specifies the pathname of the terminal window (output from tty (1)) on the gateway system used to display kdebug communication traffic. The default (null) indicates no gateway system.
$lang
"None"
Defines the programming language of current routine.
$lasteventmade
0
Displays the number of last (successful) breakpoint definition.
$lc_ctype
"C"
Displays the current locale information.
$listwindow
20
Displays the number of lines to show for list.
$main
"main"
Displays the name of the first routine in the program.
$maxstrlen
128
Defines the largest string to print fully.
$octints
0
Displays integers in octal radix.
$overloadmenu
1
Prompts for choice of overloaded C++ name.
$page
1
Paginates debugger terminal output.
$pagewindow
0
Defines the number of lines per output page.
$parentprocess
0
When the debugger detects a fork, it assigns the parent process ID to $parentprocess.
$pimode
0
Echoes input to log file on playback input.
$prompt
"(ladebug) "
Specifies debugger prompt.
$readtextfile
0
If set to non-zero, instructions are read from the text area of the binary file rather than from the memory image.
$regstyle
1
Controls the format of register names during disassembly. Valid settings are:
  • 0 = compiler names, for example, t0, ra, or zero.
  • 1 = hardware names, for example, r1, r26, or r31.
  • 2 = assembly names, for example, $1, $26, or $31.
$repeatmode
1
Repeats previous command when you press the Return key.
$showlineonstartup
0
Displays the first executable line in main.
$showwelcomemsg
1
Displays welcome message at startup time.
$stackargs
1
Shows arguments in the call stack if 1.
$statusargs
1
Prints breakpoints with parameters if 1.
$stepg0
0
Steps over routines with minimal symbols.
$stoponattach
0
Stops the running process on attach.
$stopparentonfork
0
Stops parent process execution on fork. When set to a nonzero value, this variable instructs the debugger to stop the parent process after it forks a child process. The child process continues to run if $catchforks is not set, otherwise stops. The default is 0.
$threadlevel
decthreads
Specifies POSIX threads (DECthreads) or native threads.
$usedynamictypes
1
Evaluates using C++ static or dynamic type.
$verbose
0
Produces even more output.



Appendix 2—Debugger Aliases

The debugger has the following predefined aliases:

Appendix 3—corefile_listobj.c Example

You can use the following example as an alternative to the listobj command for cases in which the debugger cannot be run on the original system. See the Transporting Core Files section for more information.
/*
  cc corefile_listobj.c -lxproc -o corefile_listobj
 */


#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>

#include <errno.h>

typedef unsigned long vma_t;

/* core file format */

#include <sys/user.h>
#include <sys/core.h>

/* dynamic loader hookup */

#include <loader.h>
typedef int (*ldr_reader_func)(vma_t from,
                               void * to,
                               long nbytes,
                               int is_string);
extern pid_t ldr_core_process();
extern int ldr_set_core_reader(ldr_reader_func reader);

/********************************************************************/

static FILE *                   corefile;
static struct core_filehdr      corehdr;
static int                      nsections;
static struct core_scnhdr *     section_headers;

int
open_corefile(const char * corename)
{
  size_t nread;

  corefile = fopen(corename, "rb");
  if (!corefile) {
    perror("Opening corefile");
    return -1;
  }
  nread = fread(&corehdr, sizeof(corehdr), 1, corefile);
  if (nread != 1) {
    perror("fread() of corefile header");
    return -1;
  }
  if (strncmp(corehdr.magic, "Core", 4) != 0) {
    fprintf(stderr, "Corefile header magic is not \"Core\"\n");
    return -1;
  }
  nsections = corehdr.nscns;
  section_headers = calloc(nsections, sizeof(section_headers[0]));
  if (!section_headers) {
    perror("Allocating corefile section headers");
    return -1;
  }
  nread = fread(section_headers, sizeof(section_headers[0]),
                nsections, corefile);
  if (nread != nsections) {
    perror("fread() of corefile section headers");
    return -1;
  }

  return 0;
}

static int
section_type_has_memory(int type)
{
  switch (type) {
  case SCNTEXT: case SCNDATA: case SCNRGN: case SCNSTACK:
    return 1;
  case SCNREGS: case SCNOVFL:
  default:
    return 0;
  }
}

static int
read_from_corefile(vma_t from,
                   void * to,
                   long nbytes,
                   int is_string)
{
  vma_t getter = from;
  char * putter = (char *) to;
  long to_go = nbytes;
  int secnum;
  size_t nxfer;

try_for_more:
  while (to_go > 0) {
    for (secnum = 0; secnum < nsections; secnum += 1) {
      if (section_type_has_memory(section_headers[secnum].scntype)) {
        vma_t vaddr = (vma_t) section_headers[secnum].vaddr;
        vma_t size  = (vma_t) section_headers[secnum].size;
        if (vaddr <= getter && getter < vaddr+size) {
          vma_t this_time = (size < to_go ? size : to_go);
          long file_offset = section_headers[secnum].scnptr+(getter-vaddr);
          if (fseek(corefile, file_offset, SEEK_SET) != 0) {
            perror("fseek() for corefile read");
            return -1;
          }
          nxfer = fread(putter, 1, this_time, corefile);
          if (nxfer != this_time) {
            perror("fread() of corefile data ");
            return -1;
          }
          to_go -= this_time;
          getter += this_time;
          putter += this_time;
          goto try_for_more;
        }
      }
    }
    fprintf("Couldn't find core address for %#lx\n", getter);
    return -1;
  }
  return 0;
}

int
main(int argc, char* argv[])
{
  pid_t process;

  if (argc != 2) {
    fprintf(stderr, "Usage is %s \n", argv[0]);
    return 1;
  }
  if (open_corefile(argv[1]) < 0)
    return -1;

  process = ldr_core_process();
  ldr_set_core_reader(read_from_corefile);

  if (ldr_xattach(process) < 0) {
    perror("Attaching to corefile");
    return 1;
  } else {
    ldr_module_t mod_id = LDR_NULL_MODULE;
    ldr_module_info_t info;
    size_t ret_size;
    while (1) {
      if (ldr_next_module(process, &mod_id) < 0) {
        perror("ldr_next_module");
        return 1;
      }
      if (mod_id == LDR_NULL_MODULE)
        break;
      if (ldr_inq_module(process, mod_id, &info,
                         sizeof(info), &ret_size) < 0) {
        perror("ldr_inq_module");
        return 1;
      }
      printf("%s\n", info.lmi_name);
    }
    ldr_xdetach(process);
    return 0;
  }
}

Appendix 4—Array Navigation Example

The debugger provides parameterized aliases and debugger variables of arbitrary types. Clever use of these can do almost any list traversal.

For example, here is how to navigate an array:

alias elt(e_) "{ p e_ }"
alias pa0(a)  "{ set $a = &a[0]; set $i = 0; elt($a[$i]); set $i = $i+1 }"
alias pan     "{ elt($a[$i]); set $i = $i+1 }"
pa0
pan
pan
pan

%ladebug a.out
...
(ladebug) alias elt(e_) "{ p e_ }"
(ladebug) alias a0(a)   "{ set $a = &a[0]; set $i = 0; elt($a[$i]); set $i = $i+1 }"
(ladebug) alias pan     "{ elt($a[$i]); set $i = $i+1 }"
...
(ladebug) pa0(a)
struct S {
  next = 0x140000178;
}
(ladebug) pan
struct S {
  next = 0x140000180;
}
(ladebug)
struct S {
  next = 0x140000188;
}
(ladebug)
struct S {
  next = 0x140000190;
}