示例#1
0
文件: stack.c 项目: mmilata/seecore
struct thread* unwind_stacks(Dwfl *dwfl, const char *core_file,
                             struct exec_map *em,
                             struct expr_context *ctx)
{
    unw_addr_space_t as;
    struct UCD_info *ui;
    struct thread *head = NULL, *tail = NULL;

    as = unw_create_addr_space(&_UCD_accessors, 0);
    fail_if(!as, "unw_create_addr_space");

    ui = _UCD_create(core_file);
    fail_if(!ui, "_UCD_create");

    for (; em != NULL; em = em->next)
    {
        if (_UCD_add_backing_file_at_vaddr(ui, em->vaddr, em->file) < 0)
        {
            fail("_UCD_add_backing_file_at_vaddr");
        }
    }

    int tnum;
    int nthreads = _UCD_get_num_threads(ui);
    for (tnum = 0; tnum < nthreads; tnum++)
    {
        struct thread *thread = xalloc(sizeof(struct thread));
        thread->frames = unwind_thread(dwfl, as, ui, tnum, ctx);
        list_append(head, tail, thread);
    }

    return head;
}
示例#2
0
int
main(int argc UNUSED, char **argv)
{
  unw_addr_space_t as;
  struct UCD_info *ui;
  unw_cursor_t c;
  int ret;

#define TEST_FRAMES 4
#define TEST_NAME_LEN 32
  int testcase = 0;
  int test_cur = 0;
  long test_start_ips[TEST_FRAMES];
  char test_names[TEST_FRAMES][TEST_NAME_LEN];

  install_sigsegv_handler();

  const char *progname = strrchr(argv[0], '/');
  if (progname)
    progname++;
  else
    progname = argv[0];

  if (!argv[1])
    error_msg_and_die("Usage: %s COREDUMP [VADDR:BINARY_FILE]...", progname);

  msg_prefix = progname;

  as = unw_create_addr_space(&_UCD_accessors, 0);
  if (!as)
    error_msg_and_die("unw_create_addr_space() failed");

  ui = _UCD_create(argv[1]);
  if (!ui)
    error_msg_and_die("_UCD_create('%s') failed", argv[1]);
  ret = unw_init_remote(&c, as, ui);
  if (ret < 0)
    error_msg_and_die("unw_init_remote() failed: ret=%d\n", ret);

  argv += 2;

  /* Enable checks for the crasher test program? */
  if (*argv && !strcmp(*argv, "-testcase"))
  {
    testcase = 1;
    logmode = LOGMODE_NONE;
    argv++;
  }

  while (*argv)
    {
      char *colon;
      unsigned long vaddr = strtoul(*argv, &colon, 16);
      if (*colon != ':')
        error_msg_and_die("Bad format: '%s'", *argv);
      if (_UCD_add_backing_file_at_vaddr(ui, vaddr, colon + 1) < 0)
        error_msg_and_die("Can't add backing file '%s'", colon + 1);
      argv++;
    }

  for (;;)
    {
      unw_word_t ip;
      ret = unw_get_reg(&c, UNW_REG_IP, &ip);
      if (ret < 0)
        error_msg_and_die("unw_get_reg(UNW_REG_IP) failed: ret=%d\n", ret);

      unw_proc_info_t pi;
      ret = unw_get_proc_info(&c, &pi);
      if (ret < 0)
        error_msg_and_die("unw_get_proc_info(ip=0x%lx) failed: ret=%d\n", (long) ip, ret);

      if (!testcase)
        printf("\tip=0x%08lx proc=%08lx-%08lx handler=0x%08lx lsda=0x%08lx\n",
				(long) ip,
				(long) pi.start_ip, (long) pi.end_ip,
				(long) pi.handler, (long) pi.lsda);

      if (testcase && test_cur < TEST_FRAMES)
        {
           unw_word_t off;

           test_start_ips[test_cur] = (long) pi.start_ip;
           if (unw_get_proc_name(&c, test_names[test_cur], sizeof(test_names[0]), &off) != 0)
           {
             test_names[test_cur][0] = '\0';
           }
           test_cur++;
        }

      log("step");
      ret = unw_step(&c);
      log("step done:%d", ret);
      if (ret < 0)
    	error_msg_and_die("FAILURE: unw_step() returned %d", ret);
      if (ret == 0)
        break;
    }
  log("stepping ended");

  /* Check that the second and third frames are equal, but distinct of the
   * others */
  if (testcase &&
       (test_cur != 4
       || test_start_ips[1] != test_start_ips[2]
       || test_start_ips[0] == test_start_ips[1]
       || test_start_ips[2] == test_start_ips[3]
       )
     )
    {
      fprintf(stderr, "FAILURE: start IPs incorrect\n");
      return -1;
    }

  if (testcase &&
       (  strcmp(test_names[0], "a")
       || strcmp(test_names[1], "b")
       || strcmp(test_names[2], "b")
       || strcmp(test_names[3], "main")
       )
     )
    {
      fprintf(stderr, "FAILURE: procedure names are missing/incorrect\n");
      return -1;
    }

  _UCD_destroy(ui);
  unw_destroy_addr_space(as);

  return 0;
}
示例#3
0
static int
read_elfnotes(char *corefilename, struct UCD_info *ui)
{

  FILE *fp = NULL;
  struct stat stbuf;
  elf64_header header;
  elf64_phdr *program_headers = NULL;
  unsigned char *notes = NULL;
  int i;
  size_t ret;
  elfnote *note;
  unsigned char *end=NULL, *curr=NULL;
  unsigned char *filenames = NULL, *descend = NULL , *previous_filenames = NULL;
  uint64_t count;
  int retval = -1;

  if (stat(corefilename, &stbuf) < 0 ) {
    goto func_exit;
  }
  if (!S_ISREG(stbuf.st_mode)) {
    goto func_exit;
  }

  fp = fopen(corefilename, "r");
  if (fp == NULL) {
    goto func_exit;
  }
  memset(&header, 0, sizeof(header));

  if (fread(&header, sizeof(header), 1, fp)!= 1) {
    goto func_exit;
  }

  if (header.ident[0]  !=0x7f ||header.ident[1]!='E'
      ||header.ident[2]!='L'  ||header.ident[3] !='F')
  {
    goto func_exit;
  }
  if ((header.ident[5] == 2)  || (header.ident[4] != 2)
      || (header.phnum == 0 ) || (header.phentsize != sizeof(elf64_phdr))) {
    goto func_exit;
  }

  program_headers = malloc(sizeof(elf64_phdr)*header.phnum);
  if (program_headers == NULL) {
    goto func_exit;
  }

  if (fseek(fp,(long)header.phoff,SEEK_SET) == -1) {
    goto func_exit;
  }

  if (fread(program_headers, sizeof(elf64_phdr), header.phnum, fp) !=  header.phnum) {
    goto func_exit;
  }


  for (i=0; i< header.phnum; i++) {
    if (program_headers[i].type != 4) continue;

    retval = fseek(fp,(long) program_headers[i].offset, SEEK_SET);
    if (retval == -1) {
      goto func_exit;
    }
    notes = malloc(program_headers[i].filesz);
    if (notes == NULL) {
      goto func_exit;
    }

    ret = fread(notes, 1, program_headers[i].filesz, fp);
    if (ret !=  program_headers[i].filesz ) {
      goto func_exit;
    }
    end = notes + program_headers[i].filesz;
    curr = notes;
    while (curr <  end) {
      unsigned char *descdata;
      note =  (elfnote*) curr;
      descdata = (unsigned char *) note->name + addr_align (note->namesz);

      if (note->type != NT_FILE) {
        curr = (unsigned char *) (descdata + addr_align (note->descsz));
        continue;
      }

      if (note->descsz < 16)  goto func_exit;
      descend = descdata + note->descsz;
      if (descdata[note->descsz - 1] != '\0') goto func_exit;

      count =  *((uint64_t *)descdata);
      descdata += 8;

      descdata += 8;

      if (note->descsz < 16 + count * 24 ) goto func_exit;

      filenames = descdata + count * 3 * 8;
      while (count-- > 0)
      {
        uint64_t start;

        if (filenames == descend) goto func_exit;

        start =  *((uint64_t*)descdata);
        descdata += 8;
        descdata += 8;
        descdata += 8;

        if (filenames && previous_filenames && !strcmp((char*)filenames,(char*)previous_filenames)) {
           previous_filenames = filenames;
           filenames += 1 + strlen ((char *) filenames);
           continue;
        }

        if (_UCD_add_backing_file_at_vaddr(ui, (long)start, (char *)filenames) < 0) {
//        fprintf(stderr, "_UCD_add_backing_file_at_vaddr FAILED %" PRId64 " %s\n", start, filenames);
        }
        previous_filenames = filenames;
        filenames += 1 + strlen ((char *) filenames);
      }
      
      curr = (unsigned char *) (descdata + addr_align (note->descsz));
    }
    if (notes) free(notes);
    notes = NULL;
  }
  retval = 0;

func_exit:
  if (fp) fclose(fp);
  if (program_headers) free(program_headers);
  if (notes) free(notes);
  return(retval);
}
示例#4
0
struct sr_core_stacktrace *
sr_parse_coredump(const char *core_file,
                   const char *exe_file,
                   char **error_msg)
{
    struct sr_core_stacktrace *stacktrace = NULL;

    /* Initialize error_msg to 'no error'. */
    if (error_msg)
        *error_msg = NULL;

    struct core_handle *ch = open_coredump(core_file, exe_file, error_msg);
    if (*error_msg)
        return NULL;

    unw_addr_space_t as;
    struct UCD_info *ui;
    as = unw_create_addr_space(&_UCD_accessors, 0);
    if (!as)
    {
        set_error("Failed to create address space");
        goto fail_destroy_handle;
    }

    ui = _UCD_create(core_file);
    if (!ui)
    {
        set_error("Failed to set up core dump accessors for '%s'", core_file);
        goto fail_destroy_as;
    }

    struct exe_mapping_data *s;
    for (s = ch->segments; s != NULL; s = s->next)
    {
        if (_UCD_add_backing_file_at_vaddr(ui, s->start, s->filename) < 0)
        {
            /* Sometimes produces:
             * >_UCD_add_backing_file_at_segment:
             * Error reading from '/usr/lib/modules/3.6.9-2.fc17.x86_64/vdso/vdso.so'
             * Ignore errors for now & fail later.
             */
            warn("Can't add backing file '%s' at addr 0x%jx", s->filename,
                 (uintmax_t)s->start);
            /* goto fail_destroy_ui; */
        }
    }

    stacktrace = sr_core_stacktrace_new();

    int tnum, nthreads = _UCD_get_num_threads(ui);
    for (tnum = 0; tnum < nthreads; ++tnum)
    {
        struct sr_core_thread *trace = unwind_thread(ui, as, ch->dwfl, tnum, error_msg);
        if (trace)
        {
            stacktrace->threads = sr_core_thread_append(stacktrace->threads, trace);
        }
        else
        {
            sr_core_stacktrace_free(stacktrace);
            stacktrace = NULL;
            break;
        }
    }

    stacktrace->executable = realpath(exe_file, NULL);
    stacktrace->signal = get_signal_number_libunwind(ui);
    /* FIXME: is this the best we can do? */
    stacktrace->crash_thread = stacktrace->threads;

    _UCD_destroy(ui);
fail_destroy_as:
    unw_destroy_addr_space(as);
fail_destroy_handle:
    core_handle_free(ch);

    return stacktrace;
}