static enum gdb_osabi arm_mach_o_osabi_sniffer_use_dyld_hint (bfd *abfd) { if (osabi_seen_in_attached_dyld == GDB_OSABI_UNKNOWN) return GDB_OSABI_UNKNOWN; bfd *nbfd = NULL; for (;;) { bfd_arch_info_type *arch_info; nbfd = bfd_openr_next_archived_file (abfd, nbfd); if (nbfd == NULL) break; if (!bfd_check_format (nbfd, bfd_object)) continue; arch_info = bfd_get_arch_info (nbfd); if (arch_info->arch == bfd_arch_arm) { if (arch_info->mach == bfd_mach_arm_4T && osabi_seen_in_attached_dyld == GDB_OSABI_DARWIN) return GDB_OSABI_DARWIN; if (arch_info->mach == bfd_mach_arm_6 && osabi_seen_in_attached_dyld == GDB_OSABI_DARWINV6) return GDB_OSABI_DARWINV6; } } return GDB_OSABI_UNKNOWN; }
int main (int argc, char **argv) { bfd *archive; bfd *last, *next; if (argc != 2) die ("bad usage"); archive = bfd_openr (argv[1], NULL); if (!bfd_check_format (archive, bfd_archive)) { bfd_close (archive); die ("bfd_check_format"); } for (last = bfd_openr_next_archived_file (archive, NULL); last; last = next) { next = bfd_openr_next_archived_file (archive, last); bfd_close (last); } for (last = bfd_openr_next_archived_file (archive, NULL); last; last = next) { next = bfd_openr_next_archived_file (archive, last); bfd_close (last); } if (!bfd_close (archive)) die ("bfd_close"); return 0; }
static void add_bfd(bfd *Bfd) { if (bfd_check_format(Bfd, bfd_object)) { bfd_info_t *BfdInfo = new(bfd_info_t); BfdInfo->FileName = Bfd->filename; memset(BfdInfo->LocalTable, 0, sizeof(BfdInfo->LocalTable)); BfdInfo->Symbols = (asymbol **)malloc(bfd_get_symtab_upper_bound(Bfd)); int NoOfSymbols = bfd_canonicalize_symtab(Bfd, BfdInfo->Symbols); bfd_map_over_sections(Bfd, (bfd_map)add_bfd_section, BfdInfo); for (int I = NoOfSymbols - 1; I >= 0; --I) { asymbol *Sym = BfdInfo->Symbols[I]; if (Sym->flags & BSF_GLOBAL) { const char *Name = strdup(Sym->name); symbol_t *Symbol = new_symbol(Name, (section_t *)Sym->section->userdata, Sym->value); stringtable_put(BfdInfo->LocalTable, Name, Symbol); stringtable_put(GlobalTable, Name, Symbol); } else if (Sym->section == bfd_com_section_ptr) { symbol_t *Symbol = (symbol_t *)stringtable_get(GlobalTable, Sym->name); bss_section_t *Section; if (!Symbol) { const char *Name = strdup(Sym->name); Section = new_bss_section(0); Symbol = new_symbol(Name, (section_t *)Section, 0); stringtable_put(GlobalTable, Name, Symbol); stringtable_put(BfdInfo->LocalTable, Name, Symbol); } else { Section = (bss_section_t *)Symbol->Section; }; if (Sym->value > Section->Size) Section->Size = Sym->value; } else if (Sym->flags & BSF_LOCAL) { const char *Name = strdup(Sym->name); symbol_t *Symbol = new_symbol(Name, (section_t *)Sym->section->userdata, Sym->value); stringtable_put(BfdInfo->LocalTable, Name, Symbol); } else if (Sym->flags & BSF_WEAK) { const char *Name = strdup(Sym->name); symbol_t *Symbol = new_symbol(Name, (section_t *)Sym->section->userdata, Sym->value); stringtable_put(WeakTable, Name, Symbol); } else if (Sym->section == bfd_und_section_ptr) { } else if (Sym->flags & BSF_DEBUGGING) { // This may be supported later } else { printf("%s: unknown symbol type: %8x.\n", Bfd->filename, Sym->flags); exit(1); }; }; } else if (bfd_check_format(Bfd, bfd_archive)) { bfd *Bfd2 = 0; while ((Bfd2 = bfd_openr_next_archived_file(Bfd, Bfd2))) add_bfd(Bfd2); }; };
bfd * open_bfd_matching_arch (bfd *archive_bfd, bfd_format expected_format) { enum gdb_osabi osabi; bfd *abfd; osabi = GDB_OSABI_UNINITIALIZED; abfd = NULL; osabi = gdbarch_osabi (get_current_arch ()); if ((osabi <= GDB_OSABI_UNKNOWN) || (osabi >= GDB_OSABI_INVALID)) osabi = gdbarch_lookup_osabi (archive_bfd); // FIXME: gdbarch_lookup_osabi() doesn't work yet on archive_bfd, hardcode if ((osabi <= GDB_OSABI_UNKNOWN) || (osabi >= GDB_OSABI_INVALID)) osabi = GDB_OSABI_DARWIN; for (;;) { abfd = bfd_openr_next_archived_file (archive_bfd, abfd); if (abfd == NULL) break; if (! bfd_check_format (abfd, expected_format)) continue; if (osabi == gdbarch_lookup_osabi_from_bfd (abfd)) break; } // Copy the filename of the archive to the binary bfd. if (abfd) { xfree(abfd->filename); abfd->filename = archive_bfd->filename; } return abfd; }
void Archive::Read(const char* filename, Symbol::SymbolIndex_t& symbolIndex) { char *target = 0; bfd *file; file = bfd_openr (filename, target); if (file == 0) { // bfd_nonfatal (filename); // return FALSE; } if (bfd_check_format (file, bfd_archive)) { // display_archive (file); bfd *arfile = 0; std::cout << "file " << bfd_get_filename (file) << std::endl; while(arfile = bfd_openr_next_archived_file (file, arfile)) { const char* objectname = bfd_get_filename (arfile); ObjectFile* o = new ObjectFile(objectname, symbolIndex); o->SetParent(*this); o->Read(arfile); std::cout << "file " << bfd_get_filename (arfile) << std::endl; } if (arfile == NULL) { //if (bfd_get_error () != bfd_error_no_more_archived_files) //bfd_fatal (bfd_get_filename (file)); //break; } } }
static struct vmap * add_vmap (LdInfo *ldi) { bfd *abfd, *last; char *mem, *objname, *filename; struct objfile *obj; struct vmap *vp; int fd; ARCH64_DECL (arch64); /* This ldi structure was allocated using alloca() in xcoff_relocate_symtab(). Now we need to have persistent object and member names, so we should save them. */ filename = LDI_FILENAME (ldi, arch64); mem = filename + strlen (filename) + 1; mem = xstrdup (mem); objname = xstrdup (filename); fd = LDI_FD (ldi, arch64); if (fd < 0) /* Note that this opens it once for every member; a possible enhancement would be to only open it once for every object. */ abfd = bfd_openr (objname, gnutarget); else abfd = bfd_fdopenr (objname, gnutarget, fd); if (!abfd) { warning (_("Could not open `%s' as an executable file: %s"), objname, bfd_errmsg (bfd_get_error ())); return NULL; } /* make sure we have an object file */ if (bfd_check_format (abfd, bfd_object)) vp = map_vmap (abfd, 0); else if (bfd_check_format (abfd, bfd_archive)) { last = 0; /* FIXME??? am I tossing BFDs? bfd? */ while ((last = bfd_openr_next_archived_file (abfd, last))) if (strcmp (mem, last->filename) == 0) break; if (!last) { warning (_("\"%s\": member \"%s\" missing."), objname, mem); bfd_close (abfd); return NULL; } if (!bfd_check_format (last, bfd_object)) { warning (_("\"%s\": member \"%s\" not in executable format: %s."), objname, mem, bfd_errmsg (bfd_get_error ())); bfd_close (last); bfd_close (abfd); return NULL; } vp = map_vmap (last, abfd); } else { warning (_("\"%s\": not in executable format: %s."), objname, bfd_errmsg (bfd_get_error ())); bfd_close (abfd); return NULL; } obj = allocate_objfile (vp->bfd, 0); vp->objfile = obj; /* Always add symbols for the main objfile. */ if (vp == vmap || auto_solib_add) vmap_add_symbols (vp); return vp; }
bfd_boolean ldfile_try_open_bfd (const char *attempt, lang_input_statement_type *entry) { entry->the_bfd = bfd_openr (attempt, entry->target); if (verbose) { if (entry->the_bfd == NULL) info_msg (_("attempt to open %s failed\n"), attempt); else info_msg (_("attempt to open %s succeeded\n"), attempt); } if (entry->the_bfd == NULL) { if (bfd_get_error () == bfd_error_invalid_target) einfo (_("%F%P: invalid BFD target `%s'\n"), entry->target); return FALSE; } /* Linker needs to decompress sections. */ entry->the_bfd->flags |= BFD_DECOMPRESS; /* This is a linker input BFD. */ entry->the_bfd->is_linker_input = 1; #ifdef ENABLE_PLUGINS if (entry->flags.lto_output) entry->the_bfd->lto_output = 1; #endif /* If we are searching for this file, see if the architecture is compatible with the output file. If it isn't, keep searching. If we can't open the file as an object file, stop the search here. If we are statically linking, ensure that we don't link a dynamic object. In the code below, it's OK to exit early if the check fails, closing the checked BFD and returning FALSE, but if the BFD checks out compatible, do not exit early returning TRUE, or the plugins will not get a chance to claim the file. */ if (entry->flags.search_dirs || !entry->flags.dynamic) { bfd *check; if (bfd_check_format (entry->the_bfd, bfd_archive)) check = bfd_openr_next_archived_file (entry->the_bfd, NULL); else check = entry->the_bfd; if (check != NULL) { if (! bfd_check_format (check, bfd_object)) { if (check == entry->the_bfd && entry->flags.search_dirs && bfd_get_error () == bfd_error_file_not_recognized && ! ldemul_unrecognized_file (entry)) { int token, skip = 0; char *arg, *arg1, *arg2, *arg3; extern FILE *yyin; /* Try to interpret the file as a linker script. */ ldfile_open_command_file (attempt); ldfile_assumed_script = TRUE; parser_input = input_selected; ldlex_both (); token = INPUT_SCRIPT; while (token != 0) { switch (token) { case OUTPUT_FORMAT: if ((token = yylex ()) != '(') continue; if ((token = yylex ()) != NAME) continue; arg1 = yylval.name; arg2 = NULL; arg3 = NULL; token = yylex (); if (token == ',') { if ((token = yylex ()) != NAME) { free (arg1); continue; } arg2 = yylval.name; if ((token = yylex ()) != ',' || (token = yylex ()) != NAME) { free (arg1); free (arg2); continue; } arg3 = yylval.name; token = yylex (); } if (token == ')') { switch (command_line.endian) { default: case ENDIAN_UNSET: arg = arg1; break; case ENDIAN_BIG: arg = arg2 ? arg2 : arg1; break; case ENDIAN_LITTLE: arg = arg3 ? arg3 : arg1; break; } if (strcmp (arg, lang_get_output_target ()) != 0) skip = 1; } free (arg1); if (arg2) free (arg2); if (arg3) free (arg3); break; case NAME: case LNAME: case VERS_IDENTIFIER: case VERS_TAG: free (yylval.name); break; case INT: if (yylval.bigint.str) free (yylval.bigint.str); break; } token = yylex (); } ldlex_popstate (); ldfile_assumed_script = FALSE; fclose (yyin); yyin = NULL; if (skip) { if (command_line.warn_search_mismatch) einfo (_("%P: skipping incompatible %s " "when searching for %s\n"), attempt, entry->local_sym_name); bfd_close (entry->the_bfd); entry->the_bfd = NULL; return FALSE; } } goto success; } if (!entry->flags.dynamic && (entry->the_bfd->flags & DYNAMIC) != 0) { einfo (_("%F%P: attempted static link of dynamic object `%s'\n"), attempt); bfd_close (entry->the_bfd); entry->the_bfd = NULL; return FALSE; } if (entry->flags.search_dirs && !bfd_arch_get_compatible (check, link_info.output_bfd, command_line.accept_unknown_input_arch) /* XCOFF archives can have 32 and 64 bit objects. */ && ! (bfd_get_flavour (check) == bfd_target_xcoff_flavour && bfd_get_flavour (link_info.output_bfd) == bfd_target_xcoff_flavour && bfd_check_format (entry->the_bfd, bfd_archive))) { if (command_line.warn_search_mismatch) einfo (_("%P: skipping incompatible %s " "when searching for %s\n"), attempt, entry->local_sym_name); bfd_close (entry->the_bfd); entry->the_bfd = NULL; return FALSE; } } } success: #ifdef ENABLE_PLUGINS /* If plugins are active, they get first chance to claim any successfully-opened input file. We skip archives here; the plugin wants us to offer it the individual members when we enumerate them, not the whole file. We also ignore corefiles, because that's just weird. It is a needed side-effect of calling bfd_check_format with bfd_object that it sets the bfd's arch and mach, which will be needed when and if we want to bfd_create a new one using this one as a template. */ if (link_info.lto_plugin_active && !no_more_claiming && bfd_check_format (entry->the_bfd, bfd_object)) plugin_maybe_claim (entry); #endif /* ENABLE_PLUGINS */ /* It opened OK, the format checked out, and the plugins have had their chance to claim it, so this is success. */ return TRUE; }
/* archive file (*.a) loading test */ int main() { int ret; int symnum; bfd* abfd; asymbol** syms; int symbol_pos, symbol_size; int index; #ifndef OBJ_TEST const char* file = "foo.a"; #else const char* file = "hello.o"; #endif unsigned char* file_o; file_o = load_file(file); abfd = bfd_openr(file, NULL); assert(abfd); ret = bfd_check_format(abfd, bfd_archive); //ret = bfd_check_format(abfd, bfd_object); assert(ret); #ifndef OBJ_TEST bfd* b = NULL; #else bfd* b = abfd;//NULL; #endif link_list_t* bfds = NULL; STEP_LOG("create function map\n"); #ifndef OBJ_TEST while(NULL != (b = bfd_openr_next_archived_file(abfd, b))) #endif { ret = bfd_check_format(b, bfd_object); assert(ret); // STEP_LOG("next\n"); if (!(bfd_get_file_flags(b) & HAS_SYMS)) { assert(bfd_get_error() == bfd_error_no_error); /* no symbol */ bfd_close(abfd); return 1; } if (NULL == bfds) { LOG("Add first:0x%08X\n", (int)b); bfds = add_item(bfds, &b, sizeof(b)); } else { LOG("Add bfd:0x%08X\n", (int)b); add_item(bfds, &b, sizeof(b)); } get_symbols(&syms, &symnum, b); create_symbol_function_pos(file_o, b, syms, symnum); } STEP_LOG("relocate function addresses\n"); link_list_t* list = bfds; while(NULL != list) { b = *(bfd**)(list->item); get_symbols(&syms, &symnum, b); reloc_file(file_o, b, syms); list = list->next; } STEP_LOG("try to get function addressses\n"); int (*func)(); void (*func1)(const char*); func = NULL; func1 = NULL; list = bfds; while(NULL != list) { b = *(bfd**)(list->item); LOG("bfd:0x%08X\n", (int)b); LOG("call goodby...."); get_symbols(&syms, &symnum, b); symbol_pos = get_symbol_pos("goodby", b, syms, symnum, file_o); if (0 != symbol_pos) { func = (int (*) ())(get_function(symbol_pos)); } LOG("call hello_someone...."); symbol_pos = get_symbol_pos("hello_someone", b, syms, symnum, file_o); if (0 != symbol_pos) { func1 = (void (*) (const char*))(get_function(symbol_pos)); } if (NULL != func && NULL != func1) break; list = list->next; } STEP_LOG("try to call functions\n"); if (NULL != func) { func(); } else { LOG("failed to call func\n"); } if (NULL != func1) { func1("WORLD!"); } else { LOG("failed to call func\n"); } delete_all_items(bfds); free(syms); bfd_close(abfd); free(file_o); return 0; }
static enum gdb_osabi arm_mach_o_osabi_sniffer (bfd *abfd) { enum gdb_osabi ret; /* The way loading works on Darwin is that for FAT files, the fork corresponding to the host system will be the one used regardless of what the type of the main executable was. So the osabi has to be determined solely by the type of the host system. */ if (strcmp (bfd_get_target (abfd), "mach-o-le") == 0) { bfd_arch_info_type *arch_info = bfd_get_arch_info (abfd); if (arch_info->arch == bfd_arch_arm) { if (arch_info->mach == bfd_mach_arm_4T) return GDB_OSABI_DARWIN; else if (arch_info->mach == bfd_mach_arm_6) return GDB_OSABI_DARWINV6; } } /* However, if we are running a cross gdb, we won't know what the target architecture is. FIXME - going to have to determine this somehow. For now, fall back to looking at the binary. */ ret = arm_mach_o_osabi_sniffer_use_dyld_hint (abfd); if (ret == GDB_OSABI_DARWINV6 || ret == GDB_OSABI_DARWIN) return ret; if (bfd_check_format (abfd, bfd_archive)) { enum gdb_osabi best = GDB_OSABI_UNKNOWN; enum gdb_osabi cur = GDB_OSABI_UNKNOWN; bfd *nbfd = NULL; for (;;) { nbfd = bfd_openr_next_archived_file (abfd, nbfd); if (nbfd == NULL) break; if (!bfd_check_format (nbfd, bfd_object)) continue; cur = arm_mach_o_osabi_sniffer (nbfd); if (cur == GDB_OSABI_DARWINV6 && best != GDB_OSABI_DARWINV6 && arm_mach_o_query_v6 ()) best = cur; if (cur == GDB_OSABI_DARWIN && best != GDB_OSABI_DARWINV6 && best != GDB_OSABI_DARWIN) best = cur; } return best; } if (!bfd_check_format (abfd, bfd_object)) return GDB_OSABI_UNKNOWN; return GDB_OSABI_UNKNOWN; }
bfd_boolean ldfile_try_open_bfd (const char *attempt, lang_input_statement_type *entry) { entry->the_bfd = bfd_openr (attempt, entry->target); if (trace_file_tries) { if (entry->the_bfd == NULL) info_msg (_("attempt to open %s failed\n"), attempt); else info_msg (_("attempt to open %s succeeded\n"), attempt); } if (entry->the_bfd == NULL) { if (bfd_get_error () == bfd_error_invalid_target) einfo (_("%F%P: invalid BFD target `%s'\n"), entry->target); return FALSE; } /* If we are searching for this file, see if the architecture is compatible with the output file. If it isn't, keep searching. If we can't open the file as an object file, stop the search here. If we are statically linking, ensure that we don't link a dynamic object. */ if (entry->search_dirs_flag || !entry->dynamic) { bfd *check; if (bfd_check_format (entry->the_bfd, bfd_archive)) check = bfd_openr_next_archived_file (entry->the_bfd, NULL); else check = entry->the_bfd; if (check != NULL) { if (! bfd_check_format (check, bfd_object)) { if (check == entry->the_bfd && entry->search_dirs_flag && bfd_get_error () == bfd_error_file_not_recognized && ! ldemul_unrecognized_file (entry)) { int token, skip = 0; char *arg, *arg1, *arg2, *arg3; extern FILE *yyin; /* Try to interpret the file as a linker script. */ ldfile_open_command_file (attempt); ldfile_assumed_script = TRUE; parser_input = input_selected; ldlex_both (); token = INPUT_SCRIPT; while (token != 0) { switch (token) { case OUTPUT_FORMAT: if ((token = yylex ()) != '(') continue; if ((token = yylex ()) != NAME) continue; arg1 = yylval.name; arg2 = NULL; arg3 = NULL; token = yylex (); if (token == ',') { if ((token = yylex ()) != NAME) { free (arg1); continue; } arg2 = yylval.name; if ((token = yylex ()) != ',' || (token = yylex ()) != NAME) { free (arg1); free (arg2); continue; } arg3 = yylval.name; token = yylex (); } if (token == ')') { switch (command_line.endian) { default: case ENDIAN_UNSET: arg = arg1; break; case ENDIAN_BIG: arg = arg2 ? arg2 : arg1; break; case ENDIAN_LITTLE: arg = arg3 ? arg3 : arg1; break; } if (strcmp (arg, lang_get_output_target ()) != 0) skip = 1; } free (arg1); if (arg2) free (arg2); if (arg3) free (arg3); break; case NAME: case LNAME: case VERS_IDENTIFIER: case VERS_TAG: free (yylval.name); break; case INT: if (yylval.bigint.str) free (yylval.bigint.str); break; } token = yylex (); } ldlex_popstate (); ldfile_assumed_script = FALSE; fclose (yyin); yyin = NULL; if (skip) { if (command_line.warn_search_mismatch) einfo (_("%P: skipping incompatible %s " "when searching for %s\n"), attempt, entry->local_sym_name); bfd_close (entry->the_bfd); entry->the_bfd = NULL; return FALSE; } } return TRUE; } if (!entry->dynamic && (entry->the_bfd->flags & DYNAMIC) != 0) { einfo (_("%F%P: attempted static link of dynamic object `%s'\n"), attempt); bfd_close (entry->the_bfd); entry->the_bfd = NULL; return FALSE; } if (entry->search_dirs_flag && !bfd_arch_get_compatible (check, link_info.output_bfd, command_line.accept_unknown_input_arch) /* XCOFF archives can have 32 and 64 bit objects. */ && ! (bfd_get_flavour (check) == bfd_target_xcoff_flavour && bfd_get_flavour (link_info.output_bfd) == bfd_target_xcoff_flavour && bfd_check_format (entry->the_bfd, bfd_archive))) { if (command_line.warn_search_mismatch) einfo (_("%P: skipping incompatible %s " "when searching for %s\n"), attempt, entry->local_sym_name); bfd_close (entry->the_bfd); entry->the_bfd = NULL; return FALSE; } } } return TRUE; }