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