• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2 // -*- Mode: C++ -*-
3 //
4 // Copyright (C) 2013-2022 Red Hat, Inc.
5 //
6 // Author: Dodji Seketeli
7 
8 /// @file
9 ///
10 /// This program takes parameters to open an elf file, lookup a symbol
11 /// in its symbol tables and report what it sees.
12 
13 #include <libgen.h>
14 #include <elf.h>
15 #include <cstring>
16 #include <iostream>
17 #include <sstream>
18 #include "abg-config.h"
19 #include "abg-dwarf-reader.h"
20 #include "abg-ir.h"
21 #include "abg-tools-utils.h"
22 
23 using std::cout;
24 using std::cerr;
25 using std::string;
26 using std::ostream;
27 using std::ostringstream;
28 using std::vector;
29 
30 using abigail::ir::environment;
31 using abigail::dwarf::lookup_symbol_from_elf;
32 using abigail::elf_symbol;
33 using abigail::elf_symbol_sptr;
34 
35 struct options
36 {
37   bool	show_help;
38   bool	display_version;
39   char* elf_path;
40   char* symbol_name;
41   bool	demangle;
42   bool absolute_path;
43 
optionsoptions44   options()
45     : show_help(false),
46       display_version(false),
47       elf_path(0),
48       symbol_name(0),
49       demangle(false),
50       absolute_path(true)
51   {}
52 };
53 
54 static void
display_usage(const string & prog_name,ostream & out)55 display_usage(const string& prog_name, ostream &out)
56 {
57   out << "usage: " << prog_name << " [options] <elf file> <symbol-name>\n"
58       << "where [options] can be:\n"
59       << "  --help  display this help string\n"
60       << "  --version|-v  display program version information and exit\n"
61       << "  --demangle  demangle the symbols from the symbol table\n"
62       << "  --no-absolute-path  do not show absolute paths in messages\n";
63 }
64 
65 static void
parse_command_line(int argc,char * argv[],options & opts)66 parse_command_line(int argc, char* argv[], options& opts)
67 {
68   if (argc < 2)
69     {
70       opts.show_help = true;
71       return;
72     }
73 
74   for (int i = 1; i < argc; ++i)
75     {
76       if (argv[i][0] != '-')
77 	{
78 	  if (!opts.elf_path)
79 	    opts.elf_path = argv[i];
80 	  else if (!opts.symbol_name)
81 	    opts.symbol_name = argv[i] ;
82 	  else
83 	    {
84 	      opts.show_help = true;
85 	      return;
86 	    }
87 	}
88       else if (!strcmp(argv[i], "--help")
89 	       || !strcmp(argv[i], "-h"))
90 	{
91 	  opts.show_help = true;
92 	  return;
93 	}
94       else if (!strcmp(argv[i], "--version")
95 	       || !strcmp(argv[i], "-v"))
96 	{
97 	  opts.display_version = true;
98 	  return;
99 	}
100       else if (!strcmp(argv[i], "--demangle"))
101 	opts.demangle = true;
102       else if (!strcmp(argv[i], "--no-absolute-path"))
103 	opts.absolute_path = false;
104       else
105 	opts.show_help = true;
106     }
107 }
108 
109 int
main(int argc,char * argv[])110 main(int argc, char* argv[])
111 {
112   options opts;
113   parse_command_line(argc, argv, opts);
114 
115   if (opts.show_help)
116     {
117       display_usage(argv[0], cout);
118       return 1;
119     }
120 
121   if (opts.display_version)
122     {
123       abigail::tools_utils::emit_prefix(argv[0], cout)
124 	<< abigail::tools_utils::get_library_version_string()
125 	<< "\n";
126       return 0;
127     }
128 
129   assert(opts.elf_path != 0
130 	 && opts.symbol_name != 0);
131 
132   string p = opts.elf_path, n = opts.symbol_name;
133   environment env;
134   vector<elf_symbol_sptr> syms;
135   if (!lookup_symbol_from_elf(env, p, n, opts.demangle, syms))
136     {
137       cout << "could not find symbol '"
138 	   << opts.symbol_name
139 	   << "' in file '";
140       if (opts.absolute_path)
141 	cout << opts.elf_path << "'\n";
142       else
143 	cout << basename(opts.elf_path);
144       return 0;
145     }
146 
147   elf_symbol_sptr sym = syms[0];
148   cout << "found symbol '" << n << "'";
149   if (n != sym->get_name())
150     cout << " (" << sym->get_name() << ")";
151   cout << ", an instance of "
152        << (elf_symbol::type) sym->get_type()
153        << " of " << sym->get_binding();
154   if (syms.size() > 1 || !sym->get_version().is_empty())
155     {
156       cout << ", of version";
157       if (syms.size () > 1)
158 	cout << "s";
159       cout << " ";
160       for (vector<elf_symbol_sptr>::const_iterator i = syms.begin();
161 	   i != syms.end();
162 	   ++i)
163 	{
164 	  if (i != syms.begin())
165 	    cout << ", ";
166 	  cout << "'" << (*i)->get_version().str() << "'";
167 	}
168     }
169   cout << '\n';
170 
171   return 0;
172 }
173