예제 #1
0
static int
scan_dyntag (int dyntag, bfd *abfd, CORE_ADDR *ptr)
{
  int arch_size, step, sect_size;
  long dyn_tag;
  CORE_ADDR dyn_ptr, dyn_addr;
  gdb_byte *bufend, *bufstart, *buf;
  Elf32_External_Dyn *x_dynp_32;
  Elf64_External_Dyn *x_dynp_64;
  struct bfd_section *sect;
  struct target_section *target_section;

  if (abfd == NULL)
    return 0;

  if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
    return 0;

  arch_size = bfd_get_arch_size (abfd);
  if (arch_size == -1)
    return 0;

  /* Find the start address of the .dynamic section.  */
  sect = bfd_get_section_by_name (abfd, ".dynamic");
  if (sect == NULL)
    return 0;

  for (target_section = current_target_sections->sections;
       target_section < current_target_sections->sections_end;
       target_section++)
    if (sect == target_section->the_bfd_section)
      break;
  if (target_section < current_target_sections->sections_end)
    dyn_addr = target_section->addr;
  else
    {
      /* ABFD may come from OBJFILE acting only as a symbol file without being
	 loaded into the target (see add_symbol_file_command).  This case is
	 such fallback to the file VMA address without the possibility of
	 having the section relocated to its actual in-memory address.  */

      dyn_addr = bfd_section_vma (abfd, sect);
    }

  /* Read in .dynamic from the BFD.  We will get the actual value
     from memory later.  */
  sect_size = bfd_section_size (abfd, sect);
  buf = bufstart = alloca (sect_size);
  if (!bfd_get_section_contents (abfd, sect,
				 buf, 0, sect_size))
    return 0;

  /* Iterate over BUF and scan for DYNTAG.  If found, set PTR and return.  */
  step = (arch_size == 32) ? sizeof (Elf32_External_Dyn)
			   : sizeof (Elf64_External_Dyn);
  for (bufend = buf + sect_size;
       buf < bufend;
       buf += step)
  {
    if (arch_size == 32)
      {
	x_dynp_32 = (Elf32_External_Dyn *) buf;
	dyn_tag = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp_32->d_tag);
	dyn_ptr = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp_32->d_un.d_ptr);
      }
    else
      {
	x_dynp_64 = (Elf64_External_Dyn *) buf;
	dyn_tag = bfd_h_get_64 (abfd, (bfd_byte *) x_dynp_64->d_tag);
	dyn_ptr = bfd_h_get_64 (abfd, (bfd_byte *) x_dynp_64->d_un.d_ptr);
      }
     if (dyn_tag == DT_NULL)
       return 0;
     if (dyn_tag == dyntag)
       {
	 /* If requested, try to read the runtime value of this .dynamic
	    entry.  */
	 if (ptr)
	   {
	     struct type *ptr_type;
	     gdb_byte ptr_buf[8];
	     CORE_ADDR ptr_addr;

	     ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
	     ptr_addr = dyn_addr + (buf - bufstart) + arch_size / 8;
	     if (target_read_memory (ptr_addr, ptr_buf, arch_size / 8) == 0)
	       dyn_ptr = extract_typed_address (ptr_buf, ptr_type);
	     *ptr = dyn_ptr;
	   }
	 return 1;
       }
  }

  return 0;
}
예제 #2
0
bfd_boolean
_bfd_elf_parse_gnu_properties (bfd *abfd, Elf_Internal_Note *note)
{
  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
  unsigned int align_size = bed->s->elfclass == ELFCLASS64 ? 8 : 4;
  bfd_byte *ptr = (bfd_byte *) note->descdata;
  bfd_byte *ptr_end = ptr + note->descsz;

  if (note->descsz < 8 || (note->descsz % align_size) != 0)
    {
bad_size:
      _bfd_error_handler
	(_("warning: %pB: corrupt GNU_PROPERTY_TYPE (%ld) size: %#lx"),
	 abfd, note->type, note->descsz);
      return FALSE;
    }

  while (ptr != ptr_end)
    {
      unsigned int type;
      unsigned int datasz;
      elf_property *prop;

      if ((size_t) (ptr_end - ptr) < 8)
	goto bad_size;

      type = bfd_h_get_32 (abfd, ptr);
      datasz = bfd_h_get_32 (abfd, ptr + 4);
      ptr += 8;

      if (datasz > (size_t) (ptr_end - ptr))
	{
	  _bfd_error_handler
	    (_("warning: %pB: corrupt GNU_PROPERTY_TYPE (%ld) type (0x%x) datasz: 0x%x"),
	     abfd, note->type, type, datasz);
	  /* Clear all properties.  */
	  elf_properties (abfd) = NULL;
	  return FALSE;
	}

      if (type >= GNU_PROPERTY_LOPROC)
	{
	  if (bed->elf_machine_code == EM_NONE)
	    {
	      /* Ignore processor-specific properties with generic ELF
		 target vector.  They should be handled by the matching
		 ELF target vector.  */
	      goto next;
	    }
	  else if (type < GNU_PROPERTY_LOUSER
		   && bed->parse_gnu_properties)
	    {
	      enum elf_property_kind kind
		= bed->parse_gnu_properties (abfd, type, ptr, datasz);
	      if (kind == property_corrupt)
		{
		  /* Clear all properties.  */
		  elf_properties (abfd) = NULL;
		  return FALSE;
		}
	      else if (kind != property_ignored)
		goto next;
	    }
	}
      else
	{
	  switch (type)
	    {
	    case GNU_PROPERTY_STACK_SIZE:
	      if (datasz != align_size)
		{
		  _bfd_error_handler
		    (_("warning: %pB: corrupt stack size: 0x%x"),
		     abfd, datasz);
		  /* Clear all properties.  */
		  elf_properties (abfd) = NULL;
		  return FALSE;
		}
	      prop = _bfd_elf_get_property (abfd, type, datasz);
	      if (datasz == 8)
		prop->u.number = bfd_h_get_64 (abfd, ptr);
	      else
		prop->u.number = bfd_h_get_32 (abfd, ptr);
	      prop->pr_kind = property_number;
	      goto next;

	    case GNU_PROPERTY_NO_COPY_ON_PROTECTED:
	      if (datasz != 0)
		{
		  _bfd_error_handler
		    (_("warning: %pB: corrupt no copy on protected size: 0x%x"),
		     abfd, datasz);
		  /* Clear all properties.  */
		  elf_properties (abfd) = NULL;
		  return FALSE;
		}
	      prop = _bfd_elf_get_property (abfd, type, datasz);
	      elf_has_no_copy_on_protected (abfd) = TRUE;
	      prop->pr_kind = property_number;
	      goto next;

	    default:
	      break;
	    }
	}

      _bfd_error_handler
	(_("warning: %pB: unsupported GNU_PROPERTY_TYPE (%ld) type: 0x%x"),
	 abfd, note->type, type);

next:
      ptr += (datasz + (align_size - 1)) & ~ (align_size - 1);
    }

  return TRUE;
}
예제 #3
0
static void
read_alphacoff_dynamic_symtab (minimal_symbol_reader &reader,
			       struct section_offsets *section_offsets,
			       struct objfile *objfile)
{
  bfd *abfd = objfile->obfd;
  struct alphacoff_dynsecinfo si;
  char *sym_secptr;
  char *str_secptr;
  char *dyninfo_secptr;
  char *got_secptr;
  bfd_size_type sym_secsize;
  bfd_size_type str_secsize;
  bfd_size_type dyninfo_secsize;
  bfd_size_type got_secsize;
  int sym_count;
  int i;
  int stripped;
  Elfalpha_External_Sym *x_symp;
  char *dyninfo_p;
  char *dyninfo_end;
  int got_entry_size = 8;
  int dt_mips_local_gotno = -1;
  int dt_mips_gotsym = -1;
  struct cleanup *cleanups;

  /* We currently only know how to handle alpha dynamic symbols.  */
  if (bfd_get_arch (abfd) != bfd_arch_alpha)
    return;

  /* Locate the dynamic symbols sections and read them in.  */
  memset ((char *) &si, 0, sizeof (si));
  bfd_map_over_sections (abfd, alphacoff_locate_sections, (void *) & si);
  if (si.sym_sect == NULL || si.str_sect == NULL
      || si.dyninfo_sect == NULL || si.got_sect == NULL)
    return;

  sym_secsize = bfd_get_section_size (si.sym_sect);
  str_secsize = bfd_get_section_size (si.str_sect);
  dyninfo_secsize = bfd_get_section_size (si.dyninfo_sect);
  got_secsize = bfd_get_section_size (si.got_sect);
  sym_secptr = (char *) xmalloc (sym_secsize);
  cleanups = make_cleanup (xfree, sym_secptr);
  str_secptr = (char *) xmalloc (str_secsize);
  make_cleanup (xfree, str_secptr);
  dyninfo_secptr = (char *) xmalloc (dyninfo_secsize);
  make_cleanup (xfree, dyninfo_secptr);
  got_secptr = (char *) xmalloc (got_secsize);
  make_cleanup (xfree, got_secptr);

  if (!bfd_get_section_contents (abfd, si.sym_sect, sym_secptr,
				 (file_ptr) 0, sym_secsize))
    {
      do_cleanups (cleanups);
      return;
    }
  if (!bfd_get_section_contents (abfd, si.str_sect, str_secptr,
				 (file_ptr) 0, str_secsize))
    {
      do_cleanups (cleanups);
      return;
    }
  if (!bfd_get_section_contents (abfd, si.dyninfo_sect, dyninfo_secptr,
				 (file_ptr) 0, dyninfo_secsize))
    {
      do_cleanups (cleanups);
      return;
    }
  if (!bfd_get_section_contents (abfd, si.got_sect, got_secptr,
				 (file_ptr) 0, got_secsize))
    {
      do_cleanups (cleanups);
      return;
    }

  /* Find the number of local GOT entries and the index for the
     first dynamic symbol in the GOT.  */
  for (dyninfo_p = dyninfo_secptr, dyninfo_end = dyninfo_p + dyninfo_secsize;
       dyninfo_p < dyninfo_end;
       dyninfo_p += sizeof (Elfalpha_External_Dyn))
    {
      Elfalpha_External_Dyn *x_dynp = (Elfalpha_External_Dyn *) dyninfo_p;
      long dyn_tag;

      dyn_tag = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_tag);
      if (dyn_tag == DT_NULL)
	break;
      else if (dyn_tag == DT_MIPS_LOCAL_GOTNO)
	{
	  if (dt_mips_local_gotno < 0)
	    dt_mips_local_gotno
	      = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_un.d_val);
	}
      else if (dyn_tag == DT_MIPS_GOTSYM)
	{
	  if (dt_mips_gotsym < 0)
	    dt_mips_gotsym
	      = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_un.d_val);
	}
    }
  if (dt_mips_local_gotno < 0 || dt_mips_gotsym < 0)
    {
      do_cleanups (cleanups);
      return;
    }

  /* Scan all dynamic symbols and enter them into the minimal symbol
     table if appropriate.  */
  sym_count = sym_secsize / sizeof (Elfalpha_External_Sym);
  stripped = (bfd_get_symcount (abfd) == 0);

  /* Skip first symbol, which is a null dummy.  */
  for (i = 1, x_symp = (Elfalpha_External_Sym *) sym_secptr + 1;
       i < sym_count;
       i++, x_symp++)
    {
      unsigned long strx;
      char *name;
      bfd_vma sym_value;
      unsigned char sym_info;
      unsigned int sym_shndx;
      int isglobal;
      enum minimal_symbol_type ms_type;

      strx = bfd_h_get_32 (abfd, (bfd_byte *) x_symp->st_name);
      if (strx >= str_secsize)
	continue;
      name = str_secptr + strx;
      if (*name == '\0' || *name == '.')
	continue;

      sym_value = bfd_h_get_64 (abfd, (bfd_byte *) x_symp->st_value);
      sym_info = bfd_h_get_8 (abfd, (bfd_byte *) x_symp->st_info);
      sym_shndx = bfd_h_get_16 (abfd, (bfd_byte *) x_symp->st_shndx);
      if (sym_shndx >= (SHN_LORESERVE & 0xffff))
	sym_shndx += SHN_LORESERVE - (SHN_LORESERVE & 0xffff);
      isglobal = (ELF_ST_BIND (sym_info) == STB_GLOBAL);

      if (sym_shndx == SHN_UNDEF)
	{
	  /* Handle undefined functions which are defined in a shared
	     library.  */
	  if (ELF_ST_TYPE (sym_info) != STT_FUNC
	      || ELF_ST_BIND (sym_info) != STB_GLOBAL)
	    continue;

	  ms_type = mst_solib_trampoline;

	  /* If sym_value is nonzero, it points to the shared library
	     trampoline entry, which is what we are looking for.

	     If sym_value is zero, then we have to get the GOT entry
	     for the symbol.

	     If the GOT entry is nonzero, it represents the quickstart
	     address of the function and we use that as the symbol
	     value.

	     If the GOT entry is zero, the function address has to be
	     resolved by the runtime loader before the executable is
	     started.  We are unable to find any meaningful address
	     for these functions in the executable file, so we skip
	     them.  */
	  if (sym_value == 0)
	    {
	      int got_entry_offset =
		(i - dt_mips_gotsym + dt_mips_local_gotno) * got_entry_size;

	      if (got_entry_offset < 0 || got_entry_offset >= got_secsize)
		continue;
	      sym_value =
		bfd_h_get_64 (abfd,
			      (bfd_byte *) (got_secptr + got_entry_offset));
	      if (sym_value == 0)
		continue;
	    }
	}
      else
	{
	  /* Symbols defined in the executable itself.  We only care
	     about them if this is a stripped executable, otherwise
	     they have been retrieved from the normal symbol table
	     already.  */
	  if (!stripped)
	    continue;

	  if (sym_shndx == SHN_MIPS_TEXT)
	    {
	      if (isglobal)
		ms_type = mst_text;
	      else
		ms_type = mst_file_text;
	    }
	  else if (sym_shndx == SHN_MIPS_DATA)
	    {
	      if (isglobal)
		ms_type = mst_data;
	      else
		ms_type = mst_file_data;
	    }
	  else if (sym_shndx == SHN_MIPS_ACOMMON)
	    {
	      if (isglobal)
		ms_type = mst_bss;
	      else
		ms_type = mst_file_bss;
	    }
	  else if (sym_shndx == SHN_ABS)
	    {
	      ms_type = mst_abs;
	    }
	  else
	    {
	      continue;
	    }
	}

      reader.record (name, sym_value, ms_type);
    }

  do_cleanups (cleanups);
}