X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Fbfd.c;h=6b4d4473edbceac01e8b06a2b7857142681c9529;hb=a643e6260e2b817cffecd200214b1fceee802ab8;hp=dd2d45d2fd88f366faa0d6ccc4c56072863ec177;hpb=fc7233808a1d88db99a5181e1ee0f6865f8f5206;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/bfd.c b/bfd/bfd.c index dd2d45d2fd..6b4d4473ed 100644 --- a/bfd/bfd.c +++ b/bfd/bfd.c @@ -1,105 +1,289 @@ - /* -*- C -*- */ +/* Generic BFD library interface and support routines. + Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Written by Cygnus Support. -/*** bfd -- binary file diddling routines by Gumby Wallace of Cygnus Support. - Every definition in this file should be exported and declared - in bfd.c. If you don't want it to be user-visible, put it in - libbfd.c! -*/ - -/* Copyright (C) 1990, 1991 Free Software Foundation, Inc. - -This file is part of BFD, the Binary File Diddler. +This file is part of BFD, the Binary File Descriptor library. -BFD is free software; you can redistribute it and/or modify +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 1, or (at your option) -any later version. +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. -BFD is distributed in the hope that it will be useful, +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with BFD; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* +SECTION + <> + + A BFD is has type <>; objects of this type are the + cornerstone of any application using <>. References + though the BFD and to data in the BFD give the entire BFD + functionality. + + Here is the struct used to define the type <>. This + contains the major data about the file, and contains pointers + to the rest of the data. + +CODE_FRAGMENT +. +.struct _bfd +.{ +. {* The filename the application opened the BFD with. *} +. CONST char *filename; +. +. {* A pointer to the target jump table. *} +. struct bfd_target *xvec; +. +. {* To avoid dragging too many header files into every file that +. includes `<>', IOSTREAM has been declared as a "char +. *", and MTIME as a "long". Their correct types, to which they +. are cast when used, are "FILE *" and "time_t". The iostream +. is the result of an fopen on the filename. *} +. char *iostream; +. +. {* Is the file being cached *} +. +. boolean cacheable; +. +. {* Marks whether there was a default target specified when the +. BFD was opened. This is used to select what matching algorithm +. to use to chose the back end. *} +. +. boolean target_defaulted; +. +. {* The caching routines use these to maintain a +. least-recently-used list of BFDs *} +. +. struct _bfd *lru_prev, *lru_next; +. +. {* When a file is closed by the caching routines, BFD retains +. state information on the file here: +. *} +. +. file_ptr where; +. +. {* and here:*} +. +. boolean opened_once; +. +. {* Set if we have a locally maintained mtime value, rather than +. getting it from the file each time: *} +. +. boolean mtime_set; +. +. {* File modified time, if mtime_set is true: *} +. +. long mtime; +. +. {* Reserved for an unimplemented file locking extension.*} +. +. int ifd; +. +. {* The format which belongs to the BFD.*} +. +. bfd_format format; +. +. {* The direction the BFD was opened with*} +. +. enum bfd_direction {no_direction = 0, +. read_direction = 1, +. write_direction = 2, +. both_direction = 3} direction; +. +. {* Format_specific flags*} +. +. flagword flags; +. +. {* Currently my_archive is tested before adding origin to +. anything. I believe that this can become always an add of +. origin, with origin set to 0 for non archive files. *} +. +. file_ptr origin; +. +. {* Remember when output has begun, to stop strange things +. happening. *} +. boolean output_has_begun; +. +. {* Pointer to linked list of sections*} +. struct sec *sections; +. +. {* The number of sections *} +. unsigned int section_count; +. +. {* Stuff only useful for object files: +. The start address. *} +. bfd_vma start_address; +. +. {* Used for input and output*} +. unsigned int symcount; +. +. {* Symbol table for output BFD*} +. struct symbol_cache_entry **outsymbols; +. +. {* Pointer to structure which contains architecture information*} +. struct bfd_arch_info *arch_info; +. +. {* Stuff only useful for archives:*} +. PTR arelt_data; +. struct _bfd *my_archive; +. struct _bfd *next; +. struct _bfd *archive_head; +. boolean has_armap; +. +. {* Used by the back end to hold private data. *} +. +. union +. { +. struct aout_data_struct *aout_data; +. struct artdata *aout_ar_data; +. struct _oasys_data *oasys_obj_data; +. struct _oasys_ar_data *oasys_ar_data; +. struct coff_tdata *coff_obj_data; +. struct ecoff_tdata *ecoff_obj_data; +. struct ieee_data_struct *ieee_data; +. struct ieee_ar_data_struct *ieee_ar_data; +. struct srec_data_struct *srec_data; +. struct tekhex_data_struct *tekhex_data; +. struct elf_obj_tdata *elf_obj_data; +. struct nlm_obj_tdata *nlm_obj_data; +. struct bout_data_struct *bout_data; +. struct sun_core_struct *sun_core_data; +. struct trad_core_struct *trad_core_data; +. struct hppa_data_struct *hppa_data; +. struct hpux_core_struct *hpux_core_data; +. struct sgi_core_struct *sgi_core_data; +. PTR any; +. } tdata; +. +. {* Used by the application to hold private data*} +. PTR usrdata; +. +. {* Where all the allocated stuff under this BFD goes *} +. struct obstack memory; +. +. {* Is this really needed in addition to usrdata? *} +. asymbol **ld_symbols; +.}; +. +*/ -/* $Id$ */ -#include "sysdep.h" #include "bfd.h" +#include "sysdep.h" #include "libbfd.h" +#include "coff/sym.h" +#include "libecoff.h" + +#undef strerror +extern char *strerror(); + -short _bfd_host_big_endian = 0x0100; - /* Accessing the above as (*(char*)&_bfd_host_big_endian), will - return 1 if the host is big-endian, 0 otherwise. - (assuming that a short is two bytes long!!! FIXME) - (See HOST_IS_BIG_ENDIAN_P in bfd.h.) */ +CONST short _bfd_host_big_endian = 0x0100; + /* Accessing the above as (*(char*)&_bfd_host_big_endian), will + return 1 if the host is big-endian, 0 otherwise. + (assuming that a short is two bytes long!!! FIXME) + (See HOST_IS_BIG_ENDIAN_P in bfd.h.) */ /** Error handling o - Most functions return nonzero on success (check doc for - precise semantics); 0 or NULL on error. + precise semantics); 0 or NULL on error. o - Internal errors are documented by the value of bfd_error. - If that is system_call_error then check errno. + If that is system_call_error then check errno. o - The easiest way to report this to the user is to use bfd_perror. */ bfd_ec bfd_error = no_error; -char *bfd_errmsgs[] = { "No error", - "System call error", - "Invalid target", - "File in wrong format", - "Invalid operation", - "Memory exhausted", - "No symbols", - "No relocation info", - "No more archived files", - "Malformed archive", - "Symbol not found", - "File format not recognized", - "File format is ambiguous", - "Section has no contents", - "Nonrepresentable section on output", - "#" - }; +CONST char *CONST bfd_errmsgs[] = { + "No error", + "System call error", + "Invalid target", + "File in wrong format", + "Invalid operation", + "Memory exhausted", + "No symbols", + "No relocation info", + "No more archived files", + "Malformed archive", + "Symbol not found", + "File format not recognized", + "File format is ambiguous", + "Section has no contents", + "Nonrepresentable section on output", + "Symbol needs debug section which does not exist", + "Bad value", + "File truncated", + "#" + }; static void DEFUN(bfd_nonrepresentable_section,(abfd, name), - CONST bfd * CONST abfd AND - CONST char * CONST name) + CONST bfd * CONST abfd AND + CONST char * CONST name) { printf("bfd error writing file %s, format %s can't represent section %s\n", - abfd->filename, - abfd->xvec->name, - name); + abfd->filename, + abfd->xvec->name, + name); + exit(1); +} + +/*ARGSUSED*/ +static +void +DEFUN(bfd_undefined_symbol,(relent, seclet), + CONST arelent *relent AND + CONST struct bfd_seclet *seclet) +{ + asymbol *symbol = *(relent->sym_ptr_ptr); + printf("bfd error relocating, symbol %s is undefined\n", + symbol->name); + exit(1); +} +/*ARGSUSED*/ +static +void +DEFUN(bfd_reloc_value_truncated,(relent, seclet), + CONST arelent *relent AND + struct bfd_seclet *seclet) +{ + printf("bfd error relocating, value truncated\n"); + exit(1); +} +/*ARGSUSED*/ +static +void +DEFUN(bfd_reloc_is_dangerous,(relent, seclet), + CONST arelent *relent AND + CONST struct bfd_seclet *seclet) +{ + printf("bfd error relocating, dangerous\n"); exit(1); } bfd_error_vector_type bfd_error_vector = { - bfd_nonrepresentable_section + bfd_nonrepresentable_section , + bfd_undefined_symbol, + bfd_reloc_value_truncated, + bfd_reloc_is_dangerous, }; -#if !defined(ANSI_LIBRARIES) -char * -strerror (code) - int code; -{ - extern int sys_nerr; - extern char *sys_errlist[]; - - return (((code < 0) || (code >= sys_nerr)) ? "(unknown error)" : - sys_errlist [code]); -} -#endif /* not ANSI_LIBRARIES */ - -char * +CONST char * bfd_errmsg (error_tag) bfd_ec error_tag; { - +#ifndef errno + extern int errno; +#endif if (error_tag == system_call_error) return strerror (errno); @@ -110,22 +294,22 @@ bfd_errmsg (error_tag) return bfd_errmsgs [(int)error_tag]; } - -void bfd_default_error_trap(error_tag) -bfd_ec error_tag; +void +DEFUN (bfd_default_error_trap, (error_tag), + bfd_ec error_tag) { printf("bfd assert fail (%s)\n", bfd_errmsg(error_tag)); } -void (*bfd_error_trap)() = bfd_default_error_trap; -void (*bfd_error_nonrepresentabltrap)() = bfd_default_error_trap; +void (*bfd_error_trap) PARAMS ((bfd_ec)) = bfd_default_error_trap; +void (*bfd_error_nonrepresentabltrap) PARAMS ((bfd_ec)) = bfd_default_error_trap; void DEFUN(bfd_perror,(message), CONST char *message) { if (bfd_error == system_call_error) - perror((char *)message); /* must be system error then... */ + perror((char *)message); /* must be system error then... */ else { if (message == NULL || *message == '\0') fprintf (stderr, "%s\n", bfd_errmsg (bfd_error)); @@ -134,456 +318,98 @@ DEFUN(bfd_perror,(message), } } -/* for error messages */ -char * -bfd_format_string (format) - bfd_format format; -{ - if (((int)format <(int) bfd_unknown) || ((int)format >=(int) bfd_type_end)) return "invalid"; - - switch (format) { - case bfd_object: return "object"; /* linker/assember/compiler output */ - case bfd_archive: return "archive"; /* object archive file */ - case bfd_core: return "core"; /* core dump */ - default: return "unknown"; - } -} - -/** Target configurations */ - -extern bfd_target *target_vector[]; - -/* Returns a pointer to the transfer vector for the object target - named target_name. If target_name is NULL, chooses the one in the - environment variable GNUTARGET; if that is null or not defined then - the first entry in the target list is chosen. Passing in the - string "default" or setting the environment variable to "default" - will cause the first entry in the target list to be returned. */ - -bfd_target * -DEFUN(bfd_find_target,(target_name), - CONST char *target_name) -{ - bfd_target **target; - extern char *getenv (); - CONST char *targname = (target_name ? target_name : getenv ("GNUTARGET")); - - /* This is safe; the vector cannot be null */ - if (targname == NULL || !strcmp (targname, "default")) - return target_vector[0]; - - for (target = &target_vector[0]; *target != NULL; target++) { - if (!strcmp (targname, (*target)->name)) - return *target; - } - - bfd_error = invalid_target; - return NULL; -} - -/* Returns a freshly-consed, NULL-terminated vector of the names of all the - valid bfd targets. Do not modify the names */ - -char ** -bfd_target_list () -{ - int vec_length= 0; - bfd_target **target; - char **name_list, **name_ptr; - - for (target = &target_vector[0]; *target != NULL; target++) - vec_length++; - - name_ptr = name_list = (char **) zalloc ((vec_length + 1) * sizeof (char **)); - - if (name_list == NULL) { - bfd_error = no_memory; - return NULL; - } - - for (target = &target_vector[0]; *target != NULL; target++) - *(name_ptr++) = (*target)->name; - - return name_list; -} - -/** Init a bfd for read of the proper format. - */ - -/* We should be able to find out if the target was defaulted or user-specified. - If the user specified the target explicitly then we should do no search. - I guess the best way to do this is to pass an extra argument which specifies - the DWIM. */ - -/* I have chanegd this always to set the filepos to the origin before - guessing. -- Gumby, 14 Februar 1991*/ - -boolean -bfd_check_format (abfd, format) - bfd *abfd; - bfd_format format; -{ - bfd_target **target, *save_targ, *right_targ; - int match_count; - - if (!bfd_read_p (abfd) || - ((int)(abfd->format) < (int)bfd_unknown) || - ((int)(abfd->format) >= (int)bfd_type_end)) { - bfd_error = invalid_operation; - return false; - } - - if (abfd->format != bfd_unknown) return (abfd->format == format) ? true:false; - - /* presume the answer is yes */ - abfd->format = format; - - bfd_seek (abfd, (file_ptr)0, SEEK_SET); /* rewind! */ - - right_targ = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd)); - if (right_targ) { - abfd->xvec = right_targ; /* Set the target as returned */ - return true; /* File position has moved, BTW */ - } - - /* This isn't a file in the specified or defaulted target type. - See if we recognize it for any other target type. (We check them - all to make sure it's uniquely recognized.) */ - - save_targ = abfd->xvec; - match_count = 0; - right_targ = 0; - - for (target = target_vector; *target != NULL; target++) { - bfd_target *temp; - - abfd->xvec = *target; /* Change BFD's target temporarily */ - bfd_seek (abfd, (file_ptr)0, SEEK_SET); - temp = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd)); - if (temp) { /* This format checks out as ok! */ - right_targ = temp; - match_count++; -#ifdef GNU960 - /* Big- and little-endian b.out archives look the same, but it doesn't - * matter: there is no difference in their headers, and member file byte - * orders will (I hope) be handled appropriately by bfd. Ditto for big - * and little coff archives. And the 4 coff/b.out object formats are - * unambiguous. So accept the first match we find. - */ - break; -#endif - } - } - - if (match_count == 1) { - abfd->xvec = right_targ; /* Change BFD's target permanently */ - return true; /* File position has moved, BTW */ - } - - abfd->xvec = save_targ; /* Restore original target type */ - abfd->format = bfd_unknown; /* Restore original format */ - bfd_error = ((match_count == 0) ? file_not_recognized : - file_ambiguously_recognized); - return false; -} - -boolean -bfd_set_format (abfd, format) - bfd *abfd; - bfd_format format; -{ - - if (bfd_read_p (abfd) || - ((int)abfd->format < (int)bfd_unknown) || - ((int)abfd->format >= (int)bfd_type_end)) { - bfd_error = invalid_operation; - return false; - } - - if (abfd->format != bfd_unknown) return (abfd->format == format) ? true:false; - - /* 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; -} - -/* Hack object and core file sections */ - -sec_ptr -DEFUN(bfd_get_section_by_name,(abfd, name), - bfd *abfd AND - CONST char *name) -{ - asection *sect; - - for (sect = abfd->sections; sect != NULL; sect = sect->next) - if (!strcmp (sect->name, name)) return sect; - return NULL; -} - -/* If you try to create a section with a name which is already in use, - returns the old section by that name instead. */ -sec_ptr -DEFUN(bfd_make_section,(abfd, name), - bfd *abfd AND - CONST char *name) -{ - asection *newsect; - asection ** prev = &abfd->sections; - asection * sect = abfd->sections; - - if (abfd->output_has_begun) { - bfd_error = invalid_operation; - return NULL; - } - - while (sect) { - if (!strcmp(sect->name, name)) return sect; - prev = §->next; - sect = sect->next; - } - - newsect = (asection *) bfd_zalloc(abfd, sizeof (asection)); - if (newsect == NULL) { - bfd_error = no_memory; - return NULL; - } - - newsect->name = name; - newsect->index = abfd->section_count++; - newsect->flags = SEC_NO_FLAGS; - - newsect->userdata = 0; - newsect->next = (asection *)NULL; - newsect->relocation = (arelent *)NULL; - newsect->reloc_count = 0; - newsect->line_filepos =0; - - if (BFD_SEND (abfd, _new_section_hook, (abfd, newsect)) != true) { - free (newsect); - return NULL; - } + +/** Symbols */ - *prev = newsect; - return newsect; -} -/* Call operation on each section. Operation gets three args: the bfd, - the section, and a void * pointer (whatever the user supplied). */ +/* +FUNCTION + bfd_get_reloc_upper_bound -/* This is attractive except that without lexical closures its use is hard - to make reentrant. */ -/*VARARGS2*/ -void -bfd_map_over_sections (abfd, operation, user_storage) - bfd *abfd; - void (*operation)(); - PTR user_storage; -{ - asection *sect; - int i = 0; - - for (sect = abfd->sections; sect != NULL; i++, sect = sect->next) - (*operation) (abfd, sect, user_storage); - - if (i != abfd->section_count) /* Debugging */ - abort(); -} +SYNOPSIS + unsigned int bfd_get_reloc_upper_bound(bfd *abfd, asection *sect); -boolean -bfd_set_section_flags (abfd, section, flags) - bfd *abfd; - sec_ptr section; - flagword flags; -{ - if ((flags & bfd_applicable_section_flags (abfd)) != flags) { - bfd_error = invalid_operation; - return false; - } +DESCRIPTION + This function return the number of bytes required to store the + relocation information associated with section <> + attached to bfd <> - section->flags = flags; -return true; -} +*/ -boolean -bfd_set_section_size (abfd, ptr, val) - bfd *abfd; - sec_ptr ptr; - unsigned long val; +unsigned int +DEFUN(bfd_get_reloc_upper_bound,(abfd, asect), + bfd *abfd AND + sec_ptr asect) { - /* Once you've started writing to any section you cannot create or change - the size of any others. */ - - if (abfd->output_has_begun) { + if (abfd->format != bfd_object) { bfd_error = invalid_operation; - return false; - } - - ptr->size = val; - - return true; -} - -boolean -bfd_set_section_contents (abfd, section, location, offset, count) - bfd *abfd; - sec_ptr section; - PTR location; - file_ptr offset; - int count; -{ - if (!(bfd_get_section_flags(abfd, section) & - SEC_HAS_CONTENTS)) { - bfd_error = no_contents; - return(false); - } /* if section has no contents */ - - if (BFD_SEND (abfd, _bfd_set_section_contents, - (abfd, section, location, offset, count))) { - abfd->output_has_begun = true; - return true; - } - - return false; -} - -boolean -bfd_get_section_contents (abfd, section, location, offset, count) - bfd *abfd; - sec_ptr section; - PTR location; - file_ptr offset; - int count; -{ - if (section->flags & SEC_CONSTRUCTOR) { - memset(location, 0, count); - return true; - } - else { - return (BFD_SEND (abfd, _bfd_get_section_contents, - (abfd, section, location, offset, count))); + return 0; } -} - - -/** Some core file info commands */ - -/* Returns a read-only string explaining what program was running when - it failed. */ -char * -bfd_core_file_failing_command (abfd) - bfd *abfd; -{ - if (abfd->format != bfd_core) { - bfd_error = invalid_operation; - return NULL; - } - return BFD_SEND (abfd, _core_file_failing_command, (abfd)); + return BFD_SEND (abfd, _get_reloc_upper_bound, (abfd, asect)); } -int -bfd_core_file_failing_signal (abfd) - bfd *abfd; -{ - if (abfd->format != bfd_core) { - bfd_error = invalid_operation; - return NULL; - } - return BFD_SEND (abfd, _core_file_failing_signal, (abfd)); -} +/* +FUNCTION + bfd_canonicalize_reloc -boolean -core_file_matches_executable_p (core_bfd, exec_bfd) - bfd *core_bfd, *exec_bfd; -{ - if ((core_bfd->format != bfd_core) || (exec_bfd->format != bfd_object)) { - bfd_error = wrong_format; - return false; - } +SYNOPSIS + unsigned int bfd_canonicalize_reloc + (bfd *abfd, + asection *sec, + arelent **loc, + asymbol **syms); - return BFD_SEND (core_bfd, _core_file_matches_executable_p, (core_bfd, exec_bfd)); -} - -/** Symbols */ +DESCRIPTION + This function calls the back end associated with the open + <> and translates the external form of the relocation + information attached to <> into the internal canonical + form. The table is placed into memory at <>, which has + been preallocated, usually by a call to + <>. -boolean -bfd_set_symtab (abfd, location, symcount) - bfd *abfd; - asymbol **location; - unsigned int symcount; -{ - if ((abfd->format != bfd_object) || (bfd_read_p (abfd))) { - bfd_error = invalid_operation; - return false; - } + The <> table is also needed for horrible internal magic + reasons. - bfd_get_outsymbols (abfd) = location; - bfd_get_symcount (abfd) = symcount; - return true; -} -/* returns the number of octets of storage required */ +*/ unsigned int -get_reloc_upper_bound (abfd, asect) - bfd *abfd; - sec_ptr asect; +DEFUN(bfd_canonicalize_reloc,(abfd, asect, location, symbols), + bfd *abfd AND + sec_ptr asect AND + arelent **location AND + asymbol **symbols) { - if (abfd->format != bfd_object) { - bfd_error = invalid_operation; - return 0; + if (abfd->format != bfd_object) { + bfd_error = invalid_operation; + return 0; + } + return BFD_SEND (abfd, _bfd_canonicalize_reloc, + (abfd, asect, location, symbols)); } - return BFD_SEND (abfd, _get_reloc_upper_bound, (abfd, asect)); -} -unsigned int -bfd_canonicalize_reloc (abfd, asect, location, symbols) - bfd *abfd; - sec_ptr asect; - arelent **location; - asymbol **symbols; -{ - if (abfd->format != bfd_object) { - bfd_error = invalid_operation; - return 0; - } +/* +FUNCTION + bfd_set_file_flags - return BFD_SEND (abfd, _bfd_canonicalize_reloc, (abfd, asect, location, symbols)); -} +SYNOPSIS + boolean bfd_set_file_flags(bfd *abfd, flagword flags); -void -bfd_print_symbol_vandf(file, symbol) -PTR file; -asymbol *symbol; -{ - flagword type = symbol->flags; - if (symbol->section != (asection *)NULL) - { - fprintf(file,"%08lx ", symbol->value+symbol->section->vma); - } - else - { - fprintf(file,"%08lx ", symbol->value); - } - fprintf(file,"%c%c%c%c%c%c%c", - (type & BSF_LOCAL) ? 'l':' ', - (type & BSF_GLOBAL) ? 'g' : ' ', - (type & BSF_IMPORT) ? 'i' : ' ', - (type & BSF_EXPORT) ? 'e' : ' ', - (type & BSF_UNDEFINED) ? 'u' : ' ', - (type & BSF_FORT_COMM) ? 'c' : ' ', - (type & BSF_DEBUGGING) ? 'd' :' '); +DESCRIPTION + This function attempts to set the flag word in the referenced + BFD structure to the value supplied. -} + Possible errors are: + o wrong_format - The target bfd was not of object format. + o invalid_operation - The target bfd was open for reading. + o invalid_operation - + The flag word contained a bit which was not applicable to the + type of file. eg, an attempt was made to set the D_PAGED bit + on a bfd format which does not support demand paging +*/ boolean bfd_set_file_flags (abfd, flags) @@ -600,16 +426,29 @@ bfd_set_file_flags (abfd, flags) return false; } + bfd_get_file_flags (abfd) = flags; if ((flags & bfd_applicable_file_flags (abfd)) != flags) { bfd_error = invalid_operation; return false; } - bfd_get_file_flags (abfd) = flags; return true; } +/* +FUNCTION + bfd_set_reloc + +SYNOPSIS + void bfd_set_reloc + (bfd *abfd, asection *sec, arelent **rel, unsigned int count) + +DESCRIPTION + This function sets the relocation pointer and count within a + section to the supplied values. +*/ +/*ARGSUSED*/ void bfd_set_reloc (ignore_abfd, asect, location, count) bfd *ignore_abfd; @@ -620,257 +459,6 @@ bfd_set_reloc (ignore_abfd, asect, location, count) asect->orelocation = location; asect->reloc_count = count; } -/* -If an output_bfd is supplied to this function the generated image -will be relocatable, the relocations are copied to the output file -after they have been changed to reflect the new state of the world. -There are two ways of reflecting the results of partial linkage in an -output file; by modifying the output data in place, and by modifying -the relocation record. Some native formats (eg basic a.out and basic -coff) have no way of specifying an addend in the relocation type, so -the addend has to go in the output data. This is no big deal since in -these formats the output data slot will always be big enough for the -addend. Complex reloc types with addends were invented to solve just -this problem. -*/ - -bfd_reloc_status_enum_type -bfd_perform_relocation(abfd, - reloc_entry, - data, - input_section, - output_bfd) -bfd *abfd; -arelent *reloc_entry; -PTR data; -asection *input_section; -bfd *output_bfd; -{ - bfd_vma relocation; - bfd_reloc_status_enum_type flag = bfd_reloc_ok; - bfd_vma relocation_before; - bfd_vma addr = reloc_entry->address ; - bfd_vma output_base = 0; - reloc_howto_type *howto = reloc_entry->howto; - asection *reloc_target_output_section; - asection *reloc_target_input_section; - asymbol *symbol; - - if (reloc_entry->sym_ptr_ptr) { - symbol = *( reloc_entry->sym_ptr_ptr); - if ((symbol->flags & BSF_UNDEFINED) && output_bfd == (bfd *)NULL) { - flag = bfd_reloc_undefined; - } - } - else { - symbol = (asymbol*)NULL; - } - - if (howto->special_function){ - bfd_reloc_status_enum_type cont; - cont = howto->special_function(abfd, - reloc_entry, - symbol, - data, - input_section); - if (cont != bfd_reloc_continue) return cont; - } - - /* - Work out which section the relocation is targetted at and the - initial relocation command value. - */ - - - if (symbol != (asymbol *)NULL){ - if (symbol->flags & BSF_FORT_COMM) { - relocation = 0; - } - else { - relocation = symbol->value; - } - if (symbol->section != (asection *)NULL) - { - reloc_target_input_section = symbol->section; - } - else { - reloc_target_input_section = (asection *)NULL; - } - } - else if (reloc_entry->section != (asection *)NULL) - { - relocation = 0; - reloc_target_input_section = reloc_entry->section; - } - else { - relocation = 0; - reloc_target_input_section = (asection *)NULL; - } - - - if (reloc_target_input_section != (asection *)NULL) { - - reloc_target_output_section = - reloc_target_input_section->output_section; - - if (output_bfd && howto->partial_inplace==false) { - output_base = 0; - } - else { - output_base = reloc_target_output_section->vma; - - } - - relocation += output_base + reloc_target_input_section->output_offset; - } - - relocation += reloc_entry->addend ; - - - if(reloc_entry->address > (bfd_vma)(input_section->size)) - { - return bfd_reloc_outofrange; - } - - - if (howto->pc_relative == true) - { - /* - Anything which started out as pc relative should end up that - way too. - - There are two ways we can see a pcrel instruction. Sometimes - the pcrel displacement has been partially calculated, it - includes the distance from the start of the section to the - instruction in it (eg sun3), and sometimes the field is - totally blank - eg m88kbcs. - */ - - - relocation -= - output_base + input_section->output_offset; - - if (howto->pcrel_offset == true) { - relocation -= reloc_entry->address; - } - - } - - if (output_bfd!= (bfd *)NULL) { - if ( howto->partial_inplace == false) { - /* - This is a partial relocation, and we want to apply the relocation - to the reloc entry rather than the raw data. Modify the reloc - inplace to reflect what we now know. - */ - reloc_entry->addend = relocation ; - reloc_entry->section = reloc_target_input_section; - if (reloc_target_input_section != (asection *)NULL) { - /* If we know the output section we can forget the symbol */ - reloc_entry->sym_ptr_ptr = (asymbol**)NULL; - } - reloc_entry->address += - input_section->output_offset; - return flag; - } - else - { - /* This is a partial relocation, but inplace, so modify the - reloc record a bit - */ - - } - } - - reloc_entry->addend = 0; - - - /* - Either we are relocating all the way, or we don't want to apply - the relocation to the reloc entry (probably because there isn't - any room in the output format to describe addends to relocs) - */ - relocation >>= howto->rightshift; - - /* Shift everything up to where it's going to be used */ - - relocation <<= howto->bitpos; - - - /* Wait for the day when all have the mask in them */ - - - - relocation_before = relocation; - - - /* What we do: - i instruction to be left alone - o offset within instruction - r relocation offset to apply - S src mask - D dst mask - N ~dst mask - A part 1 - B part 2 - R result - - Do this: - i i i i i o o o o o from bfd_get - and S S S S S to get the size offset we want - + r r r r r r r r r r to get the final value to place - and D D D D D to chop to right size - ----------------------- - A A A A A - And this: - ... i i i i i o o o o o from bfd_get - and N N N N N get instruction - ----------------------- - ... B B B B B - - And then: - B B B B B - or A A A A A - ----------------------- - R R R R R R R R R R put into bfd_put - */ - -#define DOIT(x) \ - x = ( (x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask)) - - switch (howto->size) - { - case 0: - { - char x = bfd_getchar(abfd, (char *)data + addr); - DOIT(x); - bfd_putchar(abfd,x, (unsigned char *) data + addr); - } - break; - - case 1: - { - short x = bfd_getshort(abfd, (bfd_byte *)data + addr); - DOIT(x); - bfd_putshort(abfd, x, (unsigned char *)data + addr); - } - break; - case 2: - { - long x = bfd_getlong(abfd, (bfd_byte *) data + addr); - DOIT(x); - bfd_putlong(abfd,x, (bfd_byte *)data + addr); - } - break; - case 3: - /* Do nothing */ - break; - default: - return bfd_reloc_other; - } - - return flag; -} void bfd_assert(file, line) @@ -881,6 +469,20 @@ int line; } +/* +FUNCTION + bfd_set_start_address + +DESCRIPTION + Marks the entry point of an output BFD. + +RETURNS + Returns <> on success, <> otherwise. + +SYNOPSIS + boolean bfd_set_start_address(bfd *, bfd_vma); +*/ + boolean bfd_set_start_address(abfd, vma) bfd *abfd; @@ -891,19 +493,18 @@ bfd_vma vma; } -bfd_vma bfd_log2(x) -bfd_vma x; -{ - bfd_vma result = 0; - while ( (bfd_vma)(1<< result) < x) - result++; - return result; -} +/* +FUNCTION + The bfd_get_mtime function -/* bfd_get_mtime: Return cached file modification time (e.g. as read - from archive header for archive members, or from file system if we have - been called before); else determine modify time, cache it, and - return it. */ +SYNOPSIS + long bfd_get_mtime(bfd *); + +DESCRIPTION + Return file modification time (as read from file system, or + from archive header for archive members). + +*/ long bfd_get_mtime (abfd) @@ -919,7 +520,138 @@ bfd_get_mtime (abfd) if (0 != fstat (fileno (fp), &buf)) return 0; - abfd->mtime_set = true; - abfd->mtime = buf.st_mtime; - return abfd->mtime; + abfd->mtime = buf.st_mtime; /* Save value in case anyone wants it */ + return buf.st_mtime; +} + +/* +FUNCTION + The bfd_get_size function + +SYNOPSIS + long bfd_get_size(bfd *); + +DESCRIPTION + Return file size (as read from file system) for the file + associated with a bfd. + + Note that the initial motivation for, and use of, this routine is not + so we can get the exact size of the object the bfd applies to, since + that might not be generally possible (archive members for example?). + Although it would be ideal if someone could eventually modify + it so that such results were guaranteed. + + Instead, we want to ask questions like "is this NNN byte sized + object I'm about to try read from file offset YYY reasonable?" + As as example of where we might want to do this, some object formats + use string tables for which the first sizeof(long) bytes of the table + contain the size of the table itself, including the size bytes. + If an application tries to read what it thinks is one of these + string tables, without some way to validate the size, and for + some reason the size is wrong (byte swapping error, wrong location + for the string table, etc), the only clue is likely to be a read + error when it tries to read the table, or a "virtual memory + exhausted" error when it tries to allocated 15 bazillon bytes + of space for the 15 bazillon byte table it is about to read. + This function at least allows us to answer the quesion, "is the + size reasonable?". +*/ + +long +bfd_get_size (abfd) + bfd *abfd; +{ + FILE *fp; + struct stat buf; + + fp = bfd_cache_lookup (abfd); + if (0 != fstat (fileno (fp), &buf)) + return 0; + + return buf.st_size; +} + +/* +FUNCTION + The bfd_get_gp_size function + +SYNOPSIS + int bfd_get_gp_size(bfd *); + +DESCRIPTION + Get the maximum size of objects to be optimized using the GP + register under MIPS ECOFF. This is typically set by the -G + argument to the compiler, assembler or linker. +*/ + +int +bfd_get_gp_size (abfd) + bfd *abfd; +{ + if (abfd->xvec->flavour == bfd_target_ecoff_flavour) + return ecoff_data (abfd)->gp_size; + return 0; } + +/* +FUNCTION + The bfd_set_gp_size function + +SYNOPSIS + void bfd_set_gp_size(bfd *, int); + +DESCRIPTION + Set the maximum size of objects to be optimized using the GP + register under MIPS ECOFF. This is typically set by the -G + argument to the compiler, assembler or linker. +*/ + +void +bfd_set_gp_size (abfd, i) + bfd *abfd; + int i; +{ + if (abfd->xvec->flavour == bfd_target_ecoff_flavour) + ecoff_data (abfd)->gp_size = i; +} + +/* +FUNCTION + stuff + +DESCRIPTION + stuff which should be documented + +.#define bfd_sizeof_headers(abfd, reloc) \ +. BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, reloc)) +. +.#define bfd_find_nearest_line(abfd, sec, syms, off, file, func, line) \ +. BFD_SEND (abfd, _bfd_find_nearest_line, (abfd, sec, syms, off, file, func, line)) +. +. {* Do these three do anything useful at all, for any back end? *} +.#define bfd_debug_info_start(abfd) \ +. BFD_SEND (abfd, _bfd_debug_info_start, (abfd)) +. +.#define bfd_debug_info_end(abfd) \ +. BFD_SEND (abfd, _bfd_debug_info_end, (abfd)) +. +.#define bfd_debug_info_accumulate(abfd, section) \ +. BFD_SEND (abfd, _bfd_debug_info_accumulate, (abfd, section)) +. +. +.#define bfd_stat_arch_elt(abfd, stat) \ +. BFD_SEND (abfd, _bfd_stat_arch_elt,(abfd, stat)) +. +.#define bfd_set_arch_mach(abfd, arch, mach)\ +. BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach)) +. +.#define bfd_get_relocated_section_contents(abfd, seclet, data, relocateable) \ +. BFD_SEND (abfd, _bfd_get_relocated_section_contents, (abfd, seclet, data, relocateable)) +. +.#define bfd_relax_section(abfd, section, symbols) \ +. BFD_SEND (abfd, _bfd_relax_section, (abfd, section, symbols)) +. +.#define bfd_seclet_link(abfd, data, relocateable) \ +. BFD_SEND (abfd, _bfd_seclet_link, (abfd, data, relocateable)) + +*/