1*4882a593Smuzhiyun // dwarfsrcfiles.c - Get source files associated with the dwarf in a elf file.
2*4882a593Smuzhiyun // gcc -Wall -g -O2 -lelf -ldw -o dwarfsrcfiles dwarfsrcfiles.c
3*4882a593Smuzhiyun //
4*4882a593Smuzhiyun // Copyright (C) 2011, Mark Wielaard <mjw@redhat.com>
5*4882a593Smuzhiyun //
6*4882a593Smuzhiyun // This file is free software. You can redistribute it and/or modify
7*4882a593Smuzhiyun // it under the terms of the GNU General Public License (GPL); either
8*4882a593Smuzhiyun // version 2, or (at your option) any later version.
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <argp.h>
11*4882a593Smuzhiyun #include <stdio.h>
12*4882a593Smuzhiyun #include <stdlib.h>
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun #include <dwarf.h>
15*4882a593Smuzhiyun #include <elfutils/libdw.h>
16*4882a593Smuzhiyun #include <elfutils/libdwfl.h>
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun static int
process_cu(Dwarf_Die * cu_die)19*4882a593Smuzhiyun process_cu (Dwarf_Die *cu_die)
20*4882a593Smuzhiyun {
21*4882a593Smuzhiyun Dwarf_Attribute attr;
22*4882a593Smuzhiyun const char *name;
23*4882a593Smuzhiyun const char *dir = NULL;
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun Dwarf_Files *files;
26*4882a593Smuzhiyun size_t n;
27*4882a593Smuzhiyun int i;
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun if (dwarf_tag (cu_die) != DW_TAG_compile_unit)
30*4882a593Smuzhiyun {
31*4882a593Smuzhiyun fprintf (stderr, "DIE isn't a compile unit");
32*4882a593Smuzhiyun return -1;
33*4882a593Smuzhiyun }
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun if (dwarf_attr (cu_die, DW_AT_name, &attr) == NULL)
36*4882a593Smuzhiyun {
37*4882a593Smuzhiyun fprintf(stderr, "CU doesn't have a DW_AT_name");
38*4882a593Smuzhiyun return -1;
39*4882a593Smuzhiyun }
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun name = dwarf_formstring (&attr);
42*4882a593Smuzhiyun if (name == NULL)
43*4882a593Smuzhiyun {
44*4882a593Smuzhiyun fprintf(stderr, "Couldn't get DW_AT_name as string, %s",
45*4882a593Smuzhiyun dwarf_errmsg (-1));
46*4882a593Smuzhiyun return -1;
47*4882a593Smuzhiyun }
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun if (dwarf_attr (cu_die, DW_AT_comp_dir, &attr) != NULL)
50*4882a593Smuzhiyun {
51*4882a593Smuzhiyun dir = dwarf_formstring (&attr);
52*4882a593Smuzhiyun if (dir == NULL)
53*4882a593Smuzhiyun {
54*4882a593Smuzhiyun fprintf(stderr, "Couldn't get DW_AT_comp_die as string, %s",
55*4882a593Smuzhiyun dwarf_errmsg (-1));
56*4882a593Smuzhiyun return -1;
57*4882a593Smuzhiyun }
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun if (dir == NULL)
61*4882a593Smuzhiyun printf ("%s\n", name);
62*4882a593Smuzhiyun else
63*4882a593Smuzhiyun printf ("%s/%s\n", dir, name);
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun if (dwarf_getsrcfiles (cu_die, &files, &n) != 0)
66*4882a593Smuzhiyun {
67*4882a593Smuzhiyun fprintf(stderr, "Couldn't get CU file table, %s",
68*4882a593Smuzhiyun dwarf_errmsg (-1));
69*4882a593Smuzhiyun return -1;
70*4882a593Smuzhiyun }
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun for (i = 1; i < n; i++)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun const char *file = dwarf_filesrc (files, i, NULL, NULL);
75*4882a593Smuzhiyun if (dir != NULL && file[0] != '/')
76*4882a593Smuzhiyun printf ("\t%s/%s\n", dir, file);
77*4882a593Smuzhiyun else
78*4882a593Smuzhiyun printf ("\t%s\n", file);
79*4882a593Smuzhiyun }
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun return 0;
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun int
main(int argc,char ** argv)85*4882a593Smuzhiyun main (int argc, char **argv)
86*4882a593Smuzhiyun {
87*4882a593Smuzhiyun char* args[5];
88*4882a593Smuzhiyun int res = 0;
89*4882a593Smuzhiyun Dwfl *dwfl;
90*4882a593Smuzhiyun Dwarf_Addr bias;
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun if (argc != 2) {
93*4882a593Smuzhiyun fprintf(stderr, "Usage %s <file>", argv[0]);
94*4882a593Smuzhiyun exit(EXIT_FAILURE);
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun // Pretend "dwarfsrcfiles -e <file>" was given, so we can use standard
98*4882a593Smuzhiyun // dwfl argp parser to open the file for us and get our Dwfl. Useful
99*4882a593Smuzhiyun // in case argument is an ET_REL file (like kernel modules). libdwfl
100*4882a593Smuzhiyun // will fix up relocations for us.
101*4882a593Smuzhiyun args[0] = argv[0];
102*4882a593Smuzhiyun args[1] = "-e";
103*4882a593Smuzhiyun args[2] = argv[1];
104*4882a593Smuzhiyun // We don't want to follow debug linked files due to the way OE processes
105*4882a593Smuzhiyun // files, could race against changes in the linked binary (e.g. objcopy on it)
106*4882a593Smuzhiyun args[3] = "--debuginfo-path";
107*4882a593Smuzhiyun args[4] = "/not/exist";
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun argp_parse (dwfl_standard_argp (), 5, args, 0, NULL, &dwfl);
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun Dwarf_Die *cu = NULL;
112*4882a593Smuzhiyun while ((cu = dwfl_nextcu (dwfl, cu, &bias)) != NULL)
113*4882a593Smuzhiyun res |= process_cu (cu);
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun dwfl_end (dwfl);
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun return res;
118*4882a593Smuzhiyun }
119