X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=bfd%2Fsyms.c;h=30fb74c352a1ab10a342e129cbf965eb82c2812b;hb=e98fe4f7b54cbdf29aef9287bbb1bea8801dd05a;hp=fff67e59924ef70e37ed565c5766c67e78908f1d;hpb=188d6d224e9e777c4083922b2789d9d81b155ee8;p=binutils-gdb.git diff --git a/bfd/syms.c b/bfd/syms.c index fff67e59924..30fb74c352a 100644 --- a/bfd/syms.c +++ b/bfd/syms.c @@ -1,5 +1,6 @@ /* Generic symbol-table support for the BFD library. - Copyright (C) 1990-1991 Free Software Foundation, Inc. + Copyright (C) 1990, 91, 92, 93, 94, 95, 96, 97, 1998 + Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -16,357 +17,1185 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -/*doc* -@section Symbols -BFD trys to maintain as much symbol information as it can when it -moves information from file to file. BFD passes information to -applications though the @code{asymbol} structure. When the application -requests the symbol table, BFD reads the table in the native form and -translates parts of it into the internal format. To maintain more than -the infomation passed to applications some targets keep -some information 'behind the sceans', in a structure only the -particular back end knows about. For example, the coff back end keeps -the original symbol table structure as well as the canonical structure -when a BFD is read in. On output, the coff back end can reconstruct -the output symbol table so that no information is lost, even -information unique to coff which BFD doesn't know or understand. If a -coff symbol table was read, but was written through an a.out back end, -all the coff specific information would be lost. (.. until BFD 2 :). - -The symbol table of a BFD is not necessarily read in until a -canonicalize request is made. Then the BFD back end fills in a table -provided by the application with pointers to the canonical -information. - -To output symbols, the application provides BFD with a table of -pointers to pointers to @code{asymbol}s. This allows applications like -the linker to output a symbol as read, since the 'behind the sceens' -information will be still available. - +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* +SECTION + Symbols + + BFD tries to maintain as much symbol information as it can when + it moves information from file to file. BFD passes information + to applications though the <> structure. When the + application requests the symbol table, BFD reads the table in + the native form and translates parts of it into the internal + format. To maintain more than the information passed to + applications, some targets keep some information ``behind the + scenes'' in a structure only the particular back end knows + about. For example, the coff back end keeps the original + symbol table structure as well as the canonical structure when + a BFD is read in. On output, the coff back end can reconstruct + the output symbol table so that no information is lost, even + information unique to coff which BFD doesn't know or + understand. If a coff symbol table were read, but were written + through an a.out back end, all the coff specific information + would be lost. The symbol table of a BFD + is not necessarily read in until a canonicalize request is + made. Then the BFD back end fills in a table provided by the + application with pointers to the canonical information. To + output symbols, the application provides BFD with a table of + pointers to pointers to <>s. This allows applications + like the linker to output a symbol as it was read, since the ``behind + the scenes'' information will be still available. @menu -* Reading Symbols:: -* Writing Symbols:: -* typedef asymbol:: -* symbol handling functions:: +@* Reading Symbols:: +@* Writing Symbols:: +@* Mini Symbols:: +@* typedef asymbol:: +@* symbol handling functions:: @end menu -@node Reading Symbols, Writing Symbols, Symbols, Symbols -@subsection Reading Symbols -There are two stages to reading a symbol table from a BFD; allocating -storage, and the actual reading process. This is an excerpt from an -appliction which reads the symbol table: - -*+ - unsigned int storage_needed; - asymbol **symbol_table; - unsigned int number_of_symbols; - unsigned int i; - - storage_needed = get_symtab_upper_bound (abfd); - - if (storage_needed == 0) { - return ; - } - symbol_table = (asymbol **) malloc (storage_needed); - ... - number_of_symbols = - bfd_canonicalize_symtab (abfd, symbol_table); - - for (i = 0; i < number_of_symbols; i++) { - process_symbol (symbol_table[i]); - } -*- - -All storage for the symbols themselves is in an obstack connected to -the BFD, and is freed when the BFD is closed. - -@node Writing Symbols, typedef asymbol, Reading Symbols, Symbols -@subsection Writing Symbols -Writing of a symbol table is automatic when a BFD open for writing -is closed. The application attaches a vector of pointers to pointers to symbols -to the BFD being written, and fills in the symbol count. The close and -cleanup code reads through the table provided and performs all the -necessary operations. The outputing code must always be provided with -an 'owned' symbol; one which has come from another BFD, or one which -has been created using @code{bfd_make_empty_symbol}. - -An example showing the creation of a symbol table with only one -element: - -*+ -#include "bfd.h" -main() -{ - bfd *abfd; - asymbol *ptrs[2]; - asymbol *new; - - abfd = bfd_openw("foo","a.out-sunos-big"); - bfd_set_format(abfd, bfd_object); - new = bfd_make_empty_symbol(abfd); - new->name = "dummy_symbol"; - new->section = (asection *)0; - new->flags = BSF_ABSOLUTE | BSF_GLOBAL; - new->value = 0x12345; - - ptrs[0] = new; - ptrs[1] = (asymbol *)0; - - bfd_set_symtab(abfd, ptrs, 1); - bfd_close(abfd); -} +INODE +Reading Symbols, Writing Symbols, Symbols, Symbols +SUBSECTION + Reading symbols + + There are two stages to reading a symbol table from a BFD: + allocating storage, and the actual reading process. This is an + excerpt from an application which reads the symbol table: + +| long storage_needed; +| asymbol **symbol_table; +| long number_of_symbols; +| long i; +| +| storage_needed = bfd_get_symtab_upper_bound (abfd); +| +| if (storage_needed < 0) +| FAIL +| +| if (storage_needed == 0) { +| return ; +| } +| symbol_table = (asymbol **) xmalloc (storage_needed); +| ... +| number_of_symbols = +| bfd_canonicalize_symtab (abfd, symbol_table); +| +| if (number_of_symbols < 0) +| FAIL +| +| for (i = 0; i < number_of_symbols; i++) { +| process_symbol (symbol_table[i]); +| } + + All storage for the symbols themselves is in an objalloc + connected to the BFD; it is freed when the BFD is closed. + + +INODE +Writing Symbols, Mini Symbols, Reading Symbols, Symbols +SUBSECTION + Writing symbols + + Writing of a symbol table is automatic when a BFD open for + writing is closed. The application attaches a vector of + pointers to pointers to symbols to the BFD being written, and + fills in the symbol count. The close and cleanup code reads + through the table provided and performs all the necessary + operations. The BFD output code must always be provided with an + ``owned'' symbol: one which has come from another BFD, or one + which has been created using <>. Here is an + example showing the creation of a symbol table with only one element: + +| #include "bfd.h" +| main() +| { +| bfd *abfd; +| asymbol *ptrs[2]; +| asymbol *new; +| +| abfd = bfd_openw("foo","a.out-sunos-big"); +| bfd_set_format(abfd, bfd_object); +| new = bfd_make_empty_symbol(abfd); +| new->name = "dummy_symbol"; +| new->section = bfd_make_section_old_way(abfd, ".text"); +| new->flags = BSF_GLOBAL; +| new->value = 0x12345; +| +| ptrs[0] = new; +| ptrs[1] = (asymbol *)0; +| +| bfd_set_symtab(abfd, ptrs, 1); +| bfd_close(abfd); +| } +| +| ./makesym +| nm foo +| 00012345 A dummy_symbol + + Many formats cannot represent arbitary symbol information; for + instance, the <> object format does not allow an + arbitary number of sections. A symbol pointing to a section + which is not one of <<.text>>, <<.data>> or <<.bss>> cannot + be described. + +INODE +Mini Symbols, typedef asymbol, Writing Symbols, Symbols +SUBSECTION + Mini Symbols + + Mini symbols provide read-only access to the symbol table. + They use less memory space, but require more time to access. + They can be useful for tools like nm or objdump, which may + have to handle symbol tables of extremely large executables. + + The <> function will read the symbols + into memory in an internal form. It will return a <> + pointer to a block of memory, a symbol count, and the size of + each symbol. The pointer is allocated using <>, and + should be freed by the caller when it is no longer needed. + + The function <> will take a pointer + to a minisymbol, and a pointer to a structure returned by + <>, and return a <> structure. + The return value may or may not be the same as the value from + <> which was passed in. -./makesym -nm foo -00012345 A dummy_symbol +*/ -*- -Many formats cannot represent arbitary symbol information; for -instance the @code{a.out} object format does not allow an arbitary -number of sections. A symbol pointing to a section which is not one of -@code{.text}, @code{.data} or @code{.bss} cannot be described. -*/ +/* +DOCDD +INODE +typedef asymbol, symbol handling functions, Mini Symbols, Symbols +*/ +/* +SUBSECTION + typedef asymbol -/*doc* -@node typedef asymbol, symbol handling functions, Writing Symbols, Symbols + An <> has the form: */ -/*proto* -@subsection typedef asymbol -An @code{asymbol} has the form: -*+++ +/* +CODE_FRAGMENT + +. +.typedef struct symbol_cache_entry +.{ +. {* A pointer to the BFD which owns the symbol. This information +. is necessary so that a back end can work out what additional +. information (invisible to the application writer) is carried +. with the symbol. +. +. This field is *almost* redundant, since you can use section->owner +. instead, except that some symbols point to the global sections +. bfd_{abs,com,und}_section. This could be fixed by making +. these globals be per-bfd (or per-target-flavor). FIXME. *} +. +. struct _bfd *the_bfd; {* Use bfd_asymbol_bfd(sym) to access this field. *} +. +. {* The text of the symbol. The name is left alone, and not copied; the +. application may not alter it. *} +. CONST char *name; +. +. {* The value of the symbol. This really should be a union of a +. numeric value with a pointer, since some flags indicate that +. a pointer to another symbol is stored here. *} +. symvalue value; +. +. {* Attributes of a symbol: *} +. +.#define BSF_NO_FLAGS 0x00 +. +. {* The symbol has local scope; <> in <>. The value +. is the offset into the section of the data. *} +.#define BSF_LOCAL 0x01 +. +. {* The symbol has global scope; initialized data in <>. The +. value is the offset into the section of the data. *} +.#define BSF_GLOBAL 0x02 +. +. {* The symbol has global scope and is exported. The value is +. the offset into the section of the data. *} +.#define BSF_EXPORT BSF_GLOBAL {* no real difference *} +. +. {* A normal C symbol would be one of: +. <>, <>, <> or +. <> *} +. +. {* The symbol is a debugging record. The value has an arbitary +. meaning. *} +.#define BSF_DEBUGGING 0x08 +. +. {* The symbol denotes a function entry point. Used in ELF, +. perhaps others someday. *} +.#define BSF_FUNCTION 0x10 +. +. {* Used by the linker. *} +.#define BSF_KEEP 0x20 +.#define BSF_KEEP_G 0x40 +. +. {* A weak global symbol, overridable without warnings by +. a regular global symbol of the same name. *} +.#define BSF_WEAK 0x80 +. +. {* This symbol was created to point to a section, e.g. ELF's +. STT_SECTION symbols. *} +.#define BSF_SECTION_SYM 0x100 +. +. {* The symbol used to be a common symbol, but now it is +. allocated. *} +.#define BSF_OLD_COMMON 0x200 +. +. {* The default value for common data. *} +.#define BFD_FORT_COMM_DEFAULT_VALUE 0 +. +. {* In some files the type of a symbol sometimes alters its +. location in an output file - ie in coff a <> symbol +. which is also <> symbol appears where it was +. declared and not at the end of a section. This bit is set +. by the target BFD part to convey this information. *} +. +.#define BSF_NOT_AT_END 0x400 +. +. {* Signal that the symbol is the label of constructor section. *} +.#define BSF_CONSTRUCTOR 0x800 +. +. {* Signal that the symbol is a warning symbol. The name is a +. warning. The name of the next symbol is the one to warn about; +. if a reference is made to a symbol with the same name as the next +. symbol, a warning is issued by the linker. *} +.#define BSF_WARNING 0x1000 +. +. {* Signal that the symbol is indirect. This symbol is an indirect +. pointer to the symbol with the same name as the next symbol. *} +.#define BSF_INDIRECT 0x2000 +. +. {* BSF_FILE marks symbols that contain a file name. This is used +. for ELF STT_FILE symbols. *} +.#define BSF_FILE 0x4000 +. +. {* Symbol is from dynamic linking information. *} +.#define BSF_DYNAMIC 0x8000 +. +. {* The symbol denotes a data object. Used in ELF, and perhaps +. others someday. *} +.#define BSF_OBJECT 0x10000 +. +. flagword flags; +. +. {* A pointer to the section to which this symbol is +. relative. This will always be non NULL, there are special +. sections for undefined and absolute symbols. *} +. struct sec *section; +. +. {* Back end special data. *} +. union +. { +. PTR p; +. bfd_vma i; +. } udata; +. +.} asymbol; +*/ -$typedef struct symbol_cache_entry -${ -A pointer to the BFD which owns the symbol. This information is -necessary so that a back end can work out what additional (invisible to -the application writer) information is carried with the symbol. +#include "bfd.h" +#include "sysdep.h" +#include "libbfd.h" +#include "bfdlink.h" +#include "aout/stab_gnu.h" -$ struct _bfd *the_bfd; +static char coff_section_type PARAMS ((const char *)); -The text of the symbol. The name is left alone, and not copied - the -application may not alter it. +/* +DOCDD +INODE +symbol handling functions, , typedef asymbol, Symbols +SUBSECTION + Symbol handling functions +*/ -$ CONST char *name; +/* +FUNCTION + bfd_get_symtab_upper_bound -The value of the symbol. +DESCRIPTION + Return the number of bytes required to store a vector of pointers + to <> for all the symbols in the BFD @var{abfd}, + including a terminal NULL pointer. If there are no symbols in + the BFD, then return 0. If an error occurs, return -1. -$ symvalue value; +.#define bfd_get_symtab_upper_bound(abfd) \ +. BFD_SEND (abfd, _bfd_get_symtab_upper_bound, (abfd)) -Attributes of a symbol: +*/ -$#define BSF_NO_FLAGS 0x00 +/* +FUNCTION + bfd_is_local_label -The symbol has local scope; @code{static} in @code{C}. The value is -the offset into the section of the data. +SYNOPSIS + boolean bfd_is_local_label(bfd *abfd, asymbol *sym); -$#define BSF_LOCAL 0x01 +DESCRIPTION + Return true if the given symbol @var{sym} in the BFD @var{abfd} is + a compiler generated local label, else return false. +*/ -The symbol has global scope; initialized data in @code{C}. The value -is the offset into the section of the data. +boolean +bfd_is_local_label (abfd, sym) + bfd *abfd; + asymbol *sym; +{ + if ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0) + return false; + if (sym->name == NULL) + return false; + if (sym->flags & BSF_DEBUGGING) + return true; + return bfd_is_local_label_name (abfd, sym->name); +} -$#define BSF_GLOBAL 0x02 +/* +FUNCTION + bfd_is_local_label_name -Obsolete +SYNOPSIS + boolean bfd_is_local_label_name(bfd *abfd, const char *name); -$#define BSF_IMPORT 0x04 +DESCRIPTION + Return true if a symbol with the name @var{name} in the BFD + @var{abfd} is a compiler generated local label, else return + false. This just checks whether the name has the form of a + local label. -The symbol has global scope, and is exported. The value is the offset -into the section of the data. +.#define bfd_is_local_label_name(abfd, name) \ +. BFD_SEND (abfd, _bfd_is_local_label_name, (abfd, name)) +*/ -$#define BSF_EXPORT 0x08 +/* +FUNCTION + bfd_canonicalize_symtab -The symbol is undefined. @code{extern} in @code{C}. The value has no meaning. +DESCRIPTION + Read the symbols from the BFD @var{abfd}, and fills in + the vector @var{location} with pointers to the symbols and + a trailing NULL. + Return the actual number of symbol pointers, not + including the NULL. -$#define BSF_UNDEFINED 0x10 -The symbol is common, initialized to zero; default in @code{C}. The -value is the size of the object in bytes. +.#define bfd_canonicalize_symtab(abfd, location) \ +. BFD_SEND (abfd, _bfd_canonicalize_symtab,\ +. (abfd, location)) -$#define BSF_FORT_COMM 0x20 +*/ -A normal @code{C} symbol would be one of: -@code{BSF_LOCAL}, @code{BSF_FORT_COMM}, @code{BSF_UNDEFINED} or @code{BSF_EXPORT|BSD_GLOBAL} -The symbol is a debugging record. The value has an arbitary meaning. +/* +FUNCTION + bfd_set_symtab -$#define BSF_DEBUGGING 0x40 +SYNOPSIS + boolean bfd_set_symtab (bfd *abfd, asymbol **location, unsigned int count); -The symbol has no section attached, any value is the actual value and -is not a relative offset to a section. +DESCRIPTION + Arrange that when the output BFD @var{abfd} is closed, + the table @var{location} of @var{count} pointers to symbols + will be written. +*/ -$#define BSF_ABSOLUTE 0x80 +boolean +bfd_set_symtab (abfd, location, symcount) + bfd *abfd; + asymbol **location; + unsigned int symcount; +{ + if ((abfd->format != bfd_object) || (bfd_read_p (abfd))) + { + bfd_set_error (bfd_error_invalid_operation); + return false; + } -Used by the linker + bfd_get_outsymbols (abfd) = location; + bfd_get_symcount (abfd) = symcount; + return true; +} -$#define BSF_KEEP 0x10000 -$#define BSF_KEEP_G 0x80000 +/* +FUNCTION + bfd_print_symbol_vandf -Unused +SYNOPSIS + void bfd_print_symbol_vandf(PTR file, asymbol *symbol); -$#define BSF_WEAK 0x100000 -$#define BSF_CTOR 0x200000 -$#define BSF_FAKE 0x400000 +DESCRIPTION + Print the value and flags of the @var{symbol} supplied to the + stream @var{file}. +*/ +void +bfd_print_symbol_vandf (arg, symbol) + PTR arg; + asymbol *symbol; +{ + FILE *file = (FILE *) arg; + flagword type = symbol->flags; + if (symbol->section != (asection *) NULL) + { + fprintf_vma (file, symbol->value + symbol->section->vma); + } + else + { + fprintf_vma (file, symbol->value); + } + + /* This presumes that a symbol can not be both BSF_DEBUGGING and + BSF_DYNAMIC, nor more than one of BSF_FUNCTION, BSF_FILE, and + BSF_OBJECT. */ + fprintf (file, " %c%c%c%c%c%c%c", + ((type & BSF_LOCAL) + ? (type & BSF_GLOBAL) ? '!' : 'l' + : (type & BSF_GLOBAL) ? 'g' : ' '), + (type & BSF_WEAK) ? 'w' : ' ', + (type & BSF_CONSTRUCTOR) ? 'C' : ' ', + (type & BSF_WARNING) ? 'W' : ' ', + (type & BSF_INDIRECT) ? 'I' : ' ', + (type & BSF_DEBUGGING) ? 'd' : (type & BSF_DYNAMIC) ? 'D' : ' ', + ((type & BSF_FUNCTION) + ? 'F' + : ((type & BSF_FILE) + ? 'f' + : ((type & BSF_OBJECT) ? 'O' : ' ')))); +} -The symbol used to be a common symbol, but now it is allocated. -$#define BSF_OLD_COMMON 0x800000 +/* +FUNCTION + bfd_make_empty_symbol -The default value for common data. +DESCRIPTION + Create a new <> structure for the BFD @var{abfd} + and return a pointer to it. -$#define BFD_FORT_COMM_DEFAULT_VALUE 0 + This routine is necessary because each back end has private + information surrounding the <>. Building your own + <> and pointing to it will not create the private + information, and will cause problems later on. -In some files the type of a symbol sometimes alters its location -in an output file - ie in coff a @code{ISFCN} symbol which is also @code{C_EXT} -symbol appears where it was declared and not at the end of a section. -This bit is set by the target BFD part to convey this information. +.#define bfd_make_empty_symbol(abfd) \ +. BFD_SEND (abfd, _bfd_make_empty_symbol, (abfd)) +*/ -$#define BSF_NOT_AT_END 0x40000 +/* +FUNCTION + bfd_make_debug_symbol -Signal that the symbol is the label of constructor section. +DESCRIPTION + Create a new <> structure for the BFD @var{abfd}, + to be used as a debugging symbol. Further details of its use have + yet to be worked out. -$#define BSF_CONSTRUCTOR 0x1000000 +.#define bfd_make_debug_symbol(abfd,ptr,size) \ +. BFD_SEND (abfd, _bfd_make_debug_symbol, (abfd, ptr, size)) +*/ -Signal that the symbol is a warning symbol. If the symbol is a warning -symbol, then the value field (I know this is tacky) will point to the -asymbol which when referenced will cause the warning. +struct section_to_type +{ + CONST char *section; + char type; +}; + +/* Map section names to POSIX/BSD single-character symbol types. + This table is probably incomplete. It is sorted for convenience of + adding entries. Since it is so short, a linear search is used. */ +static CONST struct section_to_type stt[] = +{ + {"*DEBUG*", 'N'}, + {".bss", 'b'}, + {"zerovars", 'b'}, /* MRI .bss */ + {".data", 'd'}, + {"vars", 'd'}, /* MRI .data */ + {".rdata", 'r'}, /* Read only data. */ + {".rodata", 'r'}, /* Read only data. */ + {".sbss", 's'}, /* Small BSS (uninitialized data). */ + {".scommon", 'c'}, /* Small common. */ + {".sdata", 'g'}, /* Small initialized data. */ + {".text", 't'}, + {"code", 't'}, /* MRI .text */ + {0, 0} +}; + +/* Return the single-character symbol type corresponding to + section S, or '?' for an unknown COFF section. + + Check for any leading string which matches, so .text5 returns + 't' as well as .text */ + +static char +coff_section_type (s) + const char *s; +{ + CONST struct section_to_type *t; -$#define BSF_WARNING 0x2000000 + for (t = &stt[0]; t->section; t++) + if (!strncmp (s, t->section, strlen (t->section))) + return t->type; -Signal that the symbol is indirect. The value of the symbol is a -pointer to an undefined asymbol which contains the name to use -instead. + return '?'; +} -$#define BSF_INDIRECT 0x4000000 +#ifndef islower +#define islower(c) ((c) >= 'a' && (c) <= 'z') +#endif +#ifndef toupper +#define toupper(c) (islower(c) ? ((c) & ~0x20) : (c)) +#endif -$ flagword flags; +/* +FUNCTION + bfd_decode_symclass -Aointer to the section to which this symbol is relative, or 0 if the -symbol is absolute or undefined. Note that it is not sufficient to set -this location to 0 to mark a symbol as absolute - the flag -@code{BSF_ABSOLUTE} must be set also. +DESCRIPTION + Return a character corresponding to the symbol + class of @var{symbol}, or '?' for an unknown class. -$ struct sec *section; +SYNOPSIS + int bfd_decode_symclass(asymbol *symbol); +*/ +int +bfd_decode_symclass (symbol) + asymbol *symbol; +{ + char c; + + if (bfd_is_com_section (symbol->section)) + return 'C'; + if (bfd_is_und_section (symbol->section)) + return 'U'; + if (bfd_is_ind_section (symbol->section)) + return 'I'; + if (symbol->flags & BSF_WEAK) + return 'W'; + if (!(symbol->flags & (BSF_GLOBAL | BSF_LOCAL))) + return '?'; + + if (bfd_is_abs_section (symbol->section)) + c = 'a'; + else if (symbol->section) + c = coff_section_type (symbol->section->name); + else + return '?'; + if (symbol->flags & BSF_GLOBAL) + c = toupper (c); + return c; + + /* We don't have to handle these cases just yet, but we will soon: + N_SETV: 'v'; + N_SETA: 'l'; + N_SETT: 'x'; + N_SETD: 'z'; + N_SETB: 's'; + N_INDR: 'i'; + */ +} -Back end special data. This is being phased out in favour of making -this a union. +/* +FUNCTION + bfd_symbol_info -$ PTR udata; -$} asymbol; -*--- +DESCRIPTION + Fill in the basic info about symbol that nm needs. + Additional info may be added by the back-ends after + calling this function. +SYNOPSIS + void bfd_symbol_info(asymbol *symbol, symbol_info *ret); */ -#include "sysdep.h" -#include "bfd.h" -#include "libbfd.h" - -/*doc* -@node symbol handling functions, Symbols, typedef asymbol, Symbols -@subsection Symbol Handling Functions +void +bfd_symbol_info (symbol, ret) + asymbol *symbol; + symbol_info *ret; +{ + ret->type = bfd_decode_symclass (symbol); + if (ret->type != 'U') + ret->value = symbol->value + symbol->section->vma; + else + ret->value = 0; + ret->name = symbol->name; +} -*/ +/* +FUNCTION + bfd_copy_private_symbol_data -/*proto* get_symtab_upper_bound -Returns the number of bytes required in a vector of pointers to -@code{asymbols} for all the symbols in the supplied BFD, including a -terminal NULL pointer. If there are no symbols in the BFD, then 0 is -returned. -*+ -#define get_symtab_upper_bound(abfd) \ - BFD_SEND (abfd, _get_symtab_upper_bound, (abfd)) -*- +SYNOPSIS + boolean bfd_copy_private_symbol_data(bfd *ibfd, asymbol *isym, bfd *obfd, asymbol *osym); -*/ +DESCRIPTION + Copy private symbol information from @var{isym} in the BFD + @var{ibfd} to the symbol @var{osym} in the BFD @var{obfd}. + Return <> on success, <> on error. Possible error + returns are: -/*proto* bfd_canonicalize_symtab -Supplied a BFD and a pointer to an uninitialized vector of pointers. -This reads in the symbols from the BFD, and fills in the table with -pointers to the symbols, and a trailing NULL. The routine returns the -actual number of symbol pointers not including the NULL. + o <> - + Not enough memory exists to create private data for @var{osec}. -*+ -#define bfd_canonicalize_symtab(abfd, location) \ - BFD_SEND (abfd, _bfd_canonicalize_symtab,\ - (abfd, location)) +.#define bfd_copy_private_symbol_data(ibfd, isymbol, obfd, osymbol) \ +. BFD_SEND (obfd, _bfd_copy_private_symbol_data, \ +. (ibfd, isymbol, obfd, osymbol)) -*- */ +/* The generic version of the function which returns mini symbols. + This is used when the backend does not provide a more efficient + version. It just uses BFD asymbol structures as mini symbols. */ -/*proto* bfd_set_symtab -Provided a table of pointers to to symbols and a count, writes to the -output BFD the symbols when closed. +long +_bfd_generic_read_minisymbols (abfd, dynamic, minisymsp, sizep) + bfd *abfd; + boolean dynamic; + PTR *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; + + syms = (asymbol **) bfd_malloc ((size_t) 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 = (PTR) syms; + *sizep = sizeof (asymbol *); + return symcount; + + error_return: + if (syms != NULL) + free (syms); + return -1; +} -*; PROTO(boolean, bfd_set_symtab, (bfd *, asymbol **, unsigned int )); -*/ +/* The generic version of the function which converts a minisymbol to + an asymbol. We don't worry about the sym argument we are passed; + we just return the asymbol the minisymbol points to. */ -boolean -bfd_set_symtab (abfd, location, symcount) +/*ARGSUSED*/ +asymbol * +_bfd_generic_minisymbol_to_symbol (abfd, dynamic, minisym, sym) bfd *abfd; - asymbol **location; - unsigned int symcount; + boolean dynamic; + const PTR minisym; + asymbol *sym; { - if ((abfd->format != bfd_object) || (bfd_read_p (abfd))) { - bfd_error = invalid_operation; - return false; - } - - bfd_get_outsymbols (abfd) = location; - bfd_get_symcount (abfd) = symcount; - return true; + return *(asymbol **) minisym; } -/*proto* bfd_print_symbol_vandf -Prints the value and flags of the symbol supplied to the stream file. +/* Look through stabs debugging information in .stab and .stabstr + sections to find the source file and line closest to a desired + location. This is used by COFF and ELF targets. It sets *pfound + to true if it finds some information. The *pinfo field is used to + pass cached information in and out of this routine; this first time + the routine is called for a BFD, *pinfo should be NULL. The value + placed in *pinfo should be saved with the BFD, and passed back each + time this function is called. */ -*; PROTO(void, bfd_print_symbol_vandf, (PTR file, asymbol *symbol)); -*/ -void -DEFUN(bfd_print_symbol_vandf,(file, symbol), -PTR file AND -asymbol *symbol) -{ - flagword type = symbol->flags; - if (symbol->section != (asection *)NULL) - { - fprintf_vma(file, symbol->value+symbol->section->vma); - } - else - { - fprintf_vma(file, symbol->value); - } - fprintf(file," %c%c%c%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_CONSTRUCTOR) ? 'C' : ' ', - (type & BSF_WARNING) ? 'W' : ' ', - (type & BSF_INDIRECT) ? 'I' : ' ', - (type & BSF_DEBUGGING) ? 'd' :' '); +/* We use a cache by default. */ + +#define ENABLE_CACHING + +/* We keep an array of indexentry structures to record where in the + stabs section we should look to find line number information for a + particular address. */ +struct indexentry +{ + bfd_vma val; + bfd_byte *stab; + bfd_byte *str; + char *directory_name; + char *file_name; + char *function_name; +}; + +/* Compare two indexentry structures. This is called via qsort. */ + +static int +cmpindexentry (a, b) + const PTR *a; + const PTR *b; +{ + const struct indexentry *contestantA = (const struct indexentry *) a; + const struct indexentry *contestantB = (const struct indexentry *) b; + + if (contestantA->val < contestantB->val) + return -1; + else if (contestantA->val > contestantB->val) + return 1; + else + return 0; } +/* A pointer to this structure is stored in *pinfo. */ -/*proto* bfd_make_empty_symbol -This function creates a new @code{asymbol} structure for the BFD, and -returns a pointer to it. +struct stab_find_info +{ + /* The .stab section. */ + asection *stabsec; + /* The .stabstr section. */ + asection *strsec; + /* The contents of the .stab section. */ + bfd_byte *stabs; + /* The contents of the .stabstr section. */ + bfd_byte *strs; + + /* A table that indexes stabs by memory address. */ + struct indexentry *indextable; + /* The number of entries in indextable. */ + int indextablesize; + +#ifdef ENABLE_CACHING + /* Cached values to restart quickly. */ + struct indexentry *cached_indexentry; + bfd_vma cached_offset; + bfd_byte *cached_stab; + char *cached_file_name; +#endif + + /* Saved ptr to malloc'ed filename. */ + char *filename; +}; -This routine is necessary, since each back end has private information -surrounding the @code{asymbol}. Building your own @code{asymbol} and -pointing to it will not create the private information, and will cause -problems later on. -*+ -#define bfd_make_empty_symbol(abfd) \ - BFD_SEND (abfd, _bfd_make_empty_symbol, (abfd)) -*- -*/ +boolean +_bfd_stab_section_find_nearest_line (abfd, symbols, section, offset, pfound, + pfilename, pfnname, pline, pinfo) + bfd *abfd; + asymbol **symbols; + asection *section; + bfd_vma offset; + boolean *pfound; + const char **pfilename; + const char **pfnname; + unsigned int *pline; + PTR *pinfo; +{ + struct stab_find_info *info; + bfd_size_type stabsize, strsize; + bfd_byte *stab, *str; + bfd_size_type stroff; + struct indexentry *indexentry; + char *directory_name, *file_name; + + *pfound = false; + *pfilename = bfd_get_filename (abfd); + *pfnname = NULL; + *pline = 0; + + /* Stabs entries use a 12 byte format: + 4 byte string table index + 1 byte stab type + 1 byte stab other field + 2 byte stab desc field + 4 byte stab value + FIXME: This will have to change for a 64 bit object format. + + The stabs symbols are divided into compilation units. For the + first entry in each unit, the type of 0, the value is the length + of the string table for this unit, and the desc field is the + number of stabs symbols for this unit. */ + +#define STRDXOFF (0) +#define TYPEOFF (4) +#define OTHEROFF (5) +#define DESCOFF (6) +#define VALOFF (8) +#define STABSIZE (12) + + info = (struct stab_find_info *) *pinfo; + if (info != NULL) + { + if (info->stabsec == NULL || info->strsec == NULL) + { + /* No stabs debugging information. */ + return true; + } + + stabsize = info->stabsec->_raw_size; + strsize = info->strsec->_raw_size; + } + else + { + long reloc_size, reloc_count; + arelent **reloc_vector; + bfd_vma val; + int i; + char *name; + char *file_name; + char *directory_name; + char *function_name; + + info = (struct stab_find_info *) bfd_zalloc (abfd, sizeof *info); + if (info == NULL) + return false; + + /* FIXME: When using the linker --split-by-file or + --split-by-reloc options, it is possible for the .stab and + .stabstr sections to be split. We should handle that. */ + + info->stabsec = bfd_get_section_by_name (abfd, ".stab"); + info->strsec = bfd_get_section_by_name (abfd, ".stabstr"); + + if (info->stabsec == NULL || info->strsec == NULL) + { + /* No stabs debugging information. Set *pinfo so that we + can return quickly in the info != NULL case above. */ + *pinfo = (PTR) info; + return true; + } + + stabsize = info->stabsec->_raw_size; + strsize = info->strsec->_raw_size; + + info->stabs = (bfd_byte *) bfd_alloc (abfd, stabsize); + info->strs = (bfd_byte *) bfd_alloc (abfd, strsize); + if (info->stabs == NULL || info->strs == NULL) + return false; + + if (! bfd_get_section_contents (abfd, info->stabsec, info->stabs, 0, + stabsize) + || ! bfd_get_section_contents (abfd, info->strsec, info->strs, 0, + strsize)) + return false; + + /* If this is a relocateable object file, we have to relocate + the entries in .stab. This should always be simple 32 bit + relocations against symbols defined in this object file, so + this should be no big deal. */ + reloc_size = bfd_get_reloc_upper_bound (abfd, info->stabsec); + if (reloc_size < 0) + return false; + reloc_vector = (arelent **) bfd_malloc (reloc_size); + if (reloc_vector == NULL && reloc_size != 0) + return false; + reloc_count = bfd_canonicalize_reloc (abfd, info->stabsec, reloc_vector, + symbols); + if (reloc_count < 0) + { + if (reloc_vector != NULL) + free (reloc_vector); + return false; + } + if (reloc_count > 0) + { + arelent **pr; + + for (pr = reloc_vector; *pr != NULL; pr++) + { + arelent *r; + unsigned long val; + asymbol *sym; + + r = *pr; + if (r->howto->rightshift != 0 + || r->howto->size != 2 + || r->howto->bitsize != 32 + || r->howto->pc_relative + || r->howto->bitpos != 0 + || r->howto->dst_mask != 0xffffffff) + { + (*_bfd_error_handler) + (_("Unsupported .stab relocation")); + bfd_set_error (bfd_error_invalid_operation); + if (reloc_vector != NULL) + free (reloc_vector); + return false; + } + + val = bfd_get_32 (abfd, info->stabs + r->address); + val &= r->howto->src_mask; + sym = *r->sym_ptr_ptr; + val += sym->value + sym->section->vma + r->addend; + bfd_put_32 (abfd, val, info->stabs + r->address); + } + } + + if (reloc_vector != NULL) + free (reloc_vector); + + /* First time through this function, build a table matching + function VM addresses to stabs, then sort based on starting + VM address. Do this in two passes: once to count how many + table entries we'll need, and a second to actually build the + table. */ + + info->indextablesize = 0; + for (stab = info->stabs; stab < info->stabs + stabsize; stab += STABSIZE) + { + if (stab[TYPEOFF] == N_FUN) + ++info->indextablesize; + } + + if (info->indextablesize == 0) + return true; + ++info->indextablesize; + + info->indextable = ((struct indexentry *) + bfd_alloc (abfd, + (sizeof (struct indexentry) + * info->indextablesize))); + if (info->indextable == NULL) + return false; + + file_name = NULL; + directory_name = NULL; + + for (i = 0, stroff = 0, stab = info->stabs, str = info->strs; + i < info->indextablesize && stab < info->stabs + stabsize; + stab += STABSIZE) + { + switch (stab[TYPEOFF]) + { + case 0: + /* This is the first entry in a compilation unit. */ + if ((bfd_size_type) ((info->strs + strsize) - str) < stroff) + break; + str += stroff; + stroff = bfd_get_32 (abfd, stab + VALOFF); + break; + + case N_SO: + /* The main file name. */ + + file_name = (char *) str + bfd_get_32 (abfd, stab + STRDXOFF); + + if (*file_name == '\0') + { + directory_name = NULL; + file_name = NULL; + } + else if (stab + STABSIZE >= info->stabs + stabsize + || *(stab + STABSIZE + TYPEOFF) != N_SO) + { + directory_name = NULL; + } + else + { + /* Two consecutive N_SOs are a directory and a file + name. */ + stab += STABSIZE; + directory_name = file_name; + file_name = ((char *) str + + bfd_get_32 (abfd, stab + STRDXOFF)); + } + break; + + case N_SOL: + /* The name of an include file. */ + file_name = (char *) str + bfd_get_32 (abfd, stab + STRDXOFF); + break; + + case N_FUN: + /* A function name. */ + + name = (char *) str + bfd_get_32 (abfd, stab + STRDXOFF); + + if (*name == '\0') + name = NULL; + + function_name = name; + + if (name == NULL) + continue; + + val = bfd_get_32 (abfd, stab + VALOFF); + + info->indextable[i].val = val; + info->indextable[i].stab = stab; + info->indextable[i].str = str; + info->indextable[i].directory_name = directory_name; + info->indextable[i].file_name = file_name; + info->indextable[i].function_name = function_name; + + ++i; + break; + } + } + + info->indextable[i].val = (bfd_vma) -1; + info->indextable[i].stab = info->stabs + stabsize; + info->indextable[i].str = str; + info->indextable[i].directory_name = NULL; + info->indextable[i].file_name = NULL; + info->indextable[i].function_name = NULL; + ++i; + + info->indextablesize = i; + + qsort (info->indextable, i, sizeof (struct indexentry), cmpindexentry); + + *pinfo = (PTR) info; + } + + /* We are passed a section relative offset. The offsets in the + stabs information are absolute. */ + offset += bfd_get_section_vma (abfd, section); + +#ifdef ENABLE_CACHING + if (info->cached_indexentry != NULL + && offset >= info->cached_offset + && offset < (info->cached_indexentry + 1)->val) + { + stab = info->cached_stab; + indexentry = info->cached_indexentry; + file_name = info->cached_file_name; + } + else +#endif + { + /* Cache non-existant or invalid. Do binary search on + indextable. */ + + long low, high; + long mid = -1; + + indexentry = NULL; + + low = 0; + high = info->indextablesize - 1; + while (low != high) + { + mid = (high + low) / 2; + if (offset >= info->indextable[mid].val + && offset < info->indextable[mid + 1].val) + { + indexentry = &info->indextable[mid]; + break; + } + + if (info->indextable[mid].val > offset) + high = mid; + else + low = mid + 1; + } + + if (indexentry == NULL) + return true; + + stab = indexentry->stab + STABSIZE; + file_name = indexentry->file_name; + } + + directory_name = indexentry->directory_name; + str = indexentry->str; + + for (; stab < (indexentry+1)->stab; stab += STABSIZE) + { + boolean done; + bfd_vma val; + + done = false; + + switch (stab[TYPEOFF]) + { + case N_SOL: + /* The name of an include file. */ + val = bfd_get_32 (abfd, stab + VALOFF); + if (val <= offset) + { + file_name = (char *) str + bfd_get_32 (abfd, stab + STRDXOFF); + *pline = 0; + } + break; + + case N_SLINE: + case N_DSLINE: + case N_BSLINE: + /* A line number. The value is relative to the start of the + current function. */ + val = indexentry->val + bfd_get_32 (abfd, stab + VALOFF); + if (val <= offset) + { + *pline = bfd_get_16 (abfd, stab + DESCOFF); + +#ifdef ENABLE_CACHING + info->cached_stab = stab; + info->cached_offset = val; + info->cached_file_name = file_name; + info->cached_indexentry = indexentry; +#endif + } + if (val > offset) + done = true; + break; + + case N_FUN: + case N_SO: + done = true; + break; + } + + if (done) + break; + } + + *pfound = true; + + if (file_name[0] == '/' || directory_name == NULL) + *pfilename = file_name; + else + { + size_t dirlen; + + dirlen = strlen (directory_name); + if (info->filename == NULL + || strncmp (info->filename, directory_name, dirlen) != 0 + || strcmp (info->filename + dirlen, file_name) != 0) + { + if (info->filename != NULL) + free (info->filename); + info->filename = (char *) bfd_malloc (dirlen + + strlen (file_name) + + 1); + if (info->filename == NULL) + return false; + strcpy (info->filename, directory_name); + strcpy (info->filename + dirlen, file_name); + } + + *pfilename = info->filename; + } + + if (indexentry->function_name != NULL) + { + char *s; + + /* This will typically be something like main:F(0,1), so we want + to clobber the colon. It's OK to change the name, since the + string is in our own local storage anyhow. */ + + s = strchr (indexentry->function_name, ':'); + if (s != NULL) + *s = '\0'; + + *pfnname = indexentry->function_name; + } + + return true; +}