source: rtems-tools/linkers/rtems-addr2line.cpp @ 1318c11

Last change on this file since 1318c11 was 1318c11, checked in by Chris Johns <chrisj@…>, on May 24, 2018 at 6:05:44 AM

linkers: Add an address to line tool.

This tool provides a way to check the DWARF toolkit support for finding
lines from addresses.

  • Property mode set to 100644
File size: 6.9 KB
Line 
1/*
2 * Copyright (c) 2018, Chris Johns <chrisj@rtems.org>
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16/**
17 * @file
18 *
19 * @ingroup rtems_rld
20 *
21 * @brief RTEMS Address to Line is a version of the classic addr2line
22 *        utility to test the DWARF info support in the RTEMS Toolkit.
23 *
24 */
25
26#if HAVE_CONFIG_H
27#include "config.h"
28#endif
29
30#include <iomanip>
31#include <iostream>
32
33#include <signal.h>
34#include <stdlib.h>
35#include <string.h>
36#include <unistd.h>
37
38#include <getopt.h>
39
40#include <rld.h>
41#include <rld-dwarf.h>
42#include <rld-files.h>
43#include <rld-rtems.h>
44
45#ifndef HAVE_KILL
46#define kill(p,s) raise(s)
47#endif
48
49/**
50 * RTEMS Symbols options.
51 */
52static struct option rld_opts[] = {
53  { "help",         no_argument,            NULL,           'h' },
54  { "version",      no_argument,            NULL,           'V' },
55  { "verbose",      no_argument,            NULL,           'v' },
56  { "executable",   required_argument,      NULL,           'e' },
57  { "addresses",    no_argument,            NULL,           'a' },
58  { "pretty-print", no_argument,            NULL,           'p' },
59  { "basenames",    no_argument,            NULL,           's' },
60  { NULL,           0,                      NULL,            0 }
61};
62
63void
64usage (int exit_code)
65{
66  std::cout << "rtems-addr2line [options] addresses" << std::endl
67            << "Options and arguments:" << std::endl
68            << " -h        : help (also --help)" << std::endl
69            << " -V        : print version number and exit (also --version)" << std::endl
70            << " -v        : verbose (trace import parts), can supply multiple times" << std::endl
71            << "             to increase verbosity (also --verbose)" << std::endl
72            << " -e        : executable (also --executablewarn)" << std::endl
73            << " -a        : show addresses (also --addresses)" << std::endl
74            << " -p        : human readable format (also --pretty-print)" << std::endl
75            << " -s        : Strip directory paths (also --basenames)" << std::endl;
76  ::exit (exit_code);
77}
78
79static void
80fatal_signal (int signum)
81{
82  signal (signum, SIG_DFL);
83
84  /*
85   * Get the same signal again, this time not handled, so its normal effect
86   * occurs.
87   */
88  kill (getpid (), signum);
89}
90
91static void
92setup_signals (void)
93{
94  if (signal (SIGINT, SIG_IGN) != SIG_IGN)
95    signal (SIGINT, fatal_signal);
96#ifdef SIGHUP
97  if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
98    signal (SIGHUP, fatal_signal);
99#endif
100  if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
101    signal (SIGTERM, fatal_signal);
102#ifdef SIGPIPE
103  if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
104    signal (SIGPIPE, fatal_signal);
105#endif
106#ifdef SIGCHLD
107  signal (SIGCHLD, SIG_DFL);
108#endif
109}
110
111void
112unhandled_exception (void)
113{
114  std::cerr << "error: exception handling error, please report" << std::endl;
115  exit (13);
116}
117
118int
119main (int argc, char* argv[])
120{
121  int ec = 0;
122
123  setup_signals ();
124
125  std::set_terminate(unhandled_exception);
126
127  try
128  {
129    std::string exe_name = "a.out";
130    bool        show_addresses = false;
131    bool        pretty_print = false;
132    bool        show_basenames = false;
133
134    rld::set_cmdline (argc, argv);
135
136    while (true)
137    {
138      int opt = ::getopt_long (argc, argv, "hvVe:aps", rld_opts, NULL);
139      if (opt < 0)
140        break;
141
142      switch (opt)
143      {
144        case 'V':
145          std::cout << "rtems-addr2line (RTEMS Address To Line) " << rld::version ()
146                    << ", RTEMS revision " << rld::rtems::version ()
147                    << std::endl;
148          ::exit (0);
149          break;
150
151        case 'v':
152          rld::verbose_inc ();
153          break;
154
155        case 'e':
156          exe_name = optarg;
157          break;
158
159        case 'a':
160          show_addresses = true;
161          break;
162
163        case 'p':
164          pretty_print = true;
165          break;
166
167        case 's':
168          show_basenames = true;
169          break;
170
171        case '?':
172          usage (3);
173          break;
174
175        case 'h':
176          usage (0);
177          break;
178      }
179    }
180
181    /*
182     * Set the program name.
183     */
184    rld::set_progname (argv[0]);
185
186    argc -= optind;
187    argv += optind;
188
189    if (rld::verbose ())
190      std::cout << "RTEMS Address To Line " << rld::version () << std::endl;
191
192    /*
193     * If there are no object files there is nothing to link.
194     */
195    if (argc == 0)
196      throw rld::error ("no addresses provided", "options");
197
198    if (rld::verbose ())
199      std::cout << "exe: " << exe_name << std::endl;
200
201    /*
202     * Load the executable's debug info.
203     */
204    rld::files::object exe (exe_name);
205    rld::dwarf::file   debug;
206
207    try
208    {
209      /*
210       * Load the executable's ELF file debug info.
211       */
212      exe.open ();
213      exe.begin ();
214      debug.begin (exe.elf ());
215      debug.load_debug ();
216
217      for (int arg = 0; arg < argc; ++arg)
218      {
219        rld::dwarf::dwarf_address location;
220
221        if (rld::verbose ())
222          std::cout << "address: " << argv[arg] << std::endl;
223
224        /*
225         * Use the C routine as C++ does not have a way to automatically handle
226         * different bases on the input.
227         */
228        location = ::strtoul (argv[arg], 0, 0);
229
230        std::string path;
231        int         line;
232
233        debug.get_source (location, path, line);
234
235        if (show_addresses)
236        {
237          std::cout << std::hex << std::setfill ('0')
238                    << "0x" << location
239                    << std::dec << std::setfill (' ');
240
241          if (pretty_print)
242            std::cout << ": ";
243          else
244            std::cout << std::endl;
245        }
246
247        if (show_basenames)
248          std::cout << rld::path::basename (path);
249        else
250          std::cout << path;
251
252        std::cout << ':' << line << std::endl;
253      }
254
255      debug.end ();
256      exe.end ();
257      exe.close ();
258    }
259    catch (...)
260    {
261      debug.end ();
262      exe.end ();
263      exe.close ();
264      throw;
265    }
266  }
267  catch (rld::error re)
268  {
269    std::cerr << "error: "
270              << re.where << ": " << re.what
271              << std::endl;
272    ec = 10;
273  }
274  catch (std::exception e)
275  {
276    rld::output_std_exception (e, std::cerr);
277    ec = 11;
278  }
279  catch (...)
280  {
281    /*
282     * Helps to know if this happens.
283     */
284    std::cout << "error: unhandled exception" << std::endl;
285    ec = 12;
286  }
287
288  return ec;
289}
Note: See TracBrowser for help on using the repository browser.