Changeset 29ad92c in rtems-tools


Ignore:
Timestamp:
Mar 23, 2015, 6:19:01 AM (4 years ago)
Author:
Chris Johns <chrisj@…>
Branches:
4.10, 4.11, master
Children:
1703041
Parents:
8531776
Message:

trace-linker: Add options, names, enables, and triggers.

Move the options to a section so an option can be a single line. This
gives the user the ability to localise specific configurations in a
top level configuration file.

Provide support for names, enables and triggers. Names is an array of
names of the trace functions. The table is sorted and you can use an
index to reference the trace function. There is a @FUNC_INDEX@ macro
that is replaced with the trace function's index. Enables is a bitmap
of default trace enabled states for all trace functions. Triggers is
a bitmap of default triggers bit states for each trace function.
Generators can use these bitmaps to control functionality.

Currently the bitmaps are const but a generator option can be added
to disable the const and allow the capture engine access to update
the bitmaps.

Location:
linkers
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • linkers/rtems-tld.cpp

    r8531776 r29ad92c  
    11/*
    2  * Copyright (c) 2014, Chris Johns <chrisj@rtems.org>
     2 * Copyright (c) 2014-2015, Chris Johns <chrisj@rtems.org>
    33 *
    44 * Permission to use, copy, modify, and/or distribute this software for any
     
    3131#include <functional>
    3232#include <iostream>
     33#include <iomanip>
    3334#include <locale>
    3435#include <sstream>
     
    7576
    7677    /**
     78     * An option is a name and value pair. We consider options as global.
     79     */
     80    struct option
     81    {
     82      std::string name;      /**< The name of this option. */
     83      std::string value;     /**< The option's value.. */
     84
     85      /**
     86       * Load the option.
     87       */
     88      option (const std::string& name, const std::string& value)
     89        : name (name),
     90          value (value) {
     91      }
     92    };
     93
     94    /**
     95     * A container of options.
     96     */
     97    typedef std::vector < option > options;
     98
     99    /**
    77100     * A function's signature.
    78101     */
     
    191214       * Process any script based options.
    192215       */
    193       void load_options (const rld::config::section& section);
    194 
    195       /**
    196        * The the functions for the trace.
     216      void load_options (rld::config::config&        config,
     217                         const rld::config::section& section);
     218
     219      /**
     220       * The defines for the trace.
     221       */
     222      void load_defines (rld::config::config&        config,
     223                         const rld::config::section& section);
     224
     225      /**
     226       * The functions for the trace.
    197227       */
    198228      void load_functions (rld::config::config&        config,
     
    200230
    201231      /**
    202        * The the traces for the tracer.
     232       * The enables for the tracer.
     233       */
     234      void load_enables (rld::config::config&        config,
     235                         const rld::config::section& section);
     236
     237      /**
     238       * The triggers for the tracer.
     239       */
     240      void load_triggers (rld::config::config&        config,
     241                          const rld::config::section& section);
     242
     243      /**
     244       * The traces for the tracer.
    203245       */
    204246      void load_traces (rld::config::config&        config,
     
    206248
    207249      /**
     250       * Get option from the options section.
     251       */
     252      const std::string get_option (const std::string& name) const;
     253
     254      /**
    208255       * Generate the wrapper object file.
    209256       */
     
    211258
    212259      /**
     260       * Generate the trace names as a string table.
     261       */
     262      void generate_names (rld::process::tempfile& c);
     263
     264      /**
     265       * Generate the enabled trace bitmap.
     266       */
     267      void generate_enables (rld::process::tempfile& c);
     268
     269      /**
     270       * Generate the triggered trace bitmap.
     271       */
     272      void generate_triggers (rld::process::tempfile& c);
     273
     274      /**
    213275       * Generate the trace functions.
    214276       */
     
    216278
    217279      /**
     280       * Generate a bitmap.
     281       */
     282      void generate_bitmap (rld::process::tempfile& c,
     283                            const rld::strings&     names,
     284                            const std::string&      label,
     285                            const bool              global_set);
     286
     287      /**
    218288       * Get the traces.
    219289       */
     
    228298
    229299      std::string  name;          /**< The name of the trace. */
     300      rld::strings defines;       /**< Define statements. */
     301      rld::strings enables;       /**< The default enabled functions. */
     302      rld::strings triggers;      /**< The default trigger functions. */
    230303      rld::strings traces;        /**< The functions to trace. */
     304      options      options_;      /**< The options. */
    231305      functions    functions_;    /**< The functions that can be traced. */
    232306      generator    generator_;    /**< The tracer's generator. */
     
    244318       * Load the user's configuration.
    245319       */
    246       void load_config (const std::string& path,
    247                         const std::string& trace);
     320      void load_config (const std::string& name,
     321                        const std::string& trace,
     322                        const std::string& path);
    248323
    249324      /**
     
    480555       * # header      A list of include string that are single or double quoted.
    481556       * # defines     A list of sections containing defines or define record.
    482        * # defines     A list of define string that are single or double quoted.
     557       * # define      A list of define string that are single or double quoted.
    483558       * # code-blocks A list of section names of code blocks.
    484559       * # includes    A list of files to include.
     
    548623       *
    549624       *  # name      The name of trace being linked.
    550        *  # options   A list of options as per the long command line args.
     625       *  # options   A list of option sections.
     626       *  # defines   A list of sections containing defines or define record.
     627       *  # define    A list of define string that are single or double quoted.
     628       *  # enables   The list of sections containing enabled functions to trace.
     629       *  # triggers  The list of sections containing enabled functions to trigger trace on.
    551630       *  # traces    The list of sections containing function lists to trace.
    552631       *  # functions The list of sections containing function details.
     
    562641
    563642      name = section.get_record_item ("name");
    564       load_options (section);
     643      load_options (config, section);
    565644      config.includes (section);
     645      load_defines (config, section);
    566646      load_functions (config, section);
     647      load_enables (config, section);
     648      load_triggers (config, section);
    567649      load_traces (config, section);
    568650    }
    569651
    570652    void
    571     tracer::load_options (const rld::config::section& section)
    572     {
    573       rld::strings ol;
    574       rld::config::parse_items (section, "options", ol, true);
    575 
    576       for (rld::strings::const_iterator oli = ol.begin ();
    577            oli != ol.end ();
    578            ++oli)
    579       {
    580         rld::strings opts;
    581         rld::split(opts, *oli, ',');
    582         for (rld::strings::const_iterator oi = opts.begin ();
    583              oi != opts.end ();
    584              ++oi)
     653    tracer::load_options (rld::config::config&        config,
     654                          const rld::config::section& section)
     655    {
     656      rld::strings opts;
     657      rld::config::parse_items (section, "options", opts, false, true, true);
     658
     659      if (rld::verbose ())
     660        std::cout << "options: " << section.name << ": " << opts.size () << std::endl;
     661
     662      options_.clear ();
     663
     664      for (rld::strings::const_iterator osi = opts.begin ();
     665           osi != opts.end ();
     666           ++osi)
     667      {
     668        const rld::config::section& osec = config.get_section (*osi);
     669
     670        if (rld::verbose ())
     671          std::cout << " options: " << osec.name
     672                    << ": recs:" << osec.recs.size () << std::endl;
     673
     674        for (rld::config::records::const_iterator ori = osec.recs.begin ();
     675             ori != osec.recs.end ();
     676             ++ori)
    585677        {
    586           const std::string& opt = *oi;
    587           if (opt == "dump-on-error")
     678          const rld::config::record& opt = *ori;
     679
     680          if (!opt.single ())
     681              throw rld::error ("mode than one option specified", "option: " + opt.name);
     682
     683          options_.push_back (option (opt.name, opt[0]));
     684
     685          if (opt.name == "dump-on-error")
     686          {
    588687            dump_on_error = true;
    589           else if (opt == "verbose")
    590             rld::verbose_inc ();
    591           else if (opt == "prefix")
     688          }
     689          else if (opt.name == "verbose")
    592690          {
    593             rld::strings prefix;
    594             rld::split (prefix, opt, '=');
    595             if (prefix.size () != 2)
    596               throw rld::error ("invalid option", "option: " + opt);
    597             rld::cc::set_exec_prefix (prefix[1]);
     691            int level = ::strtoul(opt[0].c_str (), 0, 0);
     692            if (level == 0)
     693              level = 1;
     694            for (int l = 0; l < level; ++l)
     695              rld::verbose_inc ();
    598696          }
    599           else if (opt == "cc")
     697          else if (opt.name == "prefix")
    600698          {
    601             rld::strings cc;
    602             rld::split (cc, opt, '=');
    603             if (cc.size () != 2)
    604               throw rld::error ("invalid option", "option: " + opt);
    605             rld::cc::set_cc (cc[1]);
     699            rld::cc::set_exec_prefix (opt[0]);
    606700          }
    607           else if (opt == "ld")
     701          else if (opt.name == "cc")
    608702          {
    609             rld::strings ld;
    610             rld::split (ld, opt, '=');
    611             if (ld.size () != 2)
    612               throw rld::error ("invalid option", "option: " + opt);
    613             rld::cc::set_ld (ld[1]);
     703            rld::cc::set_cc (opt[0]);
    614704          }
    615           else if (opt == "cflags")
     705          else if (opt.name == "ld")
    616706          {
    617             rld::strings cflags;
    618             rld::split (cflags, opt, '=');
    619             if (cflags.size () < 2)
    620               throw rld::error ("invalid option", "option: " + opt);
    621             cflags.erase (cflags.begin ());
    622             rld::cc::append_flags (rld::join (cflags, "="), rld::cc::ft_cflags);
     707            rld::cc::set_ld (opt[0]);
     708          }
     709          else if (opt.name == "cflags")
     710          {
     711            rld::cc::append_flags (opt[0], rld::cc::ft_cflags);
     712          }
     713          else if (opt.name == "rtems-path")
     714          {
     715            rld::rtems::set_path(opt[0]);
     716          }
     717          else if (opt.name == "rtems-bsp")
     718          {
     719            rld::rtems::set_arch_bsp(opt[0]);
    623720          }
    624721        }
    625722      }
     723    }
     724
     725    void
     726    tracer::load_defines (rld::config::config&        config,
     727                          const rld::config::section& section)
     728    {
     729      parse (config, section, "defines", "define", defines);
    626730    }
    627731
     
    641745
    642746    void
     747    tracer::load_enables (rld::config::config&        config,
     748                          const rld::config::section& section)
     749    {
     750      parse (config, section, "enables", "enable", enables);
     751    }
     752
     753    void
     754    tracer::load_triggers (rld::config::config&        config,
     755                           const rld::config::section& section)
     756    {
     757      parse (config, section, "triggers", "trigger", triggers);
     758    }
     759
     760    void
    643761    tracer::load_traces (rld::config::config&        config,
    644762                         const rld::config::section& section)
     
    669787      }
    670788
     789      sort (traces.begin (), traces.end ());
     790
    671791      generator_ = generator (config, gen);
     792    }
     793
     794    const std::string
     795    tracer::get_option (const std::string& name) const
     796    {
     797      std::string value;
     798      for (options::const_iterator oi = options_.begin ();
     799           oi != options_.end ();
     800           ++oi)
     801      {
     802        const option& opt = *oi;
     803        if (opt.name == name)
     804        {
     805          value = opt.value;
     806          break;
     807        }
     808      }
     809      return value;
    672810    }
    673811
     
    686824        c.write_line (" *  Automatically generated.");
    687825        c.write_line (" */");
     826
     827        c.write_line ("");
     828        c.write_line ("/*");
     829        c.write_line (" * Tracer: " + name);
     830        c.write_line (" */");
     831        c.write_lines (defines);
    688832
    689833        c.write_line ("");
     
    694838        c.write_lines (generator_.headers);
    695839        c.write_line ("");
     840        generate_names (c);
     841        generate_enables (c);
     842        generate_triggers (c);
     843        c.write_line ("");
    696844        c.write_lines (generator_.code);
    697845
     
    713861        c.output (" ", std::cout, true);
    714862      }
     863    }
     864
     865    void
     866    tracer::generate_names (rld::process::tempfile& c)
     867    {
     868      const std::string opt = get_option ("gen-names");
     869
     870      if (opt == "disable")
     871        return;
     872
     873      c.write_line ("");
     874      c.write_line ("/*");
     875      c.write_line (" * Names.");
     876      c.write_line (" */");
     877
     878      std::stringstream sss;
     879      sss << "const char const* __rld_trace_names[" << traces.size() << "] = " << std::endl
     880          << "{";
     881      c.write_line (sss.str ());
     882
     883      int count = 0;
     884
     885      for (rld::strings::const_iterator ti = traces.begin ();
     886           ti != traces.end ();
     887           ++ti)
     888      {
     889        const std::string& trace = *ti;
     890        sss.str (std::string ());
     891        sss << "  /* " << std::setw (3) << count << " */ \"" << trace << "\",";
     892        c.write_line (sss.str ());
     893        ++count;
     894      }
     895
     896      c.write_line ("};");
     897    }
     898
     899    void
     900    tracer::generate_enables (rld::process::tempfile& c)
     901    {
     902      const std::string opt = get_option ("gen-enables");
     903      bool              global_state = false;
     904
     905      if (opt == "disable")
     906        return;
     907
     908      if (opt == "global-on")
     909        global_state = true;
     910
     911      c.write_line ("");
     912      c.write_line ("/*");
     913      c.write_line (" * Enables.");
     914      c.write_line (" */");
     915
     916      generate_bitmap (c, enables, "enables", global_state);
     917    }
     918
     919    void
     920    tracer::generate_triggers (rld::process::tempfile& c)
     921    {
     922      const std::string opt = get_option ("gen-triggers");
     923      bool              global_state = false;
     924
     925      if (opt == "disable")
     926        return;
     927
     928      if (opt == "global-on")
     929        global_state = true;
     930
     931      c.write_line ("");
     932      c.write_line ("/*");
     933      c.write_line (" * Triggers.");
     934      c.write_line (" */");
     935
     936      generate_bitmap (c, triggers, "triggers", global_state);
     937
     938      c.write_line ("");
    715939    }
    716940
     
    749973      c.write_line (" */");
    750974
     975      size_t count = 0;
     976
    751977      for (rld::strings::const_iterator ti = traces.begin ();
    752978           ti != traces.end ();
     
    7781004              c.write_line(" " + sig.ret + " ret;");
    7791005
     1006            std::stringstream lss;
     1007            lss << count;
     1008
    7801009            std::string l;
    7811010
    7821011            if (!generator_.entry_trace.empty ())
    7831012            {
    784               std::string l = ' ' + generator_.entry_trace;
     1013              std::string       l = ' ' + generator_.entry_trace;
    7851014              l = rld::find_replace (l, "@FUNC_NAME@", '"' + sig.name + '"');
     1015              l = rld::find_replace (l, "@FUNC_INDEX@", lss.str ());
    7861016              l = rld::find_replace (l, "@FUNC_LABEL@", sig.name);
    7871017              c.write_line(l);
     
    8241054              std::string l = ' ' + generator_.exit_trace;
    8251055              l = rld::find_replace (l, "@FUNC_NAME@", '"' + sig.name + '"');
     1056              l = rld::find_replace (l, "@FUNC_INDEX@", lss.str ());
    8261057              l = rld::find_replace (l, "@FUNC_LABEL@", sig.name);
    8271058              c.write_line(l);
     
    8441075        if (!found)
    8451076          throw rld::error ("not found", "trace function: " + trace);
    846       }
     1077
     1078        ++count;
     1079      }
     1080    }
     1081
     1082    void
     1083    tracer::generate_bitmap (rld::process::tempfile& c,
     1084                             const rld::strings&     names,
     1085                             const std::string&      label,
     1086                             const bool              global_set)
     1087    {
     1088      uint32_t bitmap_size = ((traces.size () - 1) / (4 * 8)) + 1;
     1089
     1090      std::stringstream ss;
     1091
     1092      ss << "const uint32_t __rtld_trace_" << label << "[" << bitmap_size << "] = " << std::endl
     1093         << "{" << std::endl;
     1094
     1095      size_t   count = 0;
     1096      size_t   bit = 0;
     1097      uint32_t bitmask = 0;
     1098
     1099      for (rld::strings::const_iterator ti = traces.begin ();
     1100           ti != traces.end ();
     1101           ++ti)
     1102      {
     1103        const std::string& trace = *ti;
     1104        bool               set = global_set;
     1105        if (!global_set)
     1106        {
     1107          for (rld::strings::const_iterator ni = names.begin ();
     1108               ni != names.end ();
     1109               ++ni)
     1110          {
     1111            const std::string& name = *ni;
     1112            if (trace == name)
     1113              set = true;
     1114          }
     1115        }
     1116        if (set)
     1117          bitmask |= 1 << bit;
     1118        ++bit;
     1119        ++count;
     1120        if ((bit >= 32) || (count >= traces.size ()))
     1121        {
     1122          ss << " 0x" << std::hex << std::setfill ('0') << std::setw (8) << bitmask << ',';
     1123          if ((count % 4) == 0)
     1124            ss << std::endl;
     1125          bit = 0;
     1126          bitmask = 0;
     1127        }
     1128      }
     1129
     1130      c.write_line (ss.str ());
     1131
     1132      c.write_line ("};");
    8471133    }
    8481134
     
    8801166
    8811167    void
    882     linker::load_config (const std::string& path,
    883                          const std::string& trace)
     1168    linker::load_config (const std::string& name,
     1169                         const std::string& trace,
     1170                         const std::string& path)
    8841171    {
    8851172      std::string sp = get_prefix ();
     
    8891176      rld::path::path_join (sp, "trace-linker", sp);
    8901177
     1178      if (!path.empty ())
     1179        sp = path + ':' + sp;
     1180
    8911181      if (rld::verbose ())
    8921182        std::cout << "search path: " << sp << std::endl;
     
    8941184      config.set_search_path (sp);
    8951185      config.clear ();
    896       config.load (path);
     1186      config.load (name);
    8971187      tracer_.load (config, trace);
    8981188    }
     
    10131303  { "rtems-bsp",   required_argument,      NULL,           'B' },
    10141304  { "config",      required_argument,      NULL,           'C' },
     1305  { "path",        required_argument,      NULL,           'P' },
    10151306  { "wrapper",     required_argument,      NULL,           'W' },
    10161307  { NULL,          0,                      NULL,            0 }
     
    10351326            << " -B bsp      : RTEMS arch/bsp (also --rtems-bsp)" << std::endl
    10361327            << " -W wrapper  : wrapper file name without ext (also --wrapper)" << std::endl
    1037             << " -C ini      : user configuration INI file (also --config)" << std::endl;
     1328            << " -C ini      : user configuration INI file (also --config)" << std::endl
     1329            << " -P path     : user configuration file search path (also --path)" << std::endl;
    10381330  ::exit (exit_code);
    10391331}
     
    10871379    std::string        ld_cmd;
    10881380    std::string        configuration;
     1381    std::string        path;
    10891382    std::string        trace = "tracer";
    10901383    std::string        wrapper;
     
    10961389    while (true)
    10971390    {
    1098       int opt = ::getopt_long (argc, argv, "hvwkVc:l:E:f:C:r:B:W:", rld_opts, NULL);
     1391      int opt = ::getopt_long (argc, argv, "hvwkVc:l:E:f:C:P:r:B:W:", rld_opts, NULL);
    10991392      if (opt < 0)
    11001393        break;
     
    11481441        case 'C':
    11491442          configuration = optarg;
     1443          break;
     1444
     1445        case 'P':
     1446          if (!path.empty ())
     1447            path += ":";
     1448          path += optarg;
    11501449          break;
    11511450
     
    12251524    try
    12261525    {
    1227       linker.load_config (configuration, trace);
     1526      linker.load_config (configuration, trace, path);
    12281527
    12291528      rld::process::tempfile c (".c");
  • linkers/test-trace.ini

    r8531776 r29ad92c  
    1414bsp = sparc/sis
    1515;
    16 ; Options can be defined here or on the command line.
    17 ;
    18 options = all-funcs, verbose
    19 ;
    2016; Functions to trace.
    2117;
    2218traces = test-trace, test-trace-funcs, rtems-api-task
     19;
     20; Specify the options.
     21;
     22options = test-options
    2323;
    2424; Define the function sets. These are the function's that can be
     
    3030;
    3131include = rtems.ini, rtld-base.ini
     32
     33;
     34; Options can be defined here or on the command line.
     35;
     36[trace-options]
     37all-funcs = true
     38verbose = true
    3239
    3340;
Note: See TracChangeset for help on using the changeset viewer.