X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Fcofflink.c;h=c9d23f23d3cf251f83457534c1b2e825f975c472;hb=5dccc1ddaa1d8e543c1113a83df73c6d7e6973ec;hp=2f19641289a578381411d52a54f50d02b0a8c843;hpb=e98fe4f7b54cbdf29aef9287bbb1bea8801dd05a;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/cofflink.c b/bfd/cofflink.c index 2f19641289..c9d23f23d3 100644 --- a/bfd/cofflink.c +++ b/bfd/cofflink.c @@ -1,5 +1,5 @@ /* COFF specific linker code. - Copyright 1994, 1995, 1996, 1997 Free Software Foundation, Inc. + Copyright 1994, 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. Written by Ian Lance Taylor, Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -225,30 +225,25 @@ coff_link_check_ar_symbols (abfd, info, pneeded) struct bfd_link_info *info; boolean *pneeded; { - boolean (*sym_is_global) PARAMS ((bfd *, struct internal_syment *)); bfd_size_type symesz; bfd_byte *esym; bfd_byte *esym_end; *pneeded = false; - sym_is_global = coff_backend_info (abfd)->_bfd_coff_sym_is_global; - symesz = bfd_coff_symesz (abfd); esym = (bfd_byte *) obj_coff_external_syms (abfd); esym_end = esym + obj_raw_syment_count (abfd) * symesz; while (esym < esym_end) { struct internal_syment sym; + enum coff_symbol_classification classification; bfd_coff_swap_sym_in (abfd, (PTR) esym, (PTR) &sym); - if ((sym.n_sclass == C_EXT -#ifdef C_SYSTEM - || sym.n_sclass == C_SYSTEM -#endif - || (sym_is_global && (*sym_is_global) (abfd, &sym))) - && (sym.n_scnum != 0 || sym.n_value != 0)) + classification = bfd_coff_classify_symbol (abfd, &sym); + if (classification == COFF_SYMBOL_GLOBAL + || classification == COFF_SYMBOL_COMMON) { const char *name; char buf[SYMNMLEN + 1]; @@ -290,7 +285,6 @@ coff_link_add_symbols (abfd, info) bfd *abfd; struct bfd_link_info *info; { - boolean (*sym_is_global) PARAMS ((bfd *, struct internal_syment *)); boolean keep_syms; boolean default_copy; bfd_size_type symcount; @@ -304,8 +298,6 @@ coff_link_add_symbols (abfd, info) keep_syms = obj_coff_keep_syms (abfd); obj_coff_keep_syms (abfd) = true; - sym_is_global = coff_backend_info (abfd)->_bfd_coff_sym_is_global; - if (info->keep_memory) default_copy = false; else @@ -332,21 +324,20 @@ coff_link_add_symbols (abfd, info) while (esym < esym_end) { struct internal_syment sym; + enum coff_symbol_classification classification; boolean copy; bfd_coff_swap_sym_in (abfd, (PTR) esym, (PTR) &sym); - if (sym.n_sclass == C_EXT -#ifdef C_SYSTEM - || sym.n_sclass == C_SYSTEM -#endif - || (sym_is_global && (*sym_is_global) (abfd, &sym))) + classification = bfd_coff_classify_symbol (abfd, &sym); + if (classification != COFF_SYMBOL_LOCAL) { const char *name; char buf[SYMNMLEN + 1]; flagword flags; asection *section; bfd_vma value; + boolean addit; /* This symbol is externally visible. */ @@ -363,32 +354,73 @@ coff_link_add_symbols (abfd, info) value = sym.n_value; - if (sym.n_scnum == 0) - { - if (value == 0) - { - flags = 0; - section = bfd_und_section_ptr; - } - else - { - flags = BSF_GLOBAL; - section = bfd_com_section_ptr; - } - } - else + switch (classification) { + default: + abort (); + + case COFF_SYMBOL_GLOBAL: flags = BSF_EXPORT | BSF_GLOBAL; section = coff_section_from_bfd_index (abfd, sym.n_scnum); if (! obj_pe (abfd)) value -= section->vma; + break; + + case COFF_SYMBOL_UNDEFINED: + flags = 0; + section = bfd_und_section_ptr; + break; + + case COFF_SYMBOL_COMMON: + flags = BSF_GLOBAL; + section = bfd_com_section_ptr; + break; + + case COFF_SYMBOL_PE_SECTION: + flags = BSF_SECTION_SYM | BSF_GLOBAL; + section = coff_section_from_bfd_index (abfd, sym.n_scnum); + break; } - if (! (bfd_coff_link_add_one_symbol - (info, abfd, name, flags, section, value, - (const char *) NULL, copy, false, - (struct bfd_link_hash_entry **) sym_hash))) - goto error_return; + if (sym.n_sclass == C_WEAKEXT + || (obj_pe (abfd) && sym.n_sclass == C_NT_WEAK)) + flags = BSF_WEAK; + + addit = true; + + /* In the PE format, section symbols actually refer to the + start of the output section. We handle them specially + here. */ + if (obj_pe (abfd) && (flags & BSF_SECTION_SYM) != 0) + { + *sym_hash = coff_link_hash_lookup (coff_hash_table (info), + name, false, copy, false); + if (*sym_hash != NULL) + { + if (((*sym_hash)->coff_link_hash_flags + & COFF_LINK_HASH_PE_SECTION_SYMBOL) == 0 + && (*sym_hash)->root.type != bfd_link_hash_undefined + && (*sym_hash)->root.type != bfd_link_hash_undefweak) + (*_bfd_error_handler) + ("Warning: symbol `%s' is both section and non-section", + name); + + addit = false; + } + } + + if (addit) + { + if (! (bfd_coff_link_add_one_symbol + (info, abfd, name, flags, section, value, + (const char *) NULL, copy, false, + (struct bfd_link_hash_entry **) sym_hash))) + goto error_return; + } + + if (obj_pe (abfd) && (flags & BSF_SECTION_SYM) != 0) + (*sym_hash)->coff_link_hash_flags |= + COFF_LINK_HASH_PE_SECTION_SYMBOL; if (section == bfd_com_section_ptr && (*sym_hash)->root.type == bfd_link_hash_common @@ -403,7 +435,8 @@ coff_link_add_symbols (abfd, info) && (*sym_hash)->type == T_NULL) || sym.n_scnum != 0 || (sym.n_value != 0 - && (*sym_hash)->root.type != bfd_link_hash_defined)) + && (*sym_hash)->root.type != bfd_link_hash_defined + && (*sym_hash)->root.type != bfd_link_hash_defweak)) { (*sym_hash)->class = sym.n_sclass; if (sym.n_type != T_NULL) @@ -411,7 +444,7 @@ coff_link_add_symbols (abfd, info) if ((*sym_hash)->type != T_NULL && (*sym_hash)->type != sym.n_type) (*_bfd_error_handler) - ("Warning: type of symbol `%s' changed from %d to %d in %s", + (_("Warning: type of symbol `%s' changed from %d to %d in %s"), name, (*sym_hash)->type, sym.n_type, bfd_get_filename (abfd)); (*sym_hash)->type = sym.n_type; @@ -441,6 +474,26 @@ coff_link_add_symbols (abfd, info) } } } + + if (classification == COFF_SYMBOL_PE_SECTION + && (*sym_hash)->numaux != 0) + { + /* Some PE sections (such as .bss) have a zero size in + the section header, but a non-zero size in the AUX + record. Correct that here. + + FIXME: This is not at all the right place to do this. + For example, it won't help objdump. This needs to be + done when we swap in the section header. */ + + BFD_ASSERT ((*sym_hash)->numaux == 1); + if (section->_raw_size == 0) + section->_raw_size = (*sym_hash)->aux[0].x_scn.x_scnlen; + + /* FIXME: We could test whether the section sizes + matches the size in the aux entry, but apparently + that sometimes fails unexpectedly. */ + } } esym += (sym.n_numaux + 1) * symesz; @@ -1060,7 +1113,7 @@ char **dst; static int process_embedded_commands (output_bfd, info, abfd) bfd *output_bfd; - struct bfd_link_info *info; + struct bfd_link_info *info ATTRIBUTE_UNUSED; bfd *abfd; { asection *sec = bfd_get_section_by_name (abfd, ".drectve"); @@ -1203,7 +1256,6 @@ _bfd_coff_link_input_bfd (finfo, input_bfd) struct coff_final_link_info *finfo; bfd *input_bfd; { - boolean (*sym_is_global) PARAMS ((bfd *, struct internal_syment *)); boolean (*adjust_symndx) PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, struct internal_reloc *, boolean *)); @@ -1229,7 +1281,6 @@ _bfd_coff_link_input_bfd (finfo, input_bfd) /* Move all the symbols to the output file. */ output_bfd = finfo->output_bfd; - sym_is_global = coff_backend_info (input_bfd)->_bfd_coff_sym_is_global; strings = NULL; syment_base = obj_raw_syment_count (output_bfd); isymesz = bfd_coff_symesz (input_bfd); @@ -1284,6 +1335,7 @@ _bfd_coff_link_input_bfd (finfo, input_bfd) while (esym < esym_end) { struct internal_syment isym; + enum coff_symbol_classification classification; boolean skip; boolean global; boolean dont_skip_symbol; @@ -1297,14 +1349,22 @@ _bfd_coff_link_input_bfd (finfo, input_bfd) the symbol. */ isym = *isymp; - if (isym.n_scnum != 0) - *secpp = coff_section_from_bfd_index (input_bfd, isym.n_scnum); - else + classification = bfd_coff_classify_symbol (input_bfd, &isym); + switch (classification) { - if (isym.n_value == 0) - *secpp = bfd_und_section_ptr; - else - *secpp = bfd_com_section_ptr; + default: + abort (); + case COFF_SYMBOL_GLOBAL: + case COFF_SYMBOL_PE_SECTION: + case COFF_SYMBOL_LOCAL: + *secpp = coff_section_from_bfd_index (input_bfd, isym.n_scnum); + break; + case COFF_SYMBOL_COMMON: + *secpp = bfd_com_section_ptr; + break; + case COFF_SYMBOL_UNDEFINED: + *secpp = bfd_und_section_ptr; + break; } /* Extract the flag indicating if this symbol is used by a @@ -1328,26 +1388,34 @@ _bfd_coff_link_input_bfd (finfo, input_bfd) if (! skip) { - if (isym.n_sclass == C_EXT -#ifdef C_SYSTEM - || isym.n_sclass == C_SYSTEM -#endif - || (sym_is_global && (*sym_is_global) (input_bfd, &isym))) + switch (classification) { + default: + abort (); + case COFF_SYMBOL_GLOBAL: + case COFF_SYMBOL_COMMON: + case COFF_SYMBOL_PE_SECTION: /* This is a global symbol. Global symbols come at the end of the symbol table, so skip them for now. - Function symbols, however, are an exception, and are - not moved to the end. */ + Locally defined function symbols, however, are an + exception, and are not moved to the end. */ global = true; if (! ISFCN (isym.n_type)) skip = true; - } - else - { + break; + + case COFF_SYMBOL_UNDEFINED: + /* Undefined symbols are left for the end. */ + global = true; + skip = true; + break; + + case COFF_SYMBOL_LOCAL: /* This is a local symbol. Skip it if we are discarding local symbols. */ if (finfo->info->discard == discard_all && ! dont_skip_symbol) skip = true; + break; } } @@ -1648,7 +1716,10 @@ _bfd_coff_link_input_bfd (finfo, input_bfd) /* If doing task linking, convert normal global function symbols to static functions. */ - if (finfo->info->task_link && isym.n_sclass == C_EXT) + if (finfo->info->task_link + && (isym.n_sclass == C_EXT + || isym.n_sclass == C_WEAKEXT + || (obj_pe (input_bfd) && isym.n_sclass == C_NT_WEAK))) isym.n_sclass = C_STAT; /* Output the symbol. */ @@ -2076,7 +2147,7 @@ _bfd_coff_link_input_bfd (finfo, input_bfd) && o->reloc_count != 0) { ((*_bfd_error_handler) - ("%s: relocs in section `%s', but it has no contents", + (_("%s: relocs in section `%s', but it has no contents"), bfd_get_filename (input_bfd), bfd_get_section_name (input_bfd, o))); bfd_set_error (bfd_error_no_contents); @@ -2337,12 +2408,15 @@ _bfd_coff_write_global_sym (h, data) if (isym.n_sclass == C_NULL) isym.n_sclass = C_EXT; - /* If doing task linking and this is the pass where we convert defined globals to - statics, then do that conversion now. If the symbol is not being converted, - just ignore it and it will be output during a later pass. */ + /* If doing task linking and this is the pass where we convert + defined globals to statics, then do that conversion now. If the + symbol is not being converted, just ignore it and it will be + output during a later pass. */ if (finfo->global_to_static) { - if (isym.n_sclass != C_EXT) + if (isym.n_sclass != C_EXT + && isym.n_sclass != C_WEAKEXT + && (! obj_pe (output_bfd) || isym.n_sclass != C_NT_WEAK)) { return true; } @@ -2586,6 +2660,14 @@ _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd, h = NULL; sym = NULL; } + else if (symndx < 0 + || (unsigned long) symndx >= obj_raw_syment_count (input_bfd)) + { + (*_bfd_error_handler) + ("%s: illegal symbol index %ld in relocs", + bfd_get_filename (input_bfd), symndx); + return false; + } else { h = obj_coff_sym_hashes (input_bfd)[symndx]; @@ -2702,7 +2784,7 @@ _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd, break; case bfd_reloc_outofrange: (*_bfd_error_handler) - ("%s: bad reloc address 0x%lx in section `%s'", + (_("%s: bad reloc address 0x%lx in section `%s'"), bfd_get_filename (input_bfd), (unsigned long) rel->r_vaddr, bfd_get_section_name (input_bfd, input_section));