source: rtems-tools/rtemstoolkit/rld.cpp @ 0f481ad

5
Last change on this file since 0f481ad was 0f481ad, checked in by Chris Johns <chrisj@…>, on 05/24/18 at 06:02:59

rtemstoolkit: Add an output routine for a std::exception.

The output routine is used by a number of tools.

  • Property mode set to 100644
File size: 9.2 KB
Line 
1/*
2 * Copyright (c) 2011, 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_ld
20 *
21 * @brief RTEMS Linker.
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 <sys/stat.h>
33
34#include <rld.h>
35
36namespace rld
37{
38  static int verbose_level = 0;
39
40  /**
41   * The program's command line.
42   */
43  static std::string cmdline;
44
45  /**
46   * The program name as set by the caller.
47   */
48  static std::string progname;
49
50  /**
51   * The option container.
52   */
53  typedef std::vector < std::string > library_container;
54
55  /**
56   * The libraries the user provided on the command line.
57   */
58  static library_container libpaths;
59
60  /**
61   * The libraries pass on the command line.
62   */
63  static library_container libs;
64
65  /**
66   * The libraries.
67   */
68  static library_container libraries;
69
70  /**
71   * The version major number.
72   */
73  static uint64_t _version_major;
74
75  /**
76   * The version minor number.
77   */
78  static uint64_t _version_minor;
79
80  /**
81   * The version revision number.
82   */
83  static uint64_t _version_revision;
84
85  void
86  output_std_exception (std::exception e, std::ostream& out)
87  {
88    int   status;
89    char* realname;
90    realname = abi::__cxa_demangle (e.what(), 0, 0, &status);
91    out << "error: exception: " << realname << " [";
92    ::free (realname);
93    const std::type_info &ti = typeid (e);
94    realname = abi::__cxa_demangle (ti.name(), 0, 0, &status);
95    out << realname << "] " << e.what () << std::endl;
96    ::free (realname);
97  }
98
99  bool
100  starts_with(const std::string& s1, const std::string& s2)
101  {
102    return s2.size () <= s1.size () && s1.compare (0, s2.size (), s2) == 0;
103  }
104
105  const std::string
106  ltrim (const std::string& s)
107  {
108    std::string t = s;
109    t.erase (t.begin (),
110             std::find_if (t.begin (), t.end (),
111                         std::not1 (std::ptr_fun < int, int > (std::isspace))));
112    return t;
113  }
114
115  const std::string
116  rtrim (const std::string& s)
117  {
118    std::string t = s;
119    t.erase (std::find_if (t.rbegin (), t.rend (),
120                           std::not1 (std::ptr_fun < int, int > (std::isspace))).base(),
121             t.end());
122    return t;
123  }
124
125  const std::string
126  trim (const std::string& s)
127  {
128    return ltrim (rtrim (s));
129  }
130
131  const std::string
132  dequote (const std::string& s)
133  {
134    if (!s.empty ())
135    {
136      char front = s[0];
137      char back = s[s.length () - 1];
138      if ((front == '"') || (front == '\''))
139      {
140        if (front != back)
141          throw rld::error ("invalid quoting", "string: " + s);
142        return s.substr (1, s.length () - (1 + 1));
143      }
144    }
145    return s;
146  }
147
148  const std::string
149  find_replace(const std::string& sin,
150               const std::string& out,
151               const std::string& in)
152  {
153    std::string s = sin;
154    size_t      pos = 0;
155    while ((pos = s.find (out, pos)) != std::string::npos)
156    {
157      s.replace (pos, out.length (), in);
158      pos += in.length ();
159    }
160    return s;
161  }
162
163  const strings
164  split (strings&           se,
165         const std::string& s,
166         char               delimiter,
167         bool               strip_quotes,
168         bool               strip_whitespace,
169         bool               empty)
170  {
171    std::stringstream ss(s);
172    std::string       e;
173    se.clear ();
174    while (std::getline (ss, e, delimiter))
175    {
176      if (strip_whitespace)
177        e = trim (e);
178      if (strip_quotes)
179        e = dequote (e);
180      if (empty || !e.empty ())
181      {
182        se.push_back (e);
183      }
184    }
185    return se;
186  }
187
188  const std::string
189  join (const strings& ss, const std::string& separator)
190  {
191    std::string s;
192    for (strings::const_iterator ssi = ss.begin ();
193         ssi != ss.end ();
194         ++ssi)
195    {
196      s += *ssi;
197      if ((ssi + 1) != ss.end ())
198        s += separator;
199    }
200    return s;
201  }
202
203  const std::string
204  tolower (const std::string& sin)
205  {
206    std::string s = sin;
207    std::transform (s.begin (), s.end (), s.begin (), ::tolower);
208    return s;
209  }
210
211  void
212  version_parse (const std::string& str,
213                 uint64_t&          major,
214                 uint64_t&          minor,
215                 uint64_t&          revision)
216  {
217    strings parts;
218
219    rld::split (parts, str, '.');
220
221    if (parts.size () >= 1)
222    {
223      std::istringstream iss (parts[0]);
224      iss >> major;
225    }
226
227    if (parts.size () >= 2)
228    {
229      std::istringstream iss (parts[1]);
230      iss >> minor;
231    }
232
233    if (parts.size () >= 3)
234    {
235      size_t p = parts[2].find ('_');
236
237      if (p != std::string::npos)
238        parts[2].erase (p);
239
240      std::istringstream iss (parts[2]);
241
242      if (p != std::string::npos)
243        iss >> std::hex;
244
245      iss >> revision;
246    }
247  }
248
249  void
250  verbose_inc ()
251  {
252    ++verbose_level;
253  }
254
255  int
256  verbose (int level)
257  {
258    return verbose_level && (verbose_level >= level) ? verbose_level : 0;
259  }
260
261  const std::string
262  version ()
263  {
264    return RTEMS_RELEASE;
265  }
266
267  uint64_t
268  version_major ()
269  {
270    if (_version_major == 0)
271      version_parse (version (),
272                     _version_major,
273                     _version_minor,
274                     _version_revision);
275    return _version_major;
276  }
277
278  uint64_t
279  version_minor ()
280  {
281    if (_version_major == 0)
282      version_parse (version (),
283                     _version_major,
284                     _version_minor,
285                     _version_revision);
286    return _version_minor;
287  }
288
289  uint64_t
290  version_revision ()
291  {
292    if (_version_major == 0)
293      version_parse (version (),
294                     _version_major,
295                     _version_minor,
296                     _version_revision);
297    return _version_revision;
298  }
299
300  void
301  set_cmdline (int argc, char* argv[])
302  {
303    cmdline.clear ();
304    for (int arg = 0; arg < argc; ++arg)
305    {
306      std::string a = argv[arg];
307      cmdline += ' ' + a;
308    }
309    cmdline = rld::trim (cmdline);
310  }
311
312  const std::string
313  get_cmdline ()
314  {
315    return cmdline;
316  }
317
318  void
319  set_progname (const std::string& progname_)
320  {
321    if (rld::path::check_file (progname_))
322      progname = rld::path::path_abs (progname_);
323    else
324    {
325      rld::path::paths paths;
326      rld::path::get_system_path (paths);
327      for (rld::path::paths::const_iterator path = paths.begin ();
328           path != paths.end ();
329           ++path)
330      {
331        std::string pp;
332        rld::path::path_join (*path, progname_, pp);
333        if (rld::path::check_file (pp))
334        {
335          progname = rld::path::path_abs (pp);
336          break;
337        }
338      }
339    }
340  }
341
342  const std::string
343  get_progname ()
344  {
345    return progname;
346  }
347
348  const std::string
349  get_program_name ()
350  {
351    return rld::path::basename (progname);
352  }
353
354  const std::string
355  get_program_path ()
356  {
357    return rld::path::dirname (progname);
358  }
359
360  const std::string
361  get_prefix ()
362  {
363    std::string pp = get_program_path ();
364    if (rld::path::basename (pp) == "bin")
365      return rld::path::dirname (pp);
366    return pp;
367  }
368
369  void
370  map (rld::files::cache& cache, rld::symbols::table& symbols)
371  {
372    std::cout << "Archive files    : " << cache.archive_count () << std::endl;
373    std::cout << "Object files     : " << cache.object_count () << std::endl;
374    std::cout << "Exported symbols : " << symbols.size () << std::endl;
375
376    std::cout << "Archives:" << std::endl;
377    cache.output_archive_files (std::cout);
378    std::cout << "Objects:" << std::endl;
379    cache.output_object_files (std::cout);
380
381    std::cout << "Exported symbols:" << std::endl;
382    rld::symbols::output (std::cout, symbols);
383    std::cout << "Unresolved symbols:" << std::endl;
384    cache.output_unresolved_symbols (std::cout);
385  }
386
387  void
388  warn_unused_externals (rld::files::object_list& objects)
389  {
390    bool first = true;
391    for (rld::files::object_list::iterator oli = objects.begin ();
392         oli != objects.end ();
393         ++oli)
394    {
395      rld::files::object&     object = *(*oli);
396      rld::symbols::pointers& externals = object.external_symbols ();
397
398      if (rld::symbols::referenced (externals) != externals.size ())
399      {
400        if (first)
401        {
402          std::cout << "Unreferenced externals in object files:" << std::endl;
403          first = false;
404        }
405
406        std::cout << ' ' << object.name ().basename () << std::endl;
407
408        for (rld::symbols::pointers::iterator sli = externals.begin ();
409             sli != externals.end ();
410             ++sli)
411        {
412          rld::symbols::symbol& sym = *(*sli);
413          if (sym.references () == 0)
414            std::cout << "  " << sym.name () << std::endl;
415        }
416      }
417    }
418  }
419
420}
Note: See TracBrowser for help on using the repository browser.