source: rtems-tools/linkers/rtems-rapper.cpp @ 8bb0d53

4.104.115
Last change on this file since 8bb0d53 was 8bb0d53, checked in by Chris Johns <chrisj@…>, on 12/19/12 at 05:24:24

RAP file utility. Decompressors RAP files.

  • Property mode set to 100644
File size: 7.9 KB
Line 
1/*
2 * Copyright (c) 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 RAP Manager lets you look at and play with RAP files.
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-compression.h>
41#include <rld-files.h>
42#include <rld-process.h>
43
44#ifndef HAVE_KILL
45#define kill(p,s) raise(s)
46#endif
47
48#define RAP_
49/**
50 * A class to manage a RAP file.
51 */
52class rap
53{
54public:
55  /**
56   * Open a RAP file and read the header.
57   */
58  rap (const std::string& name);
59
60  /**
61   * Close the RAP file.
62   */
63  ~rap ();
64
65  /**
66   * Parse header.
67   */
68  void parse_header ();
69
70  /**
71   * Expand the image.
72   */
73  void expand ();
74
75  /**
76   * The name.
77   */
78  const std::string name () const;
79
80private:
81
82  rld::files::image image;
83  std::string       header;
84  size_t            rhdr_len;
85  uint32_t          rhdr_length;
86  uint32_t          rhdr_version;
87  std::string       rhdr_compression;
88  uint32_t          rhdr_checksum;
89};
90
91rap::rap (const std::string& name)
92  : image (name),
93    rhdr_len (0),
94    rhdr_length (0),
95    rhdr_version (0),
96    rhdr_checksum (0)
97{
98  image.open ();
99  parse_header ();
100}
101
102rap::~rap ()
103{
104  image.close ();
105}
106
107void
108rap::parse_header ()
109{
110  std::string name = image.name ().full ();
111
112  char rhdr[64];
113
114  image.seek_read (0, (uint8_t*) rhdr, 64);
115
116  if ((rhdr[0] != 'R') || (rhdr[1] != 'A') || (rhdr[2] != 'P') || (rhdr[3] != ','))
117    throw rld::error ("Invalid RAP file", "open: " + name);
118
119  char* sptr = rhdr + 4;
120  char* eptr;
121
122  rhdr_length = ::strtoul (sptr, &eptr, 10);
123
124  if (*eptr != ',')
125    throw rld::error ("Cannot parse RAP header", "open: " + name);
126
127  sptr = eptr + 1;
128
129  rhdr_version = ::strtoul (sptr, &eptr, 10);
130
131  if (*eptr != ',')
132    throw rld::error ("Cannot parse RAP header", "open: " + name);
133
134  sptr = eptr + 1;
135
136  if ((sptr[0] == 'N') &&
137      (sptr[1] == 'O') &&
138      (sptr[2] == 'N') &&
139      (sptr[3] == 'E'))
140  {
141    rhdr_compression = "NONE";
142    eptr = sptr + 4;
143  }
144  else if ((sptr[0] == 'L') &&
145           (sptr[1] == 'Z') &&
146           (sptr[2] == '7') &&
147           (sptr[3] == '7'))
148  {
149    rhdr_compression = "LZ77";
150    eptr = sptr + 4;
151  }
152  else
153    throw rld::error ("Cannot parse RAP header", "open: " + name);
154
155  if (*eptr != ',')
156    throw rld::error ("Cannot parse RAP header", "open: " + name);
157
158  sptr = eptr + 1;
159
160  rhdr_checksum = strtoul (sptr, &eptr, 16);
161
162  if (*eptr != '\n')
163    throw rld::error ("Cannot parse RAP header", "open: " + name);
164
165  rhdr_len = eptr - rhdr + 1;
166
167  header.insert (0, rhdr, rhdr_len);
168
169  image.seek (rhdr_len);
170}
171
172void
173rap::expand ()
174{
175  std::string name = image.name ().full ();
176  std::string extension = rld::files::extension (image.name ().full ());
177
178  name = name.substr (0, name.size () - extension.size ()) + ".xrap";
179
180  image.seek (rhdr_len);
181
182  rld::compress::compressor comp (image, 2 * 1024, false);
183  rld::files::image         out (name);
184
185  out.open (true);
186  comp.read (out, 0, image.size () - rhdr_len);
187  out.close ();
188}
189
190const std::string
191rap::name () const
192{
193  return image.name ().full ();
194}
195
196void
197rap_expander (rld::files::paths& raps)
198{
199  std::cout << "Expanding .... " << std::endl;
200  for (rld::files::paths::iterator pi = raps.begin();
201       pi != raps.end();
202       ++pi)
203  {
204    rap r (*pi);
205    std::cout << ' ' << r.name () << std::endl;
206    r.expand ();
207  }
208}
209
210/**
211 * RTEMS RAP options.
212 */
213static struct option rld_opts[] = {
214  { "help",        no_argument,            NULL,           'h' },
215  { "version",     no_argument,            NULL,           'V' },
216  { "verbose",     no_argument,            NULL,           'v' },
217  { "warn",        no_argument,            NULL,           'w' },
218  { "expand",      no_argument,            NULL,           'x' },
219  { NULL,          0,                      NULL,            0 }
220};
221
222void
223usage (int exit_code)
224{
225  std::cout << "rtems-rap [options] objects" << std::endl
226            << "Options and arguments:" << std::endl
227            << " -h        : help (also --help)" << std::endl
228            << " -V        : print linker version number and exit (also --version)" << std::endl
229            << " -v        : verbose (trace import parts), can be supply multiple times" << std::endl
230            << "             to increase verbosity (also --verbose)" << std::endl
231            << " -w        : generate warnings (also --warn)" << std::endl
232            << " -x        : expand (also --expand)" << std::endl;
233  ::exit (exit_code);
234}
235
236static void
237fatal_signal (int signum)
238{
239  signal (signum, SIG_DFL);
240
241  rld::process::temporaries.clean_up ();
242
243  /*
244   * Get the same signal again, this time not handled, so its normal effect
245   * occurs.
246   */
247  kill (getpid (), signum);
248}
249
250static void
251setup_signals (void)
252{
253  if (signal (SIGINT, SIG_IGN) != SIG_IGN)
254    signal (SIGINT, fatal_signal);
255#ifdef SIGHUP
256  if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
257    signal (SIGHUP, fatal_signal);
258#endif
259  if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
260    signal (SIGTERM, fatal_signal);
261#ifdef SIGPIPE
262  if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
263    signal (SIGPIPE, fatal_signal);
264#endif
265#ifdef SIGCHLD
266  signal (SIGCHLD, SIG_DFL);
267#endif
268}
269
270int
271main (int argc, char* argv[])
272{
273  int ec = 0;
274
275  setup_signals ();
276
277  try
278  {
279    rld::files::paths raps;
280    bool              expand = false;
281#if HAVE_WARNINGS
282    bool              warnings = false;
283#endif
284
285    while (true)
286    {
287      int opt = ::getopt_long (argc, argv, "hvwVx", rld_opts, NULL);
288      if (opt < 0)
289        break;
290
291      switch (opt)
292      {
293        case 'V':
294          std::cout << "rtems-rap (RTEMS RAP Manager) " << rld::version ()
295                    << std::endl;
296          ::exit (0);
297          break;
298
299        case 'v':
300          rld::verbose_inc ();
301          break;
302
303        case 'w':
304#if HAVE_WARNINGS
305          warnings = true;
306#endif
307          break;
308
309        case '?':
310          usage (3);
311          break;
312
313        case 'h':
314          usage (0);
315          break;
316
317        case 'x':
318          expand = true;
319          break;
320      }
321    }
322
323    argc -= optind;
324    argv += optind;
325
326    std::cout << "RTEMS RAP " << rld::version () << std::endl;
327
328    /*
329     * If there are no RAP files so there is nothing to do.
330     */
331    if (argc == 0)
332      throw rld::error ("no RAP files", "options");
333
334    /*
335     * Load the remaining command line arguments into a container.
336     */
337    while (argc--)
338      raps.push_back (*argv++);
339
340    if (expand)
341      rap_expander (raps);
342  }
343  catch (rld::error re)
344  {
345    std::cerr << "error: "
346              << re.where << ": " << re.what
347              << std::endl;
348    ec = 10;
349  }
350  catch (std::exception e)
351  {
352    int   status;
353    char* realname;
354    realname = abi::__cxa_demangle (e.what(), 0, 0, &status);
355    std::cerr << "error: exception: " << realname << " [";
356    ::free (realname);
357    const std::type_info &ti = typeid (e);
358    realname = abi::__cxa_demangle (ti.name(), 0, 0, &status);
359    std::cerr << realname << "] " << e.what () << std::endl;
360    ::free (realname);
361    ec = 11;
362  }
363  catch (...)
364  {
365    /*
366     * Helps to know if this happens.
367     */
368    std::cout << "error: unhandled exception" << std::endl;
369    ec = 12;
370  }
371
372  return ec;
373}
Note: See TracBrowser for help on using the repository browser.