xref: /netbsd-src/external/gpl3/binutils.old/dist/gprofng/src/gp-display-src.cc (revision ccd9df534e375a4366c5b55f23782053c7a98d82)
1 /* Copyright (C) 2021 Free Software Foundation, Inc.
2    Contributed by Oracle.
3 
4    This file is part of GNU Binutils.
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3, or (at your option)
9    any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 51 Franklin Street - Fifth Floor, Boston,
19    MA 02110-1301, USA.  */
20 
21 #include "config.h"
22 #include <unistd.h>
23 #include <fcntl.h>
24 
25 #include "util.h"
26 #include "DbeApplication.h"
27 #include "DbeSession.h"
28 #include "Function.h"
29 #include "LoadObject.h"
30 #include "Module.h"
31 #include "DbeView.h"
32 #include "Print.h"
33 #include "DbeFile.h"
34 #include "Command.h"
35 
36 class er_src : public DbeApplication
37 {
38 public:
39   er_src (int argc, char *argv[]);
40   void start (int argc, char *argv[]);
41 
42 private:
43 
44   // override methods in base class
45   void usage ();
46   int check_args (int argc, char *argv[]);
47   void run_args (int argc, char *argv[]);
48 
49   enum Obj_Types
50   {
51     OT_EXE_ELF = 0, OT_JAVA_CLASS, OT_JAR_FILE, OT_UNKNOWN
52   };
53 
54   void open (char *exe);
55   void dump_annotated (char *name, char* sel, char *src, DbeView *dbev,
56 		       bool is_dis, bool first);
57   void checkJavaClass (char *exe);
58   void print_header (bool first, const char* text);
59   void proc_cmd (CmdType cmd_type, bool first, char *arg1,
60 		 const char *arg2, const char *arg3 = NULL);
61   FILE *set_outfile (char *cmd, FILE *&set_file);
62 
63   bool is_java_class ()     { return obj_type == OT_JAVA_CLASS; }
64 
65   int dbevindex;
66   DbeView *dbev;
67   LoadObject *lo;
68   Obj_Types obj_type;
69   const char *out_fname;
70   FILE *out_file;
71   bool isDisasm;
72   bool isFuncs;
73   bool isDFuncs;
74   bool isSrc;
75   bool v_opt;
76   int multiple;
77   char *str_compcom;
78   bool hex_visible;
79   int src_visible;
80   int vis_src;
81   int vis_dis;
82   int threshold_src;
83   int threshold_dis;
84   int threshold;
85   int vis_bits;
86 };
87 
88 static int
89 real_main (int argc, char *argv[])
90 {
91   er_src *src = new er_src (argc, argv);
92   src->start (argc, argv);
93   delete src;
94   return 0;
95 }
96 
97 int
98 main (int argc, char *argv[])
99 {
100   return catch_out_of_memory (real_main, argc, argv);
101 }
102 
103 er_src::er_src (int argc, char *argv[])
104 : DbeApplication (argc, argv)
105 {
106   obj_type = OT_UNKNOWN;
107   out_fname = "<stdout>";
108   out_file = stdout;
109   isDisasm = false;
110   isFuncs = false;
111   isDFuncs = false;
112   isSrc = false;
113   v_opt = false;
114   multiple = 0;
115   lo = NULL;
116 }
117 
118 static int
119 FuncNameCmp (const void *a, const void *b)
120 {
121   Function *item1 = *((Function **) a);
122   Function *item2 = *((Function **) b);
123   return strcmp (item1->get_mangled_name (), item2->get_mangled_name ());
124 }
125 
126 static int
127 FuncAddrCmp (const void *a, const void *b)
128 {
129   Function *item1 = *((Function **) a);
130   Function *item2 = *((Function **) b);
131   return (item1->img_offset == item2->img_offset) ?
132 	  FuncNameCmp (a, b) : item1->img_offset > item2->img_offset ? 1 : -1;
133 }
134 
135 void
136 er_src::usage ()
137 {
138 
139 /*
140   Ruud - Isolate this line because it has an argument.  Otherwise it would be at the
141   end of a long usage list.
142 */
143   printf ( GTXT (
144     "Usage: gprofng display src [OPTION(S)] TARGET-OBJECT\n"));
145 
146   printf ( GTXT (
147     "\n"
148     "Display the source code listing, or source code interleaved with disassembly code,\n"
149     "as extracted from the target object (an executable, shared object, object file, or\n"
150     "a Java .class file).\n"
151     "\n"
152     "Options:\n"
153     "\n"
154     " --version           print the version number and exit.\n"
155     " --help              print usage information and exit.\n"
156     " --verbose {on|off}  enable (on) or disable (off) verbose mode; the default is \"off\".\n"
157     "\n"
158     " -func                   list all the functions from the given object.\n"
159     "\n"
160     " -source item tag    show the source code for item; the tag is used to\n"
161     "                     differentiate in case of multiple occurences with\n"
162     "                     the same name; the combination of \"all -1\" selects\n"
163     "                     all the functions in the object; the default is\n"
164     "                     \"-source all -1\".\n"
165     "\n"
166     " -disasm item tag        show the source code, interleaved with the disassembled\n"
167     "                         instructions; the same definitions for item and tag apply.\n"
168     "\n"
169     " -outfile <filename>     write results to file <filename>; a dash (-) writes to\n"
170     "                         stdout; this is also the default; note that this only\n"
171     "                         affects options included to the right of this option.\n"
172     "\n"
173    "Documentation:\n"
174     "\n"
175     "A getting started guide for gprofng is maintained as a Texinfo manual. If the info and\n"
176     "gprofng programs are properly installed at your site, the command \"info gprofng\"\n"
177     "should give you access to this document.\n"
178     "\n"
179     "See also:\n"
180     "\n"
181     "gprofng(1), gp-archive(1), gp-collect-app(1), gp-display-html(1), gp-display-text(1)\n"));
182 /*
183   printf (GTXT ("Usage: %s [OPTION] a.out/.so/.o/.class\n\n"), whoami);
184   printf (GTXT ("    -func                     List all the functions from the given object\n"
185 		"    -source, -src item tag    Show the annotated source for the listed item\n"
186 		"    -disasm item tag          Include the disassembly in the listing\n"
187 		"    -V                        Print the current release version of er_src\n"
188 		"    -cc, -scc, -dcc com_spec  Define the compiler commentary classes to show\n"
189 		"    -outfile filename         Open filename for output\n"));
190 */
191   exit (0);
192 }
193 
194 void
195 er_src::start (int argc, char *argv[])
196 {
197   dbevindex = dbeSession->createView (0, -1);
198   dbev = dbeSession->getView (dbevindex);
199 
200   // get options
201   check_args (argc, argv);
202   run_args (argc, argv);
203   if (out_file != stdout)
204     fclose (out_file);
205 }
206 
207 FILE *
208 er_src::set_outfile (char *cmd, FILE *&set_file)
209 {
210   FILE *new_file;
211   if (!strcasecmp (cmd, "-"))
212     {
213       new_file = stdout;
214       out_fname = "<stdout>";
215     }
216   else
217     {
218       char *cmdpath;
219       char *fname = strstr (cmd, "~/");
220       // Handle ~ in file names
221       char *home = getenv ("HOME");
222       if (fname != NULL && home != NULL)
223 	cmdpath = dbe_sprintf ("%s/%s", home, fname + 2);
224       else if ((fname = strstr (cmd, "~")) != NULL && home != NULL)
225 	cmdpath = dbe_sprintf ("/home/%s", fname + 1);
226       else
227 	cmdpath = strdup (cmd);
228       new_file = fopen (cmdpath, "w");
229       if (new_file == NULL)
230 	{
231 	  fprintf (stderr, GTXT ("Unable to open file: %s"), cmdpath);
232 	  free (cmdpath);
233 	  return NULL;
234 	}
235       out_fname = cmdpath;
236     }
237   if (set_file && (set_file != stdout))
238     fclose (set_file);
239 
240   set_file = new_file;
241   return set_file;
242 }
243 
244 void
245 er_src::proc_cmd (CmdType cmd_type, bool first, char *arg1,
246 		  const char *arg2, const char *arg3)
247 {
248   Cmd_status status;
249   Module *module;
250   Function *fitem;
251   int mindex, findex;
252   switch (cmd_type)
253     {
254     case SOURCE:
255       dbev->set_view_mode (VMODE_USER);
256       print_anno_file (arg1, arg2, arg3, false,
257 		       stdout, stdin, out_file, dbev, false);
258       break;
259     case DISASM:
260       dbev->set_view_mode (VMODE_MACHINE);
261       print_header (first, GTXT ("Annotated disassembly\n"));
262       print_anno_file (arg1, arg2, arg3, true,
263 		       stdout, stdin, out_file, dbev, false);
264       break;
265     case OUTFILE:
266       if (arg1)
267 	set_outfile (arg1, out_file);
268       break;
269     case FUNCS:
270       print_header (false, GTXT ("Function list\n"));
271       fprintf (out_file, GTXT ("Functions sorted in lexicographic order\n"));
272       fprintf (out_file, GTXT ("\nLoad Object: %s\n\n"), lo->get_name ());
273       if (lo->wsize == W32)
274 	fprintf (out_file, GTXT ("    Address     Size        Name\n\n"));
275       else
276 	fprintf (out_file, GTXT ("    Address                     Size        Name\n\n"));
277 
278       Vec_loop (Module*, lo->seg_modules, mindex, module)
279       {
280 	module->functions->sort (FuncNameCmp);
281 	const char *fmt = (lo->wsize == W32) ?
282 		GTXT ("  0x%08llx  %8lld      %s\n") :
283 		GTXT ("  0x%016llx  %16lld      %s\n");
284 	Vec_loop (Function*, module->functions, findex, fitem)
285 	{
286 	  fprintf (out_file, fmt,
287 		   (ull_t) fitem->img_offset,
288 		   (ull_t) fitem->size,
289 		   fitem->get_name ());
290 	}
291       }
292       break;
293     case DUMPFUNC:
294       lo->functions->sort (FuncAddrCmp);
295       print_header (first, GTXT ("Dump functions\n"));
296       lo->dump_functions (out_file);
297       first = false;
298       break;
299     case SCOMPCOM:
300       status = dbev->proc_compcom (arg1, true, false);
301       if (status != CMD_OK)
302 	fprintf (stderr, GTXT ("Error: %s"), Command::get_err_string (status));
303       break;
304     case DCOMPCOM:
305       status = dbev->proc_compcom (arg1, false, false);
306       if (status != CMD_OK)
307 	fprintf (stderr, GTXT ("Error: %s"), Command::get_err_string (status));
308       break;
309     case COMPCOM:
310       status = dbev->proc_compcom (arg1, true, false);
311       if (status != CMD_OK)
312 	fprintf (stderr, GTXT ("Error: %s: %s"), Command::get_err_string (status), arg1);
313       status = dbev->proc_compcom (arg1, false, false);
314       if (status != CMD_OK)
315 	fprintf (stderr, GTXT ("Error: %s: %s"), Command::get_err_string (status), arg1);
316       break;
317     case HELP:
318       usage ();
319       break;
320     case VERSION_cmd:
321       if (out_file != stdout)
322 // Ruud
323 	Application::print_version_info ();
324 /*
325 	fprintf (out_file, "GNU %s version %s\n", get_basename (prog_name), VERSION);
326 */
327       break;
328     default:
329       fprintf (stderr, GTXT ("Invalid option"));
330       break;
331     }
332 }
333 
334 void
335 er_src::run_args (int argc, char *argv[])
336 {
337   CmdType cmd_type;
338   int arg_count, cparam;
339   char *arg;
340   char *arg1;
341   const char *arg2;
342   bool first = true;
343   bool space;
344   Module *module;
345   int mindex;
346 
347   for (int i = 1; i < argc; i++)
348     {
349       if (*argv[i] != '-')
350 	{
351 	  if (!multiple)
352 	    { // er_src -V exe
353 	      space = false;
354 	      dbev->set_view_mode (VMODE_USER);
355 	      print_header (first, GTXT ("Annotated source\n"));
356 	      Vec_loop (Module*, lo->seg_modules, mindex, module)
357 	      {
358 		if ((module->flags & MOD_FLAG_UNKNOWN) != 0 ||
359 		    module->lang_code == Sp_lang_unknown)
360 		  continue;
361 		if (space)
362 		  fprintf (out_file, "\n");
363 		print_anno_file (module->file_name, "1", NULL, false,
364 				 stdout, stdin, out_file, dbev, false);
365 		space = true;
366 	      }
367 	    }
368 	  break;
369 	}
370       if (strncmp (argv[i], NTXT ("--whoami="), 9) == 0)
371 	{
372 	  whoami = argv[i] + 9;
373 	  continue;
374 	}
375       switch (cmd_type = Command::get_command (argv[i] + 1, arg_count, cparam))
376 	{
377 	case SOURCE:
378 	case DISASM:
379 	  {
380 	    i += arg_count;
381 	    multiple++;
382 	    if (i >= argc || argv[i] == NULL ||
383 		(*(argv[i]) == '-' && atoi (argv[i]) != -1) || i + 1 == argc)
384 	      {
385 		i--;
386 		arg = argv[i];
387 		arg2 = "1";
388 	      }
389 	    else
390 	      {
391 		arg = argv[i - 1];
392 		if (*(argv[i]) == '-' && atoi (argv[i]) == -1 &&
393 		    streq (arg, NTXT ("all")))
394 		  {
395 		    space = false;
396 		    if (cmd_type == SOURCE)
397 		      print_header (first, GTXT ("Annotated source\n"));
398 		    else
399 		      print_header (first, GTXT ("Annotated disassembly\n"));
400 		    Vec_loop (Module*, lo->seg_modules, mindex, module)
401 		    {
402 		      if ((module->flags & MOD_FLAG_UNKNOWN) != 0 ||
403 			  module->lang_code == Sp_lang_unknown)
404 			continue;
405 		      if (space)
406 			fprintf (out_file, "\n");
407 		      proc_cmd (cmd_type, first, module->file_name, "1");
408 		      space = true;
409 		    }
410 		    first = false;
411 		    break;
412 		  }
413 		arg2 = argv[i];
414 	      }
415 	    char *fcontext = NULL;
416 	    arg1 = parse_fname (arg, &fcontext);
417 	    if (arg1 == NULL)
418 	      {
419 		fprintf (stderr, GTXT ("Error: Invalid function/file setting: %s\n"), arg1);
420 		free (fcontext);
421 		break;
422 	      }
423 	    proc_cmd (cmd_type, first, arg1, arg2, fcontext);
424 	    free (arg1);
425 	    free (fcontext);
426 	    first = false;
427 	    break;
428 	  }
429 	case OUTFILE:
430 	case FUNCS:
431 	case DUMPFUNC:
432 	case COMPCOM:
433 	case SCOMPCOM:
434 	case DCOMPCOM:
435 	case VERSION_cmd:
436 	case HELP:
437 	  proc_cmd (cmd_type, first, (arg_count > 0) ? argv[i + 1] : NULL,
438 		    (arg_count > 1) ? argv[i + 2] : NULL);
439 	  i += arg_count;
440 	  break;
441 	default:
442 	  if (streq (argv[i] + 1, NTXT ("all")) || streq (argv[i] + 1, NTXT ("dall")))
443 	    {
444 	      first = false;
445 	      multiple++;
446 	      if (streq (argv[i] + 1, NTXT ("all")))
447 		proc_cmd (FUNCS, first, NULL, NULL);
448 	      else
449 		proc_cmd (DUMPFUNC, first, NULL, NULL);
450 	      space = false;
451 	      print_header (first, GTXT ("Annotated source\n"));
452 	      Vec_loop (Module*, lo->seg_modules, mindex, module)
453 	      {
454 		if ((module->flags & MOD_FLAG_UNKNOWN) != 0 ||
455 		    module->lang_code == Sp_lang_unknown)
456 		  continue;
457 		if (space)
458 		  fprintf (out_file, "\n");
459 		proc_cmd (SOURCE, first, module->file_name, "1");
460 		space = true;
461 	      }
462 	      print_header (first, GTXT ("Annotated disassembly\n"));
463 	      Vec_loop (Module*, lo->seg_modules, mindex, module)
464 	      {
465 		if ((module->flags & MOD_FLAG_UNKNOWN) != 0 ||
466 		    module->lang_code == Sp_lang_unknown)
467 		  continue;
468 		if (space)
469 		  fprintf (out_file, "\n");
470 		proc_cmd (DISASM, first, module->file_name, "1");
471 		space = true;
472 	      }
473 	    }
474 	  else
475 	    {
476 	      proc_cmd (cmd_type, first, (arg_count > 0) ? argv[i + 1] : NULL,
477 			(arg_count > 1) ? argv[i + 2] : NULL);
478 	      i += arg_count;
479 	      break;
480 	    }
481 	}
482     }
483 }
484 
485 int
486 er_src::check_args (int argc, char *argv[])
487 {
488   CmdType cmd_type = UNKNOWN_CMD;
489   int arg_count, cparam;
490   int i;
491   char *exe;
492   bool first = true;
493   if (argc == 1)
494     usage ();
495 
496   // If any comments from the .rc files, log them to stderr
497   Emsg * rcmsg = fetch_comments ();
498   while (rcmsg != NULL)
499     {
500       fprintf (stderr, "%s: %s\n", prog_name, rcmsg->get_msg ());
501       rcmsg = rcmsg->next;
502     }
503 
504   // Parsing the command line
505   opterr = 0;
506   exe = NULL;
507   for (i = 1; i < argc; i++)
508     {
509       if (*argv[i] != '-')
510 	{
511 	  exe = argv[i];
512 	  if (i == 1)
513 	    { // er_src exe ?
514 	      if (!exe)
515 		usage ();
516 	      if (argc == 3) // er_src exe file
517 		usage ();
518 	    }
519 	  else if (v_opt && !multiple && !exe && !str_compcom) // just er_src -V
520 	      exit (0);
521 	  if (argc < i + 1 || argc > i + 3)
522 	    usage ();
523 	  i++;
524 	  if (argc > i)
525 	    usage ();
526 	  open (exe);
527 	  return i;
528 	}
529       switch (cmd_type = Command::get_command (argv[i] + 1, arg_count, cparam))
530 	{
531 	case WHOAMI:
532 	  whoami = argv[i] + 1 + cparam;
533 	  break;
534 	case HELP:
535 	  i += arg_count;
536 	  multiple++;
537 	  usage ();
538 	  break;
539 	case VERSION_cmd:
540 	  if (first)
541 	    {
542 // Ruud
543 	      Application::print_version_info ();
544 /*
545 	      printf ("GNU %s version %s\n", get_basename (prog_name), VERSION);
546 */
547 	      v_opt = true;
548 	      first = false;
549 	    }
550 	  break;
551 	case SOURCE:
552 	case DISASM:
553 	  i += arg_count;
554 	  multiple++;
555 	  isDisasm = true;
556 	  if (i >= argc || argv[i] == NULL ||
557 	      (*(argv[i]) == '-' && atoi (argv[i]) != -1) || (i + 1 == argc))
558 	    i--;
559 	  break;
560 	case DUMPFUNC:
561 	  i += arg_count;
562 	  multiple++;
563 	  break;
564 	case FUNCS:
565 	  i += arg_count;
566 	  multiple++;
567 	  break;
568 	case OUTFILE:
569 	case COMPCOM:
570 	case SCOMPCOM:
571 	case DCOMPCOM:
572 	  i += arg_count;
573 	  break;
574 	default:
575 	  if (!(streq (argv[i] + 1, NTXT ("all")) ||
576 		streq (argv[i] + 1, NTXT ("dall"))))
577 	    {
578 	      fprintf (stderr, "Error: invalid option: `%s'\n", argv[i]);
579 	      exit (1);
580 	    }
581 	}
582     }
583   if (!exe && !(argc == 2 && cmd_type == VERSION_cmd))
584     usage ();
585   return i;
586 }
587 
588 void
589 er_src::checkJavaClass (char* exe)
590 {
591   unsigned char cf_buf[4];
592   unsigned int magic_number;
593   int fd = ::open (exe, O_RDONLY | O_LARGEFILE);
594   if (fd == -1)
595     return;
596   if (sizeof (cf_buf) == read_from_file (fd, cf_buf, sizeof (cf_buf)))
597     {
598       magic_number = cf_buf[0] << 24;
599       magic_number |= cf_buf[1] << 16;
600       magic_number |= cf_buf[2] << 8;
601       magic_number |= cf_buf[3];
602       if (magic_number == 0xcafebabe)
603 	obj_type = OT_JAVA_CLASS;
604     }
605   close (fd);
606 }
607 
608 void
609 er_src::print_header (bool first, const char* text)
610 {
611   if (!first)
612     fprintf (out_file, "\n");
613   if (multiple > 1)
614     {
615       fprintf (out_file, NTXT ("%s"), text);
616       fprintf (out_file, "---------------------------------------\n");
617     }
618 }
619 
620 void
621 er_src::dump_annotated (char *name, char *sel, char *src, DbeView *dbevr,
622 			bool is_dis, bool first)
623 {
624   Module *module;
625   bool space;
626   int mindex;
627   print_header (first, (is_dis) ? ((is_java_class ()) ?
628 				   GTXT ("Annotated bytecode\n") :
629 				   GTXT ("Annotated disassembly\n")) :
630 		GTXT ("Annotated source\n"));
631   if (!name)
632     {
633       space = false;
634       Vec_loop (Module*, lo->seg_modules, mindex, module)
635       {
636 	if ((module->flags & MOD_FLAG_UNKNOWN) != 0 ||
637 	    (!is_dis && module->lang_code == Sp_lang_unknown))
638 	  continue;
639 	if (space)
640 	  fprintf (out_file, "\n");
641 	print_anno_file (module->file_name, sel, src, is_dis,
642 			 stdout, stdin, out_file, dbevr, false);
643 	space = true;
644       }
645     }
646   else
647     print_anno_file (name, sel, src, is_dis, stdout, stdin, out_file, dbevr, false);
648 }
649 
650 static bool
651 isFatal (bool isDisasm, LoadObject::Arch_status status)
652 {
653   if (isDisasm)
654     {
655       switch (status)
656 	{
657 	  // non-fatal errors for disassembly
658 	case LoadObject::ARCHIVE_BAD_STABS:
659 	case LoadObject::ARCHIVE_NO_STABS:
660 	  return false;
661 	default:
662 	  return true;
663 	}
664     }
665   return true;
666 }
667 
668 void
669 er_src::open (char *exe)
670 {
671   LoadObject::Arch_status status;
672   char *errstr;
673   Module *module;
674   Vector<Histable*> *module_lst;
675 
676   // Construct the Segment structure
677   char *path = strdup (exe);
678   lo = dbeSession->createLoadObject (path);
679   if (NULL == lo->dbeFile->find_file (lo->dbeFile->get_name ()))
680     {
681       fprintf (stderr, GTXT ("%s: Error: unable to open file %s\n"), prog_name, lo->dbeFile->get_name ());
682       exit (1);
683     }
684   checkJavaClass (exe);
685 
686   if (is_java_class ())
687     {
688       lo->type = LoadObject::SEG_TEXT;
689       lo->set_platform (Java, Wnone);
690       lo->id = (uint64_t) - 1; // see AnalyzerSession::ask_which for details
691       module = dbeSession->createClassFile (dbe_strdup (exe));
692       module->loadobject = lo;
693       lo->seg_modules->append (module);
694       module->dbeFile->set_location (exe);
695       if (module->readFile () != module->AE_OK)
696 	{
697 	  Emsg *emsg = module->get_error ();
698 	  if (emsg)
699 	    {
700 	      fprintf (stderr, GTXT ("%s: Error: %s\n"), prog_name, emsg->get_msg ());
701 	      return;
702 	    }
703 	  fprintf (stderr, GTXT ("%s: Error: Could not read class file `%s'\n"), prog_name, exe);
704 	  return;
705 	}
706       status = lo->sync_read_stabs ();
707       if (status != LoadObject::ARCHIVE_SUCCESS)
708 	{
709 	  if (status == LoadObject::ARCHIVE_ERR_OPEN)
710 	    {
711 	      fprintf (stderr, GTXT ("%s: Error: Could not read class file `%s'\n"), prog_name, exe);
712 	      return;
713 	    }
714 	  else
715 	    {
716 	      if (isDisasm)
717 		if (status == LoadObject::ARCHIVE_NO_STABS)
718 		  {
719 		    fprintf (stderr, GTXT ("%s: Error: `%s' is interface; disassembly annotation not available\n"), prog_name, exe);
720 		    return;
721 		  }
722 	    }
723 	}
724     }
725   else
726     {
727       status = lo->sync_read_stabs ();
728       if (status != LoadObject::ARCHIVE_SUCCESS)
729 	{
730 	  errstr = lo->status_str (status);
731 	  if (errstr)
732 	    {
733 	      fprintf (stderr, "%s: %s\n", prog_name, errstr);
734 	      free (errstr);
735 	    }
736 	  if (isFatal (isDisasm, status))
737 	    return;
738 	}
739       obj_type = OT_EXE_ELF;
740 
741       // if .o file, then set file as the exe name
742       if (lo->is_relocatable ())
743 	{
744 	  // find the module, if we can
745 	  module_lst = new Vector<Histable*>;
746 	  module = dbeSession->map_NametoModule (path, module_lst, 0);
747 	  if (module == NULL)
748 	    // Create a module with the right name
749 	    module = dbeSession->createModule (lo, path);
750 	}
751     }
752 }
753