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; }
/** * 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); }
/** * 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; }
static int mac (Dwarf_Macro *macro, void *dbg) { static int level = 0; unsigned int opcode; dwarf_macro_opcode (macro, &opcode); switch (opcode) { case DW_MACRO_GNU_transparent_include: { Dwarf_Attribute at; int r = dwarf_macro_param (macro, 0, &at); assert (r == 0); Dwarf_Word w; r = dwarf_formudata (&at, &w); assert (r == 0); printf ("%*sinclude %#" PRIx64 "\n", level, "", w); ++level; include (dbg, w, DWARF_GETMACROS_START); --level; printf ("%*s/include\n", level, ""); break; } case DW_MACRO_GNU_start_file: { Dwarf_Files *files; size_t nfiles; if (dwarf_macro_getsrcfiles (dbg, macro, &files, &nfiles) < 0) printf ("dwarf_macro_getsrcfiles: %s\n", dwarf_errmsg (dwarf_errno ())); Dwarf_Word w = 0; dwarf_macro_param2 (macro, &w, NULL); const char *name = dwarf_filesrc (files, (size_t) w, NULL, NULL); printf ("%*sfile %s\n", level, "", name); ++level; break; } case DW_MACRO_GNU_end_file: { --level; printf ("%*s/file\n", level, ""); break; } case DW_MACINFO_define: case DW_MACRO_GNU_define_indirect: { const char *value; dwarf_macro_param2 (macro, NULL, &value); printf ("%*s%s\n", level, "", value); break; } case DW_MACINFO_undef: case DW_MACRO_GNU_undef_indirect: break; default: { size_t paramcnt; dwarf_macro_getparamcnt (macro, ¶mcnt); printf ("%*sopcode %u with %zd arguments\n", level, "", opcode, paramcnt); break; } } return DWARF_CB_ABORT; }
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; }
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; }
static void analyze_type(Dwarf_Die *die, struct type *ty) { int ret; Dwarf_Attribute at; /* find out the values of name, byte_size and type attributes * even though not all of them make sense for all tags */ char *name = NULL; if (dwarf_attr(die, DW_AT_name, &at) != NULL) { name = xstrdup(dwarf_formstring(&at)); } struct type sub_type = { .name = NULL, .width = 0 }; if (dwarf_attr(die, DW_AT_type, &at) != NULL) { Dwarf_Die sub_die; if (dwarf_formref_die(&at, &sub_die) != NULL) analyze_type(&sub_die, &sub_type); } Dwarf_Word width = 0; if (dwarf_attr(die, DW_AT_byte_size, &at) != NULL) { ret = dwarf_formudata(&at, &width); fail_if(ret == -1, "dwarf_formudata"); } switch (dwarf_tag(die)) { case DW_TAG_base_type: ty->name = name; name = NULL; ty->width = (unsigned)width; /* TODO: what about encoding? */ break; /* type modifiers */ case DW_TAG_const_type: ty->name = xsprintf("const %s", sub_type.name ?: "void"); ty->width = sub_type.width; break; case DW_TAG_pointer_type: ty->width = (unsigned)width; ty->name = xsprintf("%s*", sub_type.name ?: "void"); break; case DW_TAG_restrict_type: ty->name = xsprintf("%s restrict", sub_type.name ?: "void"); ty->width = sub_type.width; break; case DW_TAG_volatile_type: ty->name = xsprintf("volatile %s", sub_type.name ?: "void"); ty->width = sub_type.width; break; case DW_TAG_typedef: ty->name = name; name = NULL; ty->width = sub_type.width; break; case DW_TAG_array_type: ty->name = xsprintf("%s[]", sub_type.name); ty->width = POINTER_SIZE; break; case DW_TAG_structure_type: if (name) ty->name = xsprintf("struct %s", name); else ty->name = xstrdup("struct"); ty->width = (unsigned)width; break; case DW_TAG_union_type: if (name) ty->name = xsprintf("union %s", name); else ty->name = xstrdup("union"); ty->width = (unsigned)width; break; case DW_TAG_class_type: ty->name = xsprintf("class %s", name); ty->width = (unsigned)width; break; case DW_TAG_enumeration_type: ty->name = xsprintf("enum %s", name); ty->width = (unsigned)width; break; case DW_TAG_subroutine_type: ty->name = xstrdup("FUNCTION"); ty->width = 0; /* TODO */ break; default: warn("Unknown type 0x%x named %s with width %u", dwarf_tag(die), name, (unsigned)width); break; } free(sub_type.name); free(name); } void analyze_name_location(Dwarf_Die *die, Dwarf_Files *files, char **name, struct location* loc) { int ret; Dwarf_Attribute at; Dwarf_Word w; if (dwarf_attr_integrate(die, DW_AT_name, &at) != NULL) { *name = xstrdup(dwarf_formstring(&at)); } if (dwarf_attr_integrate(die, DW_AT_decl_file, &at) != NULL) { ret = dwarf_formudata(&at, &w); fail_if(ret == -1, "dwarf_formudata"); loc->file = xstrdup(dwarf_filesrc(files, (size_t)w, NULL, NULL)); } if (dwarf_attr_integrate(die, DW_AT_decl_line, &at) != NULL) { ret = dwarf_formudata(&at, &w); fail_if(ret == -1, "dwarf_formudata"); loc->line = (unsigned)w; } }