static file_ptr cache_bwrite (struct bfd *abfd, const void *where, file_ptr nbytes) { file_ptr nwrite; FILE *f = bfd_cache_lookup (abfd, 0); if (f == NULL) return 0; nwrite = fwrite (where, 1, nbytes, f); if (nwrite < nbytes && ferror (f)) { bfd_set_error (bfd_error_system_call); return -1; } return nwrite; }
/* FUNCTION bfd_canonicalize_reloc SYNOPSIS long bfd_canonicalize_reloc (bfd *abfd, asection *sec, arelent **loc, asymbol **syms); DESCRIPTION Call the back end associated with the open BFD @var{abfd} and translate the external form of the relocation information attached to @var{sec} into the internal canonical form. Place the table into memory at @var{loc}, which has been preallocated, usually by a call to <<bfd_get_reloc_upper_bound>>. Returns the number of relocs, or -1 on error. The @var{syms} table is also needed for horrible internal magic reasons. */ long bfd_canonicalize_reloc (bfd *abfd, sec_ptr asect, arelent **location, asymbol **symbols) { if (abfd->format != bfd_object) { bfd_set_error (bfd_error_invalid_operation); return -1; } return BFD_SEND (abfd, _bfd_canonicalize_reloc, (abfd, asect, location, symbols)); }
bfd_boolean bfd_set_file_flags (bfd *abfd, flagword flags) { if (abfd->format != bfd_object) { bfd_set_error (bfd_error_wrong_format); return FALSE; } if (bfd_read_p (abfd)) { bfd_set_error (bfd_error_invalid_operation); return FALSE; } bfd_get_file_flags (abfd) = flags; if ((flags & bfd_applicable_file_flags (abfd)) != flags) { bfd_set_error (bfd_error_invalid_operation); return FALSE; } return TRUE; }
static file_ptr cache_bwrite (struct bfd *abfd, const void *where, file_ptr nbytes) { file_ptr nwrite; FILE *f = bfd_cache_lookup (abfd, 0); if (f == NULL) return 0; #if defined(__BEOS__) || defined(__HAIKU__) { if (_bfdio_files[fileno(f)] == 1) { file_ptr eof; file_ptr pos; pos = ftell (f); fseek (f, 0L, SEEK_END); eof = ftell(f); if (eof < pos) { file_ptr diff; static char zeros[512]; diff = pos - eof; while (diff >= sizeof (zeros)) { fwrite(zeros, sizeof (zeros), 1, f); diff -= sizeof (zeros); } if (diff > 0) fwrite(zeros, diff, 1, f); } else fseek (f, pos, SEEK_SET); _bfdio_files[fileno(f)] = 0; } } #endif nwrite = fwrite (where, 1, nbytes, f); if (nwrite < nbytes && ferror (f)) { bfd_set_error (bfd_error_system_call); return -1; } return nwrite; }
static file_ptr spu_bfd_iovec_pread (bfd *abfd, void *stream, void *buf, file_ptr nbytes, file_ptr offset) { CORE_ADDR addr = *(CORE_ADDR *)stream; int ret; ret = target_read_memory (addr + offset, buf, nbytes); if (ret != 0) { bfd_set_error (bfd_error_invalid_operation); return -1; } return nbytes; }
static int input_file_get (char *buf, int buflen) { int size; size = fread (buf, sizeof (char), buflen, f_in); if (size < 0) { #ifdef BFD_ASSEMBLER bfd_set_error (bfd_error_system_call); #endif as_perror (_("Can't read from %s"), file_name); size = 0; } return size; }
/* Returns 0 for success, negative value for failure (in which case bfd_get_error can retrieve the error code). */ int bfd_stat (bfd *abfd, struct stat *statbuf) { int result; if ((abfd->flags & BFD_IN_MEMORY) != 0) abort (); if (abfd->iovec) result = abfd->iovec->bstat (abfd, statbuf); else result = -1; if (result < 0) bfd_set_error (bfd_error_system_call); return result; }
static bfd_boolean elf32_sparc_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) { bfd *obfd = info->output_bfd; bfd_boolean error; unsigned long ibfd_mach; /* FIXME: This should not be static. */ static unsigned long previous_ibfd_e_flags = (unsigned long) -1; if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour || bfd_get_flavour (obfd) != bfd_target_elf_flavour) return TRUE; error = FALSE; ibfd_mach = bfd_get_mach (ibfd); if (bfd_mach_sparc_64bit_p (ibfd_mach)) { error = TRUE; _bfd_error_handler (_("%B: compiled for a 64 bit system and target is 32 bit"), ibfd); } else if ((ibfd->flags & DYNAMIC) == 0) { if (bfd_get_mach (obfd) < ibfd_mach) bfd_set_arch_mach (obfd, bfd_arch_sparc, ibfd_mach); } if (((elf_elfheader (ibfd)->e_flags & EF_SPARC_LEDATA) != previous_ibfd_e_flags) && previous_ibfd_e_flags != (unsigned long) -1) { _bfd_error_handler (_("%B: linking little endian files with big endian files"), ibfd); error = TRUE; } previous_ibfd_e_flags = elf_elfheader (ibfd)->e_flags & EF_SPARC_LEDATA; if (error) { bfd_set_error (bfd_error_bad_value); return FALSE; } return _bfd_sparc_elf_merge_private_bfd_data (ibfd, info); }
bfd * _bfd_new_bfd () { bfd *nbfd; nbfd = (bfd *) bfd_zmalloc ((bfd_size_type) sizeof (bfd)); if (nbfd == NULL) return NULL; nbfd->id = _bfd_id_counter++; nbfd->memory = (PTR) objalloc_create (); if (nbfd->memory == NULL) { bfd_set_error (bfd_error_no_memory); free (nbfd); return NULL; } nbfd->arch_info = &bfd_default_arch_struct; nbfd->direction = no_direction; nbfd->iostream = NULL; nbfd->where = 0; if (!bfd_hash_table_init_n (&nbfd->section_htab, bfd_section_hash_newfunc, 251)) { free (nbfd); return NULL; } nbfd->sections = (asection *) NULL; nbfd->section_tail = &nbfd->sections; nbfd->format = bfd_unknown; nbfd->my_archive = (bfd *) NULL; nbfd->origin = 0; nbfd->opened_once = FALSE; nbfd->output_has_begun = FALSE; nbfd->section_count = 0; nbfd->usrdata = (PTR) NULL; nbfd->cacheable = FALSE; nbfd->flags = BFD_NO_FLAGS; nbfd->mtime_set = FALSE; return nbfd; }
asection * bfd_make_section_old_way (bfd *abfd, const char *name) { asection *newsect; if (abfd->output_has_begun) { bfd_set_error (bfd_error_invalid_operation); return NULL; } if (strcmp (name, BFD_ABS_SECTION_NAME) == 0) newsect = bfd_abs_section_ptr; else if (strcmp (name, BFD_COM_SECTION_NAME) == 0) newsect = bfd_com_section_ptr; else if (strcmp (name, BFD_UND_SECTION_NAME) == 0) newsect = bfd_und_section_ptr; else if (strcmp (name, BFD_IND_SECTION_NAME) == 0) newsect = bfd_ind_section_ptr; else { struct section_hash_entry *sh; sh = section_hash_lookup (&abfd->section_htab, name, TRUE, FALSE); if (sh == NULL) return NULL; newsect = &sh->section; if (newsect->name != NULL) { /* Section already exists. */ return newsect; } newsect->name = name; return bfd_section_init (abfd, newsect); } /* Call new_section_hook when "creating" the standard abs, com, und and ind sections to tack on format specific section data. Also, create a proper section symbol. */ if (! BFD_SEND (abfd, _new_section_hook, (abfd, newsect))) return NULL; return newsect; }
bfd_size_type bfd_bread (void *ptr, bfd_size_type size, bfd *abfd) { size_t nread; /* If this is an archive element, don't read past the end of this element. */ if (abfd->arelt_data != NULL) { size_t maxbytes = ((struct areltdata *) abfd->arelt_data)->parsed_size; if (size > maxbytes) size = maxbytes; } if ((abfd->flags & BFD_IN_MEMORY) != 0) { struct bfd_in_memory *bim; bfd_size_type get; bim = abfd->iostream; get = size; if (abfd->where + get > bim->size) { if (bim->size < (bfd_size_type) abfd->where) get = 0; else get = bim->size - abfd->where; bfd_set_error (bfd_error_file_truncated); } memcpy (ptr, bim->buffer + abfd->where, (size_t) get); abfd->where += get; return get; } if (abfd->iovec) nread = abfd->iovec->bread (abfd, ptr, size); else nread = 0; if (nread != (size_t) -1) abfd->where += nread; return nread; }
static file_ptr memory_bread (bfd *abfd, void *ptr, file_ptr size) { struct bfd_in_memory *bim; bfd_size_type get; bim = (struct bfd_in_memory *) abfd->iostream; get = size; if (abfd->where + get > bim->size) { if (bim->size < (bfd_size_type) abfd->where) get = 0; else get = bim->size - abfd->where; bfd_set_error (bfd_error_file_truncated); } memcpy (ptr, bim->buffer + abfd->where, (size_t) get); return get; }
static void ldfile_open_command_file_1 (const char *name, bfd_boolean default_only) { FILE *ldlex_input_stack; ldlex_input_stack = ldfile_find_command_file (name, "", default_only); if (ldlex_input_stack == NULL) { bfd_set_error (bfd_error_system_call); einfo (_("%P%F: cannot open linker script file %s: %E\n"), name); } lex_push_file (ldlex_input_stack, name); ldfile_input_filename = name; lineno = 1; saved_script_handle = ldlex_input_stack; }
struct bfd_hash_entry * bfd_hash_lookup (struct bfd_hash_table *table, const char *string, bfd_boolean create, bfd_boolean copy) { unsigned long hash; struct bfd_hash_entry *hashp; unsigned int len; unsigned int _index; hash = bfd_hash_hash (string, &len); _index = hash % table->size; for (hashp = table->table[_index]; hashp != NULL; hashp = hashp->next) { if (hashp->hash == hash && strcmp (hashp->string, string) == 0) return hashp; } if (! create) return NULL; if (copy) { char *new_string; new_string = (char *) objalloc_alloc ((struct objalloc *) table->memory, len + 1); if (!new_string) { bfd_set_error (bfd_error_no_memory); return NULL; } memcpy (new_string, string, len + 1); string = new_string; } return bfd_hash_insert (table, string, hash); }
static bfd_boolean bfd_cache_delete (bfd *abfd) { bfd_boolean ret; if (fclose ((FILE *) abfd->iostream) == 0) ret = TRUE; else { ret = FALSE; bfd_set_error (bfd_error_system_call); } snip (abfd); abfd->iostream = NULL; --open_files; return ret; }
static bfd_boolean mcore_emit_base_file_entry (struct bfd_link_info *info, bfd *output_bfd, asection *input_section, bfd_vma reloc_offset) { bfd_vma addr = reloc_offset - input_section->vma + input_section->output_offset + input_section->output_section->vma; if (coff_data (output_bfd)->pe) addr -= pe_data (output_bfd)->pe_opthdr.ImageBase; if (fwrite (&addr, sizeof (addr), 1, (FILE *) info->base_file) == 1) return TRUE; bfd_set_error (bfd_error_system_call); return FALSE; }
long _bfd_generic_read_minisymbols (bfd *abfd, bfd_boolean dynamic, void **minisymsp, unsigned int *sizep) { long storage; asymbol **syms = NULL; long symcount; if (dynamic) storage = bfd_get_dynamic_symtab_upper_bound (abfd); else storage = bfd_get_symtab_upper_bound (abfd); if (storage < 0) goto error_return; if (storage == 0) return 0; syms = (asymbol **) bfd_malloc (storage); if (syms == NULL) goto error_return; if (dynamic) symcount = bfd_canonicalize_dynamic_symtab (abfd, syms); else symcount = bfd_canonicalize_symtab (abfd, syms); if (symcount < 0) goto error_return; *minisymsp = syms; *sizep = sizeof (asymbol *); return symcount; error_return: bfd_set_error (bfd_error_no_symbols); if (syms != NULL) free (syms); return -1; }
bfd_size_type bfd_bwrite (const void *ptr, bfd_size_type size, bfd *abfd) { size_t nwrote; if (abfd->iovec) nwrote = abfd->iovec->bwrite (abfd, ptr, size); else nwrote = 0; if (nwrote != (size_t) -1) abfd->where += nwrote; if (nwrote != size) { #ifdef ENOSPC errno = ENOSPC; #endif bfd_set_error (bfd_error_system_call); } return nwrote; }
bfd_boolean bfd_compress_section (bfd *abfd, sec_ptr sec, bfd_byte *uncompressed_buffer) { bfd_size_type uncompressed_size = sec->size; /* Error if not opened for write. */ if (abfd->direction != write_direction || uncompressed_size == 0 || uncompressed_buffer == NULL || sec->contents != NULL || sec->compressed_size != 0 || sec->compress_status != COMPRESS_SECTION_NONE) { bfd_set_error (bfd_error_invalid_operation); return FALSE; } /* Compress it. */ return bfd_compress_section_contents (abfd, sec, uncompressed_buffer, uncompressed_size) != 0; }
void as_perror (const char *gripe, /* Unpunctuated error theme. */ const char *filename) { const char *errtxt; int saved_errno = errno; as_show_where (); fprintf (stderr, gripe, filename); errno = saved_errno; #ifdef BFD_ASSEMBLER errtxt = bfd_errmsg (bfd_get_error ()); #else errtxt = xstrerror (errno); #endif fprintf (stderr, ": %s\n", errtxt); errno = 0; #ifdef BFD_ASSEMBLER bfd_set_error (bfd_error_no_error); #endif }
void * bfd_mmap (bfd *abfd, void *addr, bfd_size_type len, int prot, int flags, file_ptr offset, void **map_addr, bfd_size_type *map_len) { while (abfd->my_archive != NULL && !bfd_is_thin_archive (abfd->my_archive)) { offset += abfd->origin; abfd = abfd->my_archive; } if (abfd->iovec == NULL) { bfd_set_error (bfd_error_invalid_operation); return (void *) -1; } return abfd->iovec->bmmap (abfd, addr, len, prot, flags, offset, map_addr, map_len); }
static FILE * bfd_cache_lookup_worker (bfd *abfd, enum cache_flag flag) { bfd *orig_bfd = abfd; if ((abfd->flags & BFD_IN_MEMORY) != 0) abort (); while (abfd->my_archive != NULL && !bfd_is_thin_archive (abfd->my_archive)) abfd = abfd->my_archive; if (abfd->iostream != NULL) { /* Move the file to the start of the cache. */ if (abfd != bfd_last_cache) { snip (abfd); insert (abfd); } return (FILE *) abfd->iostream; } if (flag & CACHE_NO_OPEN) return NULL; if (bfd_open_file (abfd) == NULL) ; else if (!(flag & CACHE_NO_SEEK) && _bfd_real_fseek ((FILE *) abfd->iostream, abfd->where, SEEK_SET) != 0 && !(flag & CACHE_NO_SEEK_ERROR)) bfd_set_error (bfd_error_system_call); else return (FILE *) abfd->iostream; /* xgettext:c-format */ _bfd_error_handler (_("reopening %B: %s\n"), orig_bfd, bfd_errmsg (bfd_get_error ())); return NULL; }
sec_ptr bfd_make_section_anyway_with_flags (bfd *abfd, const char *name, flagword flags) { struct section_hash_entry *sh; asection *newsect; if (abfd->output_has_begun) { bfd_set_error (bfd_error_invalid_operation); return NULL; } sh = section_hash_lookup (&abfd->section_htab, name, TRUE, FALSE); if (sh == NULL) return NULL; newsect = &sh->section; if (newsect->name != NULL) { /* We are making a section of the same name. Put it in the section hash table. Even though we can't find it directly by a hash lookup, we'll be able to find the section by traversing sh->root.next quicker than looking at all the bfd sections. */ struct section_hash_entry *new_sh; new_sh = (struct section_hash_entry *) bfd_section_hash_newfunc (NULL, &abfd->section_htab, name); if (new_sh == NULL) return NULL; new_sh->root = sh->root; sh->root.next = &new_sh->root; newsect = &new_sh->section; } newsect->flags = flags; newsect->name = name; return bfd_section_init (abfd, newsect); }
bfd_boolean bfd_arm_merge_machines (bfd *ibfd, bfd *obfd) { unsigned int in = bfd_get_mach (ibfd); unsigned int out = bfd_get_mach (obfd); /* If the output architecture is unknown, we now have a value to set. */ if (out == bfd_mach_arm_unknown) bfd_set_arch_mach (obfd, bfd_arch_arm, in); /* If the input architecture is unknown, then so must be the output architecture. */ else if (in == bfd_mach_arm_unknown) /* FIXME: We ought to have some way to override this on the command line. */ bfd_set_arch_mach (obfd, bfd_arch_arm, bfd_mach_arm_unknown); /* If they are the same then nothing needs to be done. */ else if (out == in) ; /* Otherwise the general principle that a earlier architecture can be linked with a later architecture to produce a binary that will execute on the later architecture. We fail however if we attempt to link a Cirrus EP9312 binary with an Intel XScale binary, since these architecture have co-processors which will not both be present on the same physical hardware. */ else if (in == bfd_mach_arm_ep9312 && (out == bfd_mach_arm_XScale || out == bfd_mach_arm_iWMMXt || out == bfd_mach_arm_iWMMXt2)) { _bfd_error_handler (_("\ error: %B is compiled for the EP9312, whereas %B is compiled for XScale"), ibfd, obfd); bfd_set_error (bfd_error_wrong_format); return FALSE; }
asection * bfd_make_section_old_way (bfd *abfd, const char *name) { struct section_hash_entry *sh; asection *newsect; if (abfd->output_has_begun) { bfd_set_error (bfd_error_invalid_operation); return NULL; } if (strcmp (name, BFD_ABS_SECTION_NAME) == 0) return bfd_abs_section_ptr; if (strcmp (name, BFD_COM_SECTION_NAME) == 0) return bfd_com_section_ptr; if (strcmp (name, BFD_UND_SECTION_NAME) == 0) return bfd_und_section_ptr; if (strcmp (name, BFD_IND_SECTION_NAME) == 0) return bfd_ind_section_ptr; sh = section_hash_lookup (&abfd->section_htab, name, TRUE, FALSE); if (sh == NULL) return NULL; newsect = &sh->section; if (newsect->name != NULL) { /* Section already exists. */ return newsect; } newsect->name = name; return bfd_section_init (abfd, newsect); }
bfd_boolean bfd_set_format (bfd *abfd, bfd_format format) { if (bfd_read_p (abfd) || (unsigned int) abfd->format >= (unsigned int) bfd_type_end) { bfd_set_error (bfd_error_invalid_operation); return FALSE; } if (abfd->format != bfd_unknown) return abfd->format == format; /* Presume the answer is yes. */ abfd->format = format; if (!BFD_SEND_FMT (abfd, _bfd_set_format, (abfd))) { abfd->format = bfd_unknown; return FALSE; } return TRUE; }
bfd * _bfd_new_bfd (void) { bfd *nbfd; nbfd = (bfd *) bfd_zmalloc (sizeof (bfd)); if (nbfd == NULL) return NULL; if (bfd_use_reserved_id) { nbfd->id = --bfd_reserved_id_counter; --bfd_use_reserved_id; } else nbfd->id = bfd_id_counter++; nbfd->memory = objalloc_create (); if (nbfd->memory == NULL) { bfd_set_error (bfd_error_no_memory); free (nbfd); return NULL; } nbfd->arch_info = &bfd_default_arch_struct; if (!bfd_hash_table_init_n (& nbfd->section_htab, bfd_section_hash_newfunc, sizeof (struct section_hash_entry), 13)) { free (nbfd); return NULL; } return nbfd; }
static const bfd_target * aout_adobe_callback (bfd *abfd) { struct internal_exec *execp = exec_hdr (abfd); asection *sect; struct external_segdesc ext[1]; char *section_name; char try_again[30]; /* Name and number. */ char *newname; int trynum; flagword flags; /* Architecture and machine type -- unknown in this format. */ bfd_set_arch_mach (abfd, bfd_arch_unknown, 0L); /* The positions of the string table and symbol table. */ obj_str_filepos (abfd) = N_STROFF (*execp); obj_sym_filepos (abfd) = N_SYMOFF (*execp); /* Suck up the section information from the file, one section at a time. */ for (;;) { bfd_size_type amt = sizeof (*ext); if (bfd_bread ( ext, amt, abfd) != amt) { if (bfd_get_error () != bfd_error_system_call) bfd_set_error (bfd_error_wrong_format); return NULL; } switch (ext->e_type[0]) { case N_TEXT: section_name = ".text"; flags = SEC_CODE | SEC_LOAD | SEC_ALLOC | SEC_HAS_CONTENTS; break; case N_DATA: section_name = ".data"; flags = SEC_DATA | SEC_LOAD | SEC_ALLOC | SEC_HAS_CONTENTS; break; case N_BSS: section_name = ".bss"; flags = SEC_DATA | SEC_HAS_CONTENTS; break; case 0: goto no_more_sections; default: (*_bfd_error_handler) (_("%B: Unknown section type in a.out.adobe file: %x\n"), abfd, ext->e_type[0]); goto no_more_sections; } /* First one is called ".text" or whatever; subsequent ones are ".text1", ".text2", ... */ bfd_set_error (bfd_error_no_error); sect = bfd_make_section_with_flags (abfd, section_name, flags); trynum = 0; while (!sect) { if (bfd_get_error () != bfd_error_no_error) /* Some other error -- slide into the sunset. */ return NULL; sprintf (try_again, "%s%d", section_name, ++trynum); sect = bfd_make_section_with_flags (abfd, try_again, flags); } /* Fix the name, if it is a sprintf'd name. */ if (sect->name == try_again) { amt = strlen (sect->name); newname = bfd_zalloc (abfd, amt); if (newname == NULL) return NULL; strcpy (newname, sect->name); sect->name = newname; } /* Assumed big-endian. */ sect->size = ((ext->e_size[0] << 8) | ext->e_size[1] << 8 | ext->e_size[2]); sect->vma = H_GET_32 (abfd, ext->e_virtbase); sect->filepos = H_GET_32 (abfd, ext->e_filebase); /* FIXME XXX alignment? */ /* Set relocation information for first section of each type. */ if (trynum == 0) switch (ext->e_type[0]) { case N_TEXT: sect->rel_filepos = N_TRELOFF (*execp); sect->reloc_count = execp->a_trsize; break; case N_DATA: sect->rel_filepos = N_DRELOFF (*execp); sect->reloc_count = execp->a_drsize; break; default: break; } } no_more_sections: adata (abfd).reloc_entry_size = sizeof (struct reloc_std_external); adata (abfd).symbol_entry_size = sizeof (struct external_nlist); adata (abfd).page_size = 1; /* Not applicable. */ adata (abfd).segment_size = 1; /* Not applicable. */ adata (abfd).exec_bytes_size = EXEC_BYTES_SIZE; return abfd->xvec; }
static const bfd_target * irix_core_core_file_p (bfd *abfd) { int val; struct coreout coreout; struct idesc *idg, *idf, *ids; bfd_size_type amt; val = bfd_bread ((PTR) &coreout, (bfd_size_type) sizeof coreout, abfd); if (val != sizeof coreout) { if (bfd_get_error () != bfd_error_system_call) bfd_set_error (bfd_error_wrong_format); return 0; } if (coreout.c_version != CORE_VERSION1) return 0; /* Have we got a corefile? */ switch (coreout.c_magic) { case CORE_MAGIC: break; #ifdef CORE_MAGIC64 case CORE_MAGIC64: break; #endif #ifdef CORE_MAGICN32 case CORE_MAGICN32: break; #endif default: return 0; /* Un-identifiable or not corefile. */ } amt = sizeof (struct sgi_core_struct); core_hdr (abfd) = (struct sgi_core_struct *) bfd_zalloc (abfd, amt); if (!core_hdr (abfd)) return NULL; strncpy (core_command (abfd), coreout.c_name, CORE_NAMESIZE); core_signal (abfd) = coreout.c_sigcause; if (bfd_seek (abfd, coreout.c_vmapoffset, SEEK_SET) != 0) goto fail; /* Process corefile sections. */ #ifdef CORE_MAGIC64 if (coreout.c_magic == (int) CORE_MAGIC64) { if (! do_sections64 (abfd, & coreout)) goto fail; } else #endif if (! do_sections (abfd, & coreout)) goto fail; /* Make sure that the regs are contiguous within the core file. */ idg = &coreout.c_idesc[I_GPREGS]; idf = &coreout.c_idesc[I_FPREGS]; ids = &coreout.c_idesc[I_SPECREGS]; if (idg->i_offset + idg->i_len != idf->i_offset || idf->i_offset + idf->i_len != ids->i_offset) goto fail; /* Can't deal with non-contig regs */ if (bfd_seek (abfd, idg->i_offset, SEEK_SET) != 0) goto fail; if (!make_bfd_asection (abfd, ".reg", SEC_HAS_CONTENTS, idg->i_len + idf->i_len + ids->i_len, 0, idg->i_offset)) goto fail; /* OK, we believe you. You're a core file (sure, sure). */ bfd_default_set_arch_mach (abfd, bfd_arch_mips, 0); return abfd->xvec; fail: bfd_release (abfd, core_hdr (abfd)); core_hdr (abfd) = NULL; bfd_section_list_clear (abfd); return NULL; }
int main (int argc, char **argv) { char *emulation; long start_time = get_run_time (); #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) setlocale (LC_MESSAGES, ""); #endif #if defined (HAVE_SETLOCALE) setlocale (LC_CTYPE, ""); #endif bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); program_name = argv[0]; xmalloc_set_program_name (program_name); START_PROGRESS (program_name, 0); expandargv (&argc, &argv); bfd_init (); bfd_set_error_program_name (program_name); xatexit (ld_cleanup); /* Set up the sysroot directory. */ ld_sysroot = get_sysroot (argc, argv); if (*ld_sysroot) { if (*TARGET_SYSTEM_ROOT == 0) { einfo ("%P%F: this linker was not configured to use sysroots\n"); ld_sysroot = ""; } else ld_canon_sysroot = lrealpath (ld_sysroot); } if (ld_canon_sysroot) ld_canon_sysroot_len = strlen (ld_canon_sysroot); else ld_canon_sysroot_len = -1; /* Set the default BFD target based on the configured target. Doing this permits the linker to be configured for a particular target, and linked against a shared BFD library which was configured for a different target. The macro TARGET is defined by Makefile. */ if (! bfd_set_default_target (TARGET)) { einfo (_("%X%P: can't set BFD default target to `%s': %E\n"), TARGET); xexit (1); } #if YYDEBUG { extern int yydebug; yydebug = 1; } #endif config.build_constructors = TRUE; config.rpath_separator = ':'; config.split_by_reloc = (unsigned) -1; config.split_by_file = (bfd_size_type) -1; config.make_executable = TRUE; config.magic_demand_paged = TRUE; config.text_read_only = TRUE; command_line.warn_mismatch = TRUE; command_line.warn_search_mismatch = TRUE; command_line.check_section_addresses = -1; command_line.disable_target_specific_optimizations = -1; /* We initialize DEMANGLING based on the environment variable COLLECT_NO_DEMANGLE. The gcc collect2 program will demangle the output of the linker, unless COLLECT_NO_DEMANGLE is set in the environment. Acting the same way here lets us provide the same interface by default. */ demangling = getenv ("COLLECT_NO_DEMANGLE") == NULL; link_info.allow_undefined_version = TRUE; link_info.keep_memory = TRUE; link_info.combreloc = TRUE; link_info.strip_discarded = TRUE; link_info.emit_hash = TRUE; link_info.callbacks = &link_callbacks; link_info.input_bfds_tail = &link_info.input_bfds; /* SVR4 linkers seem to set DT_INIT and DT_FINI based on magic _init and _fini symbols. We are compatible. */ link_info.init_function = "_init"; link_info.fini_function = "_fini"; link_info.relax_pass = 1; link_info.pei386_auto_import = -1; link_info.spare_dynamic_tags = 5; link_info.path_separator = ':'; ldfile_add_arch (""); emulation = get_emulation (argc, argv); ldemul_choose_mode (emulation); default_target = ldemul_choose_target (argc, argv); config.maxpagesize = bfd_emul_get_maxpagesize (default_target); config.commonpagesize = bfd_emul_get_commonpagesize (default_target); lang_init (); ldemul_before_parse (); lang_has_input_file = FALSE; parse_args (argc, argv); if (config.hash_table_size != 0) bfd_hash_set_default_size (config.hash_table_size); ldemul_set_symbols (); if (link_info.relocatable) { if (command_line.check_section_addresses < 0) command_line.check_section_addresses = 0; if (link_info.shared) einfo (_("%P%F: -r and -shared may not be used together\n")); } /* We may have -Bsymbolic, -Bsymbolic-functions, --dynamic-list-data, --dynamic-list-cpp-new, --dynamic-list-cpp-typeinfo and --dynamic-list FILE. -Bsymbolic and -Bsymbolic-functions are for shared libraries. -Bsymbolic overrides all others and vice versa. */ switch (command_line.symbolic) { case symbolic_unset: break; case symbolic: /* -Bsymbolic is for shared library only. */ if (link_info.shared) { link_info.symbolic = TRUE; /* Should we free the unused memory? */ link_info.dynamic_list = NULL; command_line.dynamic_list = dynamic_list_unset; } break; case symbolic_functions: /* -Bsymbolic-functions is for shared library only. */ if (link_info.shared) command_line.dynamic_list = dynamic_list_data; break; } switch (command_line.dynamic_list) { case dynamic_list_unset: break; case dynamic_list_data: link_info.dynamic_data = TRUE; case dynamic_list: link_info.dynamic = TRUE; break; } if (! link_info.shared) { if (command_line.filter_shlib) einfo (_("%P%F: -F may not be used without -shared\n")); if (command_line.auxiliary_filters) einfo (_("%P%F: -f may not be used without -shared\n")); } if (! link_info.shared || link_info.pie) link_info.executable = TRUE; /* Treat ld -r -s as ld -r -S -x (i.e., strip all local symbols). I don't see how else this can be handled, since in this case we must preserve all externally visible symbols. */ if (link_info.relocatable && link_info.strip == strip_all) { link_info.strip = strip_debugger; if (link_info.discard == discard_sec_merge) link_info.discard = discard_all; } /* If we have not already opened and parsed a linker script, try the default script from command line first. */ if (saved_script_handle == NULL && command_line.default_script != NULL) { ldfile_open_command_file (command_line.default_script); parser_input = input_script; yyparse (); } /* If we have not already opened and parsed a linker script read the emulation's appropriate default script. */ if (saved_script_handle == NULL) { int isfile; char *s = ldemul_get_script (&isfile); if (isfile) ldfile_open_default_command_file (s); else { lex_string = s; lex_redirect (s); } parser_input = input_script; yyparse (); lex_string = NULL; } if (trace_file_tries) { if (saved_script_handle) info_msg (_("using external linker script:")); else info_msg (_("using internal linker script:")); info_msg ("\n==================================================\n"); if (saved_script_handle) { static const int ld_bufsz = 8193; size_t n; char *buf = (char *) xmalloc (ld_bufsz); rewind (saved_script_handle); while ((n = fread (buf, 1, ld_bufsz - 1, saved_script_handle)) > 0) { buf[n] = 0; info_msg (buf); } rewind (saved_script_handle); free (buf); } else { int isfile; info_msg (ldemul_get_script (&isfile)); } info_msg ("\n==================================================\n"); } lang_final (); if (!lang_has_input_file) { if (version_printed) xexit (0); einfo (_("%P%F: no input files\n")); } if (trace_files) info_msg (_("%P: mode %s\n"), emulation); ldemul_after_parse (); if (config.map_filename) { if (strcmp (config.map_filename, "-") == 0) { config.map_file = stdout; } else { config.map_file = fopen (config.map_filename, FOPEN_WT); if (config.map_file == (FILE *) NULL) { bfd_set_error (bfd_error_system_call); einfo (_("%P%F: cannot open map file %s: %E\n"), config.map_filename); } } } lang_process (); /* Print error messages for any missing symbols, for any warning symbols, and possibly multiple definitions. */ if (link_info.relocatable) link_info.output_bfd->flags &= ~EXEC_P; else link_info.output_bfd->flags |= EXEC_P; ldwrite (); if (config.map_file != NULL) lang_map (); if (command_line.cref) output_cref (config.map_file != NULL ? config.map_file : stdout); if (nocrossref_list != NULL) check_nocrossrefs (); lang_finish (); /* Even if we're producing relocatable output, some non-fatal errors should be reported in the exit status. (What non-fatal errors, if any, do we want to ignore for relocatable output?) */ if (!config.make_executable && !force_make_executable) { if (trace_files) einfo (_("%P: link errors found, deleting executable `%s'\n"), output_filename); /* The file will be removed by remove_output. */ xexit (1); } else { if (! bfd_close (link_info.output_bfd)) einfo (_("%F%B: final close failed: %E\n"), link_info.output_bfd); /* If the --force-exe-suffix is enabled, and we're making an executable file and it doesn't end in .exe, copy it to one which does. */ if (! link_info.relocatable && command_line.force_exe_suffix) { int len = strlen (output_filename); if (len < 4 || (strcasecmp (output_filename + len - 4, ".exe") != 0 && strcasecmp (output_filename + len - 4, ".dll") != 0)) { FILE *src; FILE *dst; const int bsize = 4096; char *buf = (char *) xmalloc (bsize); int l; char *dst_name = (char *) xmalloc (len + 5); strcpy (dst_name, output_filename); strcat (dst_name, ".exe"); src = fopen (output_filename, FOPEN_RB); dst = fopen (dst_name, FOPEN_WB); if (!src) einfo (_("%X%P: unable to open for source of copy `%s'\n"), output_filename); if (!dst) einfo (_("%X%P: unable to open for destination of copy `%s'\n"), dst_name); while ((l = fread (buf, 1, bsize, src)) > 0) { int done = fwrite (buf, 1, l, dst); if (done != l) einfo (_("%P: Error writing file `%s'\n"), dst_name); } fclose (src); if (fclose (dst) == EOF) einfo (_("%P: Error closing file `%s'\n"), dst_name); free (dst_name); free (buf); } } } END_PROGRESS (program_name); if (config.stats) { #ifdef HAVE_SBRK char *lim = (char *) sbrk (0); #endif long run_time = get_run_time () - start_time; fflush (stdout); fprintf (stderr, _("%s: total time in link: %ld.%06ld\n"), program_name, run_time / 1000000, run_time % 1000000); #ifdef HAVE_SBRK fprintf (stderr, _("%s: data size %ld\n"), program_name, (long) (lim - (char *) &environ)); #endif fflush (stderr); } /* Prevent remove_output from doing anything, after a successful link. */ output_filename = NULL; xexit (0); return 0; }