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 <corefile>\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;

  }

}