Exemplo n.º 1
0
BT_HIDDEN
int bt_dwarf_die_get_call_file(struct bt_dwarf_die *die, char **filename)
{
	int ret;
	Dwarf_Sword file_no;
	const char *_filename = NULL;
	Dwarf_Files *src_files = NULL;
	Dwarf_Attribute *file_attr = NULL;
	struct bt_dwarf_die *cu_die = NULL;

	if (!die || !filename) {
		goto error;
	}

	file_attr = g_new0(Dwarf_Attribute, 1);
	if (!file_attr) {
		goto error;
	}

	file_attr = dwarf_attr(die->dwarf_die, DW_AT_call_file, file_attr);
	if (!file_attr) {
		goto error;
	}

	ret = dwarf_formsdata(file_attr, &file_no);
	if (ret) {
		goto error;
	}

	cu_die = bt_dwarf_die_create(die->cu);
	if (!cu_die) {
		goto error;
	}

	ret = dwarf_getsrcfiles(cu_die->dwarf_die, &src_files, NULL);
	if (ret) {
		goto error;
	}

	_filename = dwarf_filesrc(src_files, file_no, NULL, NULL);
	if (!_filename) {
		goto error;
	}

	*filename = strdup(_filename);

	bt_dwarf_die_destroy(cu_die);
	g_free(file_attr);

	return 0;

error:
	bt_dwarf_die_destroy(cu_die);
	g_free(file_attr);

	return -1;
}
Exemplo n.º 2
0
/**
 * die_get_call_file - Get callsite file name of inlined function instance
 * @in_die: a DIE of an inlined function instance
 *
 * Get call-site file name of @in_die. This means from which file the inline
 * function is called.
 */
const char *die_get_call_file(Dwarf_Die *in_die)
{
	Dwarf_Die cu_die;
	Dwarf_Files *files;
	int idx;

	idx = die_get_call_fileno(in_die);
	if (idx < 0 || !dwarf_diecu(in_die, &cu_die, NULL, NULL) ||
	    dwarf_getsrcfiles(&cu_die, &files, NULL) != 0)
		return NULL;

	return dwarf_filesrc(files, idx, NULL, NULL);
}
Exemplo n.º 3
0
/**
 * cu_find_realpath - Find the realpath of the target file
 * @cu_die: A DIE(dwarf information entry) of CU(compilation Unit)
 * @fname:  The tail filename of the target file
 *
 * Find the real(long) path of @fname in @cu_die.
 */
const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname)
{
	Dwarf_Files *files;
	size_t nfiles, i;
	const char *src = NULL;
	int ret;

	if (!fname)
		return NULL;

	ret = dwarf_getsrcfiles(cu_die, &files, &nfiles);
	if (ret != 0)
		return NULL;

	for (i = 0; i < nfiles; i++) {
		src = dwarf_filesrc(files, i, NULL, NULL);
		if (strtailcmp(src, fname) == 0)
			break;
	}
	if (i == nfiles)
		return NULL;
	return src;
}
Exemplo n.º 4
0
static struct frame* unwind_thread(Dwfl *dwfl, unw_addr_space_t as,
                                   struct UCD_info *ui, int thread_no,
                                   struct expr_context *ctx)
{
    info("thread %d:", thread_no);

    int i, ret;
    unw_cursor_t c, c_cfa;

    _UCD_select_thread(ui, thread_no);

    ret = unw_init_remote(&c, as, ui);
    fail_if(ret < 0, "unw_init_remote");

    ret = unw_init_remote(&c_cfa, as, ui);
    fail_if(ret < 0, "unw_init_remote");

    struct frame *head = NULL, *tail = NULL;

    /* infinite loop insurance */
    int count = 1000;
    while (--count > 0)
    {
        unw_word_t ip;
        ret = unw_get_reg(&c, UNW_REG_IP, &ip);
        fail_if(ret < 0, "unw_get_reg");

        if (ip == 0)
            break;

        unw_word_t off;
        char funcname[10*1024];
        funcname[0] = '\0';
        ret = unw_get_proc_name(&c, funcname, sizeof(funcname)-1, &off);
        if (ret < 0)
        {
            warn("unw_get_proc_name failed for IP %lx", (unsigned long)ip);
        }
        info("\t%llx %s", (unsigned long long)ip, funcname);

        /* According to spec[1], CFA is RSP of the previous frame. However,
         * libunwind returns CFA = RSP of the current frame. So we need to keep
         * track of the previous (i.e. next to be unwound) frame.
         *
         * [1] System V Application Binary Interface AMD64 Architecture
         *     Processor Supplement
         *     http://www.x86-64.org/documentation/abi.pdf
         */
        ctx->cfa = 0;
        ret = unw_step(&c_cfa);
        if (ret > 0)
        {
            unw_word_t cfa;
            ret = unw_get_reg(&c_cfa, UNW_X86_64_CFA, &cfa);
            if (ret == 0)
            {
                ctx->cfa = (Dwarf_Addr)cfa;
            }
        }

        /* find compilation unit owning the IP */
        Dwarf_Die *cu = dwfl_addrdie(dwfl, (Dwarf_Addr)ip, &(ctx->bias));
        if (!cu)
        {
            warn("\t\tcannot find CU for ip %lx", (unsigned long)ip);
            goto synth_frame;
        }

        if (!supported_language(cu))
        {
            warn("\t\tunsupported CU language");
            goto synth_frame;
        }

        /* needed by child_variables */
        Dwarf_Files *files;
        ret = dwarf_getsrcfiles(cu, &files, NULL);
        fail_if(ret == -1, "dwarf_getsrcfiles");

        /* dwarf expression evaluation needs register values */
        ctx->curs = &c;
        ctx->ip = (Dwarf_Addr)ip; /* TODO: subtract 1 as this is return address? */

        /* TODO: we have CU - fall back to CU name if subprogram not found */

        /* Following code deals with inlined functions, which do not have their
         * own stack frame. It is somewhat ugly due to two constraints:
         *  - we want to produce at least one frame even if analyze_scopes
         *    fails
         *  - we may want to further process the frame that is returned the
         *    last, i.e. the one that belongs to the non-inlined function
         */
        Dwarf_Die *scopes;
        int nscopes = dwarf_getscopes(cu, (Dwarf_Addr)ip, &scopes);
        struct frame *frame = analyze_scopes(&scopes, &nscopes, ctx, files, false);

        if (frame == NULL)
        {
            goto synth_frame;
        }

        struct frame *last_frame;
        while (frame)
        {
            list_append(head, tail, frame);
            last_frame = frame;
            frame = analyze_scopes(&scopes, &nscopes, ctx, files, true);
        }
        frame = last_frame;
        /* frame->ip = (uint64_t)ip; */

        goto next;

synth_frame:
        /* synthesize frame even though we have no other information except
         * that it's there */
        frame = xalloc(sizeof(*frame));
        list_append(head, tail, frame);
        /* frame->ip = (uint64_t)ip; */

next:
        ret = unw_step(&c);
        fail_if(ret < 0, "unw_step");

        if (ret == 0)
            break;
    }

    return head;
}
Exemplo n.º 5
0
int
main (int argc, char *argv[])
{
  int result = 0;
  int cnt;

  for (cnt = 1; cnt < argc; ++cnt)
    {
      int fd = open (argv[cnt], O_RDONLY);

      Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
      if (dbg == NULL)
	{
	  printf ("%s not usable\n", argv[cnt]);
	  result = 1;
	  if (fd != -1)
	    close (fd);
	  continue;
	}

      Dwarf_Off o = 0;
      Dwarf_Off ncu;
      Dwarf_Off ao;
      size_t cuhl;
      uint8_t asz;
      uint8_t osz;
      while (dwarf_nextcu (dbg, o, &ncu, &cuhl, &ao, &asz, &osz) == 0)
	{
	  printf ("cuhl = %zu, o = %llu, asz = %hhu, osz = %hhu, ncu = %llu\n",
		  cuhl, (unsigned long long int) ao,
		  asz, osz, (unsigned long long int) ncu);

	  Dwarf_Die die_mem;
	  Dwarf_Die *die = dwarf_offdie (dbg, o + cuhl, &die_mem);
	  if (die == NULL)
	    {
	      printf ("%s: cannot get CU die\n", argv[cnt]);
	      result = 1;
	      break;
	    }

	  Dwarf_Files *files;
	  size_t nfiles;
	  if (dwarf_getsrcfiles (die, &files, &nfiles) != 0)
	    {
	      printf ("%s: cannot get files\n", argv[cnt]);
	      result = 1;
	      break;
	    }

	  for (int i = 0; i < nfiles; ++i)
	    printf (" file[%d] = \"%s\"\n", i,
		    dwarf_filesrc (files, i, NULL, NULL));

	  o = ncu;
	}

      dwarf_end (dbg);
      close (fd);
    }

  return result;
}
Exemplo n.º 6
0
static int
process_cu (Dwarf_Die *cu_die)
{
  Dwarf_Attribute attr;
  const char *name;
  const char *dir = NULL;
  
  Dwarf_Files *files;
  size_t n;
  int i;
  
  if (dwarf_tag (cu_die) != DW_TAG_compile_unit)
    {
      fprintf (stderr, "DIE isn't a compile unit");
      return -1;
    }
  
  if (dwarf_attr (cu_die, DW_AT_name, &attr) == NULL)
    {
      fprintf(stderr, "CU doesn't have a DW_AT_name");
      return -1;
    }
  
  name = dwarf_formstring (&attr);
  if (name == NULL)
    {
      fprintf(stderr, "Couldn't get DW_AT_name as string, %s",
	     dwarf_errmsg (-1));
      return -1;
    }
  
  if (dwarf_attr (cu_die, DW_AT_comp_dir, &attr) != NULL)
    {
      dir = dwarf_formstring (&attr);
      if (dir == NULL)
	{
	  fprintf(stderr, "Couldn't get DW_AT_comp_die as string, %s",
		 dwarf_errmsg (-1));
	  return -1;
	}
    }
  
  if (dir == NULL)
    printf ("%s\n", name);
  else
    printf ("%s/%s\n", dir, name);
  
  if (dwarf_getsrcfiles (cu_die, &files, &n) != 0)
    {
      fprintf(stderr, "Couldn't get CU file table, %s",
	     dwarf_errmsg (-1));
      return -1;
    }
  
  for (i = 1; i < n; i++)
    {
      const char *file = dwarf_filesrc (files, i, NULL, NULL);
      if (dir != NULL && file[0] != '/')
	printf ("\t%s/%s\n", dir, file);
      else
	printf ("\t%s\n", file);
    }
  
  return 0;
}