| /* Copyright (C) 2021-2024 Free Software Foundation, Inc. | |
| Contributed by Oracle. | |
| This file is part of GNU Binutils. | |
| This program is free software; you can redistribute it and/or modify | |
| it under the terms of the GNU General Public License as published by | |
| the Free Software Foundation; either version 3, or (at your option) | |
| any later version. | |
| This program is distributed in the hope that it will be useful, | |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| GNU General Public License for more details. | |
| You should have received a copy of the GNU General Public License | |
| along with this program; if not, write to the Free Software | |
| Foundation, 51 Franklin Street - Fifth Floor, Boston, | |
| MA 02110-1301, USA. */ | |
| #include "config.h" | |
| #include <unistd.h> | |
| #include <fcntl.h> | |
| #include "util.h" | |
| #include "DbeApplication.h" | |
| #include "DbeSession.h" | |
| #include "Function.h" | |
| #include "LoadObject.h" | |
| #include "Module.h" | |
| #include "DbeView.h" | |
| #include "Print.h" | |
| #include "DbeFile.h" | |
| #include "Command.h" | |
| class er_src : public DbeApplication | |
| { | |
| public: | |
| er_src (int argc, char *argv[]); | |
| void start (int argc, char *argv[]); | |
| private: | |
| // override methods in base class | |
| void usage (); | |
| int check_args (int argc, char *argv[]); | |
| void run_args (int argc, char *argv[]); | |
| enum Obj_Types | |
| { | |
| OT_EXE_ELF = 0, OT_JAVA_CLASS, OT_JAR_FILE, OT_UNKNOWN | |
| }; | |
| void open (char *exe); | |
| void dump_annotated (char *name, char* sel, char *src, DbeView *dbev, | |
| bool is_dis, bool first); | |
| void checkJavaClass (char *exe); | |
| void print_header (bool first, const char* text); | |
| void proc_cmd (CmdType cmd_type, bool first, char *arg1, | |
| const char *arg2, const char *arg3 = NULL); | |
| FILE *set_outfile (char *cmd, FILE *&set_file); | |
| bool is_java_class () { return obj_type == OT_JAVA_CLASS; } | |
| int dbevindex; | |
| DbeView *dbev; | |
| LoadObject *lo; | |
| Obj_Types obj_type; | |
| const char *out_fname; | |
| FILE *out_file; | |
| bool isDisasm; | |
| bool isFuncs; | |
| bool isDFuncs; | |
| bool isSrc; | |
| bool v_opt; | |
| int multiple; | |
| char *str_compcom; | |
| }; | |
| static int | |
| real_main (int argc, char *argv[]) | |
| { | |
| er_src *src = new er_src (argc, argv); | |
| src->start (argc, argv); | |
| delete src; | |
| return 0; | |
| } | |
| int | |
| main (int argc, char *argv[]) | |
| { | |
| return catch_out_of_memory (real_main, argc, argv); | |
| } | |
| er_src::er_src (int argc, char *argv[]) | |
| : DbeApplication (argc, argv) | |
| { | |
| obj_type = OT_UNKNOWN; | |
| out_fname = "<stdout>"; | |
| out_file = stdout; | |
| isDisasm = false; | |
| isFuncs = false; | |
| isDFuncs = false; | |
| isSrc = false; | |
| v_opt = false; | |
| multiple = 0; | |
| lo = NULL; | |
| } | |
| static int | |
| FuncNameCmp (const void *a, const void *b) | |
| { | |
| Function *item1 = *((Function **) a); | |
| Function *item2 = *((Function **) b); | |
| return strcmp (item1->get_mangled_name (), item2->get_mangled_name ()); | |
| } | |
| static int | |
| FuncAddrCmp (const void *a, const void *b) | |
| { | |
| Function *item1 = *((Function **) a); | |
| Function *item2 = *((Function **) b); | |
| return (item1->img_offset == item2->img_offset) ? | |
| FuncNameCmp (a, b) : item1->img_offset > item2->img_offset ? 1 : -1; | |
| } | |
| void | |
| er_src::usage () | |
| { | |
| /* | |
| Ruud - Isolate this line because it has an argument. Otherwise it would be at the | |
| end of a long usage list. | |
| */ | |
| printf ( GTXT ( | |
| "Usage: gprofng display src [OPTION(S)] TARGET-OBJECT\n")); | |
| printf ( GTXT ( | |
| "\n" | |
| "Display the source code listing, or source code interleaved with disassembly code,\n" | |
| "as extracted from the target object (an executable, shared object, object file, or\n" | |
| "a Java .class file).\n" | |
| "\n" | |
| "Options:\n" | |
| "\n" | |
| " --version print the version number and exit.\n" | |
| " --help print usage information and exit.\n" | |
| " --verbose {on|off} enable (on) or disable (off) verbose mode; the default is \"off\".\n" | |
| "\n" | |
| " -func list all the functions from the given object.\n" | |
| "\n" | |
| " -source item tag show the source code for item; the tag is used to\n" | |
| " differentiate in case of multiple occurences with\n" | |
| " the same name; the combination of \"all -1\" selects\n" | |
| " all the functions in the object; the default is\n" | |
| " \"-source all -1\".\n" | |
| "\n" | |
| " -disasm item tag show the source code, interleaved with the disassembled\n" | |
| " instructions; the same definitions for item and tag apply.\n" | |
| "\n" | |
| " -outfile <filename> write results to file <filename>; a dash (-) writes to\n" | |
| " stdout; this is also the default; note that this only\n" | |
| " affects options included to the right of this option.\n" | |
| "\n" | |
| "Documentation:\n" | |
| "\n" | |
| "A getting started guide for gprofng is maintained as a Texinfo manual. If the info and\n" | |
| "gprofng programs are properly installed at your site, the command \"info gprofng\"\n" | |
| "should give you access to this document.\n" | |
| "\n" | |
| "See also:\n" | |
| "\n" | |
| "gprofng(1), gp-archive(1), gp-collect-app(1), gp-display-html(1), gp-display-text(1)\n")); | |
| /* | |
| printf (GTXT ("Usage: %s [OPTION] a.out/.so/.o/.class\n\n"), whoami); | |
| printf (GTXT (" -func List all the functions from the given object\n" | |
| " -source, -src item tag Show the annotated source for the listed item\n" | |
| " -disasm item tag Include the disassembly in the listing\n" | |
| " -V Print the current release version of er_src\n" | |
| " -cc, -scc, -dcc com_spec Define the compiler commentary classes to show\n" | |
| " -outfile filename Open filename for output\n")); | |
| */ | |
| exit (0); | |
| } | |
| void | |
| er_src::start (int argc, char *argv[]) | |
| { | |
| dbevindex = dbeSession->createView (0, -1); | |
| dbev = dbeSession->getView (dbevindex); | |
| // get options | |
| check_args (argc, argv); | |
| run_args (argc, argv); | |
| if (out_file != stdout) | |
| fclose (out_file); | |
| } | |
| FILE * | |
| er_src::set_outfile (char *cmd, FILE *&set_file) | |
| { | |
| FILE *new_file; | |
| if (!strcasecmp (cmd, "-")) | |
| { | |
| new_file = stdout; | |
| out_fname = "<stdout>"; | |
| } | |
| else | |
| { | |
| char *cmdpath; | |
| char *fname = strstr (cmd, "~/"); | |
| // Handle ~ in file names | |
| char *home = getenv ("HOME"); | |
| if (fname != NULL && home != NULL) | |
| cmdpath = dbe_sprintf ("%s/%s", home, fname + 2); | |
| else if ((fname = strstr (cmd, "~")) != NULL && home != NULL) | |
| cmdpath = dbe_sprintf ("/home/%s", fname + 1); | |
| else | |
| cmdpath = strdup (cmd); | |
| new_file = fopen (cmdpath, "w"); | |
| if (new_file == NULL) | |
| { | |
| fprintf (stderr, GTXT ("Unable to open file: %s"), cmdpath); | |
| free (cmdpath); | |
| return NULL; | |
| } | |
| out_fname = cmdpath; | |
| } | |
| if (set_file && (set_file != stdout)) | |
| fclose (set_file); | |
| set_file = new_file; | |
| return set_file; | |
| } | |
| void | |
| er_src::proc_cmd (CmdType cmd_type, bool first, char *arg1, | |
| const char *arg2, const char *arg3) | |
| { | |
| Cmd_status status; | |
| Module *module; | |
| Function *fitem; | |
| int mindex, findex; | |
| switch (cmd_type) | |
| { | |
| case SOURCE: | |
| dbev->set_view_mode (VMODE_USER); | |
| print_anno_file (arg1, arg2, arg3, false, | |
| stdout, stdin, out_file, dbev, false); | |
| break; | |
| case DISASM: | |
| dbev->set_view_mode (VMODE_MACHINE); | |
| print_header (first, GTXT ("Annotated disassembly\n")); | |
| print_anno_file (arg1, arg2, arg3, true, | |
| stdout, stdin, out_file, dbev, false); | |
| break; | |
| case OUTFILE: | |
| if (arg1) | |
| set_outfile (arg1, out_file); | |
| break; | |
| case FUNCS: | |
| print_header (false, GTXT ("Function list\n")); | |
| fprintf (out_file, GTXT ("Functions sorted in lexicographic order\n")); | |
| fprintf (out_file, GTXT ("\nLoad Object: %s\n\n"), lo->get_name ()); | |
| if (lo->wsize == W32) | |
| fprintf (out_file, GTXT (" Address Size Name\n\n")); | |
| else | |
| fprintf (out_file, GTXT (" Address Size Name\n\n")); | |
| Vec_loop (Module*, lo->seg_modules, mindex, module) | |
| { | |
| module->functions->sort (FuncNameCmp); | |
| const char *fmt = (lo->wsize == W32) ? | |
| GTXT (" 0x%08llx %8lld %s\n") : | |
| GTXT (" 0x%016llx %16lld %s\n"); | |
| Vec_loop (Function*, module->functions, findex, fitem) | |
| { | |
| fprintf (out_file, fmt, | |
| (ull_t) fitem->img_offset, | |
| (ull_t) fitem->size, | |
| fitem->get_name ()); | |
| } | |
| } | |
| break; | |
| case DUMPFUNC: | |
| lo->functions->sort (FuncAddrCmp); | |
| print_header (first, GTXT ("Dump functions\n")); | |
| lo->dump_functions (out_file); | |
| first = false; | |
| break; | |
| case SCOMPCOM: | |
| status = dbev->proc_compcom (arg1, true, false); | |
| if (status != CMD_OK) | |
| fprintf (stderr, GTXT ("Error: %s"), Command::get_err_string (status)); | |
| break; | |
| case DCOMPCOM: | |
| status = dbev->proc_compcom (arg1, false, false); | |
| if (status != CMD_OK) | |
| fprintf (stderr, GTXT ("Error: %s"), Command::get_err_string (status)); | |
| break; | |
| case COMPCOM: | |
| status = dbev->proc_compcom (arg1, true, false); | |
| if (status != CMD_OK) | |
| fprintf (stderr, GTXT ("Error: %s: %s"), Command::get_err_string (status), arg1); | |
| status = dbev->proc_compcom (arg1, false, false); | |
| if (status != CMD_OK) | |
| fprintf (stderr, GTXT ("Error: %s: %s"), Command::get_err_string (status), arg1); | |
| break; | |
| case HELP: | |
| usage (); | |
| break; | |
| case VERSION_cmd: | |
| if (out_file != stdout) | |
| // Ruud | |
| Application::print_version_info (); | |
| /* | |
| fprintf (out_file, "GNU %s version %s\n", get_basename (prog_name), VERSION); | |
| */ | |
| break; | |
| default: | |
| fprintf (stderr, GTXT ("Invalid option")); | |
| break; | |
| } | |
| } | |
| void | |
| er_src::run_args (int argc, char *argv[]) | |
| { | |
| CmdType cmd_type; | |
| int arg_count, cparam; | |
| char *arg; | |
| char *arg1; | |
| const char *arg2; | |
| bool first = true; | |
| bool space; | |
| Module *module; | |
| int mindex; | |
| for (int i = 1; i < argc; i++) | |
| { | |
| if (*argv[i] != '-') | |
| { | |
| if (!multiple) | |
| { // er_src -V exe | |
| space = false; | |
| dbev->set_view_mode (VMODE_USER); | |
| print_header (first, GTXT ("Annotated source\n")); | |
| Vec_loop (Module*, lo->seg_modules, mindex, module) | |
| { | |
| if ((module->flags & MOD_FLAG_UNKNOWN) != 0 || | |
| module->lang_code == Sp_lang_unknown) | |
| continue; | |
| if (space) | |
| fprintf (out_file, "\n"); | |
| print_anno_file (module->file_name, "1", NULL, false, | |
| stdout, stdin, out_file, dbev, false); | |
| space = true; | |
| } | |
| } | |
| break; | |
| } | |
| if (strncmp (argv[i], NTXT ("--whoami="), 9) == 0) | |
| { | |
| whoami = argv[i] + 9; | |
| continue; | |
| } | |
| switch (cmd_type = Command::get_command (argv[i] + 1, arg_count, cparam)) | |
| { | |
| case SOURCE: | |
| case DISASM: | |
| { | |
| i += arg_count; | |
| multiple++; | |
| if (i >= argc || argv[i] == NULL || | |
| (*(argv[i]) == '-' && atoi (argv[i]) != -1) || i + 1 == argc) | |
| { | |
| i--; | |
| arg = argv[i]; | |
| arg2 = "1"; | |
| } | |
| else | |
| { | |
| arg = argv[i - 1]; | |
| if (*(argv[i]) == '-' && atoi (argv[i]) == -1 && | |
| streq (arg, NTXT ("all"))) | |
| { | |
| space = false; | |
| if (cmd_type == SOURCE) | |
| print_header (first, GTXT ("Annotated source\n")); | |
| else | |
| print_header (first, GTXT ("Annotated disassembly\n")); | |
| Vec_loop (Module*, lo->seg_modules, mindex, module) | |
| { | |
| if ((module->flags & MOD_FLAG_UNKNOWN) != 0 || | |
| module->lang_code == Sp_lang_unknown) | |
| continue; | |
| if (space) | |
| fprintf (out_file, "\n"); | |
| proc_cmd (cmd_type, first, module->file_name, "1"); | |
| space = true; | |
| } | |
| first = false; | |
| break; | |
| } | |
| arg2 = argv[i]; | |
| } | |
| char *fcontext = NULL; | |
| arg1 = parse_fname (arg, &fcontext); | |
| if (arg1 == NULL) | |
| { | |
| fprintf (stderr, GTXT ("Error: Invalid function/file setting: %s\n"), arg1); | |
| free (fcontext); | |
| break; | |
| } | |
| proc_cmd (cmd_type, first, arg1, arg2, fcontext); | |
| free (arg1); | |
| free (fcontext); | |
| first = false; | |
| break; | |
| } | |
| case OUTFILE: | |
| case FUNCS: | |
| case DUMPFUNC: | |
| case COMPCOM: | |
| case SCOMPCOM: | |
| case DCOMPCOM: | |
| case VERSION_cmd: | |
| case HELP: | |
| proc_cmd (cmd_type, first, (arg_count > 0) ? argv[i + 1] : NULL, | |
| (arg_count > 1) ? argv[i + 2] : NULL); | |
| i += arg_count; | |
| break; | |
| default: | |
| if (streq (argv[i] + 1, NTXT ("all")) || streq (argv[i] + 1, NTXT ("dall"))) | |
| { | |
| first = false; | |
| multiple++; | |
| if (streq (argv[i] + 1, NTXT ("all"))) | |
| proc_cmd (FUNCS, first, NULL, NULL); | |
| else | |
| proc_cmd (DUMPFUNC, first, NULL, NULL); | |
| space = false; | |
| print_header (first, GTXT ("Annotated source\n")); | |
| Vec_loop (Module*, lo->seg_modules, mindex, module) | |
| { | |
| if ((module->flags & MOD_FLAG_UNKNOWN) != 0 || | |
| module->lang_code == Sp_lang_unknown) | |
| continue; | |
| if (space) | |
| fprintf (out_file, "\n"); | |
| proc_cmd (SOURCE, first, module->file_name, "1"); | |
| space = true; | |
| } | |
| print_header (first, GTXT ("Annotated disassembly\n")); | |
| Vec_loop (Module*, lo->seg_modules, mindex, module) | |
| { | |
| if ((module->flags & MOD_FLAG_UNKNOWN) != 0 || | |
| module->lang_code == Sp_lang_unknown) | |
| continue; | |
| if (space) | |
| fprintf (out_file, "\n"); | |
| proc_cmd (DISASM, first, module->file_name, "1"); | |
| space = true; | |
| } | |
| } | |
| else | |
| { | |
| proc_cmd (cmd_type, first, (arg_count > 0) ? argv[i + 1] : NULL, | |
| (arg_count > 1) ? argv[i + 2] : NULL); | |
| i += arg_count; | |
| break; | |
| } | |
| } | |
| } | |
| } | |
| int | |
| er_src::check_args (int argc, char *argv[]) | |
| { | |
| CmdType cmd_type = UNKNOWN_CMD; | |
| int arg_count, cparam; | |
| int i; | |
| char *exe; | |
| bool first = true; | |
| if (argc == 1) | |
| usage (); | |
| // If any comments from the .rc files, log them to stderr | |
| Emsg * rcmsg = fetch_comments (); | |
| while (rcmsg != NULL) | |
| { | |
| fprintf (stderr, "%s: %s\n", prog_name, rcmsg->get_msg ()); | |
| rcmsg = rcmsg->next; | |
| } | |
| // Parsing the command line | |
| opterr = 0; | |
| exe = NULL; | |
| for (i = 1; i < argc; i++) | |
| { | |
| if (*argv[i] != '-') | |
| { | |
| exe = argv[i]; | |
| if (i == 1) | |
| { // er_src exe ? | |
| if (!exe) | |
| usage (); | |
| if (argc == 3) // er_src exe file | |
| usage (); | |
| } | |
| else if (v_opt && !multiple && !exe && !str_compcom) // just er_src -V | |
| exit (0); | |
| if (argc < i + 1 || argc > i + 3) | |
| usage (); | |
| i++; | |
| if (argc > i) | |
| usage (); | |
| open (exe); | |
| return i; | |
| } | |
| switch (cmd_type = Command::get_command (argv[i] + 1, arg_count, cparam)) | |
| { | |
| case WHOAMI: | |
| whoami = argv[i] + 1 + cparam; | |
| break; | |
| case HELP: | |
| i += arg_count; | |
| multiple++; | |
| usage (); | |
| break; | |
| case VERSION_cmd: | |
| if (first) | |
| { | |
| // Ruud | |
| Application::print_version_info (); | |
| /* | |
| printf ("GNU %s version %s\n", get_basename (prog_name), VERSION); | |
| */ | |
| v_opt = true; | |
| first = false; | |
| } | |
| break; | |
| case SOURCE: | |
| case DISASM: | |
| i += arg_count; | |
| multiple++; | |
| isDisasm = true; | |
| if (i >= argc || argv[i] == NULL || | |
| (*(argv[i]) == '-' && atoi (argv[i]) != -1) || (i + 1 == argc)) | |
| i--; | |
| break; | |
| case DUMPFUNC: | |
| i += arg_count; | |
| multiple++; | |
| break; | |
| case FUNCS: | |
| i += arg_count; | |
| multiple++; | |
| break; | |
| case OUTFILE: | |
| case COMPCOM: | |
| case SCOMPCOM: | |
| case DCOMPCOM: | |
| i += arg_count; | |
| break; | |
| default: | |
| if (!(streq (argv[i] + 1, NTXT ("all")) || | |
| streq (argv[i] + 1, NTXT ("dall")))) | |
| { | |
| fprintf (stderr, "Error: invalid option: `%s'\n", argv[i]); | |
| exit (1); | |
| } | |
| } | |
| } | |
| if (!exe && !(argc == 2 && cmd_type == VERSION_cmd)) | |
| usage (); | |
| return i; | |
| } | |
| void | |
| er_src::checkJavaClass (char* exe) | |
| { | |
| unsigned char cf_buf[4]; | |
| unsigned int magic_number; | |
| int fd = ::open (exe, O_RDONLY | O_LARGEFILE); | |
| if (fd == -1) | |
| return; | |
| if (sizeof (cf_buf) == read_from_file (fd, cf_buf, sizeof (cf_buf))) | |
| { | |
| magic_number = cf_buf[0] << 24; | |
| magic_number |= cf_buf[1] << 16; | |
| magic_number |= cf_buf[2] << 8; | |
| magic_number |= cf_buf[3]; | |
| if (magic_number == 0xcafebabe) | |
| obj_type = OT_JAVA_CLASS; | |
| } | |
| close (fd); | |
| } | |
| void | |
| er_src::print_header (bool first, const char* text) | |
| { | |
| if (!first) | |
| fprintf (out_file, "\n"); | |
| if (multiple > 1) | |
| { | |
| fprintf (out_file, NTXT ("%s"), text); | |
| fprintf (out_file, "---------------------------------------\n"); | |
| } | |
| } | |
| void | |
| er_src::dump_annotated (char *name, char *sel, char *src, DbeView *dbevr, | |
| bool is_dis, bool first) | |
| { | |
| Module *module; | |
| bool space; | |
| int mindex; | |
| print_header (first, (is_dis) ? ((is_java_class ()) ? | |
| GTXT ("Annotated bytecode\n") : | |
| GTXT ("Annotated disassembly\n")) : | |
| GTXT ("Annotated source\n")); | |
| if (!name) | |
| { | |
| space = false; | |
| Vec_loop (Module*, lo->seg_modules, mindex, module) | |
| { | |
| if ((module->flags & MOD_FLAG_UNKNOWN) != 0 || | |
| (!is_dis && module->lang_code == Sp_lang_unknown)) | |
| continue; | |
| if (space) | |
| fprintf (out_file, "\n"); | |
| print_anno_file (module->file_name, sel, src, is_dis, | |
| stdout, stdin, out_file, dbevr, false); | |
| space = true; | |
| } | |
| } | |
| else | |
| print_anno_file (name, sel, src, is_dis, stdout, stdin, out_file, dbevr, false); | |
| } | |
| static bool | |
| isFatal (bool isDisasm, LoadObject::Arch_status status) | |
| { | |
| if (isDisasm) | |
| { | |
| switch (status) | |
| { | |
| // non-fatal errors for disassembly | |
| case LoadObject::ARCHIVE_BAD_STABS: | |
| case LoadObject::ARCHIVE_NO_STABS: | |
| return false; | |
| default: | |
| return true; | |
| } | |
| } | |
| return true; | |
| } | |
| void | |
| er_src::open (char *exe) | |
| { | |
| LoadObject::Arch_status status; | |
| char *errstr; | |
| Module *module; | |
| Vector<Histable*> *module_lst; | |
| // Construct the Segment structure | |
| char *path = strdup (exe); | |
| lo = dbeSession->createLoadObject (path); | |
| if (NULL == lo->dbeFile->find_file (lo->dbeFile->get_name ())) | |
| { | |
| fprintf (stderr, GTXT ("%s: Error: unable to open file %s\n"), prog_name, lo->dbeFile->get_name ()); | |
| exit (1); | |
| } | |
| checkJavaClass (exe); | |
| if (is_java_class ()) | |
| { | |
| lo->type = LoadObject::SEG_TEXT; | |
| lo->set_platform (Java, Wnone); | |
| lo->id = (uint64_t) - 1; // see AnalyzerSession::ask_which for details | |
| module = dbeSession->createClassFile (dbe_strdup (exe)); | |
| module->loadobject = lo; | |
| lo->seg_modules->append (module); | |
| module->dbeFile->set_location (exe); | |
| if (module->readFile () != module->AE_OK) | |
| { | |
| Emsg *emsg = module->get_error (); | |
| if (emsg) | |
| { | |
| fprintf (stderr, GTXT ("%s: Error: %s\n"), prog_name, emsg->get_msg ()); | |
| return; | |
| } | |
| fprintf (stderr, GTXT ("%s: Error: Could not read class file `%s'\n"), prog_name, exe); | |
| return; | |
| } | |
| status = lo->sync_read_stabs (); | |
| if (status != LoadObject::ARCHIVE_SUCCESS) | |
| { | |
| if (status == LoadObject::ARCHIVE_ERR_OPEN) | |
| { | |
| fprintf (stderr, GTXT ("%s: Error: Could not read class file `%s'\n"), prog_name, exe); | |
| return; | |
| } | |
| else | |
| { | |
| if (isDisasm) | |
| if (status == LoadObject::ARCHIVE_NO_STABS) | |
| { | |
| fprintf (stderr, GTXT ("%s: Error: `%s' is interface; disassembly annotation not available\n"), prog_name, exe); | |
| return; | |
| } | |
| } | |
| } | |
| } | |
| else | |
| { | |
| status = lo->sync_read_stabs (); | |
| if (status != LoadObject::ARCHIVE_SUCCESS) | |
| { | |
| errstr = lo->status_str (status); | |
| if (errstr) | |
| { | |
| fprintf (stderr, "%s: %s\n", prog_name, errstr); | |
| free (errstr); | |
| } | |
| if (isFatal (isDisasm, status)) | |
| return; | |
| } | |
| obj_type = OT_EXE_ELF; | |
| // if .o file, then set file as the exe name | |
| if (lo->is_relocatable ()) | |
| { | |
| // find the module, if we can | |
| module_lst = new Vector<Histable*>; | |
| module = dbeSession->map_NametoModule (path, module_lst, 0); | |
| if (module == NULL) | |
| // Create a module with the right name | |
| module = dbeSession->createModule (lo, path); | |
| } | |
| } | |
| } |