1 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2 // -*- Mode: C++ -*-
3 //
4 // Copyright (C) 2013-2020 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 <elf.h>
14 #include <cstring>
15 #include <iostream>
16 #include <sstream>
17 #include "abg-config.h"
18 #include "abg-dwarf-reader.h"
19 #include "abg-ir.h"
20 #include "abg-tools-utils.h"
21
22 using std::cout;
23 using std::cerr;
24 using std::string;
25 using std::ostream;
26 using std::ostringstream;
27 using std::vector;
28
29 using abigail::ir::environment;
30 using abigail::ir::environment_sptr;
31 using abigail::dwarf_reader::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 return 0;
126 }
127
128 assert(opts.elf_path != 0
129 && opts.symbol_name != 0);
130
131 string p = opts.elf_path, n = opts.symbol_name;
132 environment_sptr env(new environment);
133 vector<elf_symbol_sptr> syms;
134 if (!lookup_symbol_from_elf(env.get(), p, n, opts.demangle, syms))
135 {
136 cout << "could not find symbol '"
137 << opts.symbol_name
138 << "' in file '";
139 if (opts.absolute_path)
140 cout << opts.elf_path << "'\n";
141 else
142 cout << basename(opts.elf_path);
143 return 0;
144 }
145
146 elf_symbol_sptr sym = syms[0];
147 cout << "found symbol '" << n << "'";
148 if (n != sym->get_name())
149 cout << " (" << sym->get_name() << ")";
150 cout << ", an instance of "
151 << (elf_symbol::type) sym->get_type()
152 << " of " << sym->get_binding();
153 if (syms.size() > 1 || !sym->get_version().is_empty())
154 {
155 cout << ", of version";
156 if (syms.size () > 1)
157 cout << "s";
158 cout << " ";
159 for (vector<elf_symbol_sptr>::const_iterator i = syms.begin();
160 i != syms.end();
161 ++i)
162 {
163 if (i != syms.begin())
164 cout << ", ";
165 cout << "'" << (*i)->get_version().str() << "'";
166 }
167 }
168 cout << '\n';
169
170 return 0;
171 }
172