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