コード例 #1
0
ファイル: _UCD_create.c プロジェクト: AmirAbrams/haiku
struct UCD_info *
_UCD_create(const char *filename)
{
  union
    {
      Elf32_Ehdr h32;
      Elf64_Ehdr h64;
    } elf_header;
#define elf_header32 elf_header.h32
#define elf_header64 elf_header.h64
  bool _64bits;

  struct UCD_info *ui = memset(malloc(sizeof(*ui)), 0, sizeof(*ui));
  ui->edi.di_cache.format = -1;
  ui->edi.di_debug.format = -1;
#if UNW_TARGET_IA64
  ui->edi.ktab.format = -1;
#endif

  int fd = ui->coredump_fd = open(filename, O_RDONLY);
  if (fd < 0)
    goto err;
  ui->coredump_filename = strdup(filename);

  /* No sane ELF32 file is going to be smaller then ELF64 _header_,
   * so let's just read 64-bit sized one.
   */
  if (read(fd, &elf_header64, sizeof(elf_header64)) != sizeof(elf_header64))
    {
      Debug(0, "'%s' is not an ELF file\n", filename);
      goto err;
    }

  if (memcmp(&elf_header32, ELFMAG, SELFMAG) != 0)
    {
      Debug(0, "'%s' is not an ELF file\n", filename);
      goto err;
    }

  if (elf_header32.e_ident[EI_CLASS] != ELFCLASS32
   && elf_header32.e_ident[EI_CLASS] != ELFCLASS64)
    {
      Debug(0, "'%s' is not a 32/64 bit ELF file\n", filename);
      goto err;
    }

  if (WE_ARE_LITTLE_ENDIAN != (elf_header32.e_ident[EI_DATA] == ELFDATA2LSB))
    {
      Debug(0, "'%s' is endian-incompatible\n", filename);
      goto err;
    }

  _64bits = (elf_header32.e_ident[EI_CLASS] == ELFCLASS64);
  if (_64bits && sizeof(elf_header64.e_entry) > sizeof(off_t))
    {
      Debug(0, "Can't process '%s': 64-bit file "
               "while only %ld bits are supported",
            filename, 8L * sizeof(off_t));
      goto err;
    }

  /* paranoia check */
  if (_64bits
            ? 0 /* todo: (elf_header64.e_ehsize != NN || elf_header64.e_phentsize != NN) */
            : (elf_header32.e_ehsize != 52 || elf_header32.e_phentsize != 32)
  )
    {
      Debug(0, "'%s' has wrong e_ehsize or e_phentsize\n", filename);
      goto err;
    }

  off_t ofs = (_64bits ? elf_header64.e_phoff : elf_header32.e_phoff);
  if (lseek(fd, ofs, SEEK_SET) != ofs)
    {
      Debug(0, "Can't read phdrs from '%s'\n", filename);
      goto err;
    }
  unsigned size = ui->phdrs_count = (_64bits ? elf_header64.e_phnum : elf_header32.e_phnum);
  coredump_phdr_t *phdrs = ui->phdrs = memset(malloc(size * sizeof(phdrs[0])), 0, size * sizeof(phdrs[0]));
  if (_64bits)
    {
      coredump_phdr_t *cur = phdrs;
      unsigned i = 0;
      while (i < size)
        {
          Elf64_Phdr hdr64;
          if (read(fd, &hdr64, sizeof(hdr64)) != sizeof(hdr64))
            {
              Debug(0, "Can't read phdrs from '%s'\n", filename);
              goto err;
            }
          cur->p_type   = hdr64.p_type  ;
          cur->p_flags  = hdr64.p_flags ;
          cur->p_offset = hdr64.p_offset;
          cur->p_vaddr  = hdr64.p_vaddr ;
          /*cur->p_paddr  = hdr32.p_paddr ; always 0 */
//TODO: check that and abort if it isn't?
          cur->p_filesz = hdr64.p_filesz;
          cur->p_memsz  = hdr64.p_memsz ;
          cur->p_align  = hdr64.p_align ;
          /* cur->backing_filename = NULL; - done by memset */
          cur->backing_fd = -1;
          cur->backing_filesize = hdr64.p_filesz;
          i++;
          cur++;
        }
    } else {
      coredump_phdr_t *cur = phdrs;
      unsigned i = 0;
      while (i < size)
        {
          Elf32_Phdr hdr32;
          if (read(fd, &hdr32, sizeof(hdr32)) != sizeof(hdr32))
            {
              Debug(0, "Can't read phdrs from '%s'\n", filename);
              goto err;
            }
          cur->p_type   = hdr32.p_type  ;
          cur->p_flags  = hdr32.p_flags ;
          cur->p_offset = hdr32.p_offset;
          cur->p_vaddr  = hdr32.p_vaddr ;
          /*cur->p_paddr  = hdr32.p_paddr ; always 0 */
          cur->p_filesz = hdr32.p_filesz;
          cur->p_memsz  = hdr32.p_memsz ;
          cur->p_align  = hdr32.p_align ;
          /* cur->backing_filename = NULL; - done by memset */
          cur->backing_fd = -1;
          cur->backing_filesize = hdr32.p_memsz;
          i++;
          cur++;
        }
    }

    unsigned i = 0;
    coredump_phdr_t *cur = phdrs;
    while (i < size)
      {
        Debug(2, "phdr[%03d]: type:%d", i, cur->p_type);
        if (cur->p_type == PT_NOTE)
          {
            Elf32_Nhdr *note_hdr, *note_end;
            unsigned n_threads;

            ui->note_phdr = malloc(cur->p_filesz);
            if (lseek(fd, cur->p_offset, SEEK_SET) != (off_t)cur->p_offset
             || (uoff_t)read(fd, ui->note_phdr, cur->p_filesz) != cur->p_filesz)
              {
                    Debug(0, "Can't read PT_NOTE from '%s'\n", filename);
                    goto err;
              }

            note_end = STRUCT_MEMBER_P (ui->note_phdr, cur->p_filesz);

            /* Count number of threads */
            n_threads = 0;
            note_hdr = (Elf32_Nhdr *)ui->note_phdr;
            while (NOTE_FITS (note_hdr, note_end))
              {
                if (note_hdr->n_type == NT_PRSTATUS)
                  n_threads++;

                note_hdr = NOTE_NEXT (note_hdr);
              }

            ui->n_threads = n_threads;
            ui->threads = malloc(sizeof (void *) * n_threads);

            n_threads = 0;
            note_hdr = (Elf32_Nhdr *)ui->note_phdr;
            while (NOTE_FITS (note_hdr, note_end))
              {
                if (note_hdr->n_type == NT_PRSTATUS)
                  ui->threads[n_threads++] = NOTE_DATA (note_hdr);

                note_hdr = NOTE_NEXT (note_hdr);
              }
          }
        if (cur->p_type == PT_LOAD)
          {
            Debug(2, " ofs:%08llx va:%08llx filesize:%08llx memsize:%08llx flg:%x",
                                (unsigned long long) cur->p_offset,
                                (unsigned long long) cur->p_vaddr,
                                (unsigned long long) cur->p_filesz,
                                (unsigned long long) cur->p_memsz,
                                cur->p_flags
            );
            if (cur->p_filesz < cur->p_memsz)
              Debug(2, " partial");
            if (cur->p_flags & PF_X)
              Debug(2, " executable");
          }
        Debug(2, "\n");
        i++;
        cur++;
      }

    if (ui->n_threads == 0)
      {
        Debug(0, "No NT_PRSTATUS note found in '%s'\n", filename);
        goto err;
      }

    ui->prstatus = ui->threads[0];

  return ui;

 err:
  _UCD_destroy(ui);
  return NULL;
}
コード例 #2
0
int
main(int argc , char **argv)
{
  unw_addr_space_t as;
  unw_cursor_t cursor;
  struct UCD_info *ui;
  unw_word_t ip, sp, off;
  char buf[512], name[256];
  int line;
  int depth = 0;
  int ret;
  bool pybt_done = false;
#define TEST_NAME_LEN 256 

  install_signal_handler();

  if (argc != 3) {
    fprintf(stderr, "Usage: %s <binary> <corefile>", argv[0]);
    exit(1);
  }

  as = unw_create_addr_space(&_UCD_accessors, 0);
  if (!as) {
    fprintf(stderr, "unw_create_addr_space() failed");
    exit(1);
  }

  ui = _UCD_create(argv[2]);
  if (!ui) {
    fprintf(stderr,"_UCD_create('%s') failed", argv[1]);
    exit(1);
  }
  ret = unw_init_remote(&cursor, as, ui);
  if (ret < 0) {
    fprintf(stderr,"unw_init_remote() failed: ret=%d\n", ret);
    exit(1);
  }

  read_elfnotes(argv[2], ui);

  while (unw_step(&cursor) > 0) {
    // Avoid going too deep
    if (depth++ > MAX_STACK_DEPTH) {
      exit(1);
    }
    unw_get_reg(&cursor, UNW_REG_IP, &ip);
    unw_get_reg(&cursor, UNW_REG_SP, &sp);


    if (unw_get_proc_name(&cursor, name, sizeof (name), &off) == 0) {
      if (off) {
        snprintf(buf, sizeof (buf), "<%s+0x%lx>", name, (long) off);
      } else {
        snprintf(buf, sizeof (buf), "<%s>", name);
      }
    }

    /* Check for Python backtrace */
    if (!strncmp(name,"PyEval_EvalFrameEx", 18) && !pybt_done) {
      pybacktrace(cursor);
      pybt_done = true;
    }
    rw_get_file_and_line((long)ip, name, argv[1], 256, &line);
    printf("%016lx %s <%s:%d> (sp=%016lx)\n",
            (long) ip, buf, basename(name), line, (long) sp);

  }
  _UCD_destroy(ui);
  unw_destroy_addr_space(as);

  return 0;
}
コード例 #3
0
ファイル: test-coredump-unwind.c プロジェクト: A-And/coreclr
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;
}
コード例 #4
0
ファイル: core_unwind_libunwind.c プロジェクト: abrt/satyr
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;
}