[PATCH v3 17/22] linkers: Add an address to line tool.
Chris Johns
chrisj at rtems.org
Mon Jun 18 02:29:15 UTC 2018
This tool provides a way to check the DWARF toolkit support for finding
lines from addresses.
---
linkers/rtems-addr2line.cpp | 289 ++++++++++++++++++++++++++++++++++++++++++++
linkers/wscript | 15 ++-
2 files changed, 303 insertions(+), 1 deletion(-)
create mode 100644 linkers/rtems-addr2line.cpp
diff --git a/linkers/rtems-addr2line.cpp b/linkers/rtems-addr2line.cpp
new file mode 100644
index 0000000..2e79c62
--- /dev/null
+++ b/linkers/rtems-addr2line.cpp
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2018, Chris Johns <chrisj at rtems.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rld
+ *
+ * @brief RTEMS Address to Line is a version of the classic addr2line
+ * utility to test the DWARF info support in the RTEMS Toolkit.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <iomanip>
+#include <iostream>
+
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <getopt.h>
+
+#include <rld.h>
+#include <rld-dwarf.h>
+#include <rld-files.h>
+#include <rld-rtems.h>
+
+#ifndef HAVE_KILL
+#define kill(p,s) raise(s)
+#endif
+
+/**
+ * RTEMS Symbols options.
+ */
+static struct option rld_opts[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, 'V' },
+ { "verbose", no_argument, NULL, 'v' },
+ { "executable", required_argument, NULL, 'e' },
+ { "addresses", no_argument, NULL, 'a' },
+ { "pretty-print", no_argument, NULL, 'p' },
+ { "basenames", no_argument, NULL, 's' },
+ { NULL, 0, NULL, 0 }
+};
+
+void
+usage (int exit_code)
+{
+ std::cout << "rtems-addr2line [options] addresses" << std::endl
+ << "Options and arguments:" << std::endl
+ << " -h : help (also --help)" << std::endl
+ << " -V : print version number and exit (also --version)" << std::endl
+ << " -v : verbose (trace import parts), can supply multiple times" << std::endl
+ << " to increase verbosity (also --verbose)" << std::endl
+ << " -e : executable (also --executablewarn)" << std::endl
+ << " -a : show addresses (also --addresses)" << std::endl
+ << " -p : human readable format (also --pretty-print)" << std::endl
+ << " -s : Strip directory paths (also --basenames)" << std::endl;
+ ::exit (exit_code);
+}
+
+static void
+fatal_signal (int signum)
+{
+ signal (signum, SIG_DFL);
+
+ /*
+ * Get the same signal again, this time not handled, so its normal effect
+ * occurs.
+ */
+ kill (getpid (), signum);
+}
+
+static void
+setup_signals (void)
+{
+ if (signal (SIGINT, SIG_IGN) != SIG_IGN)
+ signal (SIGINT, fatal_signal);
+#ifdef SIGHUP
+ if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
+ signal (SIGHUP, fatal_signal);
+#endif
+ if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
+ signal (SIGTERM, fatal_signal);
+#ifdef SIGPIPE
+ if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
+ signal (SIGPIPE, fatal_signal);
+#endif
+#ifdef SIGCHLD
+ signal (SIGCHLD, SIG_DFL);
+#endif
+}
+
+void
+unhandled_exception (void)
+{
+ std::cerr << "error: exception handling error, please report" << std::endl;
+ exit (13);
+}
+
+int
+main (int argc, char* argv[])
+{
+ int ec = 0;
+
+ setup_signals ();
+
+ std::set_terminate(unhandled_exception);
+
+ try
+ {
+ std::string exe_name = "a.out";
+ bool show_addresses = false;
+ bool pretty_print = false;
+ bool show_basenames = false;
+
+ rld::set_cmdline (argc, argv);
+
+ while (true)
+ {
+ int opt = ::getopt_long (argc, argv, "hvVe:aps", rld_opts, NULL);
+ if (opt < 0)
+ break;
+
+ switch (opt)
+ {
+ case 'V':
+ std::cout << "rtems-addr2line (RTEMS Address To Line) " << rld::version ()
+ << ", RTEMS revision " << rld::rtems::version ()
+ << std::endl;
+ ::exit (0);
+ break;
+
+ case 'v':
+ rld::verbose_inc ();
+ break;
+
+ case 'e':
+ exe_name = optarg;
+ break;
+
+ case 'a':
+ show_addresses = true;
+ break;
+
+ case 'p':
+ pretty_print = true;
+ break;
+
+ case 's':
+ show_basenames = true;
+ break;
+
+ case '?':
+ usage (3);
+ break;
+
+ case 'h':
+ usage (0);
+ break;
+ }
+ }
+
+ /*
+ * Set the program name.
+ */
+ rld::set_progname (argv[0]);
+
+ argc -= optind;
+ argv += optind;
+
+ if (rld::verbose ())
+ std::cout << "RTEMS Address To Line " << rld::version () << std::endl;
+
+ /*
+ * If there are no object files there is nothing to link.
+ */
+ if (argc == 0)
+ throw rld::error ("no addresses provided", "options");
+
+ if (rld::verbose ())
+ std::cout << "exe: " << exe_name << std::endl;
+
+ /*
+ * Load the executable's debug info.
+ */
+ rld::files::object exe (exe_name);
+ rld::dwarf::file debug;
+
+ try
+ {
+ /*
+ * Load the executable's ELF file debug info.
+ */
+ exe.open ();
+ exe.begin ();
+ debug.begin (exe.elf ());
+ debug.load_debug ();
+
+ for (int arg = 0; arg < argc; ++arg)
+ {
+ rld::dwarf::dwarf_address location;
+
+ if (rld::verbose ())
+ std::cout << "address: " << argv[arg] << std::endl;
+
+ /*
+ * Use the C routine as C++ does not have a way to automatically handle
+ * different bases on the input.
+ */
+ location = ::strtoul (argv[arg], 0, 0);
+
+ std::string path;
+ int line;
+
+ debug.get_source (location, path, line);
+
+ if (show_addresses)
+ {
+ std::cout << std::hex << std::setfill ('0')
+ << "0x" << location
+ << std::dec << std::setfill (' ');
+
+ if (pretty_print)
+ std::cout << ": ";
+ else
+ std::cout << std::endl;
+ }
+
+ if (show_basenames)
+ std::cout << rld::path::basename (path);
+ else
+ std::cout << path;
+
+ std::cout << ':' << line << std::endl;
+ }
+
+ debug.end ();
+ exe.end ();
+ exe.close ();
+ }
+ catch (...)
+ {
+ debug.end ();
+ exe.end ();
+ exe.close ();
+ throw;
+ }
+ }
+ catch (rld::error re)
+ {
+ std::cerr << "error: "
+ << re.where << ": " << re.what
+ << std::endl;
+ ec = 10;
+ }
+ catch (std::exception e)
+ {
+ rld::output_std_exception (e, std::cerr);
+ ec = 11;
+ }
+ catch (...)
+ {
+ /*
+ * Helps to know if this happens.
+ */
+ std::cout << "error: unhandled exception" << std::endl;
+ ec = 12;
+ }
+
+ return ec;
+}
diff --git a/linkers/wscript b/linkers/wscript
index 10fe2a0..23d3f9c 100644
--- a/linkers/wscript
+++ b/linkers/wscript
@@ -58,6 +58,7 @@ def build(bld):
rtemstoolkit + '/elftoolchain/libelf',
rtemstoolkit + '/elftoolchain/libdwarf',
rtemstoolkit + '/elftoolchain/common',
+ rtemstoolkit + '/elftoolchain/libelftc',
rtemstoolkit + '/libiberty']
if bld.env.DEST_OS == 'win32':
conf['includes'] += [rtemstoolkit + '/win32']
@@ -70,7 +71,7 @@ def build(bld):
#
# The list of modules.
#
- modules = ['rld', 'dwarf', 'elf', 'iberty']
+ modules = ['rld', 'elftc', 'dwarf', 'elf', 'iberty']
#
# The list of defines
@@ -165,5 +166,17 @@ def build(bld):
linkflags = conf['linkflags'],
use = modules)
+ #
+ # Build the address to line tool.
+ #
+ bld.program(target = 'rtems-addr2line',
+ source = ['rtems-addr2line.cpp'],
+ defines = defines,
+ includes = ['.'] + conf['includes'],
+ cflags = conf['cflags'] + conf['warningflags'],
+ cxxflags = conf['cxxflags'] + conf['warningflags'],
+ linkflags = conf['linkflags'],
+ use = modules)
+
def tags(ctx):
ctx.exec_command('etags $(find . -name \*.[sSch])', shell = True)
--
2.15.1
More information about the devel
mailing list