예제 #1
0
static bfd_boolean
gldelf64ltsmip_try_needed (const char *name, int force)
{
  bfd *abfd;
  const char *soname;

  abfd = bfd_openr (name, bfd_get_target (output_bfd));
  if (abfd == NULL)
    return FALSE;
  if (! bfd_check_format (abfd, bfd_object))
    {
      bfd_close (abfd);
      return FALSE;
    }
  if ((bfd_get_file_flags (abfd) & DYNAMIC) == 0)
    {
      bfd_close (abfd);
      return FALSE;
    }

  /* For DT_NEEDED, they have to match.  */
  if (abfd->xvec != output_bfd->xvec)
    {
      bfd_close (abfd);
      return FALSE;
    }

  /* Check whether this object would include any conflicting library
     versions.  If FORCE is set, then we skip this check; we use this
     the second time around, if we couldn't find any compatible
     instance of the shared library.  */

  if (! force)
    {
      struct bfd_link_needed_list *needed;

      if (! bfd_elf_get_bfd_needed_list (abfd, &needed))
	einfo ("%F%P:%B: bfd_elf_get_bfd_needed_list failed: %E\n", abfd);

      if (needed != NULL)
	{
	  global_vercheck_needed = needed;
	  global_vercheck_failed = FALSE;
	  lang_for_each_input_file (gldelf64ltsmip_vercheck);
	  if (global_vercheck_failed)
	    {
	      bfd_close (abfd);
	      /* Return FALSE to force the caller to move on to try
		 another file on the search path.  */
	      return FALSE;
	    }

	  /* But wait!  It gets much worse.  On Linux, if a shared
	     library does not use libc at all, we are supposed to skip
	     it the first time around in case we encounter a shared
	     library later on with the same name which does use the
	     version of libc that we want.  This is much too horrible
	     to use on any system other than Linux.  */

	  {
	    struct bfd_link_needed_list *l;

	    for (l = needed; l != NULL; l = l->next)
	      if (strncmp (l->name, "libc.so", 7) == 0)
		break;
	    if (l == NULL)
	      {
		bfd_close (abfd);
		return FALSE;
	      }
	  }

	}
    }

  /* We've found a dynamic object matching the DT_NEEDED entry.  */

  /* We have already checked that there is no other input file of the
     same name.  We must now check again that we are not including the
     same file twice.  We need to do this because on many systems
     libc.so is a symlink to, e.g., libc.so.1.  The SONAME entry will
     reference libc.so.1.  If we have already included libc.so, we
     don't want to include libc.so.1 if they are the same file, and we
     can only check that using stat.  */

  if (bfd_stat (abfd, &global_stat) != 0)
    einfo ("%F%P:%B: bfd_stat failed: %E\n", abfd);

  /* First strip off everything before the last '/'.  */
  soname = lbasename (abfd->filename);

  if (trace_file_tries)
    info_msg (_("found %s at %s\n"), soname, name);

  global_found = FALSE;
  lang_for_each_input_file (gldelf64ltsmip_stat_needed);
  if (global_found)
    {
      /* Return TRUE to indicate that we found the file, even though
	 we aren't going to do anything with it.  */
      return TRUE;
    }

  /* Tell the ELF backend that we don't want the output file to have a
     DT_NEEDED entry for this file.  */
  bfd_elf_set_dt_needed_name (abfd, "");

  /* Tell the ELF backend that the output file needs a DT_NEEDED
     entry for this file if it is used to resolve the reference in
     a regular object.  */
  bfd_elf_set_dt_needed_soname (abfd, soname);

  /* Add this file into the symbol table.  */
  if (! bfd_link_add_symbols (abfd, &link_info))
    einfo ("%F%B: could not read symbols: %E\n", abfd);

  return TRUE;
}
예제 #2
0
파일: bfdtest.c 프로젝트: great90/gcl
int build_symbol_table_bfd ( char *oname ) {

    int u,v;
    asymbol **q;

    bfd_init();
    if ( ! ( exe_bfd = bfd_openr ( oname, 0 ) ) ) {
        fprintf ( stderr, "Cannot open %s.\n", oname );
        exit ( 0 );
    }
    
    if ( ! bfd_check_format ( exe_bfd, bfd_object ) ) {
        fprintf ( stderr, "I'm not an object.\n" );
        exit ( 0 );
    }
    
    if ( !(link_info.hash = bfd_link_hash_table_create ( exe_bfd ) ) ) {
        fprintf ( stderr, "Cannot make hash table.\n" );
        exit ( 0 );
    }
    
    if ( !bfd_link_add_symbols ( exe_bfd, &link_info ) ) {
        fprintf ( stderr, "Cannot add self symbols\n.\n" );
        exit ( 0 );
    }
    
    if ( ( u = bfd_get_symtab_upper_bound ( exe_bfd ) ) < 0 ) {
        fprintf ( stderr, "Cannot get self's symtab upper bound.\n" );
        exit ( 0 );
    }
    
    fprintf ( stderr, "Allocating symbol table (%d bytes)\n", u );
    q = (asymbol **) malloc ( u );

    if ( ( v = bfd_canonicalize_symtab ( exe_bfd, q ) ) < 0 ) {
        fprintf ( stderr, "Cannot canonicalize self's symtab.\n" );
        exit ( 0 );
    }

#ifdef _WIN32        
    for ( u=0; u < v; u++ ) {
        char *c;
        if ( ( c = (char *) strstr ( q[u]->name, "_" ) ) ) {
            struct bfd_link_hash_entry *h;
            if ( ( h = bfd_link_hash_lookup ( link_info.hash,
                                                q[u]->name, MY_BFD_TRUE,MY_BFD_TRUE,MY_BFD_TRUE ) ) ) {
                h->type=bfd_link_hash_defined;
                if ( !q[u]->section )
                    fprintf ( stderr, "Symbol is missing section.\n" );
                h->u.def.value   = q[u]->value + q[u]->section->vma;
                h->u.def.section = q[u]->section;
                fprintf ( stderr, "Processed %s\n", q[u]->name );
            } else {
                fprintf ( stderr, "Cannot make new hash entry.\n" );
            }
        }
    }
#else    
    for (u=0;u<v;u++) {
        char *c;
        if ((c=(char *)strstr(q[u]->name,"@@GLIBC\n" ))) {
            struct bfd_link_hash_entry *h;
            *c=0;
            if (!(h=bfd_link_hash_lookup(link_info.hash,q[u]->name,MY_BFD_TRUE,MY_BFD_TRUE,MY_BFD_TRUE)))
                fprintf ( stderr, "Cannot make new hash entry.\n" );
            h->type=bfd_link_hash_defined;
            if (!q[u]->section)
                fprintf ( stderr, "Symbol is missing section.\n" );
            h->u.def.value=q[u]->value+q[u]->section->vma;
            h->u.def.section=q[u]->section;
            *c='@';
        }
    }
#endif        
    bfd_close ( exe_bfd );
    free(q);
    return 0;
    
}