[PATCH] linkers/syms: Add symbol filtering.

chrisj at rtems.org chrisj at rtems.org
Mon Feb 11 05:43:14 UTC 2019


From: Chris Johns <chrisj at rtems.org>

- Filter symbols by regx.
- Return the name of a symbol via demangled() even it is not
  a mangled C++ function.
---
 linkers/rtems-syms.cpp       | 122 +++++++++++++++++++++++++++++------
 rtemstoolkit/rld-symbols.cpp |   6 +-
 2 files changed, 106 insertions(+), 22 deletions(-)

diff --git a/linkers/rtems-syms.cpp b/linkers/rtems-syms.cpp
index 58df50f..5ebdceb 100644
--- a/linkers/rtems-syms.cpp
+++ b/linkers/rtems-syms.cpp
@@ -29,6 +29,7 @@
 #include <fstream>
 #include <iomanip>
 #include <iostream>
+#include <regex>
 
 #include <cxxabi.h>
 #include <signal.h>
@@ -142,6 +143,70 @@ c_embedded_trailer (rld::process::tempfile& c)
   temporary_file_paint (c, c_rtl_call_body);
 }
 
+/**
+ * Filter the symbols given a list of regx expressions.
+ */
+class symbol_filter
+{
+public:
+  typedef std::vector < std::string > expressions;
+
+  symbol_filter ();
+
+  void load (const std::string& file);
+  void add (const std::string& re);
+
+  void filter (const rld::symbols::symtab& symbols,
+               rld::symbols::symtab&       filtered_symbols);
+
+private:
+
+  expressions expr;
+};
+
+symbol_filter::symbol_filter ()
+{
+}
+
+void
+symbol_filter::load (const std::string& file)
+{
+  std::ifstream in (file);
+  std::string   re;
+  while (in >> re)
+    add (re);
+}
+
+void
+symbol_filter::add (const std::string& re)
+{
+  expr.push_back (re);
+}
+
+void
+symbol_filter::filter (const rld::symbols::symtab& symbols,
+                       rld::symbols::symtab&       filtered_symbols)
+{
+  if (expr.size () > 0)
+  {
+    for (auto& re : expr)
+    {
+      const std::regex sym_re(re);
+      for (const auto& sym : symbols)
+      {
+        std::smatch      m;
+        if (std::regex_match (sym.second->demangled (), m, sym_re))
+          filtered_symbols[sym.first] = sym.second;
+      }
+    }
+  }
+  else
+  {
+    for (const auto& sym : symbols)
+      filtered_symbols[sym.first] = sym.second;
+  }
+}
+
 /**
  * Generate the symbol map object file for loading or linking into
  * a running RTEMS machine.
@@ -192,28 +257,21 @@ output_sym::operator ()(const rld::symbols::symtab::value_type& value)
 
 static void
 generate_c (rld::process::tempfile& c,
-            rld::symbols::table&    symbols,
+            rld::symbols::symtab&   symbols,
             bool                    embed)
 {
   temporary_file_paint (c, c_header);
 
   /*
-   * Add the global symbols.
+   * Add the symbols. The is the globals and the weak symbols that have been
+   * linked into the base image. A weak symbols present in the base image is no
+   * longer weak and should be consider a global symbol. You cannot link a
+   * global symbol with the same in a dynamically loaded module.
    */
-  std::for_each (symbols.globals ().begin (),
-                 symbols.globals ().end (),
+  std::for_each (symbols.begin (),
+                 symbols.end (),
                  output_sym (c, embed, false));
 
-  /*
-   * Add the weak symbols that have been linked into the base image. A weak
-   * symbols present in the base image is no longer weak and should be consider
-   * a global symbol. You cannot link a global symbol with the same in a
-   * dynamically loaded module.
-   */
-  std::for_each (symbols.weaks ().begin (),
-                 symbols.weaks ().end (),
-                 output_sym (c, embed, true));
-
   temporary_file_paint (c, c_trailer);
 
   if (embed)
@@ -225,7 +283,7 @@ generate_c (rld::process::tempfile& c,
 static void
 generate_symmap (rld::process::tempfile& c,
                  const std::string&      output,
-                 rld::symbols::table&    symbols,
+                 rld::symbols::symtab&   symbols,
                  bool                    embed)
 {
   c.open (true);
@@ -283,6 +341,8 @@ static struct option rld_opts[] = {
   { "cc",          required_argument,      NULL,           'C' },
   { "exec-prefix", required_argument,      NULL,           'E' },
   { "cflags",      required_argument,      NULL,           'c' },
+  { "filter",      required_argument,      NULL,           'f' },
+  { "filter-re",   required_argument,      NULL,           'F' },
   { NULL,          0,                      NULL,            0 }
 };
 
@@ -301,9 +361,11 @@ usage (int exit_code)
             << " -S file   : symbol's C file (also --symc)" << std::endl
             << " -o file   : output object file (also --output)" << std::endl
             << " -m file   : output a map file (also --map)" << std::endl
-            << " -C file   : execute file as the target C compiler (also --cc)" << std::endl
+            << " -C file   : target C compiler executable (also --cc)" << std::endl
             << " -E prefix : the RTEMS tool prefix (also --exec-prefix)" << std::endl
-            << " -c cflags : C compiler flags (also --cflags)" << std::endl;
+            << " -c cflags : C compiler flags (also --cflags)" << std::endl
+            << " -f file   : file of symbol filters (also --filter)" << std::endl
+            << " -F re     : filter regx expression (also --filter-re)" << std::endl;
   ::exit (exit_code);
 }
 
@@ -352,6 +414,7 @@ main (int argc, char* argv[])
   {
     rld::files::cache   kernel;
     rld::symbols::table symbols;
+    symbol_filter       filter;
     std::string         kernel_name;
     std::string         output;
     std::string         map;
@@ -363,7 +426,7 @@ main (int argc, char* argv[])
 
     while (true)
     {
-      int opt = ::getopt_long (argc, argv, "hvVwkef:S:o:m:E:c:C:", rld_opts, NULL);
+      int opt = ::getopt_long (argc, argv, "hvVwkef:S:o:m:E:c:C:f:F:", rld_opts, NULL);
       if (opt < 0)
         break;
 
@@ -419,6 +482,14 @@ main (int argc, char* argv[])
           symc = optarg;
           break;
 
+        case 'f':
+          filter.load (optarg);
+          break;
+
+        case 'F':
+          filter.add (optarg);
+          break;
+
         case '?':
           usage (3);
           break;
@@ -478,6 +549,17 @@ main (int argc, char* argv[])
       if (!rld::cc::is_cc_set () && !rld::cc::is_exec_prefix_set ())
         rld::cc::set_exec_prefix (rld::elf::machine_type ());
 
+      /*
+       * Filter the symbols.
+       */
+      rld::symbols::symtab filter_symbols;
+      filter.filter (symbols.globals (), filter_symbols);
+      filter.filter (symbols.weaks (), filter_symbols);
+      if (filter_symbols.size () == 0)
+        throw rld::error ("no filtered symbols", "filter");
+      if (rld::verbose ())
+        std::cout << "Filtered symbols: " << filter_symbols.size () << std::endl;
+
       /*
        * Create a map file if asked too.
        */
@@ -490,7 +572,7 @@ main (int argc, char* argv[])
         mout << "RTEMS Kernel Symbols Map" << std::endl
              << " kernel: " << kernel_name << std::endl
              << std::endl;
-        rld::symbols::output (mout, symbols);
+        rld::symbols::output (mout, filter_symbols);
         mout.close ();
       }
 
@@ -510,7 +592,7 @@ main (int argc, char* argv[])
         /*
          * Generate and compile the symbol map.
          */
-        generate_symmap (c, output, symbols, embed);
+        generate_symmap (c, output, filter_symbols, embed);
       }
 
       kernel.close ();
diff --git a/rtemstoolkit/rld-symbols.cpp b/rtemstoolkit/rld-symbols.cpp
index 642d53f..00af9b5 100644
--- a/rtemstoolkit/rld-symbols.cpp
+++ b/rtemstoolkit/rld-symbols.cpp
@@ -88,7 +88,8 @@ namespace rld
     {
       if (!object_)
         throw rld_error_at ("object pointer is 0");
-      demangle_name (name_, demangled_);
+      if (!demangle_name (name_, demangled_))
+        demangled_ = name_;
     }
 
     symbol::symbol (int                 index,
@@ -100,7 +101,8 @@ namespace rld
         esym_ (esym),
         references_ (0)
     {
-      demangle_name (name_, demangled_);
+      if (!demangle_name (name_, demangled_))
+        demangled_ = name_;
     }
 
     symbol::symbol (const std::string&  name,
-- 
2.17.2 (Apple Git-113)



More information about the devel mailing list