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; }
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; }