source: rtems-tools/linkers/rtems-syms.cpp @ 5025439

4.104.115
Last change on this file since 5025439 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: 9.0 KB
Line 
1/*
2 * Copyright (c) 2011-2012, 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 Symbols Main manages opions, sequence of operations and exceptions.
22 *
23 */
24
25#if HAVE_CONFIG_H
26#include "config.h"
27#endif
28
29#include <iostream>
30
31#include <cxxabi.h>
32#include <signal.h>
33#include <stdlib.h>
34#include <string.h>
35#include <unistd.h>
36
37#include <getopt.h>
38
39#include <rld.h>
40#include <rld-cc.h>
41#include <rld-outputter.h>
42#include <rld-process.h>
43#include <rld-resolver.h>
44
45#ifndef HAVE_KILL
46#define kill(p,s) raise(s)
47#endif
48
49/**
50 * RTEMS Linker options. This needs to be rewritten to be like cc where only a
51 * single '-' and long options is present.
52 */
53static struct option rld_opts[] = {
54  { "help",        no_argument,            NULL,           'h' },
55  { "version",     no_argument,            NULL,           'V' },
56  { "verbose",     no_argument,            NULL,           'v' },
57  { "warn",        no_argument,            NULL,           'w' },
58  { "lib-path",    required_argument,      NULL,           'L' },
59  { "lib",         required_argument,      NULL,           'l' },
60  { "no-stdlibs",  no_argument,            NULL,           'n' },
61  { "cc",          required_argument,      NULL,           'C' },
62  { "exec-prefix", required_argument,      NULL,           'E' },
63  { "march",       required_argument,      NULL,           'a' },
64  { "mcpu",        required_argument,      NULL,           'c' },
65  { NULL,          0,                      NULL,            0 }
66};
67
68void
69usage (int exit_code)
70{
71  std::cout << "rtems-syms [options] objects" << std::endl
72            << "Options and arguments:" << std::endl
73            << " -h        : help (also --help)" << std::endl
74            << " -V        : print linker version number and exit (also --version)" << std::endl
75            << " -v        : verbose (trace import parts), can supply multiple times" << std::endl
76            << "             to increase verbosity (also --verbose)" << std::endl
77            << " -w        : generate warnings (also --warn)" << std::endl
78            << " -L path   : path to a library, add multiple for more than" << std::endl
79            << "             one path (also --lib-path)" << std::endl
80            << " -l lib    : add lib to the libraries searched, add multiple" << std::endl
81            << "             for more than one library (also --lib)" << std::endl
82            << " -S        : search standard libraries (also --stdlibs)" << std::endl
83            << " -C file   : execute file as the target C compiler (also --cc)" << std::endl
84            << " -E prefix : the RTEMS tool prefix (also --exec-prefix)" << std::endl
85            << " -c cflags : C compiler flags (also --cflags)" << std::endl;
86  ::exit (exit_code);
87}
88
89static void
90fatal_signal (int signum)
91{
92  signal (signum, SIG_DFL);
93
94  rld::process::temporaries_clean_up ();
95
96  /*
97   * Get the same signal again, this time not handled, so its normal effect
98   * occurs.
99   */
100  kill (getpid (), signum);
101}
102
103static void
104setup_signals (void)
105{
106  if (signal (SIGINT, SIG_IGN) != SIG_IGN)
107    signal (SIGINT, fatal_signal);
108#ifdef SIGHUP
109  if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
110    signal (SIGHUP, fatal_signal);
111#endif
112  if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
113    signal (SIGTERM, fatal_signal);
114#ifdef SIGPIPE
115  if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
116    signal (SIGPIPE, fatal_signal);
117#endif
118#ifdef SIGCHLD
119  signal (SIGCHLD, SIG_DFL);
120#endif
121}
122
123int
124main (int argc, char* argv[])
125{
126  int ec = 0;
127
128  setup_signals ();
129
130  try
131  {
132    rld::files::cache   cache;
133    rld::path::paths    libpaths;
134    rld::path::paths    libs;
135    rld::path::paths    objects;
136    rld::path::paths    libraries;
137    rld::symbols::table symbols;
138    std::string         base_name;
139    std::string         cc_name;
140    bool                standard_libs = false;
141#if HAVE_WARNINGS
142    bool                warnings = false;
143#endif
144
145    libpaths.push_back (".");
146
147    while (true)
148    {
149      int opt = ::getopt_long (argc, argv, "hvwVSE:L:l:c:C:", rld_opts, NULL);
150      if (opt < 0)
151        break;
152
153      switch (opt)
154      {
155        case 'V':
156          std::cout << "rtems-syms (RTEMS Symbols) " << rld::version ()
157                    << std::endl;
158          ::exit (0);
159          break;
160
161        case 'v':
162          rld::verbose_inc ();
163          break;
164
165        case 'w':
166#if HAVE_WARNINGS
167          warnings = true;
168#endif
169          break;
170
171        case 'l':
172          /*
173           * The order is important. It is the search order.
174           */
175          libs.push_back (optarg);
176          break;
177
178        case 'L':
179          if ((optarg[::strlen (optarg) - 1] == '/') ||
180              (optarg[::strlen (optarg) - 1] == '\\'))
181            optarg[::strlen (optarg) - 1] = '\0';
182          libpaths.push_back (optarg);
183          break;
184
185        case 'S':
186          standard_libs = true;
187          break;
188
189        case 'C':
190          if (rld::cc::is_exec_prefix_set ())
191            std::cerr << "warning: exec-prefix ignored when CC provided" << std::endl;
192          rld::cc::set_cc (optarg);
193          break;
194
195        case 'E':
196          if (rld::cc::is_cc_set ())
197            std::cerr << "warning: exec-prefix ignored when CC provided" << std::endl;
198          rld::cc::set_exec_prefix (optarg);
199          break;
200
201        case 'c':
202          rld::cc::set_flags (optarg, rld::cc::ft_cflags);
203          break;
204
205        case '?':
206          usage (3);
207          break;
208
209        case 'h':
210          usage (0);
211          break;
212      }
213    }
214
215    argc -= optind;
216    argv += optind;
217
218    std::cout << "RTEMS Symbols " << rld::version () << std::endl;
219
220    /*
221     * If there are no object files there is nothing to link.
222     */
223    if (argc == 0)
224      throw rld::error ("no object files", "options");
225
226    /*
227     * Load the remaining command line arguments into the cache as object
228     * files.
229     */
230    while (argc--)
231      objects.push_back (*argv++);
232
233    /*
234     * Add the object files to the cache.
235     */
236    cache.add (objects);
237
238    /*
239     * Open the cache.
240     */
241    cache.open ();
242
243    /*
244     * If the full path to CC is not provided and the exec-prefix is not set by
245     * the command line see if it can be detected from the object file
246     * types. This must be after we have added the object files because they
247     * are used when detecting.
248     */
249    if (!rld::cc::is_cc_set () && !rld::cc::is_exec_prefix_set ())
250      rld::cc::set_exec_prefix (rld::elf::machine_type ());
251
252    /*
253     * Get the standard library paths
254     */
255    if (standard_libs)
256      rld::cc::get_standard_libpaths (libpaths);
257
258    /*
259     * Get the command line libraries.
260     */
261    rld::files::find_libraries (libraries, libpaths, libs);
262
263    /*
264     * Are we to load standard libraries ?
265     */
266    if (standard_libs)
267      rld::cc::get_standard_libs (libraries, libpaths);
268
269    /*
270     * Load the library to the cache.
271     */
272    cache.add_libraries (libraries);
273
274    /*
275     * Begin the archive session. This opens the archives and leaves them open
276     * while we the symbol table is being used. The symbols reference object
277     * files and the object files may reference archives and it is assumed they
278     * are open and available. It is also assumed the number of library
279     * archives being managed is less than the maximum file handles this
280     * process can have open at any one time. If this is not the case this
281     * approach would need to be reconsidered and the overhead of opening and
282     * closing archives added.
283     */
284    try
285    {
286      /*
287       * Load the symbol table.
288       */
289      cache.load_symbols (symbols);
290
291      rld::map (cache, symbols);
292    }
293    catch (...)
294    {
295      cache.archives_end ();
296      throw;
297    }
298
299    cache.archives_end ();
300  }
301  catch (rld::error re)
302  {
303    std::cerr << "error: "
304              << re.where << ": " << re.what
305              << std::endl;
306    ec = 10;
307  }
308  catch (std::exception e)
309  {
310    int   status;
311    char* realname;
312    realname = abi::__cxa_demangle (e.what(), 0, 0, &status);
313    std::cerr << "error: exception: " << realname << " [";
314    ::free (realname);
315    const std::type_info &ti = typeid (e);
316    realname = abi::__cxa_demangle (ti.name(), 0, 0, &status);
317    std::cerr << realname << "] " << e.what () << std::endl;
318    ::free (realname);
319    ec = 11;
320  }
321  catch (...)
322  {
323    /*
324     * Helps to know if this happens.
325     */
326    std::cout << "error: unhandled exception" << std::endl;
327    ec = 12;
328  }
329
330  return ec;
331}
Note: See TracBrowser for help on using the repository browser.