Ejemplo n.º 1
0
struct bound_minimal_symbol
lookup_minimal_symbol_text (const char *name, struct objfile *objf)
{
  struct objfile *objfile;
  struct minimal_symbol *msymbol;
  struct bound_minimal_symbol found_symbol = { NULL, NULL };
  struct bound_minimal_symbol found_file_symbol = { NULL, NULL };

  unsigned int hash = msymbol_hash (name) % MINIMAL_SYMBOL_HASH_SIZE;

  for (objfile = object_files;
       objfile != NULL && found_symbol.minsym == NULL;
       objfile = objfile->next)
    {
      if (objf == NULL || objf == objfile
	  || objf == objfile->separate_debug_objfile_backlink)
	{
	  for (msymbol = objfile->per_bfd->msymbol_hash[hash];
	       msymbol != NULL && found_symbol.minsym == NULL;
	       msymbol = msymbol->hash_next)
	    {
	      if (strcmp (MSYMBOL_LINKAGE_NAME (msymbol), name) == 0 &&
		  (MSYMBOL_TYPE (msymbol) == mst_text
		   || MSYMBOL_TYPE (msymbol) == mst_text_gnu_ifunc
		   || MSYMBOL_TYPE (msymbol) == mst_file_text))
		{
		  switch (MSYMBOL_TYPE (msymbol))
		    {
		    case mst_file_text:
		      found_file_symbol.minsym = msymbol;
		      found_file_symbol.objfile = objfile;
		      break;
		    default:
		      found_symbol.minsym = msymbol;
		      found_symbol.objfile = objfile;
		      break;
		    }
		}
	    }
	}
    }
  /* External symbols are best.  */
  if (found_symbol.minsym)
    return found_symbol;

  /* File-local symbols are next best.  */
  return found_file_symbol;
}
Ejemplo n.º 2
0
struct bound_minimal_symbol
lookup_minimal_symbol_solib_trampoline (const char *name,
					struct objfile *objf)
{
  struct objfile *objfile;
  struct minimal_symbol *msymbol;
  struct bound_minimal_symbol found_symbol = { NULL, NULL };

  unsigned int hash = msymbol_hash (name) % MINIMAL_SYMBOL_HASH_SIZE;

  for (objfile = object_files;
       objfile != NULL;
       objfile = objfile->next)
    {
      if (objf == NULL || objf == objfile
	  || objf == objfile->separate_debug_objfile_backlink)
	{
	  for (msymbol = objfile->per_bfd->msymbol_hash[hash];
	       msymbol != NULL;
	       msymbol = msymbol->hash_next)
	    {
	      if (strcmp (MSYMBOL_LINKAGE_NAME (msymbol), name) == 0 &&
		  MSYMBOL_TYPE (msymbol) == mst_solib_trampoline)
		{
		  found_symbol.objfile = objfile;
		  found_symbol.minsym = msymbol;
		  return found_symbol;
		}
	    }
	}
    }

  return found_symbol;
}
Ejemplo n.º 3
0
int
in_gnu_ifunc_stub (CORE_ADDR pc)
{
  bound_minimal_symbol msymbol
    = lookup_minimal_symbol_by_pc_section (pc, NULL,
					   lookup_msym_prefer::GNU_IFUNC);
  return msymbol.minsym && MSYMBOL_TYPE (msymbol.minsym) == mst_text_gnu_ifunc;
}
Ejemplo n.º 4
0
static void
convert_symbol_bmsym (struct compile_c_instance *context,
		      struct bound_minimal_symbol bmsym)
{
  struct minimal_symbol *msym = bmsym.minsym;
  struct objfile *objfile = bmsym.objfile;
  struct type *type;
  enum gcc_c_symbol_kind kind;
  gcc_type sym_type;
  gcc_decl decl;
  CORE_ADDR addr;

  addr = MSYMBOL_VALUE_ADDRESS (objfile, msym);

  /* Conversion copied from write_exp_msymbol.  */
  switch (MSYMBOL_TYPE (msym))
    {
    case mst_text:
    case mst_file_text:
    case mst_solib_trampoline:
      type = objfile_type (objfile)->nodebug_text_symbol;
      kind = GCC_C_SYMBOL_FUNCTION;
      break;

    case mst_text_gnu_ifunc:
      /* nodebug_text_gnu_ifunc_symbol would cause:
	 function return type cannot be function  */
      type = objfile_type (objfile)->nodebug_text_symbol;
      kind = GCC_C_SYMBOL_FUNCTION;
      addr = gnu_ifunc_resolve_addr (target_gdbarch (), addr);
      break;

    case mst_data:
    case mst_file_data:
    case mst_bss:
    case mst_file_bss:
      type = objfile_type (objfile)->nodebug_data_symbol;
      kind = GCC_C_SYMBOL_VARIABLE;
      break;

    case mst_slot_got_plt:
      type = objfile_type (objfile)->nodebug_got_plt_symbol;
      kind = GCC_C_SYMBOL_FUNCTION;
      break;

    default:
      type = objfile_type (objfile)->nodebug_unknown_symbol;
      kind = GCC_C_SYMBOL_VARIABLE;
      break;
    }

  sym_type = convert_type (context, type);
  decl = C_CTX (context)->c_ops->build_decl (C_CTX (context),
					     MSYMBOL_NATURAL_NAME (msym),
					     kind, sym_type, NULL, addr,
					     NULL, 0);
  C_CTX (context)->c_ops->bind (C_CTX (context), decl, 1 /* is_global */);
}
Ejemplo n.º 5
0
/* Create the terminating entry of OBJFILE's minimal symbol table.
   If OBJFILE->msymbols is zero, allocate a single entry from
   OBJFILE->objfile_obstack; otherwise, just initialize
   OBJFILE->msymbols[OBJFILE->minimal_symbol_count].  */
void
terminate_minimal_symbol_table (struct objfile *objfile)
{
  if (! objfile->msymbols)
    objfile->msymbols = ((struct minimal_symbol *)
                         obstack_alloc (&objfile->objfile_obstack,
                                        sizeof (objfile->msymbols[0])));

  {
    struct minimal_symbol *m
      = &objfile->msymbols[objfile->minimal_symbol_count];

    memset (m, 0, sizeof (*m));
    /* Don't rely on these enumeration values being 0's.  */
    MSYMBOL_TYPE (m) = mst_unknown;
    SYMBOL_INIT_LANGUAGE_SPECIFIC (m, language_unknown);
  }
}
Ejemplo n.º 6
0
bool
found_minimal_symbols::maybe_collect (const char *sfile,
				      struct objfile *objfile,
				      minimal_symbol *msymbol)
{
  switch (MSYMBOL_TYPE (msymbol))
    {
    case mst_file_text:
    case mst_file_data:
    case mst_file_bss:
      if (sfile == NULL
	  || filename_cmp (msymbol->filename, sfile) == 0)
	{
	  file_symbol.minsym = msymbol;
	  file_symbol.objfile = objfile;
	}
      break;

    case mst_solib_trampoline:

      /* If a trampoline symbol is found, we prefer to keep
	 looking for the *real* symbol.  If the actual symbol
	 is not found, then we'll use the trampoline
	 entry.  */
      if (trampoline_symbol.minsym == NULL)
	{
	  trampoline_symbol.minsym = msymbol;
	  trampoline_symbol.objfile = objfile;
	}
      break;

    case mst_unknown:
    default:
      external_symbol.minsym = msymbol;
      external_symbol.objfile = objfile;
      /* We have the real symbol.  No use looking further.  */
      return true;
    }

  /* Keep looking.  */
  return false;
}
static int
add_pe_forwarded_sym (minimal_symbol_reader &reader,
		      const char *sym_name, const char *forward_dll_name,
		      const char *forward_func_name, int ordinal,
		      const char *dll_name, struct objfile *objfile)
{
  CORE_ADDR vma, baseaddr;
  struct bound_minimal_symbol msymbol;
  enum minimal_symbol_type msymtype;
  char *qualified_name, *bare_name;
  int forward_dll_name_len = strlen (forward_dll_name);
  int forward_func_name_len = strlen (forward_func_name);
  int forward_len = forward_dll_name_len + forward_func_name_len + 2;
  char *forward_qualified_name = (char *) alloca (forward_len);
  short section;

  xsnprintf (forward_qualified_name, forward_len, "%s!%s", forward_dll_name,
	     forward_func_name);


  msymbol = lookup_minimal_symbol_and_objfile (forward_qualified_name);

  if (!msymbol.minsym)
    {
      int i;

      for (i = 0; i < forward_dll_name_len; i++)
	forward_qualified_name[i] = tolower (forward_qualified_name[i]);
      msymbol = lookup_minimal_symbol_and_objfile (forward_qualified_name);
    }

  if (!msymbol.minsym)
    {
      if (debug_coff_pe_read)
	fprintf_unfiltered (gdb_stdlog, _("Unable to find function \"%s\" in"
			    " dll \"%s\", forward of \"%s\" in dll \"%s\"\n"),
			    forward_func_name, forward_dll_name, sym_name,
			    dll_name);
      return 0;
    }

  if (debug_coff_pe_read > 1)
    fprintf_unfiltered (gdb_stdlog, _("Adding forwarded exported symbol"
			" \"%s\" in dll \"%s\", pointing to \"%s\"\n"),
			sym_name, dll_name, forward_qualified_name);

  vma = BMSYMBOL_VALUE_ADDRESS (msymbol);
  msymtype = MSYMBOL_TYPE (msymbol.minsym);
  section = MSYMBOL_SECTION (msymbol.minsym);

  /* Generate a (hopefully unique) qualified name using the first part
     of the dll name, e.g. KERNEL32!AddAtomA.  This matches the style
     used by windbg from the "Microsoft Debugging Tools for Windows".  */

  if (sym_name == NULL || *sym_name == '\0')
    bare_name = xstrprintf ("#%d", ordinal);
  else
    bare_name = xstrdup (sym_name);

  qualified_name = xstrprintf ("%s!%s", dll_name, bare_name);

  /* Note that this code makes a minimal symbol whose value may point
     outside of any section in this objfile.  These symbols can't
     really be relocated properly, but nevertheless we make a stab at
     it, choosing an approach consistent with the history of this
     code.  */
  baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));

  reader.record_with_info (qualified_name, vma - baseaddr, msymtype, section);

  /* Enter the plain name as well, which might not be unique.  */
  reader.record_with_info (bare_name, vma - baseaddr, msymtype, section);
  xfree (qualified_name);
  xfree (bare_name);

  return 1;
}
Ejemplo n.º 8
0
static CORE_ADDR
hppa_hpux_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
{
  struct gdbarch *gdbarch = get_frame_arch (frame);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  int word_size = gdbarch_ptr_bit (gdbarch) / 8;
  long orig_pc = pc;
  long prev_inst, curr_inst, loc;
  struct minimal_symbol *msym;
  struct unwind_table_entry *u;

  /* Addresses passed to dyncall may *NOT* be the actual address
     of the function.  So we may have to do something special.  */
  if (pc == hppa_symbol_address("$$dyncall"))
    {
      pc = (CORE_ADDR) get_frame_register_unsigned (frame, 22);

      /* If bit 30 (counting from the left) is on, then pc is the address of
         the PLT entry for this function, not the address of the function
         itself.  Bit 31 has meaning too, but only for MPE.  */
      if (pc & 0x2)
	pc = (CORE_ADDR) read_memory_integer (pc & ~0x3, word_size,
					      byte_order);
    }
  if (pc == hppa_symbol_address("$$dyncall_external"))
    {
      pc = (CORE_ADDR) get_frame_register_unsigned (frame, 22);
      pc = (CORE_ADDR) read_memory_integer (pc & ~0x3, word_size, byte_order);
    }
  else if (pc == hppa_symbol_address("_sr4export"))
    pc = (CORE_ADDR) get_frame_register_unsigned (frame, 22);

  /* Get the unwind descriptor corresponding to PC, return zero
     if no unwind was found.  */
  u = find_unwind_entry (pc);
  if (!u)
    return 0;

  /* If this isn't a linker stub, then return now.  */
  /* elz: attention here! (FIXME) because of a compiler/linker 
     error, some stubs which should have a non zero stub_unwind.stub_type 
     have unfortunately a value of zero.  So this function would return here
     as if we were not in a trampoline.  To fix this, we go look at the partial
     symbol information, which reports this guy as a stub.
     (FIXME): Unfortunately, we are not that lucky: it turns out that the 
     partial symbol information is also wrong sometimes.  This is because 
     when it is entered (somread.c::som_symtab_read()) it can happen that
     if the type of the symbol (from the som) is Entry, and the symbol is
     in a shared library, then it can also be a trampoline.  This would be OK,
     except that I believe the way they decide if we are ina shared library
     does not work.  SOOOO..., even if we have a regular function w/o
     trampolines its minimal symbol can be assigned type mst_solib_trampoline.
     Also, if we find that the symbol is a real stub, then we fix the unwind
     descriptor, and define the stub type to be EXPORT.
     Hopefully this is correct most of the times.  */
  if (u->stub_unwind.stub_type == 0)
    {

/* elz: NOTE (FIXME!) once the problem with the unwind information is fixed
   we can delete all the code which appears between the lines.  */
/*--------------------------------------------------------------------------*/
      msym = lookup_minimal_symbol_by_pc (pc);

      if (msym == NULL || MSYMBOL_TYPE (msym) != mst_solib_trampoline)
	return orig_pc == pc ? 0 : pc & ~0x3;

      else if (msym != NULL && MSYMBOL_TYPE (msym) == mst_solib_trampoline)
	{
	  struct objfile *objfile;
	  struct minimal_symbol *msymbol;
	  int function_found = 0;

	  /* Go look if there is another minimal symbol with the same name as 
	     this one, but with type mst_text.  This would happen if the msym
	     is an actual trampoline, in which case there would be another
	     symbol with the same name corresponding to the real function.  */

	  ALL_MSYMBOLS (objfile, msymbol)
	  {
	    if (MSYMBOL_TYPE (msymbol) == mst_text
		&& strcmp (SYMBOL_LINKAGE_NAME (msymbol),
			    SYMBOL_LINKAGE_NAME (msym)) == 0)
	      {
		function_found = 1;
		break;
	      }
	  }

	  if (function_found)
	    /* The type of msym is correct (mst_solib_trampoline), but
	       the unwind info is wrong, so set it to the correct value.  */
	    u->stub_unwind.stub_type = EXPORT;
	  else
	    /* The stub type info in the unwind is correct (this is not a
	       trampoline), but the msym type information is wrong, it
	       should be mst_text.  So we need to fix the msym, and also
	       get out of this function.  */
	    {
	      MSYMBOL_TYPE (msym) = mst_text;
	      return orig_pc == pc ? 0 : pc & ~0x3;
	    }
	}

/*--------------------------------------------------------------------------*/
    }
Ejemplo n.º 9
0
static int
add_pe_forwarded_sym (const char *sym_name, const char *forward_dll_name,
		      const char *forward_func_name, int ordinal,
		      const char *dll_name, struct objfile *objfile)
{
  CORE_ADDR vma;
  struct bound_minimal_symbol msymbol;
  enum minimal_symbol_type msymtype;
  char *qualified_name, *bare_name;
  int forward_dll_name_len = strlen (forward_dll_name);
  int forward_func_name_len = strlen (forward_func_name);
  int forward_len = forward_dll_name_len + forward_func_name_len + 2;
  char *forward_qualified_name = alloca (forward_len);

  xsnprintf (forward_qualified_name, forward_len, "%s!%s", forward_dll_name,
	     forward_func_name);


  msymbol = lookup_minimal_symbol_and_objfile (forward_qualified_name);

  if (!msymbol.minsym)
    {
      int i;

      for (i = 0; i < forward_dll_name_len; i++)
	forward_qualified_name[i] = tolower (forward_qualified_name[i]);
      msymbol = lookup_minimal_symbol_and_objfile (forward_qualified_name);
    }

  if (!msymbol.minsym)
    {
      if (debug_coff_pe_read)
	fprintf_unfiltered (gdb_stdlog, _("Unable to find function \"%s\" in"
			    " dll \"%s\", forward of \"%s\" in dll \"%s\"\n"),
			    forward_func_name, forward_dll_name, sym_name,
			    dll_name);
      return 0;
    }

  if (debug_coff_pe_read > 1)
    fprintf_unfiltered (gdb_stdlog, _("Adding forwarded exported symbol"
			" \"%s\" in dll \"%s\", pointing to \"%s\"\n"),
			sym_name, dll_name, forward_qualified_name);

  vma = SYMBOL_VALUE_ADDRESS (msymbol.minsym);
  msymtype = MSYMBOL_TYPE (msymbol.minsym);

  /* Generate a (hopefully unique) qualified name using the first part
     of the dll name, e.g. KERNEL32!AddAtomA.  This matches the style
     used by windbg from the "Microsoft Debugging Tools for Windows".  */

  if (sym_name == NULL || *sym_name == '\0')
    bare_name = xstrprintf ("#%d", ordinal);
  else
    bare_name = xstrdup (sym_name);

  qualified_name = xstrprintf ("%s!%s", dll_name, bare_name);

  prim_record_minimal_symbol (qualified_name, vma, msymtype, objfile);

  /* Enter the plain name as well, which might not be unique.  */
  prim_record_minimal_symbol (bare_name, vma, msymtype, objfile);
  xfree (qualified_name);
  xfree (bare_name);

  return 1;
}
Ejemplo n.º 10
0
bound_minimal_symbol
lookup_minimal_symbol_by_pc_section (CORE_ADDR pc_in, struct obj_section *section,
				     lookup_msym_prefer prefer)
{
  int lo;
  int hi;
  int newobj;
  struct objfile *objfile;
  struct minimal_symbol *msymbol;
  struct minimal_symbol *best_symbol = NULL;
  struct objfile *best_objfile = NULL;
  struct bound_minimal_symbol result;

  if (section == NULL)
    {
      section = find_pc_section (pc_in);
      if (section == NULL)
	return {};
    }

  minimal_symbol_type want_type = msym_prefer_to_msym_type (prefer);

  /* We can not require the symbol found to be in section, because
     e.g. IRIX 6.5 mdebug relies on this code returning an absolute
     symbol - but find_pc_section won't return an absolute section and
     hence the code below would skip over absolute symbols.  We can
     still take advantage of the call to find_pc_section, though - the
     object file still must match.  In case we have separate debug
     files, search both the file and its separate debug file.  There's
     no telling which one will have the minimal symbols.  */

  gdb_assert (section != NULL);

  for (objfile = section->objfile;
       objfile != NULL;
       objfile = objfile_separate_debug_iterate (section->objfile, objfile))
    {
      CORE_ADDR pc = pc_in;

      /* If this objfile has a minimal symbol table, go search it using
         a binary search.  Note that a minimal symbol table always consists
         of at least two symbols, a "real" symbol and the terminating
         "null symbol".  If there are no real symbols, then there is no
         minimal symbol table at all.  */

      if (objfile->per_bfd->minimal_symbol_count > 0)
	{
	  int best_zero_sized = -1;

          msymbol = objfile->per_bfd->msymbols;
	  lo = 0;
	  hi = objfile->per_bfd->minimal_symbol_count - 1;

	  /* This code assumes that the minimal symbols are sorted by
	     ascending address values.  If the pc value is greater than or
	     equal to the first symbol's address, then some symbol in this
	     minimal symbol table is a suitable candidate for being the
	     "best" symbol.  This includes the last real symbol, for cases
	     where the pc value is larger than any address in this vector.

	     By iterating until the address associated with the current
	     hi index (the endpoint of the test interval) is less than
	     or equal to the desired pc value, we accomplish two things:
	     (1) the case where the pc value is larger than any minimal
	     symbol address is trivially solved, (2) the address associated
	     with the hi index is always the one we want when the interation
	     terminates.  In essence, we are iterating the test interval
	     down until the pc value is pushed out of it from the high end.

	     Warning: this code is trickier than it would appear at first.  */

	  if (frob_address (objfile, &pc)
	      && pc >= MSYMBOL_VALUE_RAW_ADDRESS (&msymbol[lo]))
	    {
	      while (MSYMBOL_VALUE_RAW_ADDRESS (&msymbol[hi]) > pc)
		{
		  /* pc is still strictly less than highest address.  */
		  /* Note "new" will always be >= lo.  */
		  newobj = (lo + hi) / 2;
		  if ((MSYMBOL_VALUE_RAW_ADDRESS (&msymbol[newobj]) >= pc)
		      || (lo == newobj))
		    {
		      hi = newobj;
		    }
		  else
		    {
		      lo = newobj;
		    }
		}

	      /* If we have multiple symbols at the same address, we want
	         hi to point to the last one.  That way we can find the
	         right symbol if it has an index greater than hi.  */
	      while (hi < objfile->per_bfd->minimal_symbol_count - 1
		     && (MSYMBOL_VALUE_RAW_ADDRESS (&msymbol[hi])
			 == MSYMBOL_VALUE_RAW_ADDRESS (&msymbol[hi + 1])))
		hi++;

	      /* Skip various undesirable symbols.  */
	      while (hi >= 0)
		{
		  /* Skip any absolute symbols.  This is apparently
		     what adb and dbx do, and is needed for the CM-5.
		     There are two known possible problems: (1) on
		     ELF, apparently end, edata, etc. are absolute.
		     Not sure ignoring them here is a big deal, but if
		     we want to use them, the fix would go in
		     elfread.c.  (2) I think shared library entry
		     points on the NeXT are absolute.  If we want
		     special handling for this it probably should be
		     triggered by a special mst_abs_or_lib or some
		     such.  */

		  if (MSYMBOL_TYPE (&msymbol[hi]) == mst_abs)
		    {
		      hi--;
		      continue;
		    }

		  /* If SECTION was specified, skip any symbol from
		     wrong section.  */
		  if (section
		      /* Some types of debug info, such as COFF,
			 don't fill the bfd_section member, so don't
			 throw away symbols on those platforms.  */
		      && MSYMBOL_OBJ_SECTION (objfile, &msymbol[hi]) != NULL
		      && (!matching_obj_sections
			  (MSYMBOL_OBJ_SECTION (objfile, &msymbol[hi]),
			   section)))
		    {
		      hi--;
		      continue;
		    }

		  /* If we are looking for a trampoline and this is a
		     text symbol, or the other way around, check the
		     preceding symbol too.  If they are otherwise
		     identical prefer that one.  */
		  if (hi > 0
		      && MSYMBOL_TYPE (&msymbol[hi]) != want_type
		      && MSYMBOL_TYPE (&msymbol[hi - 1]) == want_type
		      && (MSYMBOL_SIZE (&msymbol[hi])
			  == MSYMBOL_SIZE (&msymbol[hi - 1]))
		      && (MSYMBOL_VALUE_RAW_ADDRESS (&msymbol[hi])
			  == MSYMBOL_VALUE_RAW_ADDRESS (&msymbol[hi - 1]))
		      && (MSYMBOL_OBJ_SECTION (objfile, &msymbol[hi])
			  == MSYMBOL_OBJ_SECTION (objfile, &msymbol[hi - 1])))
		    {
		      hi--;
		      continue;
		    }

		  /* If the minimal symbol has a zero size, save it
		     but keep scanning backwards looking for one with
		     a non-zero size.  A zero size may mean that the
		     symbol isn't an object or function (e.g. a
		     label), or it may just mean that the size was not
		     specified.  */
		  if (MSYMBOL_SIZE (&msymbol[hi]) == 0)
		    {
		      if (best_zero_sized == -1)
			best_zero_sized = hi;
		      hi--;
		      continue;
		    }

		  /* If we are past the end of the current symbol, try
		     the previous symbol if it has a larger overlapping
		     size.  This happens on i686-pc-linux-gnu with glibc;
		     the nocancel variants of system calls are inside
		     the cancellable variants, but both have sizes.  */
		  if (hi > 0
		      && MSYMBOL_SIZE (&msymbol[hi]) != 0
		      && pc >= (MSYMBOL_VALUE_RAW_ADDRESS (&msymbol[hi])
				+ MSYMBOL_SIZE (&msymbol[hi]))
		      && pc < (MSYMBOL_VALUE_RAW_ADDRESS (&msymbol[hi - 1])
			       + MSYMBOL_SIZE (&msymbol[hi - 1])))
		    {
		      hi--;
		      continue;
		    }

		  /* Otherwise, this symbol must be as good as we're going
		     to get.  */
		  break;
		}

	      /* If HI has a zero size, and best_zero_sized is set,
		 then we had two or more zero-sized symbols; prefer
		 the first one we found (which may have a higher
		 address).  Also, if we ran off the end, be sure
		 to back up.  */
	      if (best_zero_sized != -1
		  && (hi < 0 || MSYMBOL_SIZE (&msymbol[hi]) == 0))
		hi = best_zero_sized;

	      /* If the minimal symbol has a non-zero size, and this
		 PC appears to be outside the symbol's contents, then
		 refuse to use this symbol.  If we found a zero-sized
		 symbol with an address greater than this symbol's,
		 use that instead.  We assume that if symbols have
		 specified sizes, they do not overlap.  */

	      if (hi >= 0
		  && MSYMBOL_SIZE (&msymbol[hi]) != 0
		  && pc >= (MSYMBOL_VALUE_RAW_ADDRESS (&msymbol[hi])
			    + MSYMBOL_SIZE (&msymbol[hi])))
		{
		  if (best_zero_sized != -1)
		    hi = best_zero_sized;
		  else
		    /* Go on to the next object file.  */
		    continue;
		}

	      /* The minimal symbol indexed by hi now is the best one in this
	         objfile's minimal symbol table.  See if it is the best one
	         overall.  */

	      if (hi >= 0
		  && ((best_symbol == NULL) ||
		      (MSYMBOL_VALUE_RAW_ADDRESS (best_symbol) <
		       MSYMBOL_VALUE_RAW_ADDRESS (&msymbol[hi]))))
		{
		  best_symbol = &msymbol[hi];
		  best_objfile = objfile;
		}
	    }
	}
    }

  result.minsym = best_symbol;
  result.objfile = best_objfile;
  return result;
}
Ejemplo n.º 11
0
int
find_pc_partial_function_gnu_ifunc (CORE_ADDR pc, const char **name,
				    CORE_ADDR *address, CORE_ADDR *endaddr,
				    int *is_gnu_ifunc_p)
{
  struct obj_section *section;
  struct symbol *f;
  struct minimal_symbol *msymbol;
  struct symtab *symtab = NULL;
  struct objfile *objfile;
  int i;
  CORE_ADDR mapped_pc;

  /* To ensure that the symbol returned belongs to the correct setion
     (and that the last [random] symbol from the previous section
     isn't returned) try to find the section containing PC.  First try
     the overlay code (which by default returns NULL); and second try
     the normal section code (which almost always succeeds).  */
  section = find_pc_overlay (pc);
  if (section == NULL)
    section = find_pc_section (pc);

  mapped_pc = overlay_mapped_address (pc, section);

  if (mapped_pc >= cache_pc_function_low
      && mapped_pc < cache_pc_function_high
      && section == cache_pc_function_section)
    goto return_cached_value;

  msymbol = lookup_minimal_symbol_by_pc_section (mapped_pc, section);
  ALL_OBJFILES (objfile)
  {
    if (objfile->sf)
      symtab = objfile->sf->qf->find_pc_sect_symtab (objfile, msymbol,
						     mapped_pc, section, 0);
    if (symtab)
      break;
  }

  if (symtab)
    {
      /* Checking whether the msymbol has a larger value is for the
	 "pathological" case mentioned in print_frame_info.  */
      f = find_pc_sect_function (mapped_pc, section);
      if (f != NULL
	  && (msymbol == NULL
	      || (BLOCK_START (SYMBOL_BLOCK_VALUE (f))
		  >= SYMBOL_VALUE_ADDRESS (msymbol))))
	{
	  cache_pc_function_low = BLOCK_START (SYMBOL_BLOCK_VALUE (f));
	  cache_pc_function_high = BLOCK_END (SYMBOL_BLOCK_VALUE (f));
	  cache_pc_function_name = SYMBOL_LINKAGE_NAME (f);
	  cache_pc_function_section = section;
	  cache_pc_function_is_gnu_ifunc = TYPE_GNU_IFUNC (SYMBOL_TYPE (f));
	  goto return_cached_value;
	}
    }

  /* Not in the normal symbol tables, see if the pc is in a known
     section.  If it's not, then give up.  This ensures that anything
     beyond the end of the text seg doesn't appear to be part of the
     last function in the text segment.  */

  if (!section)
    msymbol = NULL;

  /* Must be in the minimal symbol table.  */
  if (msymbol == NULL)
    {
      /* No available symbol.  */
      if (name != NULL)
	*name = 0;
      if (address != NULL)
	*address = 0;
      if (endaddr != NULL)
	*endaddr = 0;
      if (is_gnu_ifunc_p != NULL)
	*is_gnu_ifunc_p = 0;
      return 0;
    }

  cache_pc_function_low = SYMBOL_VALUE_ADDRESS (msymbol);
  cache_pc_function_name = SYMBOL_LINKAGE_NAME (msymbol);
  cache_pc_function_section = section;
  cache_pc_function_is_gnu_ifunc = MSYMBOL_TYPE (msymbol) == mst_text_gnu_ifunc;

  /* If the minimal symbol has a size, use it for the cache.
     Otherwise use the lesser of the next minimal symbol in the same
     section, or the end of the section, as the end of the
     function.  */

  if (MSYMBOL_SIZE (msymbol) != 0)
    cache_pc_function_high = cache_pc_function_low + MSYMBOL_SIZE (msymbol);
  else
    {
      /* Step over other symbols at this same address, and symbols in
	 other sections, to find the next symbol in this section with
	 a different address.  */

      for (i = 1; SYMBOL_LINKAGE_NAME (msymbol + i) != NULL; i++)
	{
	  if (SYMBOL_VALUE_ADDRESS (msymbol + i)
	      != SYMBOL_VALUE_ADDRESS (msymbol)
	      && SYMBOL_OBJ_SECTION (msymbol + i)
	      == SYMBOL_OBJ_SECTION (msymbol))
	    break;
	}

      if (SYMBOL_LINKAGE_NAME (msymbol + i) != NULL
	  && SYMBOL_VALUE_ADDRESS (msymbol + i)
	  < obj_section_endaddr (section))
	cache_pc_function_high = SYMBOL_VALUE_ADDRESS (msymbol + i);
      else
	/* We got the start address from the last msymbol in the objfile.
	   So the end address is the end of the section.  */
	cache_pc_function_high = obj_section_endaddr (section);
    }

 return_cached_value:

  if (address)
    {
      if (pc_in_unmapped_range (pc, section))
	*address = overlay_unmapped_address (cache_pc_function_low, section);
      else
	*address = cache_pc_function_low;
    }

  if (name)
    *name = cache_pc_function_name;

  if (endaddr)
    {
      if (pc_in_unmapped_range (pc, section))
	{
	  /* Because the high address is actually beyond the end of
	     the function (and therefore possibly beyond the end of
	     the overlay), we must actually convert (high - 1) and
	     then add one to that.  */

	  *endaddr = 1 + overlay_unmapped_address (cache_pc_function_high - 1,
						   section);
	}
      else
	*endaddr = cache_pc_function_high;
    }

  if (is_gnu_ifunc_p)
    *is_gnu_ifunc_p = cache_pc_function_is_gnu_ifunc;

  return 1;
}
Ejemplo n.º 12
0
struct compile_module *
compile_object_load (const char *object_file, const char *source_file,
		     enum compile_i_scope_types scope, void *scope_data)
{
  struct cleanup *cleanups, *cleanups_free_objfile;
  bfd *abfd;
  struct setup_sections_data setup_sections_data;
  CORE_ADDR addr, regs_addr, out_value_addr = 0;
  struct symbol *func_sym;
  struct type *func_type;
  struct bound_minimal_symbol bmsym;
  long storage_needed;
  asymbol **symbol_table, **symp;
  long number_of_symbols, missing_symbols;
  struct type *dptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
  unsigned dptr_type_len = TYPE_LENGTH (dptr_type);
  struct compile_module *retval;
  struct type *regs_type, *out_value_type = NULL;
  char *filename, **matching;
  struct objfile *objfile;
  int expect_parameters;
  struct type *expect_return_type;
  struct munmap_list *munmap_list_head = NULL;

  filename = tilde_expand (object_file);
  cleanups = make_cleanup (xfree, filename);

  abfd = gdb_bfd_open (filename, gnutarget, -1);
  if (abfd == NULL)
    error (_("\"%s\": could not open as compiled module: %s"),
          filename, bfd_errmsg (bfd_get_error ()));
  make_cleanup_bfd_unref (abfd);

  if (!bfd_check_format_matches (abfd, bfd_object, &matching))
    error (_("\"%s\": not in loadable format: %s"),
          filename, gdb_bfd_errmsg (bfd_get_error (), matching));

  if ((bfd_get_file_flags (abfd) & (EXEC_P | DYNAMIC)) != 0)
    error (_("\"%s\": not in object format."), filename);

  setup_sections_data.last_size = 0;
  setup_sections_data.last_section_first = abfd->sections;
  setup_sections_data.last_prot = -1;
  setup_sections_data.last_max_alignment = 1;
  setup_sections_data.munmap_list_headp = &munmap_list_head;
  make_cleanup (munmap_listp_free_cleanup, &munmap_list_head);
  bfd_map_over_sections (abfd, setup_sections, &setup_sections_data);
  setup_sections (abfd, NULL, &setup_sections_data);

  storage_needed = bfd_get_symtab_upper_bound (abfd);
  if (storage_needed < 0)
    error (_("Cannot read symbols of compiled module \"%s\": %s"),
          filename, bfd_errmsg (bfd_get_error ()));

  /* SYMFILE_VERBOSE is not passed even if FROM_TTY, user is not interested in
     "Reading symbols from ..." message for automatically generated file.  */
  objfile = symbol_file_add_from_bfd (abfd, filename, 0, NULL, 0, NULL);
  cleanups_free_objfile = make_cleanup_free_objfile (objfile);

  func_sym = lookup_global_symbol_from_objfile (objfile,
						GCC_FE_WRAPPER_FUNCTION,
						VAR_DOMAIN).symbol;
  if (func_sym == NULL)
    error (_("Cannot find function \"%s\" in compiled module \"%s\"."),
	   GCC_FE_WRAPPER_FUNCTION, objfile_name (objfile));
  func_type = SYMBOL_TYPE (func_sym);
  if (TYPE_CODE (func_type) != TYPE_CODE_FUNC)
    error (_("Invalid type code %d of function \"%s\" in compiled "
	     "module \"%s\"."),
	   TYPE_CODE (func_type), GCC_FE_WRAPPER_FUNCTION,
	   objfile_name (objfile));

  switch (scope)
    {
    case COMPILE_I_SIMPLE_SCOPE:
      expect_parameters = 1;
      expect_return_type = builtin_type (target_gdbarch ())->builtin_void;
      break;
    case COMPILE_I_RAW_SCOPE:
      expect_parameters = 0;
      expect_return_type = builtin_type (target_gdbarch ())->builtin_void;
      break;
    case COMPILE_I_PRINT_ADDRESS_SCOPE:
    case COMPILE_I_PRINT_VALUE_SCOPE:
      expect_parameters = 2;
      expect_return_type = builtin_type (target_gdbarch ())->builtin_void;
      break;
    default:
      internal_error (__FILE__, __LINE__, _("invalid scope %d"), scope);
    }
  if (TYPE_NFIELDS (func_type) != expect_parameters)
    error (_("Invalid %d parameters of function \"%s\" in compiled "
	     "module \"%s\"."),
	   TYPE_NFIELDS (func_type), GCC_FE_WRAPPER_FUNCTION,
	   objfile_name (objfile));
  if (!types_deeply_equal (expect_return_type, TYPE_TARGET_TYPE (func_type)))
    error (_("Invalid return type of function \"%s\" in compiled "
	    "module \"%s\"."),
	  GCC_FE_WRAPPER_FUNCTION, objfile_name (objfile));

  /* The memory may be later needed
     by bfd_generic_get_relocated_section_contents
     called from default_symfile_relocate.  */
  symbol_table = obstack_alloc (&objfile->objfile_obstack, storage_needed);
  number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
  if (number_of_symbols < 0)
    error (_("Cannot parse symbols of compiled module \"%s\": %s"),
          filename, bfd_errmsg (bfd_get_error ()));

  missing_symbols = 0;
  for (symp = symbol_table; symp < symbol_table + number_of_symbols; symp++)
    {
      asymbol *sym = *symp;

      if (sym->flags != 0)
	continue;
      sym->flags = BSF_GLOBAL;
      sym->section = bfd_abs_section_ptr;
      if (strcmp (sym->name, "_GLOBAL_OFFSET_TABLE_") == 0)
	{
	  if (compile_debug)
	    fprintf_unfiltered (gdb_stdlog,
				"ELF symbol \"%s\" relocated to zero\n",
				sym->name);

	  /* It seems to be a GCC bug, with -mcmodel=large there should be no
	     need for _GLOBAL_OFFSET_TABLE_.  Together with -fPIE the data
	     remain PC-relative even with _GLOBAL_OFFSET_TABLE_ as zero.  */
	  sym->value = 0;
	  continue;
	}
      bmsym = lookup_minimal_symbol (sym->name, NULL, NULL);
      switch (bmsym.minsym == NULL
	      ? mst_unknown : MSYMBOL_TYPE (bmsym.minsym))
	{
	case mst_text:
	  sym->value = BMSYMBOL_VALUE_ADDRESS (bmsym);
	  if (compile_debug)
	    fprintf_unfiltered (gdb_stdlog,
				"ELF mst_text symbol \"%s\" relocated to %s\n",
				sym->name,
				paddress (target_gdbarch (), sym->value));
	  break;
	case mst_text_gnu_ifunc:
	  sym->value = gnu_ifunc_resolve_addr (target_gdbarch (),
					       BMSYMBOL_VALUE_ADDRESS (bmsym));
	  if (compile_debug)
	    fprintf_unfiltered (gdb_stdlog,
				"ELF mst_text_gnu_ifunc symbol \"%s\" "
				"relocated to %s\n",
				sym->name,
				paddress (target_gdbarch (), sym->value));
	  break;
	default:
	  warning (_("Could not find symbol \"%s\" "
		     "for compiled module \"%s\"."),
		   sym->name, filename);
	  missing_symbols++;
	}
    }
  if (missing_symbols)
    error (_("%ld symbols were missing, cannot continue."), missing_symbols);

  bfd_map_over_sections (abfd, copy_sections, symbol_table);

  regs_type = get_regs_type (func_sym, objfile);
  if (regs_type == NULL)
    regs_addr = 0;
  else
    {
      /* Use read-only non-executable memory protection.  */
      regs_addr = gdbarch_infcall_mmap (target_gdbarch (),
					TYPE_LENGTH (regs_type),
					GDB_MMAP_PROT_READ);
      gdb_assert (regs_addr != 0);
      munmap_list_add (&munmap_list_head, regs_addr, TYPE_LENGTH (regs_type));
      if (compile_debug)
	fprintf_unfiltered (gdb_stdlog,
			    "allocated %s bytes at %s for registers\n",
			    paddress (target_gdbarch (),
				      TYPE_LENGTH (regs_type)),
			    paddress (target_gdbarch (), regs_addr));
      store_regs (regs_type, regs_addr);
    }

  if (scope == COMPILE_I_PRINT_ADDRESS_SCOPE
      || scope == COMPILE_I_PRINT_VALUE_SCOPE)
    {
      out_value_type = get_out_value_type (func_sym, objfile, scope);
      if (out_value_type == NULL)
	{
	  do_cleanups (cleanups);
	  return NULL;
	}
      check_typedef (out_value_type);
      out_value_addr = gdbarch_infcall_mmap (target_gdbarch (),
					     TYPE_LENGTH (out_value_type),
					     (GDB_MMAP_PROT_READ
					      | GDB_MMAP_PROT_WRITE));
      gdb_assert (out_value_addr != 0);
      munmap_list_add (&munmap_list_head, out_value_addr,
		       TYPE_LENGTH (out_value_type));
      if (compile_debug)
	fprintf_unfiltered (gdb_stdlog,
			    "allocated %s bytes at %s for printed value\n",
			    paddress (target_gdbarch (),
				      TYPE_LENGTH (out_value_type)),
			    paddress (target_gdbarch (), out_value_addr));
    }

  discard_cleanups (cleanups_free_objfile);

  retval = xmalloc (sizeof (*retval));
  retval->objfile = objfile;
  retval->source_file = xstrdup (source_file);
  retval->func_sym = func_sym;
  retval->regs_addr = regs_addr;
  retval->scope = scope;
  retval->scope_data = scope_data;
  retval->out_value_type = out_value_type;
  retval->out_value_addr = out_value_addr;

  /* CLEANUPS will free MUNMAP_LIST_HEAD.  */
  retval->munmap_list_head = munmap_list_head;
  munmap_list_head = NULL;

  do_cleanups (cleanups);

  return retval;
}
Ejemplo n.º 13
0
int
addr_inside_main_func (CORE_ADDR pc)
{
  struct minimal_symbol *msymbol;

  if (symfile_objfile == 0)
    return 0;

  /* APPLE LOCAL begin don't recompute start/end of main */
  /* If we've already found the start/end addrs of main, don't
     recompute them.  This will probably be fixed in the FSF sources
     soon too, in which case this change can be dropped.
     jmolenda/2004-04-28 */
  if (symfile_objfile->ei.main_func_lowpc != INVALID_ENTRY_LOWPC
      && symfile_objfile->ei.main_func_highpc != INVALID_ENTRY_LOWPC)
    return (symfile_objfile->ei.main_func_lowpc <= pc
            && symfile_objfile->ei.main_func_highpc > pc);
  /* APPLE LOCAL end don't recompute start/end of main */

  /* APPLE LOCAL begin don't restrict lookup_minimal_symbol's object file */
  /* Don't restrict lookup_minimal_symbol's object file to
     symfile_objfile -- this will fail for ZeroLink apps where
     symfile_objfile is just the ZL launcher stub.  */
  msymbol = lookup_minimal_symbol (main_name (), NULL, NULL);
  /* APPLE LOCAL end don't restrict lookup_minimal_symbol's object file */

  /* If the address range hasn't been set up at symbol reading time,
     set it up now.  */

  if (msymbol != NULL
      && symfile_objfile->ei.main_func_lowpc == INVALID_ENTRY_LOWPC
      && symfile_objfile->ei.main_func_highpc == INVALID_ENTRY_HIGHPC)
    {
      /* brobecker/2003-10-10: We used to rely on lookup_symbol() to
	 search the symbol associated to the "main" function.
	 Unfortunately, lookup_symbol() uses the current-language
	 la_lookup_symbol_nonlocal function to do the global symbol
	 search.  Depending on the language, this can introduce
	 certain side-effects, because certain languages, for instance
	 Ada, may find more than one match.  Therefore we prefer to
	 search the "main" function symbol using its address rather
	 than its name.  */
      struct symbol *mainsym =
	find_pc_function (SYMBOL_VALUE_ADDRESS (msymbol));

      if (mainsym && SYMBOL_CLASS (mainsym) == LOC_BLOCK)
	{
	  /* APPLE LOCAL begin address ranges  */
	  struct block *bl = SYMBOL_BLOCK_VALUE (mainsym);

	  if (BLOCK_RANGES (bl))
	    {
	      symfile_objfile->ei.main_func_lowpc = BLOCK_LOWEST_PC (bl);
	      symfile_objfile->ei.main_func_highpc = BLOCK_HIGHEST_PC (bl);
	    }
	  else
	    {
	      symfile_objfile->ei.main_func_lowpc =
		BLOCK_START (SYMBOL_BLOCK_VALUE (mainsym));
	      symfile_objfile->ei.main_func_highpc =
		BLOCK_END (SYMBOL_BLOCK_VALUE (mainsym));
	    }
	  /* APPLE LOCAL end address ranges  */
	}
    }

  /* Not in the normal symbol tables, see if "main" is in the partial
     symbol table.  If it's not, then give up.  */
  if (msymbol != NULL && MSYMBOL_TYPE (msymbol) == mst_text)
    {
      CORE_ADDR maddr = SYMBOL_VALUE_ADDRESS (msymbol);
      asection *msect = SYMBOL_BFD_SECTION (msymbol);
      struct obj_section *osect = find_pc_sect_section (maddr, msect);

      if (osect != NULL)
	{
	  int i;

	  /* Step over other symbols at this same address, and symbols
	     in other sections, to find the next symbol in this
	     section with a different address.  */
	  for (i = 1; SYMBOL_LINKAGE_NAME (msymbol + i) != NULL; i++)
	    {
	      if (SYMBOL_VALUE_ADDRESS (msymbol + i) != maddr
		  && SYMBOL_BFD_SECTION (msymbol + i) == msect)
		break;
	    }

	  symfile_objfile->ei.main_func_lowpc = maddr;

	  /* Use the lesser of the next minimal symbol in the same
	     section, or the end of the section, as the end of the
	     function.  */
	  if (SYMBOL_LINKAGE_NAME (msymbol + i) != NULL
	      && SYMBOL_VALUE_ADDRESS (msymbol + i) < osect->endaddr)
	    symfile_objfile->ei.main_func_highpc =
	      SYMBOL_VALUE_ADDRESS (msymbol + i);
	  else
	    /* We got the start address from the last msymbol in the
	       objfile.  So the end address is the end of the
	       section.  */
	    symfile_objfile->ei.main_func_highpc = osect->endaddr;
	}
    }

  return (symfile_objfile->ei.main_func_lowpc <= pc
	  && symfile_objfile->ei.main_func_highpc > pc);
}
Ejemplo n.º 14
0
int
inside_main_func (CORE_ADDR pc)
{
  struct minimal_symbol *msymbol;

  if (symfile_objfile == 0)
    return 0;

  msymbol = lookup_minimal_symbol (main_name (), NULL, symfile_objfile);

  /* If the address range hasn't been set up at symbol reading time,
     set it up now.  */

  if (msymbol != NULL
      && symfile_objfile->ei.main_func_lowpc == INVALID_ENTRY_LOWPC
      && symfile_objfile->ei.main_func_highpc == INVALID_ENTRY_HIGHPC)
    {
      /* brobecker/2003-10-10: We used to rely on lookup_symbol() to
	 search the symbol associated to the "main" function.
	 Unfortunately, lookup_symbol() uses the current-language
	 la_lookup_symbol_nonlocal function to do the global symbol
	 search.  Depending on the language, this can introduce
	 certain side-effects, because certain languages, for instance
	 Ada, may find more than one match.  Therefore we prefer to
	 search the "main" function symbol using its address rather
	 than its name.  */
      struct symbol *mainsym =
	find_pc_function (SYMBOL_VALUE_ADDRESS (msymbol));

      if (mainsym && SYMBOL_CLASS (mainsym) == LOC_BLOCK)
	{
	  symfile_objfile->ei.main_func_lowpc =
	    BLOCK_START (SYMBOL_BLOCK_VALUE (mainsym));
	  symfile_objfile->ei.main_func_highpc =
	    BLOCK_END (SYMBOL_BLOCK_VALUE (mainsym));
	}
    }

  /* Not in the normal symbol tables, see if "main" is in the partial
     symbol table.  If it's not, then give up.  */
  if (msymbol != NULL && MSYMBOL_TYPE (msymbol) == mst_text)
    {
      CORE_ADDR maddr = SYMBOL_VALUE_ADDRESS (msymbol);
      asection *msect = SYMBOL_BFD_SECTION (msymbol);
      struct obj_section *osect = find_pc_sect_section (maddr, msect);

      if (osect != NULL)
	{
	  int i;

	  /* Step over other symbols at this same address, and symbols
	     in other sections, to find the next symbol in this
	     section with a different address.  */
	  for (i = 1; SYMBOL_LINKAGE_NAME (msymbol + i) != NULL; i++)
	    {
	      if (SYMBOL_VALUE_ADDRESS (msymbol + i) != maddr
		  && SYMBOL_BFD_SECTION (msymbol + i) == msect)
		break;
	    }

	  symfile_objfile->ei.main_func_lowpc = maddr;

	  /* Use the lesser of the next minimal symbol in the same
	     section, or the end of the section, as the end of the
	     function.  */
	  if (SYMBOL_LINKAGE_NAME (msymbol + i) != NULL
	      && SYMBOL_VALUE_ADDRESS (msymbol + i) < osect->endaddr)
	    symfile_objfile->ei.main_func_highpc =
	      SYMBOL_VALUE_ADDRESS (msymbol + i);
	  else
	    /* We got the start address from the last msymbol in the
	       objfile.  So the end address is the end of the
	       section.  */
	    symfile_objfile->ei.main_func_highpc = osect->endaddr;
	}
    }

  return (symfile_objfile->ei.main_func_lowpc <= pc
	  && symfile_objfile->ei.main_func_highpc > pc);
}
Ejemplo n.º 15
0
struct compile_module *
compile_object_load (const char *object_file, const char *source_file)
{
  struct cleanup *cleanups, *cleanups_free_objfile;
  bfd *abfd;
  struct setup_sections_data setup_sections_data;
  CORE_ADDR addr, func_addr, regs_addr;
  struct bound_minimal_symbol bmsym;
  long storage_needed;
  asymbol **symbol_table, **symp;
  long number_of_symbols, missing_symbols;
  struct type *dptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
  unsigned dptr_type_len = TYPE_LENGTH (dptr_type);
  struct compile_module *retval;
  struct type *regs_type;
  char *filename, **matching;
  struct objfile *objfile;

  filename = tilde_expand (object_file);
  cleanups = make_cleanup (xfree, filename);

  abfd = gdb_bfd_open (filename, gnutarget, -1);
  if (abfd == NULL)
    error (_("\"%s\": could not open as compiled module: %s"),
          filename, bfd_errmsg (bfd_get_error ()));
  make_cleanup_bfd_unref (abfd);

  if (!bfd_check_format_matches (abfd, bfd_object, &matching))
    error (_("\"%s\": not in loadable format: %s"),
          filename, gdb_bfd_errmsg (bfd_get_error (), matching));

  if ((bfd_get_file_flags (abfd) & (EXEC_P | DYNAMIC)) != 0)
    error (_("\"%s\": not in object format."), filename);

  setup_sections_data.last_size = 0;
  setup_sections_data.last_section_first = abfd->sections;
  setup_sections_data.last_prot = -1;
  setup_sections_data.last_max_alignment = 1;
  bfd_map_over_sections (abfd, setup_sections, &setup_sections_data);
  setup_sections (abfd, NULL, &setup_sections_data);

  storage_needed = bfd_get_symtab_upper_bound (abfd);
  if (storage_needed < 0)
    error (_("Cannot read symbols of compiled module \"%s\": %s"),
          filename, bfd_errmsg (bfd_get_error ()));

  /* SYMFILE_VERBOSE is not passed even if FROM_TTY, user is not interested in
     "Reading symbols from ..." message for automatically generated file.  */
  objfile = symbol_file_add_from_bfd (abfd, filename, 0, NULL, 0, NULL);
  cleanups_free_objfile = make_cleanup_free_objfile (objfile);

  bmsym = lookup_minimal_symbol_text (GCC_FE_WRAPPER_FUNCTION, objfile);
  if (bmsym.minsym == NULL || MSYMBOL_TYPE (bmsym.minsym) == mst_file_text)
    error (_("Could not find symbol \"%s\" of compiled module \"%s\"."),
	   GCC_FE_WRAPPER_FUNCTION, filename);
  func_addr = BMSYMBOL_VALUE_ADDRESS (bmsym);

  /* The memory may be later needed
     by bfd_generic_get_relocated_section_contents
     called from default_symfile_relocate.  */
  symbol_table = obstack_alloc (&objfile->objfile_obstack, storage_needed);
  number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
  if (number_of_symbols < 0)
    error (_("Cannot parse symbols of compiled module \"%s\": %s"),
          filename, bfd_errmsg (bfd_get_error ()));

  missing_symbols = 0;
  for (symp = symbol_table; symp < symbol_table + number_of_symbols; symp++)
    {
      asymbol *sym = *symp;

      if (sym->flags != 0)
	continue;
      if (compile_debug)
	fprintf_unfiltered (gdb_stdout,
			    "lookup undefined ELF symbol \"%s\"\n",
			    sym->name);
      sym->flags = BSF_GLOBAL;
      sym->section = bfd_abs_section_ptr;
      if (strcmp (sym->name, "_GLOBAL_OFFSET_TABLE_") == 0)
	{
	  sym->value = 0;
	  continue;
	}
      bmsym = lookup_minimal_symbol (sym->name, NULL, NULL);
      switch (bmsym.minsym == NULL
	      ? mst_unknown : MSYMBOL_TYPE (bmsym.minsym))
	{
	case mst_text:
	  sym->value = BMSYMBOL_VALUE_ADDRESS (bmsym);
	  break;
	default:
	  warning (_("Could not find symbol \"%s\" "
		     "for compiled module \"%s\"."),
		   sym->name, filename);
	  missing_symbols++;
	}
    }
  if (missing_symbols)
    error (_("%ld symbols were missing, cannot continue."), missing_symbols);

  bfd_map_over_sections (abfd, copy_sections, symbol_table);

  regs_type = get_regs_type (objfile);
  if (regs_type == NULL)
    regs_addr = 0;
  else
    {
      /* Use read-only non-executable memory protection.  */
      regs_addr = gdbarch_infcall_mmap (target_gdbarch (),
					TYPE_LENGTH (regs_type),
					GDB_MMAP_PROT_READ);
      gdb_assert (regs_addr != 0);
      store_regs (regs_type, regs_addr);
    }

  discard_cleanups (cleanups_free_objfile);
  do_cleanups (cleanups);

  retval = xmalloc (sizeof (*retval));
  retval->objfile = objfile;
  retval->source_file = xstrdup (source_file);
  retval->func_addr = func_addr;
  retval->regs_addr = regs_addr;
  return retval;
}