source: rtems-tools/linkers/rtems-tld.cpp @ 8807135

4.104.115
Last change on this file since 8807135 was 8807135, checked in by Chris Johns <chrisj@…>, on 09/06/14 at 10:19:45

Refactor the CC flags. Fix the various linkers. The trace linker is compiling.

  • Property mode set to 100644
File size: 26.7 KB
Line 
1/*
2 * Copyright (c) 2014, 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 Trace Linker manages creating a tracable RTEMS executable.
22 *
23 */
24
25#if HAVE_CONFIG_H
26#include "config.h"
27#endif
28
29#include <algorithm>
30#include <cctype>
31#include <functional>
32#include <iostream>
33#include <locale>
34#include <sstream>
35
36#include <cxxabi.h>
37#include <signal.h>
38#include <stdlib.h>
39#include <string.h>
40#include <unistd.h>
41
42#include <getopt.h>
43
44#include <rld.h>
45#include <rld-cc.h>
46#include <rld-config.h>
47#include <rld-process.h>
48#include <rld-rtems.h>
49
50#ifndef HAVE_KILL
51#define kill(p,s) raise(s)
52#endif
53
54namespace rld
55{
56  /**
57   * RTEMS Trace Linker.
58   */
59  namespace trace
60  {
61    /**
62     * A container of arguments.
63     */
64    typedef std::vector < std::string > function_args;
65
66    /**
67     * The return value.
68     */
69    typedef std::string function_return;
70
71    /**
72     * A function's signature.
73     */
74    struct signature
75    {
76      std::string     name; /**< The function's name. */
77      function_args   args; /**< The function's list of arguments. */
78      function_return ret;  /**< The fuctions return value. */
79
80      /**
81       * The default constructor.
82       */
83      signature ();
84
85      /**
86       * Construct the signature loading it from the configuration.
87       */
88      signature (const rld::config::record& record);
89
90      /**
91       * Return the function's declaration.
92       */
93      const std::string decl () const;
94    };
95
96    /**
97     * A container of signatures.
98     */
99    typedef std::map < std::string, signature > signatures;
100
101    /**
102     * A function is list of function signatures headers and defines that allow
103     * a function to be wrapped.
104     */
105    struct function
106    {
107      std::string  name;        /**< The name of this wrapper. */
108      rld::strings headers;     /**< Include statements. */
109      rld::strings defines;     /**< Define statements. */
110      signatures   signatures_; /**< Signatures in this function. */
111
112      /**
113       * Load the function.
114       */
115      function (rld::config::config& config,
116                const std::string&   name);
117
118      /**
119       * Dump the function.
120       */
121      void dump (std::ostream& out) const;
122    };
123
124    /**
125     * A container of functions.
126     */
127    typedef std::vector < function > functions;
128
129    /**
130     * A generator and that contains the functions used to trace arguments and
131     * return values. It also provides the implementation of those functions.
132     */
133    struct generator
134    {
135      std::string  name;            /**< The name of this wrapper. */
136      rld::strings headers;         /**< Include statements. */
137      rld::strings defines;         /**< Define statements. */
138      std::string  map_sym_prefix;  /**< Mapping symbol prefix. */
139      std::string  arg_trace;       /**< Code template to trace an argument. */
140      std::string  ret_trace;       /**< Code template to trace the return value. */
141      rld::strings code;            /**< Code block inserted before the trace code. */
142
143      /**
144       * Default constructor.
145       */
146      generator ();
147
148      /**
149       * Load the generator.
150       */
151      generator (rld::config::config& config,
152                 const std::string&   name);
153
154      /**
155       * Dump the generator.
156       */
157      void dump (std::ostream& out) const;
158    };
159
160    /**
161     * Tracer.
162     */
163    class tracer
164    {
165    public:
166      tracer ();
167
168      /**
169       * Load the user's configuration.
170       */
171      void load (rld::config::config& config,
172                 const std::string&   section);
173
174      /**
175       * The the functions for the trace.
176       */
177      void load_functions (rld::config::config&        config,
178                           const rld::config::section& section);
179
180      /**
181       * The the traces for the tracer.
182       */
183      void load_traces (rld::config::config&        config,
184                        const rld::config::section& section);
185
186      /**
187       * Generate the wrapper object file.
188       */
189      const std::string generate ();
190
191      /**
192       * Generate the trace functions.
193       */
194      void generate_traces (rld::process::tempfile& c);
195
196      /**
197       * Dump the wrapper.
198       */
199      void dump (std::ostream& out) const;
200
201    private:
202
203      std::string  name;       /**< The name of the trace. */
204      std::string  bsp;        /**< The BSP we are linking to. */
205      rld::strings traces;     /**< The functions to trace. */
206      functions    functions_; /**< The functions that can be traced. */
207      generator    generator_; /**< The tracer's generator. */
208    };
209
210    /**
211     * Trace Linker.
212     */
213    class linker
214    {
215    public:
216      linker ();
217
218      /**
219       * Load the user's configuration.
220       */
221      void load_config (const std::string& path,
222                        const std::string& trace);
223
224      /**
225       * Generate the C file.
226       */
227      void generate_wrapper ();
228
229      /**
230       * Compile the C file.
231       */
232      void compile_wrapper ();
233
234      /**
235       * Dump the linker.
236       */
237      void dump (std::ostream& out) const;
238
239    private:
240
241      rld::config::config config;     /**< User configuration. */
242      tracer              tracer_;    /**< The tracer */
243      std::string         wrapper_c;  /**< Wrapper C source file. */
244      std::string         wrapper_o;  /**< Wrapper object file. */
245    };
246
247    /**
248     * Recursive parser for strings.
249     */
250    void
251    parse (rld::config::config&        config,
252           const rld::config::section& section,
253           const std::string&          sec_name,
254           const std::string&          rec_name,
255           rld::strings&               items,
256           bool                        split = true,
257           int                         depth = 0)
258    {
259      if (depth > 32)
260        throw rld::error ("too deep", "parsing: " + sec_name + '/' + rec_name);
261
262      rld::config::parse_items (section, rec_name, items, false, false, split);
263
264      rld::strings sl;
265
266      rld::config::parse_items (section, sec_name, sl);
267
268      for (rld::strings::iterator sli = sl.begin ();
269           sli != sl.end ();
270           ++sli)
271      {
272        const rld::config::section& sec = config.get_section (*sli);
273        parse (config, sec, sec_name, rec_name, items, split, depth + 1);
274      }
275
276      /*
277       * Make the items unique.
278       */
279      rld::strings::iterator ii;
280      ii = std::unique (items.begin (), items.end ());
281      items.resize (std::distance (items.begin (), ii));
282    }
283
284    signature::signature ()
285    {
286    }
287
288    signature::signature (const rld::config::record& record)
289    {
290      /*
291       * There can only be one function signature in the configuration.
292       */
293      if (!record.single ())
294        throw rld::error ("duplicate", "signature: " + record.name);
295
296      name = record.name;
297
298      /*
299       * Signatures are defined as the return value then the arguments
300       * delimited by a comma and white space. No checking is made of the
301       * return value or arguments.
302       */
303      rld::strings si;
304      rld::config::parse_items (record, si);
305
306      if (si.size () == 0)
307        throw rld::error ("no return value", "signature: " + record.name);
308      if (si.size () == 1)
309          throw rld::error ("no arguments", "signature: " + record.name);
310
311      ret = si[0];
312      args.resize (si.size () - 1);
313      std::copy (si.begin ()  + 1, si.end (), args.begin ());
314    }
315
316    const std::string
317    signature::decl () const
318    {
319      std::string ds = ret + ' ' + name + '(';
320      int         arg = 0;
321      for (function_args::const_iterator ai = args.begin ();
322           ai != args.end ();
323           ++ai)
324        {
325          if (ai != args.begin ())
326            ds += ", ";
327          ds += (*ai) + " a" + rld::to_string (++arg);
328        }
329      ds += ')';
330      return ds;
331    }
332
333    function::function (rld::config::config& config,
334                        const std::string&   name)
335      : name (name)
336    {
337      /*
338       * A function section optionally contain one or more records of:
339       *
340       * # headers     A list of sections containing headers or header records.
341       * # header      A list of include string that are single or double quoted.
342       * # defines     A list of sections containing defines or define record.
343       * # defines     A list of define string that are single or double quoted.
344       * # signatures  A list of section names of signatures.
345       * # includes    A list of files to include.
346       *
347       * @note The quoting and list spliting is a little weak because a delimiter
348       *       in a quote should not be seen as a delimiter.
349       */
350      const rld::config::section& section = config.get_section (name);
351
352      config.includes (section);
353
354      parse (config, section, "headers", "header", headers);
355      parse (config, section, "defines", "define", defines);
356
357      rld::strings sig_list;
358      section.get_record_items ("signatures", sig_list);
359
360      for (rld::strings::const_iterator sli = sig_list.begin ();
361           sli != sig_list.end ();
362           ++sli)
363      {
364        const rld::config::section& sig_sec = config.get_section (*sli);
365        for (rld::config::records::const_iterator si = sig_sec.recs.begin ();
366             si != sig_sec.recs.end ();
367             ++si)
368        {
369          signature sig (*si);
370          signatures_[sig.name] = sig;
371        }
372      }
373    }
374
375    void
376    function::dump (std::ostream& out) const
377    {
378      out << "   Function: " << name << std::endl
379          << "    Headers: " << headers.size () << std::endl;
380      for (rld::strings::const_iterator hi = headers.begin ();
381           hi != headers.end ();
382           ++hi)
383      {
384        out << "     " << (*hi) << std::endl;
385      }
386      out << "   Defines: " << defines.size () << std::endl;
387      for (rld::strings::const_iterator di = defines.begin ();
388           di != defines.end ();
389           ++di)
390      {
391        out << "     " << (*di) << std::endl;
392      }
393      out << "   Signatures: " << signatures_.size () << std::endl;
394      for (signatures::const_iterator si = signatures_.begin ();
395           si != signatures_.end ();
396           ++si)
397      {
398        const signature& sig = (*si).second;
399        out << "     " << sig.name << ": " << sig.decl () << ';' << std::endl;
400      }
401    }
402
403    generator::generator ()
404    {
405    }
406
407    generator::generator (rld::config::config& config,
408                          const std::string&   name)
409      : name (name)
410    {
411      /*
412       * A generator section optionally contain one or more records of:
413       *
414       * # headers     A list of sections containing headers or header records.
415       * # header      A list of include string that are single or double quoted.
416       * # defines     A list of sections containing defines or define record.
417       * # defines     A list of define string that are single or double quoted.
418       * # code-blocks A list of section names of code blocks.
419       * # includes    A list of files to include.
420       *
421       * @note The quoting and list spliting is a little weak because a delimiter
422       *       in a quote should not be seen as a delimiter.
423       */
424      const rld::config::section& section = config.get_section (name);
425
426      config.includes (section);
427
428      parse (config, section, "headers",     "header", headers);
429      parse (config, section, "defines",     "define", defines);
430      parse (config, section, "code-blocks", "code",   code, false);
431
432      map_sym_prefix = section.get_record_item ("map-sym-prefix");
433      arg_trace = rld::dequote (section.get_record_item ("arg-trace"));
434      ret_trace = rld::dequote (section.get_record_item ("ret-trace"));
435    }
436
437    void
438    generator::dump (std::ostream& out) const
439    {
440      out << "  Generator: " << name << std::endl
441          << "   Headers: " << headers.size () << std::endl;
442      for (rld::strings::const_iterator hi = headers.begin ();
443           hi != headers.end ();
444           ++hi)
445      {
446        out << "    " << (*hi) << std::endl;
447      }
448      out << "   Defines: " << defines.size () << std::endl;
449      for (rld::strings::const_iterator di = defines.begin ();
450           di != defines.end ();
451           ++di)
452      {
453        out << "    " << (*di) << std::endl;
454      }
455      out << "   Mapping Symbol Prefix: " << map_sym_prefix << std::endl
456          << "   Arg Trace Code: " << arg_trace << std::endl
457          << "   Return Trace Code: " << ret_trace << std::endl
458          << "   Code blocks: " << std::endl;
459      for (rld::strings::const_iterator ci = code.begin ();
460           ci != code.end ();
461           ++ci)
462      {
463        out << "      > "
464            << rld::find_replace (*ci, "\n", "\n      | ") << std::endl;
465      }
466    }
467
468    tracer::tracer ()
469    {
470    }
471
472    void
473    tracer::load (rld::config::config& config,
474                  const std::string&   tname)
475    {
476      /*
477       * The configuration must contain a "section" section. This is the top level
478       * configuration and may contain:
479       *
480       *  # name      The name of trace being linked.
481       *  # bsp       The architecture/bsp name of the BSP.
482       *  # options   A list of options as per the long command line args.
483       *  # traces    The list of sections containing function lists to trace.
484       *  # functions The list of sections containing function details.
485       *  # include   The list of files to include.
486       *
487       * The following records are required:
488       *
489       *  # name
490       *  # bsp
491       *  # trace
492       *  # functions
493       */
494      const rld::config::section& section = config.get_section (tname);
495
496      config.includes (section);
497
498      name = section.get_record_item ("name");
499      bsp  = section.get_record_item ("bsp");
500
501      load_functions (config, section);
502      load_traces (config, section);
503    }
504
505    void
506    tracer::load_functions (rld::config::config&        config,
507                            const rld::config::section& section)
508    {
509      rld::strings fl;
510      rld::config::parse_items (section, "functions", fl, true);
511      for (rld::strings::const_iterator fli = fl.begin ();
512           fli != fl.end ();
513           ++fli)
514      {
515        functions_.push_back (function (config, *fli));
516      }
517    }
518
519    void
520    tracer::load_traces (rld::config::config&        config,
521                         const rld::config::section& section)
522    {
523      parse (config, section, "traces", "trace", traces);
524
525      rld::strings gens;
526      std::string  gen;
527
528      parse (config, section, "traces", "generator", gens);
529
530      if (gens.size () > 1)
531        throw rld::error ("duplicate generators", "tracer: " + section.name);
532
533      if (gens.size () == 0)
534      {
535        gen =
536          config.get_section ("default-generator").get_record_item ("generator");
537      }
538      else
539      {
540        gen = gens[0];
541      }
542
543      generator_ = generator (config, gen);
544    }
545
546    const std::string
547    tracer::generate ()
548    {
549      rld::process::tempfile c (".c");
550
551      c.open (true);
552
553      if (rld::verbose ())
554        std::cout << "wrapper C file: " << c.name () << std::endl;
555
556      try
557      {
558        c.write_line ("/*");
559        c.write_line (" * RTEMS Trace Linker Wrapper");
560        c.write_line (" *  Automatically generated.");
561        c.write_line (" */");
562
563        c.write_line ("");
564        c.write_line ("/*");
565        c.write_line (" * Generator: " + generator_.name);
566        c.write_line (" */");
567        c.write_lines (generator_.defines);
568        c.write_lines (generator_.headers);
569        c.write_line ("");
570        c.write_lines (generator_.code);
571
572        generate_traces (c);
573      }
574      catch (...)
575      {
576        c.close ();
577        throw;
578      }
579
580      c.close ();
581
582      return c.name ();
583    }
584
585    void
586    tracer::generate_traces (rld::process::tempfile& c)
587    {
588      for (functions::const_iterator fi = functions_.begin ();
589           fi != functions_.end ();
590           ++fi)
591      {
592        const function& funcs = *fi;
593
594        for (rld::strings::const_iterator ti = traces.begin ();
595             ti != traces.end ();
596             ++ti)
597        {
598          const std::string&         trace = *ti;
599          signatures::const_iterator si = funcs.signatures_.find (trace);
600
601          if (si != funcs.signatures_.end ())
602          {
603            c.write_line ("");
604            c.write_line ("/*");
605            c.write_line (" * Function: " + funcs.name);
606            c.write_line (" */");
607            c.write_lines (funcs.defines);
608            c.write_lines (funcs.headers);
609            break;
610          }
611        }
612      }
613
614      c.write_line ("");
615      c.write_line ("/*");
616      c.write_line (" * Wrappers.");
617      c.write_line (" */");
618
619      for (rld::strings::const_iterator ti = traces.begin ();
620           ti != traces.end ();
621           ++ti)
622      {
623        const std::string& trace = *ti;
624        bool               found = false;
625
626        for (functions::const_iterator fi = functions_.begin ();
627             fi != functions_.end ();
628             ++fi)
629        {
630          const function&            funcs = *fi;
631          signatures::const_iterator si = funcs.signatures_.find (trace);
632
633          if (si != funcs.signatures_.end ())
634          {
635            found = true;
636
637            const signature& sig = (*si).second;
638
639            c.write_line("");
640            c.write_line(sig.decl ());
641            c.write_line("{");
642
643            std::string l;
644
645            /*
646             * @todo Need to define as part of the function signature if ret
647             *       processing is required.
648             */
649            if (sig.ret != "void")
650            {
651              c.write_line(" " + sig.ret + " ret;");
652              l = " ret =";
653            }
654
655            l += " " + generator_.map_sym_prefix + sig.name + '(';
656            for (size_t a = 0; a < sig.args.size (); ++a)
657            {
658              if (a)
659                l += ", ";
660              l += "a" + rld::to_string ((int) (a + 1));
661            }
662            l += ");";
663            c.write_line(l);
664
665            if (sig.ret != "void")
666            {
667              c.write_line(" return ret;");
668            }
669
670            c.write_line("}");
671          }
672        }
673
674        if (!found)
675          throw rld::error ("not found", "trace function: " + trace);
676      }
677    }
678
679    void
680    tracer::dump (std::ostream& out) const
681    {
682      out << " Tracer: " << name << std::endl
683          << "  BSP: " << bsp << std::endl
684          << "  Traces: " << traces.size () << std::endl;
685      for (rld::strings::const_iterator ti = traces.begin ();
686           ti != traces.end ();
687           ++ti)
688      {
689        out << "   " << (*ti) << std::endl;
690      }
691      out << "  Functions: " << functions_.size () << std::endl;
692      for (functions::const_iterator fi = functions_.begin ();
693           fi != functions_.end ();
694           ++fi)
695      {
696        (*fi).dump (out);
697      }
698      out << "  Generator: " << std::endl;
699      generator_.dump (out);
700    }
701
702    linker::linker ()
703    {
704    }
705
706    void
707    linker::load_config (const std::string& path,
708                         const std::string& trace)
709    {
710      config.clear ();
711      config.load (path);
712      tracer_.load (config, trace);
713    }
714
715    void
716    linker::generate_wrapper ()
717    {
718      wrapper_c = tracer_.generate ();
719    }
720
721    void
722    linker::compile_wrapper ()
723    {
724     rld::process::arg_container args;
725
726      rld::process::tempfile o (".o");
727
728      if (rld::verbose ())
729        std::cout << "wrapper O file: " << o.name () << std::endl;
730
731      rld::cc::make_cc_command (args);
732      rld::cc::append_flags (rld::cc::ft_cflags, args);
733
734      args.push_back ("-c");
735      args.push_back ("-o ");
736      args.push_back (o.name ());
737      args.push_back (wrapper_c);
738
739      rld::process::tempfile out;
740      rld::process::tempfile err;
741      rld::process::status   status;
742
743      status = rld::process::execute (rld::cc::get_cc (),
744                                      args,
745                                      out.name (),
746                                      err.name ());
747
748      if ((status.type != rld::process::status::normal) ||
749          (status.code != 0))
750      {
751        err.output (rld::cc::get_cc (), std::cout);
752        throw rld::error ("Compiler error", "compiling wrapper");
753      }
754
755      wrapper_o = o.name ();
756    }
757
758    void
759    linker::dump (std::ostream& out) const
760    {
761      const rld::config::paths& cpaths = config.get_paths ();
762      out << " Configuration Files: " << cpaths.size () << std::endl;
763      for (rld::config::paths::const_iterator pi = cpaths.begin ();
764           pi != cpaths.end ();
765           ++pi)
766      {
767        out << "  " << (*pi) << std::endl;
768      }
769
770      tracer_.dump (out);
771    }
772  }
773}
774
775/**
776 * RTEMS Trace Linker options. This needs to be rewritten to be like cc where
777 * only a single '-' and long options is present. Anything after '--' is passed
778 * to RTEMS's real linker.
779 */
780static struct option rld_opts[] = {
781  { "help",        no_argument,            NULL,           'h' },
782  { "version",     no_argument,            NULL,           'V' },
783  { "verbose",     no_argument,            NULL,           'v' },
784  { "warn",        no_argument,            NULL,           'w' },
785  { "keep",        no_argument,            NULL,           'k' },
786  { "exec-prefix", required_argument,      NULL,           'E' },
787  { "cflags",      required_argument,      NULL,           'c' },
788  { "rtems",       required_argument,      NULL,           'r' },
789  { "rtems-bsp",   required_argument,      NULL,           'B' },
790  { "config",      required_argument,      NULL,           'C' },
791  { NULL,          0,                      NULL,            0 }
792};
793
794void
795usage (int exit_code)
796{
797  std::cout << "rtems-trace-ld [options] objects" << std::endl
798            << "Options and arguments:" << std::endl
799            << " -h        : help (also --help)" << std::endl
800            << " -V        : print linker version number and exit (also --version)" << std::endl
801            << " -v        : verbose (trace import parts), can supply multiple times" << std::endl
802            << "             to increase verbosity (also --verbose)" << std::endl
803            << " -w        : generate warnings (also --warn)" << std::endl
804            << " -k        : keep temporary files (also --keep)" << std::endl
805            << " -E prefix : the RTEMS tool prefix (also --exec-prefix)" << std::endl
806            << " -c cflags : C compiler flags (also --cflags)" << std::endl
807            << " -r path   : RTEMS path (also --rtems)" << std::endl
808            << " -B bsp    : RTEMS arch/bsp (also --rtems-bsp)" << std::endl
809            << " -C ini    : user configuration INI file (also --config)" << std::endl;
810  ::exit (exit_code);
811}
812
813static void
814fatal_signal (int signum)
815{
816  signal (signum, SIG_DFL);
817
818  rld::process::temporaries_clean_up ();
819
820  /*
821   * Get the same signal again, this time not handled, so its normal effect
822   * occurs.
823   */
824  kill (getpid (), signum);
825}
826
827static void
828setup_signals (void)
829{
830  if (signal (SIGINT, SIG_IGN) != SIG_IGN)
831    signal (SIGINT, fatal_signal);
832#ifdef SIGHUP
833  if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
834    signal (SIGHUP, fatal_signal);
835#endif
836  if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
837    signal (SIGTERM, fatal_signal);
838#ifdef SIGPIPE
839  if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
840    signal (SIGPIPE, fatal_signal);
841#endif
842#ifdef SIGCHLD
843  signal (SIGCHLD, SIG_DFL);
844#endif
845}
846
847int
848main (int argc, char* argv[])
849{
850  int ec = 0;
851
852  setup_signals ();
853
854  try
855  {
856    rld::trace::linker linker;
857    std::string        ld_cmd;
858    std::string        configuration;
859    std::string        trace = "tracer";
860    bool               arch_bsp_load = false;
861
862    while (true)
863    {
864      int opt = ::getopt_long (argc, argv, "hvwkVE:c:C:r:B:", rld_opts, NULL);
865      if (opt < 0)
866        break;
867
868      switch (opt)
869      {
870        case 'V':
871          std::cout << "rtems-trace-ld (RTEMS Trace Linker) " << rld::version ()
872                    << std::endl;
873          ::exit (0);
874          break;
875
876        case 'v':
877          rld::verbose_inc ();
878          break;
879
880        case 'w':
881#if HAVE_WARNINGS
882          warnings = true;
883#endif
884          break;
885
886        case 'k':
887          rld::process::set_keep_temporary_files ();
888          break;
889
890        case 'E':
891          rld::cc::set_exec_prefix (optarg);
892          break;
893
894        case 'c':
895          rld::cc::append_flags (optarg, rld::cc::ft_cflags);
896          break;
897
898        case 'r':
899          rld::rtems::path = optarg;
900          break;
901
902        case 'B':
903          rld::rtems::arch_bsp = optarg;
904          arch_bsp_load = true;
905          break;
906
907        case 'C':
908          configuration = optarg;
909          break;
910
911        case '?':
912          usage (3);
913          break;
914
915        case 'h':
916          usage (0);
917          break;
918      }
919    }
920
921    argc -= optind;
922    argv += optind;
923
924    if (rld::verbose ())
925      std::cout << "RTEMS Trace Linker " << rld::version () << std::endl;
926
927    /*
928     * Load the arch/bsp value if provided.
929     */
930    if (arch_bsp_load)
931      rld::rtems::load_cc ();
932
933    /*
934     * Load the remaining command line arguments into the linker command line.
935     */
936    while (argc--)
937    {
938      if (ld_cmd.length () != 0)
939        ld_cmd += " ";
940      ld_cmd += *argv++;
941    }
942
943    /*
944     * If there are no object files there is nothing to link.
945     */
946    if (ld_cmd.empty ())
947      throw rld::error ("no trace linker options", "options");
948
949    /*
950     * Perform a trace link.
951     */
952    try
953    {
954      linker.load_config (configuration, trace);
955      linker.generate_wrapper ();
956      linker.compile_wrapper ();
957
958      if (rld::verbose ())
959        linker.dump (std::cout);
960    }
961    catch (...)
962    {
963      throw;
964    }
965
966  }
967  catch (rld::error re)
968  {
969    std::cerr << "error: "
970              << re.where << ": " << re.what
971              << std::endl;
972    ec = 10;
973  }
974  catch (std::exception e)
975  {
976    int   status;
977    char* realname;
978    realname = abi::__cxa_demangle (e.what(), 0, 0, &status);
979    std::cerr << "error: exception: " << realname << " [";
980    ::free (realname);
981    const std::type_info &ti = typeid (e);
982    realname = abi::__cxa_demangle (ti.name(), 0, 0, &status);
983    std::cerr << realname << "] " << e.what () << std::endl;
984    ::free (realname);
985    ec = 11;
986  }
987  catch (...)
988  {
989    /*
990     * Helps to know if this happens.
991     */
992    std::cout << "error: unhandled exception" << std::endl;
993    ec = 12;
994  }
995
996  return ec;
997}
Note: See TracBrowser for help on using the repository browser.