[ec24a37] | 1 | /* |
---|
[aac2949] | 2 | * Copyright (c) 2011-2014, Chris Johns <chrisj@rtems.org> |
---|
[ec24a37] | 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. |
---|
[aef6d90] | 7 | * |
---|
[ec24a37] | 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 | * |
---|
[977c3de] | 21 | * @brief RTEMS Symbols Main manages opions, sequence of operations and exceptions. |
---|
[ec24a37] | 22 | * |
---|
| 23 | */ |
---|
| 24 | |
---|
| 25 | #if HAVE_CONFIG_H |
---|
| 26 | #include "config.h" |
---|
| 27 | #endif |
---|
| 28 | |
---|
[aac2949] | 29 | #include <fstream> |
---|
| 30 | #include <iomanip> |
---|
[ec24a37] | 31 | #include <iostream> |
---|
| 32 | |
---|
| 33 | #include <cxxabi.h> |
---|
| 34 | #include <signal.h> |
---|
| 35 | #include <stdlib.h> |
---|
| 36 | #include <string.h> |
---|
| 37 | #include <unistd.h> |
---|
| 38 | |
---|
| 39 | #include <getopt.h> |
---|
| 40 | |
---|
| 41 | #include <rld.h> |
---|
[7461924] | 42 | #include <rld-cc.h> |
---|
[ec24a37] | 43 | #include <rld-outputter.h> |
---|
| 44 | #include <rld-process.h> |
---|
[aac2949] | 45 | #include <rld-symbols.h> |
---|
[ec24a37] | 46 | |
---|
| 47 | #ifndef HAVE_KILL |
---|
| 48 | #define kill(p,s) raise(s) |
---|
| 49 | #endif |
---|
| 50 | |
---|
[aac2949] | 51 | /** |
---|
| 52 | * Header text. |
---|
| 53 | */ |
---|
| 54 | static const char* c_header[] = |
---|
| 55 | { |
---|
| 56 | "/*", |
---|
| 57 | " * RTEMS Global Symbol Table", |
---|
| 58 | " * Automatically generated so no point in hacking on it.", |
---|
| 59 | " */", |
---|
| 60 | "", |
---|
| 61 | "#if __bfin__ || __h8300__ || __v850__", |
---|
| 62 | " extern unsigned char _rtems_rtl_base_globals[];", |
---|
| 63 | " extern unsigned int _rtems_rtl_base_globals_size;", |
---|
| 64 | "#else", |
---|
| 65 | " extern unsigned char __rtems_rtl_base_globals[];", |
---|
| 66 | " extern unsigned int __rtems_rtl_base_globals_size;", |
---|
| 67 | "#endif", |
---|
| 68 | "", |
---|
| 69 | "asm(\" .align 4\");", |
---|
| 70 | "asm(\"__rtems_rtl_base_globals:\");", |
---|
| 71 | 0 |
---|
| 72 | }; |
---|
| 73 | |
---|
| 74 | static const char* c_trailer[] = |
---|
| 75 | { |
---|
| 76 | "asm(\" .byte 0\");", |
---|
| 77 | "#if __mips__", |
---|
| 78 | " asm(\" .align 0\");", |
---|
| 79 | "#else", |
---|
| 80 | " asm(\" .balign 1\");", |
---|
| 81 | "#endif", |
---|
| 82 | "asm(\" .ascii \\\"\\xde\\xad\\xbe\\xef\\\"\");", |
---|
| 83 | "asm(\" .align 4\");", |
---|
| 84 | "asm(\"__rtems_rtl_base_globals_size:\");", |
---|
| 85 | "asm(\" .long __rtems_rtl_base_globals_size - __rtems_rtl_base_globals\");", |
---|
| 86 | "", |
---|
| 87 | "void rtems_rtl_base_sym_global_add (const unsigned char* , unsigned int );", |
---|
| 88 | 0 |
---|
| 89 | }; |
---|
| 90 | |
---|
| 91 | static const char* c_rtl_call_body[] = |
---|
| 92 | { |
---|
| 93 | "{", |
---|
| 94 | "#if __bfin__ || __h8300__ || __v850__", |
---|
| 95 | " rtems_rtl_base_sym_global_add (_rtems_rtl_base_globals,", |
---|
| 96 | " _rtems_rtl_base_globals_size);", |
---|
| 97 | "#else", |
---|
| 98 | " rtems_rtl_base_sym_global_add (__rtems_rtl_base_globals,", |
---|
| 99 | " __rtems_rtl_base_globals_size);", |
---|
| 100 | "#endif", |
---|
| 101 | "}", |
---|
| 102 | 0 |
---|
| 103 | }; |
---|
| 104 | |
---|
| 105 | /** |
---|
| 106 | * Paint the data to the temporary file. |
---|
| 107 | */ |
---|
| 108 | static void |
---|
| 109 | temporary_file_paint (rld::process::tempfile& t, const char* lines[]) |
---|
| 110 | { |
---|
| 111 | for (int l = 0; lines[l]; ++l) |
---|
| 112 | t.write_line (lines[l]); |
---|
| 113 | } |
---|
| 114 | |
---|
| 115 | /** |
---|
| 116 | * The constructor trailer. |
---|
| 117 | */ |
---|
| 118 | static void |
---|
| 119 | c_constructor_trailer (rld::process::tempfile& c) |
---|
| 120 | { |
---|
| 121 | temporary_file_paint (c, c_trailer); |
---|
| 122 | c.write_line ("static void init(void) __attribute__ ((constructor));"); |
---|
| 123 | c.write_line ("static void init(void)"); |
---|
| 124 | temporary_file_paint (c, c_rtl_call_body); |
---|
| 125 | } |
---|
| 126 | |
---|
| 127 | /** |
---|
| 128 | * The embedded trailer. |
---|
| 129 | */ |
---|
| 130 | static void |
---|
| 131 | c_embedded_trailer(rld::process::tempfile& c) |
---|
| 132 | { |
---|
| 133 | temporary_file_paint (c, c_trailer); |
---|
| 134 | c.write_line ("void rtems_rtl_base_global_syms_init(void);"); |
---|
| 135 | c.write_line ("void rtems_rtl_base_global_syms_init(void)"); |
---|
| 136 | temporary_file_paint (c, c_rtl_call_body); |
---|
| 137 | } |
---|
| 138 | |
---|
| 139 | /** |
---|
| 140 | * Generate the symbol map object file for loading or linking into |
---|
| 141 | * a running RTEMS machine. |
---|
| 142 | */ |
---|
| 143 | static void |
---|
| 144 | generate_asm (rld::process::tempfile& c, |
---|
| 145 | rld::symbols::table& symbols, |
---|
| 146 | bool embed) |
---|
| 147 | { |
---|
| 148 | temporary_file_paint (c, c_header); |
---|
| 149 | |
---|
| 150 | for (rld::symbols::symtab::const_iterator si = symbols.externals ().begin (); |
---|
| 151 | si != symbols.externals ().end (); |
---|
| 152 | ++si) |
---|
| 153 | { |
---|
| 154 | const rld::symbols::symbol& sym = *((*si).second); |
---|
| 155 | |
---|
| 156 | if (!sym.name ().empty ()) |
---|
| 157 | { |
---|
| 158 | c.write_line ("asm(\" .asciz \\\"" + sym.name () + "\\\"\");"); |
---|
| 159 | |
---|
| 160 | if (embed) |
---|
| 161 | { |
---|
| 162 | c.write_line ("#if __mips__"); |
---|
| 163 | c.write_line ("asm(\" .align 0\");"); |
---|
| 164 | c.write_line ("#else"); |
---|
| 165 | c.write_line ("asm(\" .balign 1\");"); |
---|
| 166 | c.write_line ("#endif"); |
---|
| 167 | c.write_line ("asm(\" .long " + sym.name () + "\");"); |
---|
| 168 | } |
---|
| 169 | else |
---|
| 170 | { |
---|
| 171 | std::stringstream oss; |
---|
| 172 | oss << std::hex << std::setfill ('0') << std::setw (8) << sym.value (); |
---|
| 173 | c.write_line ("asm(\" .long 0x" + oss.str () + "\");"); |
---|
| 174 | } |
---|
| 175 | } |
---|
| 176 | } |
---|
| 177 | |
---|
| 178 | if (embed) |
---|
| 179 | c_embedded_trailer (c); |
---|
| 180 | else |
---|
| 181 | c_constructor_trailer (c); |
---|
| 182 | } |
---|
| 183 | |
---|
| 184 | static void |
---|
| 185 | generate_symmap (rld::process::tempfile& c, |
---|
| 186 | const std::string& output, |
---|
| 187 | rld::symbols::table& symbols, |
---|
| 188 | bool embed) |
---|
| 189 | { |
---|
| 190 | c.open (true); |
---|
| 191 | |
---|
| 192 | if (rld::verbose ()) |
---|
| 193 | std::cout << "symbol C file: " << c.name () << std::endl; |
---|
| 194 | |
---|
| 195 | generate_asm (c, symbols, embed); |
---|
| 196 | |
---|
| 197 | if (rld::verbose ()) |
---|
| 198 | std::cout << "symbol O file: " << output << std::endl; |
---|
| 199 | |
---|
| 200 | rld::process::arg_container args; |
---|
| 201 | |
---|
| 202 | rld::cc::make_cc_command (args); |
---|
| 203 | rld::cc::append_flags (rld::cc::ft_cflags, args); |
---|
| 204 | |
---|
| 205 | args.push_back ("-O2"); |
---|
| 206 | args.push_back ("-g"); |
---|
| 207 | args.push_back ("-c"); |
---|
| 208 | args.push_back ("-o"); |
---|
| 209 | args.push_back (output); |
---|
| 210 | args.push_back (c.name ()); |
---|
| 211 | |
---|
| 212 | rld::process::tempfile out; |
---|
| 213 | rld::process::tempfile err; |
---|
| 214 | rld::process::status status; |
---|
| 215 | |
---|
| 216 | status = rld::process::execute (rld::cc::get_cc (), |
---|
| 217 | args, |
---|
| 218 | out.name (), |
---|
| 219 | err.name ()); |
---|
| 220 | |
---|
| 221 | if ((status.type != rld::process::status::normal) || |
---|
| 222 | (status.code != 0)) |
---|
| 223 | { |
---|
| 224 | err.output (rld::cc::get_cc (), std::cout); |
---|
| 225 | throw rld::error ("Compiler error", "compiling wrapper"); |
---|
| 226 | } |
---|
| 227 | } |
---|
| 228 | |
---|
[ec24a37] | 229 | /** |
---|
[7461924] | 230 | * RTEMS Linker options. This needs to be rewritten to be like cc where only a |
---|
[ec24a37] | 231 | * single '-' and long options is present. |
---|
| 232 | */ |
---|
| 233 | static struct option rld_opts[] = { |
---|
| 234 | { "help", no_argument, NULL, 'h' }, |
---|
| 235 | { "version", no_argument, NULL, 'V' }, |
---|
| 236 | { "verbose", no_argument, NULL, 'v' }, |
---|
| 237 | { "warn", no_argument, NULL, 'w' }, |
---|
[aac2949] | 238 | { "keep", no_argument, NULL, 'k' }, |
---|
| 239 | { "embed", no_argument, NULL, 'e' }, |
---|
| 240 | { "symc", required_argument, NULL, 'S' }, |
---|
| 241 | { "output", required_argument, NULL, 'o' }, |
---|
| 242 | { "map", required_argument, NULL, 'm' }, |
---|
[7461924] | 243 | { "cc", required_argument, NULL, 'C' }, |
---|
| 244 | { "exec-prefix", required_argument, NULL, 'E' }, |
---|
[aac2949] | 245 | { "cflags", required_argument, NULL, 'c' }, |
---|
[ec24a37] | 246 | { NULL, 0, NULL, 0 } |
---|
| 247 | }; |
---|
| 248 | |
---|
| 249 | void |
---|
| 250 | usage (int exit_code) |
---|
| 251 | { |
---|
[aac2949] | 252 | std::cout << "rtems-syms [options] kernel" << std::endl |
---|
[aef6d90] | 253 | << "Options and arguments:" << std::endl |
---|
| 254 | << " -h : help (also --help)" << std::endl |
---|
| 255 | << " -V : print linker version number and exit (also --version)" << std::endl |
---|
[6c4218b] | 256 | << " -v : verbose (trace import parts), can supply multiple times" << std::endl |
---|
[aef6d90] | 257 | << " to increase verbosity (also --verbose)" << std::endl |
---|
| 258 | << " -w : generate warnings (also --warn)" << std::endl |
---|
[aac2949] | 259 | << " -k : keep temporary files (also --keep)" << std::endl |
---|
| 260 | << " -e : embedded symbol table (also --embed)" << std::endl |
---|
| 261 | << " -S : symbol's C file (also --symc)" << std::endl |
---|
| 262 | << " -o file : output object file (also --output)" << std::endl |
---|
| 263 | << " -m file : output a map file (also --map)" << std::endl |
---|
[7461924] | 264 | << " -C file : execute file as the target C compiler (also --cc)" << std::endl |
---|
| 265 | << " -E prefix : the RTEMS tool prefix (also --exec-prefix)" << std::endl |
---|
[40fd7a0] | 266 | << " -c cflags : C compiler flags (also --cflags)" << std::endl; |
---|
[ec24a37] | 267 | ::exit (exit_code); |
---|
| 268 | } |
---|
| 269 | |
---|
| 270 | static void |
---|
| 271 | fatal_signal (int signum) |
---|
| 272 | { |
---|
| 273 | signal (signum, SIG_DFL); |
---|
| 274 | |
---|
[a136346] | 275 | rld::process::temporaries_clean_up (); |
---|
[ec24a37] | 276 | |
---|
[aef6d90] | 277 | /* |
---|
[ec24a37] | 278 | * Get the same signal again, this time not handled, so its normal effect |
---|
[aef6d90] | 279 | * occurs. |
---|
[ec24a37] | 280 | */ |
---|
| 281 | kill (getpid (), signum); |
---|
| 282 | } |
---|
| 283 | |
---|
| 284 | static void |
---|
| 285 | setup_signals (void) |
---|
| 286 | { |
---|
| 287 | if (signal (SIGINT, SIG_IGN) != SIG_IGN) |
---|
| 288 | signal (SIGINT, fatal_signal); |
---|
| 289 | #ifdef SIGHUP |
---|
| 290 | if (signal (SIGHUP, SIG_IGN) != SIG_IGN) |
---|
| 291 | signal (SIGHUP, fatal_signal); |
---|
| 292 | #endif |
---|
| 293 | if (signal (SIGTERM, SIG_IGN) != SIG_IGN) |
---|
| 294 | signal (SIGTERM, fatal_signal); |
---|
| 295 | #ifdef SIGPIPE |
---|
| 296 | if (signal (SIGPIPE, SIG_IGN) != SIG_IGN) |
---|
| 297 | signal (SIGPIPE, fatal_signal); |
---|
| 298 | #endif |
---|
| 299 | #ifdef SIGCHLD |
---|
| 300 | signal (SIGCHLD, SIG_DFL); |
---|
| 301 | #endif |
---|
| 302 | } |
---|
| 303 | |
---|
| 304 | int |
---|
| 305 | main (int argc, char* argv[]) |
---|
| 306 | { |
---|
| 307 | int ec = 0; |
---|
| 308 | |
---|
| 309 | setup_signals (); |
---|
| 310 | |
---|
| 311 | try |
---|
| 312 | { |
---|
[aac2949] | 313 | rld::files::cache kernel; |
---|
[ec24a37] | 314 | rld::symbols::table symbols; |
---|
[aac2949] | 315 | std::string kernel_name; |
---|
| 316 | std::string output; |
---|
| 317 | std::string map; |
---|
| 318 | std::string cc; |
---|
| 319 | std::string symc; |
---|
| 320 | bool embed = false; |
---|
[ec24a37] | 321 | bool warnings = false; |
---|
| 322 | |
---|
[aac2949] | 323 | rld::set_cmdline (argc, argv); |
---|
[ec24a37] | 324 | |
---|
| 325 | while (true) |
---|
| 326 | { |
---|
[aac2949] | 327 | int opt = ::getopt_long (argc, argv, "hvVwS:o:m:E:c:C:", rld_opts, NULL); |
---|
[ec24a37] | 328 | if (opt < 0) |
---|
| 329 | break; |
---|
[aef6d90] | 330 | |
---|
[ec24a37] | 331 | switch (opt) |
---|
| 332 | { |
---|
| 333 | case 'V': |
---|
[977c3de] | 334 | std::cout << "rtems-syms (RTEMS Symbols) " << rld::version () |
---|
[ec24a37] | 335 | << std::endl; |
---|
| 336 | ::exit (0); |
---|
| 337 | break; |
---|
[aef6d90] | 338 | |
---|
[ec24a37] | 339 | case 'v': |
---|
| 340 | rld::verbose_inc (); |
---|
| 341 | break; |
---|
[aef6d90] | 342 | |
---|
[ec24a37] | 343 | case 'w': |
---|
| 344 | warnings = true; |
---|
| 345 | break; |
---|
| 346 | |
---|
[aac2949] | 347 | case 'k': |
---|
| 348 | rld::process::set_keep_temporary_files (); |
---|
[ec24a37] | 349 | break; |
---|
| 350 | |
---|
[aac2949] | 351 | case 'e': |
---|
| 352 | embed = true; |
---|
[ec24a37] | 353 | break; |
---|
| 354 | |
---|
[aac2949] | 355 | case 'o': |
---|
| 356 | output = optarg; |
---|
| 357 | break; |
---|
| 358 | |
---|
| 359 | case 'm': |
---|
| 360 | map = optarg; |
---|
[ec24a37] | 361 | break; |
---|
| 362 | |
---|
[7461924] | 363 | case 'C': |
---|
[8807135] | 364 | if (rld::cc::is_exec_prefix_set ()) |
---|
[7461924] | 365 | std::cerr << "warning: exec-prefix ignored when CC provided" << std::endl; |
---|
[8807135] | 366 | rld::cc::set_cc (optarg); |
---|
[7461924] | 367 | break; |
---|
| 368 | |
---|
[ec24a37] | 369 | case 'E': |
---|
[8807135] | 370 | if (rld::cc::is_cc_set ()) |
---|
| 371 | std::cerr << "warning: exec-prefix ignored when CC provided" << std::endl; |
---|
| 372 | rld::cc::set_exec_prefix (optarg); |
---|
[ec24a37] | 373 | break; |
---|
| 374 | |
---|
| 375 | case 'c': |
---|
[8807135] | 376 | rld::cc::set_flags (optarg, rld::cc::ft_cflags); |
---|
[ec24a37] | 377 | break; |
---|
| 378 | |
---|
[aac2949] | 379 | case 'S': |
---|
| 380 | symc = optarg; |
---|
| 381 | break; |
---|
| 382 | |
---|
[ec24a37] | 383 | case '?': |
---|
| 384 | usage (3); |
---|
| 385 | break; |
---|
| 386 | |
---|
| 387 | case 'h': |
---|
| 388 | usage (0); |
---|
| 389 | break; |
---|
| 390 | } |
---|
| 391 | } |
---|
| 392 | |
---|
[aac2949] | 393 | /* |
---|
| 394 | * Set the program name. |
---|
| 395 | */ |
---|
| 396 | rld::set_progname (argv[0]); |
---|
| 397 | |
---|
[ec24a37] | 398 | argc -= optind; |
---|
| 399 | argv += optind; |
---|
| 400 | |
---|
[aac2949] | 401 | if (rld::verbose ()) |
---|
| 402 | std::cout << "RTEMS Kernel Symbols " << rld::version () << std::endl; |
---|
[ec24a37] | 403 | |
---|
| 404 | /* |
---|
| 405 | * If there are no object files there is nothing to link. |
---|
| 406 | */ |
---|
[977c3de] | 407 | if (argc == 0) |
---|
[aac2949] | 408 | throw rld::error ("no kernel file", "options"); |
---|
| 409 | if (argc != 1) |
---|
| 410 | throw rld::error ("only one kernel file", "options"); |
---|
| 411 | if (output.empty ()) |
---|
| 412 | throw rld::error ("no output file", "options"); |
---|
[ec24a37] | 413 | |
---|
[aac2949] | 414 | kernel_name = *argv; |
---|
[aef6d90] | 415 | |
---|
[aac2949] | 416 | if (rld::verbose ()) |
---|
| 417 | std::cout << "kernel: " << kernel_name << std::endl; |
---|
[ec24a37] | 418 | |
---|
| 419 | /* |
---|
[aac2949] | 420 | * Load the symbols from the kernel. |
---|
[ec24a37] | 421 | */ |
---|
[aac2949] | 422 | try |
---|
| 423 | { |
---|
| 424 | kernel.open (); |
---|
| 425 | kernel.add (kernel_name); |
---|
| 426 | kernel.load_symbols (symbols, true); |
---|
[ec24a37] | 427 | |
---|
[aac2949] | 428 | /* |
---|
| 429 | * If the full path to CC is not provided and the exec-prefix is not set |
---|
| 430 | * by the command line see if it can be detected from the object file |
---|
| 431 | * types. This must be after we have added the object files because they |
---|
| 432 | * are used when detecting. |
---|
| 433 | */ |
---|
| 434 | if (!cc.empty ()) |
---|
| 435 | rld::cc::set_cc (cc); |
---|
| 436 | if (!rld::cc::is_cc_set () && !rld::cc::is_exec_prefix_set ()) |
---|
| 437 | rld::cc::set_exec_prefix (rld::elf::machine_type ()); |
---|
[ec24a37] | 438 | |
---|
[aac2949] | 439 | rld::process::tempfile c (".c"); |
---|
[ec24a37] | 440 | |
---|
[aac2949] | 441 | if (!symc.empty ()) |
---|
| 442 | { |
---|
| 443 | c.override (symc); |
---|
| 444 | c.keep (); |
---|
| 445 | } |
---|
[ec24a37] | 446 | |
---|
[aac2949] | 447 | /* |
---|
| 448 | * Generate and compile the symbol map. |
---|
| 449 | */ |
---|
| 450 | generate_symmap (c, output, symbols, embed); |
---|
[ec24a37] | 451 | |
---|
[8190102] | 452 | /* |
---|
[aac2949] | 453 | * Create a map file is asked to. |
---|
[8190102] | 454 | */ |
---|
[aac2949] | 455 | if (!map.empty ()) |
---|
| 456 | { |
---|
| 457 | std::ofstream mout; |
---|
| 458 | mout.open (map); |
---|
| 459 | if (!mout.is_open ()) |
---|
| 460 | throw rld::error ("map file open failed", "map"); |
---|
| 461 | mout << "RTEMS Kernel Symbols Map" << std::endl |
---|
| 462 | << " kernel: " << kernel_name << std::endl |
---|
| 463 | << std::endl; |
---|
| 464 | rld::symbols::output (mout, symbols); |
---|
| 465 | mout.close (); |
---|
| 466 | } |
---|
[8190102] | 467 | |
---|
[aac2949] | 468 | kernel.close (); |
---|
[8190102] | 469 | } |
---|
| 470 | catch (...) |
---|
| 471 | { |
---|
[aac2949] | 472 | kernel.close (); |
---|
[8190102] | 473 | throw; |
---|
| 474 | } |
---|
[ec24a37] | 475 | |
---|
[aac2949] | 476 | kernel.close (); |
---|
[ec24a37] | 477 | } |
---|
| 478 | catch (rld::error re) |
---|
| 479 | { |
---|
| 480 | std::cerr << "error: " |
---|
| 481 | << re.where << ": " << re.what |
---|
| 482 | << std::endl; |
---|
| 483 | ec = 10; |
---|
| 484 | } |
---|
| 485 | catch (std::exception e) |
---|
[aef6d90] | 486 | { |
---|
[ec24a37] | 487 | int status; |
---|
| 488 | char* realname; |
---|
| 489 | realname = abi::__cxa_demangle (e.what(), 0, 0, &status); |
---|
[977c3de] | 490 | std::cerr << "error: exception: " << realname << " ["; |
---|
[ec24a37] | 491 | ::free (realname); |
---|
| 492 | const std::type_info &ti = typeid (e); |
---|
| 493 | realname = abi::__cxa_demangle (ti.name(), 0, 0, &status); |
---|
| 494 | std::cerr << realname << "] " << e.what () << std::endl; |
---|
| 495 | ::free (realname); |
---|
| 496 | ec = 11; |
---|
| 497 | } |
---|
| 498 | catch (...) |
---|
[aef6d90] | 499 | { |
---|
[ec24a37] | 500 | /* |
---|
| 501 | * Helps to know if this happens. |
---|
| 502 | */ |
---|
| 503 | std::cout << "error: unhandled exception" << std::endl; |
---|
| 504 | ec = 12; |
---|
| 505 | } |
---|
| 506 | |
---|
| 507 | return ec; |
---|
| 508 | } |
---|