diff options
-rw-r--r-- | ld/config.h | 11 | ||||
-rw-r--r-- | ld/ldexp.c | 537 | ||||
-rw-r--r-- | ld/ldgram.y | 54 | ||||
-rw-r--r-- | ld/ldlang.c | 545 | ||||
-rw-r--r-- | ld/ldlang.h | 242 | ||||
-rw-r--r-- | ld/ldmain.c | 84 | ||||
-rw-r--r-- | ld/ldmisc.c | 176 | ||||
-rw-r--r-- | ld/ldsym.c | 58 |
8 files changed, 995 insertions, 712 deletions
diff --git a/ld/config.h b/ld/config.h index 838276b..50cc3ca 100644 --- a/ld/config.h +++ b/ld/config.h @@ -33,13 +33,9 @@ #define EBMON29K_EMULATION_NAME "ebmon29k" #define GLDI386AOUT_EMULATION_NAME "gldi386aout" /* Otherwise default to this emulation */ -#ifndef DEFAULT_EMULATION -#ifdef GNU960 -#define DEFAULT_EMULATION GLD960_EMULATION_NAME -#else -#define DEFAULT_EMULATION GLD68K_EMULATION_NAME -#endif -#endif /* DEFAULT_EMULATION */ + +#define DEFAULT_EMULATION LNK960_EMULATION_NAME + /* Look in this variable for a target format */ #define TARGET_ENVIRON "GNUTARGET" @@ -47,6 +43,7 @@ #define GLD_TARGET "a.out-sunos-big" #define GLD68K_TARGET "a.out-sunos-big" #define LNK960_TARGET "coff-Intel-big" +#define LNK960_TARGET_LITTLE "coff-Intel-little" #define GLD960_TARGET "b.out.big" #define VANILLA_TARGET "a.out-sunos-big" #define GLDM88KBCS_TARGET "m88kbcs" @@ -1,10 +1,12 @@ -/* Copyright (C) 1991 Free Software Foundation, Inc. +/* This module handles expression trees. +Copyright (C) 1991 Free Software Foundation, Inc. +Written by Steve Chamberlain of Cygnus Support (sac@cygnus.com). This file is part of GLD, the Gnu Linker. GLD 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) +the Free Software Foundation; either version 2, or (at your option) any later version. GLD is distributed in the hope that it will be useful, @@ -17,25 +19,23 @@ along with GLD; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* - $Id$ -*/ +This module is in charge of working out the contents of expressions. -/* - * Written by Steve Chamberlain - * steve@cygnus.com - * - * This module handles expression trees. - */ +It has to keep track of the relative/absness of a symbol etc. This is +done by keeping all values in a struct (an etree_value_type) which +contains a value, a section to which it is relative and a valid bit. + +*/ -#include "sysdep.h" #include "bfd.h" +#include "sysdep.h" #include "ld.h" #include "ldmain.h" #include "ldmisc.h" #include "ldexp.h" -#include "ldgram.tab.h" +#include "ldgram.h" #include "ldsym.h" #include "ldlang.h" @@ -43,7 +43,7 @@ extern char *output_filename; extern unsigned int undefined_global_sym_count; extern unsigned int defined_global_sym_count; extern bfd *output_bfd; -extern size_t largest_section; +extern bfd_size_type largest_section; extern lang_statement_list_type file_chain; extern args_type command_line; extern ld_config_type config; @@ -55,55 +55,55 @@ extern bfd_vma print_dot; static void -exp_print_token(outfile, code) -FILE *outfile; -token_code_type code; +DEFUN(exp_print_token,(outfile, code), + FILE *outfile AND + token_code_type code) { static struct { token_code_type code; char *name; } table[] = - { - INT, "int", - NAME,"NAME", - PLUSEQ,"+=", - MINUSEQ,"-=", - MULTEQ,"*=", - DIVEQ,"/=", - LSHIFTEQ,"<<=", - RSHIFTEQ,">>=", - ANDEQ,"&=", - OREQ,"|=", - OROR,"||", - ANDAND,"&&", - EQ,"==", - NE,"!=", - LE,"<=", - GE,">=", - LSHIFT,"<<", - RSHIFT,">>=", - ALIGN_K,"ALIGN", - BLOCK,"BLOCK", - SECTIONS,"SECTIONS", - SIZEOF_HEADERS,"SIZEOF_HEADERS", - NEXT,"NEXT", - SIZEOF,"SIZEOF", - ADDR,"ADDR", - MEMORY,"MEMORY", - - - - - - DEFINED,"DEFINED", - TARGET_K,"TARGET", - SEARCH_DIR,"SEARCH_DIR", - MAP,"MAP", - LONG,"LONG", - SHORT,"SHORT", - BYTE,"BYTE", - ENTRY,"ENTRY", - 0,(char *)NULL} ; + { + INT, "int", + NAME,"NAME", + PLUSEQ,"+=", + MINUSEQ,"-=", + MULTEQ,"*=", + DIVEQ,"/=", + LSHIFTEQ,"<<=", + RSHIFTEQ,">>=", + ANDEQ,"&=", + OREQ,"|=", + OROR,"||", + ANDAND,"&&", + EQ,"==", + NE,"!=", + LE,"<=", + GE,">=", + LSHIFT,"<<", + RSHIFT,">>=", + ALIGN_K,"ALIGN", + BLOCK,"BLOCK", + SECTIONS,"SECTIONS", + SIZEOF_HEADERS,"SIZEOF_HEADERS", + NEXT,"NEXT", + SIZEOF,"SIZEOF", + ADDR,"ADDR", + MEMORY,"MEMORY", + + + + + + DEFINED,"DEFINED", + TARGET_K,"TARGET", + SEARCH_DIR,"SEARCH_DIR", + MAP,"MAP", + LONG,"LONG", + SHORT,"SHORT", + BYTE,"BYTE", + ENTRY,"ENTRY", + 0,(char *)NULL} ; @@ -119,8 +119,8 @@ token_code_type code; } static void -make_abs(ptr) -etree_value_type *ptr; +DEFUN(make_abs,(ptr), + etree_value_type *ptr) { if (ptr->section != (lang_output_section_statement_type *)NULL) { asection *s = ptr->section->bfd_section; @@ -129,9 +129,10 @@ etree_value_type *ptr; } } + static -etree_value_type new_abs(value) -bfd_vma value; +DEFUN(etree_value_type new_abs,(value), + bfd_vma value) { etree_value_type new; new.valid = true; @@ -147,17 +148,18 @@ DEFUN(check, (os, name, op), CONST char *op) { if (os == (lang_output_section_statement_type *)NULL) { - info("%F%P %s uses undefined section %s\n", op, name); + einfo("%F%P %s uses undefined section %s\n", op, name); } if (os->processed == false) { - info("%F%P %s forward reference of section %s\n",op, name); + einfo("%F%P %s forward reference of section %s\n",op, name); } } -etree_type *exp_intop(value) -bfd_vma value; +etree_type * +DEFUN(exp_intop,(value), + bfd_vma value) { - etree_type *new = (etree_type *)ldmalloc(sizeof(new->value)); + etree_type *new = (etree_type *)ldmalloc((bfd_size_type)(sizeof(new->value))); new->type.node_code = INT; new->value.value = value; new->type.node_class = etree_value; @@ -167,9 +169,9 @@ bfd_vma value; static -etree_value_type new_rel(value, section) -bfd_vma value; -lang_output_section_statement_type *section; +DEFUN(etree_value_type new_rel,(value, section), + bfd_vma value AND + lang_output_section_statement_type *section) { etree_value_type new; new.valid = true; @@ -179,9 +181,10 @@ lang_output_section_statement_type *section; } static -etree_value_type new_rel_from_section(value, section) -bfd_vma value; -lang_output_section_statement_type *section; +DEFUN(etree_value_type + new_rel_from_section, (value, section), + bfd_vma value AND + lang_output_section_statement_type *section) { etree_value_type new; new.valid = true; @@ -194,12 +197,12 @@ lang_output_section_statement_type *section; } static etree_value_type -fold_binary(tree, current_section, allocation_done, dot, dotp) -etree_type *tree; -lang_output_section_statement_type *current_section; -lang_phase_type allocation_done; -bfd_vma dot; -bfd_vma *dotp; +DEFUN(fold_binary,(tree, current_section, allocation_done, dot, dotp), + etree_type *tree AND + lang_output_section_statement_type *current_section AND + lang_phase_type allocation_done AND + bfd_vma dot AND + bfd_vma *dotp) { etree_value_type result; @@ -226,13 +229,13 @@ bfd_vma *dotp; /* Mod, both absolule*/ if (other.value == 0) { - info("%F%S % by zero\n"); + einfo("%F%S % by zero\n"); } result.value %= other.value; break; case '/': if (other.value == 0) { - info("%F%S / by zero\n"); + einfo("%F%S / by zero\n"); } result.value /= other.value; break; @@ -263,19 +266,20 @@ bfd_vma *dotp; } return result; } -etree_value_type invalid() +etree_value_type +DEFUN_VOID(invalid) { etree_value_type new; new.valid = false; return new; } -etree_value_type fold_name(tree, current_section, allocation_done, dot) -etree_type *tree; -lang_output_section_statement_type *current_section; -lang_phase_type allocation_done; -bfd_vma dot; - +etree_value_type +DEFUN(fold_name, (tree, current_section, allocation_done, dot), + etree_type *tree AND + lang_output_section_statement_type *current_section AND + lang_phase_type allocation_done AND + bfd_vma dot) { etree_value_type result; switch (tree->type.node_code) @@ -341,7 +345,7 @@ bfd_vma dot; } } if (result.valid == false) { - info("%F%S: undefined symbol `%s' referenced in expression.\n", + einfo("%F%S: undefined symbol `%s' referenced in expression.\n", tree->name.name); } @@ -367,7 +371,7 @@ bfd_vma dot; lang_output_section_statement_type *os = lang_output_section_find(tree->name.name); check(os,tree->name.name,"SIZEOF"); - result = new_abs((bfd_vma)(os->bfd_section->size)); + result = new_abs((bfd_vma)(os->bfd_section->_raw_size)); } else { result = invalid(); @@ -381,118 +385,119 @@ bfd_vma dot; return result; } -etree_value_type exp_fold_tree(tree, current_section, allocation_done, - dot, dotp) -etree_type *tree; -lang_output_section_statement_type *current_section; -lang_phase_type allocation_done; -bfd_vma dot; -bfd_vma *dotp; +etree_value_type +DEFUN(exp_fold_tree,(tree, current_section, allocation_done, + dot, dotp), + etree_type *tree AND + lang_output_section_statement_type *current_section AND + lang_phase_type allocation_done AND + bfd_vma dot AND + bfd_vma *dotp) { etree_value_type result; if (tree == (etree_type *)NULL) { - result.valid = false; - } + result.valid = false; + } else { - switch (tree->type.node_class) + switch (tree->type.node_class) + { + case etree_value: + result = new_rel(tree->value.value, current_section); + break; + case etree_unary: + result = exp_fold_tree(tree->unary.child, + current_section, + allocation_done, dot, dotp); + if (result.valid == true) { - case etree_value: - result = new_rel(tree->value.value, current_section); - break; - case etree_unary: - result = exp_fold_tree(tree->unary.child, - current_section, - allocation_done, dot, dotp); - if (result.valid == true) - { - switch(tree->type.node_code) - { - case ALIGN_K: - if (allocation_done != lang_first_phase_enum) { - result = new_rel_from_section(ALIGN(dot, - result.value) , - current_section); + switch(tree->type.node_code) + { + case ALIGN_K: + if (allocation_done != lang_first_phase_enum) { + result = new_rel_from_section(ALIGN(dot, + result.value) , + current_section); - } - else { - result.valid = false; - } - break; - case '~': - make_abs(&result); - result.value = ~result.value; - break; - case '!': - make_abs(&result); - result.value = !result.value; - break; - case '-': - make_abs(&result); - result.value = -result.value; - break; - case NEXT: - if (allocation_done ==lang_allocating_phase_enum) { - make_abs(&result); - result.value = ALIGN(dot, result.value); - } - else { - /* Return next place aligned to value */ - result.valid = false; - } - break; - default: - FAIL(); - } } + else { + result.valid = false; + } + break; + case '~': + make_abs(&result); + result.value = ~result.value; + break; + case '!': + make_abs(&result); + result.value = !result.value; + break; + case '-': + make_abs(&result); + result.value = -result.value; + break; + case NEXT: + if (allocation_done ==lang_allocating_phase_enum) { + make_abs(&result); + result.value = ALIGN(dot, result.value); + } + else { + /* Return next place aligned to value */ + result.valid = false; + } + break; + default: + FAIL(); + } + } - break; - case etree_trinary: + break; + case etree_trinary: - result = exp_fold_tree(tree->trinary.cond, - current_section, - allocation_done, dot, dotp); - if (result.valid) { + result = exp_fold_tree(tree->trinary.cond, + current_section, + allocation_done, dot, dotp); + if (result.valid) { result = exp_fold_tree(result.value ? tree->trinary.lhs:tree->trinary.rhs, current_section, allocation_done, dot, dotp); } - break; - case etree_binary: - result = fold_binary(tree, current_section, allocation_done, - dot, dotp); - break; - case etree_assign: - if (tree->assign.dst[0] == '.' && tree->assign.dst[1] == 0) { + break; + case etree_binary: + result = fold_binary(tree, current_section, allocation_done, + dot, dotp); + break; + case etree_assign: + if (tree->assign.dst[0] == '.' && tree->assign.dst[1] == 0) { /* Assignment to dot can only be done during allocation */ if (allocation_done == lang_allocating_phase_enum) { - result = exp_fold_tree(tree->assign.src, - current_section, - lang_allocating_phase_enum, dot, dotp); - if (result.valid == false) { - info("%F%S invalid assignment to location counter\n"); - } - else { - if (current_section == - (lang_output_section_statement_type *)NULL) { - info("%F%S assignment to location counter invalid outside of SECTION\n"); - } - else { - unsigned long nextdot =result.value + - current_section->bfd_section->vma; - if (nextdot < dot) { - info("%F%S cannot move location counter backwards"); + result = exp_fold_tree(tree->assign.src, + current_section, + lang_allocating_phase_enum, dot, dotp); + if (result.valid == false) { + einfo("%F%S invalid assignment to location counter\n"); } - else { - *dotp = nextdot; + else { + if (current_section == + (lang_output_section_statement_type *)NULL) { + einfo("%F%S assignment to location counter invalid outside of SECTION\n"); + } + else { + unsigned long nextdot =result.value + + current_section->bfd_section->vma; + if (nextdot < dot) { + einfo("%F%S cannot move location counter backwards"); + } + else { + *dotp = nextdot; + } + } } - } } - } } - else { + else { ldsym_type *sy = ldsym_get(tree->assign.dst); /* If this symbol has just been created then we'll place it into @@ -502,74 +507,89 @@ bfd_vma *dotp; current_section, allocation_done, dot, dotp); if (result.valid) - { - asymbol *def; - asymbol **def_ptr = (asymbol **)ldmalloc(sizeof(asymbol **)); - /* Add this definition to script file */ - def = (asymbol *)bfd_make_empty_symbol(script_file->the_bfd); - *def_ptr = def; - - - def->value = result.value; - if (result.section != - (lang_output_section_statement_type *)NULL) { - if (current_section != - (lang_output_section_statement_type *)NULL) { + { + asymbol *def; + asymbol **def_ptr ; + /* Add this definition to script file */ + if (sy->sdefs_chain) + { + def_ptr = sy->sdefs_chain; + def = *def_ptr; + + } + else + { + def_ptr = (asymbol **)ldmalloc((bfd_size_type)(sizeof(asymbol **))); + def = (asymbol + *)bfd_make_empty_symbol(script_file->the_bfd); + + + + *def_ptr = def; + } + + def->value = result.value; + if (result.section != + (lang_output_section_statement_type *)NULL) { + if (current_section != + (lang_output_section_statement_type *)NULL) { def->section = result.section->bfd_section; def->flags = BSF_GLOBAL | BSF_EXPORT; } - else { + else { /* Force to absolute */ def->value += result.section->bfd_section->vma; - def->section = (asection *)NULL; - def->flags = BSF_GLOBAL | BSF_EXPORT | BSF_ABSOLUTE; + def->section = &bfd_abs_section; + def->flags = BSF_GLOBAL | BSF_EXPORT ; } - } - else { - def->section = (asection *)NULL; - def->flags = BSF_GLOBAL | BSF_EXPORT | BSF_ABSOLUTE; - } + } + else { + def->section = &bfd_abs_section; + def->flags = BSF_GLOBAL | BSF_EXPORT ; + } - def->udata = (PTR)NULL; - def->name = sy->name; - Q_enter_global_ref(def_ptr); - } + def->udata = (PTR)NULL; + def->name = sy->name; + + if (sy->sdefs_chain == 0) Q_enter_global_ref(def_ptr); + } } - break; - case etree_name: - result = fold_name(tree, current_section, allocation_done, dot); - break; - default: - info("%F%S Need more of these %d",tree->type.node_class ); + break; + case etree_name: + result = fold_name(tree, current_section, allocation_done, dot); + break; + default: + einfo("%F%S Need more of these %d",tree->type.node_class ); - } - } + } + } return result; } -etree_value_type exp_fold_tree_no_dot(tree, current_section, allocation_done) -etree_type *tree; -lang_output_section_statement_type *current_section; -lang_phase_type allocation_done; +etree_value_type +DEFUN(exp_fold_tree_no_dot,(tree, current_section, allocation_done), + etree_type *tree AND + lang_output_section_statement_type *current_section AND + lang_phase_type allocation_done) { return exp_fold_tree(tree, current_section, allocation_done, (bfd_vma) 0, (bfd_vma *)NULL); } etree_type * -exp_binop(code, lhs, rhs) -int code; -etree_type *lhs; -etree_type *rhs; +DEFUN(exp_binop,(code, lhs, rhs), + int code AND + etree_type *lhs AND + etree_type *rhs) { etree_type value, *new; etree_value_type r; @@ -584,17 +604,17 @@ etree_type *rhs; { return exp_intop(r.value); } - new = (etree_type *)ldmalloc(sizeof(new->binary)); + new = (etree_type *)ldmalloc((bfd_size_type)(sizeof(new->binary))); memcpy((char *)new, (char *)&value, sizeof(new->binary)); return new; } etree_type * -exp_trinop(code, cond, lhs, rhs) -int code; -etree_type *cond; -etree_type *lhs; -etree_type *rhs; +DEFUN(exp_trinop,(code, cond, lhs, rhs), + int code AND + etree_type *cond AND + etree_type *lhs AND + etree_type *rhs) { etree_type value, *new; etree_value_type r; @@ -608,16 +628,16 @@ etree_type *rhs; if (r.valid) { return exp_intop(r.value); } - new = (etree_type *)ldmalloc(sizeof(new->trinary)); + new = (etree_type *)ldmalloc((bfd_size_type)(sizeof(new->trinary))); memcpy((char *)new,(char *) &value, sizeof(new->trinary)); return new; } etree_type * -exp_unop(code, child) -int code; -etree_type *child; +DEFUN(exp_unop,(code, child), + int code AND + etree_type *child) { etree_type value, *new; @@ -625,21 +645,21 @@ etree_type *child; value.unary.type.node_code = code; value.unary.child = child; value.unary.type.node_class = etree_unary; -r = exp_fold_tree_no_dot(&value,(lang_output_section_statement_type *)NULL, - lang_first_phase_enum); -if (r.valid) { + r = exp_fold_tree_no_dot(&value,(lang_output_section_statement_type *)NULL, + lang_first_phase_enum); + if (r.valid) { return exp_intop(r.value); } - new = (etree_type *)ldmalloc(sizeof(new->unary)); + new = (etree_type *)ldmalloc((bfd_size_type)(sizeof(new->unary))); memcpy((char *)new, (char *)&value, sizeof(new->unary)); return new; } etree_type * -exp_nameop(code, name) -int code; -char *name; +DEFUN(exp_nameop,(code, name), + int code AND + CONST char *name) { etree_type value, *new; @@ -655,7 +675,7 @@ char *name; if (r.valid) { return exp_intop(r.value); } - new = (etree_type *)ldmalloc(sizeof(new->name)); + new = (etree_type *)ldmalloc((bfd_size_type)(sizeof(new->name))); memcpy((char *)new, (char *)&value, sizeof(new->name)); return new; @@ -665,10 +685,10 @@ char *name; etree_type * -exp_assop(code, dst, src) -int code; -char *dst; -etree_type *src; +DEFUN(exp_assop,(code, dst, src), + int code AND + CONST char *dst AND + etree_type *src) { etree_type value, *new; @@ -684,20 +704,21 @@ etree_type *src; return exp_intop(result); } #endif - new = (etree_type*)ldmalloc(sizeof(new->assign)); + new = (etree_type*)ldmalloc((bfd_size_type)(sizeof(new->assign))); memcpy((char *)new, (char *)&value, sizeof(new->assign)); return new; } void -exp_print_tree(outfile, tree) -FILE *outfile; -etree_type *tree; +DEFUN(exp_print_tree,(outfile, tree), + FILE *outfile AND + etree_type *tree) { switch (tree->type.node_class) { case etree_value: - fprintf(outfile,"0x%08lx",(bfd_vma)(tree->value.value)); + print_address(tree->value.value); return; + case etree_assign: #if 0 if (tree->assign.dst->sdefs != (asymbol *)NULL){ @@ -752,11 +773,11 @@ etree_type *tree; bfd_vma -exp_get_vma(tree, def, name, allocation_done) -etree_type *tree; -bfd_vma def; -char *name; -lang_phase_type allocation_done; +DEFUN(exp_get_vma,(tree, def, name, allocation_done), + etree_type *tree AND + bfd_vma def AND + char *name AND + lang_phase_type allocation_done) { etree_value_type r; @@ -765,7 +786,7 @@ lang_phase_type allocation_done; (lang_output_section_statement_type *)NULL, allocation_done); if (r.valid == false && name) { - info("%F%S Nonconstant expression for %s\n",name); + einfo("%F%S Nonconstant expression for %s\n",name); } return r.value; } @@ -775,11 +796,11 @@ lang_phase_type allocation_done; } int -exp_get_value_int(tree,def,name, allocation_done) -etree_type *tree; -int def; -char *name; -lang_phase_type allocation_done; +DEFUN(exp_get_value_int,(tree,def,name, allocation_done), + etree_type *tree AND + int def AND + char *name AND + lang_phase_type allocation_done) { return (int)exp_get_vma(tree,(bfd_vma)def,name, allocation_done); } diff --git a/ld/ldgram.y b/ld/ldgram.y index bd8d0b6..a5b1731 100644 --- a/ld/ldgram.y +++ b/ld/ldgram.y @@ -1,18 +1,27 @@ -%{ -/* - * $Id$ - * - * -*/ +/* A YACC grammer to parse a superset of the AT&T linker scripting languaue. + Copyright (C) 1991 Free Software Foundation, Inc. + Written by Steve Chamberlain of Cygnus Support (steve@cygnus.com). -/* - This is a YACC grammer intended to parse a superset of the AT&T - linker scripting languaue. +This file is part of GNU ld. +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 2 of the License, or +(at your option) any later version. - Written by Steve Chamberlain steve@cygnus.com -*/ +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 this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +%{ +/* + * $Id$ + */ #define DONTDECLARE_MALLOC @@ -33,7 +42,7 @@ boolean option_v; extern unsigned int lineno; extern boolean trace_files; extern boolean write_map; - +extern boolean option_longmap; boolean hex_mode; strip_symbols_type strip_symbols=STRIP_NONE; @@ -127,8 +136,8 @@ boolean ldgram_had_equals = false; %token OPTION_format OPTION_F OPTION_u OPTION_Bstatic OPTION_N %token <integer> SIZEOF NEXT ADDR %token OPTION_d OPTION_dc OPTION_dp OPTION_x OPTION_X OPTION_defsym -%token OPTION_v OPTION_M OPTION_t STARTUP HLL SYSLIB FLOAT NOFLOAT -%token OPTION_n OPTION_r OPTION_o OPTION_b OPTION_R +%token OPTION_v OPTION_V OPTION_M OPTION_t STARTUP HLL SYSLIB FLOAT NOFLOAT +%token OPTION_n OPTION_r OPTION_o OPTION_b OPTION_R OPTION_relax %token <name> OPTION_l OPTION_L OPTION_T OPTION_Aarch OPTION_Tfile OPTION_Texp %token OPTION_Ur %token ORIGIN FILL OPTION_g @@ -168,17 +177,26 @@ command_line_option: ldversion(); option_v = true; } + | OPTION_V + { + ldversion(); + option_v = true; + } | OPTION_t { trace_files = true; } | OPTION_M { + if (write_map) { + option_longmap = true; + } write_map = true; + } | OPTION_n { config.magic_demand_paged = false; - config.text_read_only = true; } | OPTION_N { + config.text_read_only = false; config.magic_demand_paged = false; } | OPTION_s { @@ -195,11 +213,13 @@ command_line_option: config.relocateable_output = true; config.build_constructors = false; config.magic_demand_paged = false; + config.text_read_only = false; } | OPTION_Ur { config.relocateable_output = true; config.build_constructors = true; config.magic_demand_paged = false; + config.text_read_only = false; } | OPTION_o filename { @@ -225,6 +245,10 @@ command_line_option: | OPTION_d { command_line.force_common_definition = true; } + + | OPTION_relax { + command_line.relax = true; + } | OPTION_dc { command_line.force_common_definition = true; diff --git a/ld/ldlang.c b/ld/ldlang.c index c7ceba2..e974356 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -33,6 +33,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ldemul.h" #include "ldlex.h" #include "ldmisc.h" +#include "ldindr.h" +#include "ldctor.h" /* FORWARDS */ PROTO(static void, print_statements,(void)); PROTO(static void, print_statement,(lang_statement_union_type *, @@ -47,8 +49,8 @@ static lang_statement_list_type input_file_chain; stuff to the data section without pain */ static lang_statement_list_type end_of_data_section_statement_list; -/* List of statements needed to handle consxtructors */ -static lang_statement_list_type constructor_list; +/* List of statements needed to handle constructors */ +extern lang_statement_list_type constructor_list; static boolean placed_commons = false; static lang_output_section_statement_type *default_common_section; @@ -63,6 +65,7 @@ static asection common_section; static section_userdata_type common_section_userdata; static lang_statement_list_type statement_list; /* EXPORTS */ +boolean relaxing; lang_statement_list_type *stat_ptr = &statement_list; lang_input_statement_type *script_file = 0; @@ -186,7 +189,7 @@ DEFUN(lang_for_each_statement,(func), statement_list.head); } /*----------------------------------------------------------------------*/ -static void +void DEFUN(lang_list_init,(list), lang_statement_list_type *list) { @@ -492,17 +495,17 @@ static void DEFUN(init_os,(s), lang_output_section_statement_type *s) { - section_userdata_type *new = - (section_userdata_type *) + asection *section = bfd_get_section_by_name(output_bfd, s->name); + section_userdata_type *new = + (section_userdata_type *) ldmalloc((bfd_size_type)(sizeof(section_userdata_type))); s->bfd_section = bfd_get_section_by_name(output_bfd, s->name); if (s->bfd_section == (asection *)NULL) s->bfd_section = bfd_make_section(output_bfd, s->name); if (s->bfd_section == (asection *)NULL) { - info("%P%F output format %s cannot represent section called %s\n", - output_bfd->xvec->name, - s->name); + einfo("%P%F output format %s cannot represent section called %s\n", + output_bfd->xvec->name, s->name); } s->bfd_section->output_section = s->bfd_section; /* s->bfd_section->flags = s->flags;*/ @@ -511,6 +514,7 @@ DEFUN(init_os,(s), /* vma to allow us to output a section through itself */ s->bfd_section->output_offset = 0; get_userdata( s->bfd_section) = (PTR)new; + } /*********************************************************************** @@ -678,12 +682,12 @@ DEFUN(open_output,(name), if (output == (bfd *)NULL) { if (bfd_error == invalid_target) { - info("%P%F target %s not found\n", output_target); + einfo("%P%F target %s not found\n", output_target); } - info("%P%F problem opening output file %s, %E", name); + einfo("%P%F problem opening output file %s, %E", name); } - output->flags |= D_PAGED; +/* output->flags |= D_PAGED;*/ bfd_set_format(output, bfd_object); return output; } @@ -701,7 +705,7 @@ DEFUN(ldlang_open_output,(statement), output_bfd = open_output(statement->output_statement.name); ldemul_set_output_arch(); if (config.magic_demand_paged && !config.relocateable_output) - output_bfd->flags |= ~D_PAGED; + output_bfd->flags |= D_PAGED; else output_bfd->flags &= ~D_PAGED; if (config.text_read_only) @@ -809,8 +813,7 @@ DEFUN_VOID(lang_place_undefineds) def = (asymbol *)bfd_make_empty_symbol(script_file->the_bfd); *def_ptr= def; def->name = ptr->name; - def->flags = BSF_UNDEFINED; - def->section = (asection *)NULL; + def->section = &bfd_und_section; Q_enter_global_ref(def_ptr); ptr = ptr->next; } @@ -901,8 +904,8 @@ DEFUN(map_input_to_output_sections,(s, target, output_section_statement), (s->address_statement.section_name); os->addr_tree = s->address_statement.address; if (os->bfd_section == (asection *)NULL) { - info("%P%F can't set the address of undefined section %s\n", - s->address_statement.section_name); + einfo("%P%F can't set the address of undefined section %s\n", + s->address_statement.section_name); } } break; @@ -933,7 +936,7 @@ DEFUN(print_output_section_statement,(output_section_statement), print_space(); print_address(section->vma); print_space(); - print_size(section->size); + print_size(bfd_get_section_size_before_reloc(section)); print_space(); print_alignment(section->alignment_power); print_space(); @@ -1017,8 +1020,12 @@ DEFUN(print_input_section,(in), lang_input_section_type *in) { asection *i = in->section; + int size = i->flags & SEC_HAS_CONTENTS ? + bfd_get_section_size_after_reloc(i) : + bfd_get_section_size_before_reloc(i); + - if(i->size != 0) { + if(size != 0) { print_section(""); printf(" "); print_section(i->name); @@ -1026,7 +1033,7 @@ DEFUN(print_input_section,(in), if (i->output_section) { print_address(i->output_section->vma + i->output_offset); printf(" "); - print_size(i->size); + print_size(size); printf(" "); print_alignment(i->alignment_power); printf(" "); @@ -1065,7 +1072,7 @@ DEFUN(print_input_section,(in), } - print_dot = outside_section_address(i) + i->size; + print_dot = outside_section_address(i) + size; } else { printf("No output section allocated\n"); @@ -1160,65 +1167,64 @@ DEFUN(print_statement,(s, os), lang_statement_union_type *s AND lang_output_section_statement_type *os) { - while (s) { - switch (s->header.type) { - case lang_constructors_statement_enum: - printf("constructors:\n"); -print_statement(constructor_list.head, os); -break; - - case lang_wild_statement_enum: - print_wild_statement(&s->wild_statement, os); - break; - default: - printf("Fail with %d\n",s->header.type); - FAIL(); - break; - case lang_address_statement_enum: - printf("address\n"); - break; - break; - case lang_object_symbols_statement_enum: - printf("object symbols\n"); - break; - case lang_fill_statement_enum: - print_fill_statement(&s->fill_statement); - break; - case lang_data_statement_enum: - print_data_statement(&s->data_statement); - break; - case lang_input_section_enum: - print_input_section(&s->input_section); - break; - case lang_padding_statement_enum: - print_padding_statement(&s->padding_statement); - break; - case lang_output_section_statement_enum: - print_output_section_statement(&s->output_section_statement); - break; - case lang_assignment_statement_enum: - print_assignment(&s->assignment_statement, - os); - break; - - - case lang_target_statement_enum: - printf("TARGET(%s)\n", s->target_statement.target); - break; - case lang_output_statement_enum: - printf("OUTPUT(%s %s)\n", - s->output_statement.name, - output_target); - break; - case lang_input_statement_enum: - print_input_statement(&s->input_statement); - break; - case lang_afile_asection_pair_statement_enum: - FAIL(); - break; + while (s) + { + switch (s->header.type) + { + case lang_constructors_statement_enum: + printf("constructors:\n"); + print_statement(constructor_list.head, os); + break; + case lang_wild_statement_enum: + print_wild_statement(&s->wild_statement, os); + break; + default: + printf("Fail with %d\n",s->header.type); + FAIL(); + break; + case lang_address_statement_enum: + printf("address\n"); + break; + break; + case lang_object_symbols_statement_enum: + printf("object symbols\n"); + break; + case lang_fill_statement_enum: + print_fill_statement(&s->fill_statement); + break; + case lang_data_statement_enum: + print_data_statement(&s->data_statement); + break; + case lang_input_section_enum: + print_input_section(&s->input_section); + break; + case lang_padding_statement_enum: + print_padding_statement(&s->padding_statement); + break; + case lang_output_section_statement_enum: + print_output_section_statement(&s->output_section_statement); + break; + case lang_assignment_statement_enum: + print_assignment(&s->assignment_statement, + os); + break; + case lang_target_statement_enum: + printf("TARGET(%s)\n", s->target_statement.target); + break; + case lang_output_statement_enum: + printf("OUTPUT(%s %s)\n", + s->output_statement.name, + output_target); + break; + case lang_input_statement_enum: + print_input_statement(&s->input_statement); + break; + case lang_afile_asection_pair_statement_enum: + FAIL(); + break; + } + s = s->next; } - s = s->next; - } } @@ -1268,7 +1274,7 @@ DEFUN(insert_pad,(this_ptr, fill, power, output_section_statement, dot), if (power > output_section_statement->alignment_power) { output_section_statement->alignment_power = power; } - output_section_statement->size += alignment_needed; + output_section_statement->_raw_size += alignment_needed; return alignment_needed + dot; } @@ -1293,8 +1299,8 @@ DEFUN(size_input_section, (this_ptr, output_section_statement, fill, dot), which we will actually allocate */ if (((i->flags & (SEC_HAS_CONTENTS | SEC_LOAD)) == (SEC_HAS_CONTENTS | SEC_LOAD)) - && (i->size > largest_section)) { - largest_section = i->size; + && (bfd_get_section_size_before_reloc(i) > largest_section)) { + largest_section = bfd_get_section_size_before_reloc(i); } /* Remember where in the output section this input section goes */ @@ -1302,8 +1308,8 @@ DEFUN(size_input_section, (this_ptr, output_section_statement, fill, dot), i->output_offset = dot - output_section_statement->bfd_section->vma; /* Mark how big the output section must be to contain this now */ - dot += i->size; - output_section_statement->bfd_section->size = + dot += bfd_get_section_size_before_reloc(i); +output_section_statement->bfd_section->_raw_size = dot - output_section_statement->bfd_section->vma; } else @@ -1314,16 +1320,18 @@ DEFUN(size_input_section, (this_ptr, output_section_statement, fill, dot), return dot ; } - +#if 0 /* Work out the size of the output sections - from the sizes of the input sections */ + from the sizes of the input sections */ static bfd_vma -DEFUN(lang_size_sections,(s, output_section_statement, prev, fill, dot), +DEFUN(lang_size_sections,(s, output_section_statement, prev, fill, + dot), lang_statement_union_type *s AND lang_output_section_statement_type * output_section_statement AND lang_statement_union_type **prev AND unsigned short fill AND bfd_vma dot) + { /* Size up the sections from their constituent parts */ for (; s != (lang_statement_union_type *)NULL ; s = s->next) @@ -1354,7 +1362,7 @@ DEFUN(lang_size_sections,(s, output_section_statement, prev, fill, dot), lang_allocating_phase_enum, dot, &dot); if (r.valid == false) { - info("%F%S: non constant address expression for section %s\n", + einfo("%F%S: non constant address expression for section %s\n", os->name); } dot = r.value; @@ -1399,7 +1407,7 @@ DEFUN(lang_size_sections,(s, output_section_statement, prev, fill, dot), case lang_data_statement_enum: { - unsigned int size; + unsigned int size = 0; s->data_statement.output_vma = dot - output_section_statement->bfd_section->vma; s->data_statement.output_section = output_section_statement->bfd_section; @@ -1492,7 +1500,200 @@ DEFUN(lang_size_sections,(s, output_section_statement, prev, fill, dot), } return dot; } +#else +/* Sizing happens in two passes, first pass we allocate worst case + stuff. The second pass (if relaxing), we use what we learnt to + change the size of some relocs from worst case to better + */ +static boolean had_relax; + +static bfd_vma +DEFUN(lang_size_sections,(s, output_section_statement, prev, fill, + dot, relax), + lang_statement_union_type *s AND + lang_output_section_statement_type * output_section_statement AND + lang_statement_union_type **prev AND + unsigned short fill AND + bfd_vma dot AND + boolean relax) +{ + /* Size up the sections from their constituent parts */ + for (; s != (lang_statement_union_type *)NULL ; s = s->next) + { + switch (s->header.type) { + + case lang_output_section_statement_enum: + { + bfd_vma after; + lang_output_section_statement_type *os = + &(s->output_section_statement); + /* The start of a section */ + + if (os->addr_tree == (etree_type *)NULL) { + /* No address specified for this section, get one + from the region specification + */ + if (os->region == (lang_memory_region_type *)NULL) { + os->region = lang_memory_region_lookup("*default*"); + } + dot = os->region->current; + } + else { + etree_value_type r ; + r = exp_fold_tree(os->addr_tree, + (lang_output_section_statement_type *)NULL, + lang_allocating_phase_enum, + dot, &dot); + if (r.valid == false) { + einfo("%F%S: non constant address expression for section %s\n", + os->name); + } + dot = r.value; + } + /* The section starts here */ + /* First, align to what the section needs */ + + dot = align_power(dot, os->bfd_section->alignment_power); + os->bfd_section->vma = dot; + os->bfd_section->output_offset = 0; + + (void) lang_size_sections(os->children.head, os, &os->children.head, + os->fill, dot, relax); + /* Ignore the size of the input sections, use the vma and size to */ + /* align against */ + + + after = ALIGN(os->bfd_section->vma + + os->bfd_section->_raw_size, + os->block_value) ; + + + os->bfd_section->_raw_size = after - os->bfd_section->vma; + dot = os->bfd_section->vma + os->bfd_section->_raw_size; + os->processed = true; + + /* Replace into region ? */ + if (os->addr_tree == (etree_type *)NULL + && os->region !=(lang_memory_region_type*)NULL ) { + os->region->current = dot; + } + } + + break; + case lang_constructors_statement_enum: + dot = lang_size_sections(constructor_list.head, + output_section_statement, + &s->wild_statement.children.head, + fill, + dot, relax); + break; + + case lang_data_statement_enum: + { + unsigned int size = 0; + s->data_statement.output_vma = dot - output_section_statement->bfd_section->vma; + s->data_statement.output_section = + output_section_statement->bfd_section; + + switch (s->data_statement.type) { + case LONG: + size = LONG_SIZE; + break; + case SHORT: + size = SHORT_SIZE; + break; + case BYTE: + size = BYTE_SIZE; + break; + + } + dot += size; + output_section_statement->bfd_section->_raw_size += size; + } + break; + + case lang_wild_statement_enum: + + dot = lang_size_sections(s->wild_statement.children.head, + output_section_statement, + &s->wild_statement.children.head, + + fill, dot, relax); + + break; + + case lang_object_symbols_statement_enum: + create_object_symbols = output_section_statement; + break; + case lang_output_statement_enum: + case lang_target_statement_enum: + break; + case lang_input_section_enum: +if (relax) +{ + relaxing = true; + + +had_relax |= relax_section(prev); + relaxing = false; + +} + dot = size_input_section(prev, + output_section_statement, + output_section_statement->fill, dot); + break; + case lang_input_statement_enum: + break; + case lang_fill_statement_enum: + fill = s->fill_statement.fill; + break; + case lang_assignment_statement_enum: + { + bfd_vma newdot = dot; + exp_fold_tree(s->assignment_statement.exp, + output_section_statement, + lang_allocating_phase_enum, + dot, + &newdot); + + if (newdot != dot) + /* We've been moved ! so insert a pad */ + { + lang_statement_union_type *new = + (lang_statement_union_type *) + ldmalloc((bfd_size_type)(sizeof(lang_padding_statement_type))); + /* Link into existing chain */ + new->header.next = *prev; + *prev = new; + new->header.type = lang_padding_statement_enum; + new->padding_statement.output_section = + output_section_statement->bfd_section; + new->padding_statement.output_offset = + dot - output_section_statement->bfd_section->vma; + new->padding_statement.fill = fill; + new->padding_statement.size = newdot - dot; + output_section_statement->bfd_section->_raw_size += + new->padding_statement.size; + dot = newdot; + } + } + + break; + default: + FAIL(); + break; +/* This can only get here when relaxing is turned on */ + case lang_padding_statement_enum: + + case lang_address_statement_enum: + break; + } + prev = &s->header.next; + } + return dot; +} +#endif static bfd_vma DEFUN(lang_do_assignments,(s, output_section_statement, fill, dot), @@ -1518,7 +1719,7 @@ DEFUN(lang_do_assignments,(s, output_section_statement, fill, dot), &(s->output_section_statement); dot = os->bfd_section->vma; (void) lang_do_assignments(os->children.head, os, os->fill, dot); - dot = os->bfd_section->vma + os->bfd_section->size; + dot = os->bfd_section->vma + os->bfd_section->_raw_size; } break; case lang_wild_statement_enum: @@ -1542,7 +1743,7 @@ DEFUN(lang_do_assignments,(s, output_section_statement, fill, dot), value = exp_fold_tree(s->data_statement.exp, 0, lang_final_phase_enum, dot, &dot); s->data_statement.value = value.value; - if (value.valid == false) info("%F%P: Invalid data statement\n"); + if (value.valid == false) einfo("%F%P: Invalid data statement\n"); } switch (s->data_statement.type) { case LONG: @@ -1559,7 +1760,7 @@ DEFUN(lang_do_assignments,(s, output_section_statement, fill, dot), case lang_input_section_enum: { asection *in = s->input_section.section; - dot += in->size; + dot += bfd_get_section_size_before_reloc(in); } break; @@ -1787,7 +1988,9 @@ DEFUN_VOID(lang_common) ((lang_input_statement_type *) (com->the_bfd->usrdata))->common_section; /* Fix the size of the common section */ - com->section->size = ALIGN(com->section->size, align); + + com->section->_raw_size = + ALIGN(com->section->_raw_size, align); /* Remember if this is the biggest alignment ever seen */ if (power_of_two > com->section->alignment_power) { @@ -1798,7 +2001,7 @@ DEFUN_VOID(lang_common) we remember that it was common once. */ com->flags = BSF_EXPORT | BSF_GLOBAL | BSF_OLD_COMMON; - com->value = com->section->size; + com->value = com->section->_raw_size; if (write_map) { @@ -1809,7 +2012,7 @@ DEFUN_VOID(lang_common) com->the_bfd->filename); } - com->section->size += size; + com->section->_raw_size += size; } } @@ -1902,7 +2105,7 @@ DEFUN(lang_set_flags,(ptr, flags), /* ptr->flag_loadable= state;*/ break; default: - info("%P%F illegal syntax in flags\n"); + einfo("%P%F illegal syntax in flags\n"); break; } flags++; @@ -2016,6 +2219,18 @@ DEFUN_VOID(lang_final) +/* Reset the current counters in the regions */ +static void + DEFUN_VOID(reset_memory_regions) +{ + lang_memory_region_type *p = lang_memory_region_list; + for (p = lang_memory_region_list; + p != ( lang_memory_region_type *)NULL; + p = p->next) + { + p->current = p->origin; + } +} asymbol * @@ -2038,95 +2253,14 @@ DEFUN(create_symbol,(name, flags, section), return def; } -/* run through the symbol table, find all the symbols which are - constructors and for each one, create statements to do something - like.. - - for - __CTOR_LIST__, foo - - __CTOR_LIST__ = . ; - LONG(__CTOR_LIST_END - . / 4 - 2) - *(foo) - __CTOR_LIST_END= . - - Put these statements onto a special list. - -*/ - -typedef struct constructor_list -{ -ldsym_type *sym; - struct constructor_list *next; -} constructor_list_type; - -static constructor_list_type *constructor_name_list; - -void -DEFUN(ldlang_add_constructor,(name), -ldsym_type *name) -{ - - constructor_list_type *next = constructor_name_list; - - if (name->flags & SYM_CONSTRUCTOR) return; - - next = (constructor_list_type *) ldmalloc(sizeof(constructor_list_type)); - next->next= constructor_name_list; - next->sym= name; - name->flags |= SYM_CONSTRUCTOR; - constructor_name_list = next; - -} - -void -DEFUN_VOID(find_constructors) -{ - lang_statement_list_type *old = stat_ptr; - constructor_list_type *p = constructor_name_list; - stat_ptr = & constructor_list; - lang_list_init(stat_ptr); - while (p != (constructor_list_type *)NULL) - { - /* Have we already done this one ? */ - CONST char *name = p->sym->name; - int len = strlen(name); - char *end = ldmalloc(len+3); - strcpy(end, name); - strcat(end,"$e"); - - lang_add_assignment - ( exp_assop('=',name, exp_nameop(NAME,"."))); - - lang_add_data - (LONG, exp_binop('-', - exp_binop ( '/', - exp_binop ( '-', - exp_nameop(NAME, end), - exp_nameop(NAME,".")), - exp_intop(4)), - - exp_intop(2))); - - - lang_add_wild(name, (char *)NULL); - lang_add_data(LONG, exp_intop(0)); - lang_add_assignment - (exp_assop('=', end, exp_nameop(NAME,"."))); -p = p->next; - } - - - stat_ptr = old; -} void DEFUN_VOID(lang_process) { if (had_script == false) { - parse_line(ldemul_get_script()); - } + parse_line(ldemul_get_script()); + } lang_reasonable_defaults(); current_target = default_target; @@ -2164,10 +2298,42 @@ DEFUN_VOID(lang_process) ldemul_before_allocation(); + /* Size up the sections */ lang_size_sections(statement_list.head, (lang_output_section_statement_type *)NULL, - &(statement_list.head), 0, (bfd_vma)0); + &(statement_list.head), 0, (bfd_vma)0, false); + + + /* Move the global symbols around */ + lang_relocate_globals(); + + /* Now run around and relax if we can */ + if (command_line.relax) + { + reset_memory_regions(); + + had_relax = true; + while (had_relax) + { + + had_relax = false; + + lang_size_sections(statement_list.head, + (lang_output_section_statement_type *)NULL, + &(statement_list.head), 0, (bfd_vma)0, true); + /* FIXME. Until the code in relax is fixed so that it only reads in + stuff once, we cant iterate since there is no way for the linker to + know what has been patched and what hasn't */ + break; + + } + + + + + } + /* See if anything special should be done now we know how big everything is */ @@ -2180,13 +2346,11 @@ DEFUN_VOID(lang_process) (lang_output_section_statement_type *)NULL, 0, (bfd_vma)0); + /* Make sure that we're not mixing architectures */ lang_check(); - /* Move the global symbols around */ - lang_relocate_globals(); - /* Final stuffs */ lang_finish(); } @@ -2301,7 +2465,7 @@ DEFUN(lang_startup,(name), CONST char *name) { if (startup_file != (char *)NULL) { - info("%P%FMultiple STARTUP files\n"); + einfo("%P%FMultiple STARTUP files\n"); } first_file->filename = name; first_file->local_sym_name = name; @@ -2345,9 +2509,10 @@ DEFUN(lang_abs_symbol_at_beginning_of,(section, name), if (ldsym_undefined(name)) { asection *s = bfd_get_section_by_name(output_bfd, section); asymbol *def = create_symbol(name, - BSF_GLOBAL | BSF_EXPORT | - BSF_ABSOLUTE, - (asection *)NULL); + BSF_GLOBAL | BSF_EXPORT , + &bfd_abs_section); + + if (s != (asection *)NULL) { def->value = s->vma; } @@ -2372,11 +2537,11 @@ DEFUN(lang_abs_symbol_at_end_of,(section, name), asection *s = bfd_get_section_by_name(output_bfd, section); /* Add a symbol called _end */ asymbol *def = create_symbol(name, - BSF_GLOBAL | BSF_EXPORT | - BSF_ABSOLUTE, - (asection *)NULL); + BSF_GLOBAL | BSF_EXPORT , + &bfd_abs_section); + if (s != (asection *)NULL) { - def->value = s->vma + s->size; + def->value = s->vma + s->_raw_size; } else { def->value = 0; diff --git a/ld/ldlang.h b/ld/ldlang.h index bfdc9cb..acd039d 100644 --- a/ld/ldlang.h +++ b/ld/ldlang.h @@ -1,19 +1,19 @@ /* ldlang.h - - + Copyright (C) 1991 Free Software Foundation, Inc. - + This file is part of GLD, the Gnu Linker. - + GLD 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. - + GLD 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 GLD; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ @@ -24,7 +24,7 @@ typedef enum { lang_input_file_is_symbols_only_enum, lang_input_file_is_marker_enum, lang_input_file_is_fake_enum, -lang_input_file_is_search_file_enum, + lang_input_file_is_search_file_enum, lang_input_file_is_file_enum } lang_input_file_enum_type; typedef unsigned short fill_type; @@ -34,12 +34,7 @@ typedef struct statement_list { } lang_statement_list_type; -typedef struct { - boolean flag_read; - boolean flag_write; - boolean flag_executable; - boolean flag_loadable; -} lang_section_flags_type; + typedef struct memory_region_struct { char *name; @@ -47,37 +42,38 @@ typedef struct memory_region_struct { bfd_vma origin; bfd_offset length; bfd_vma current; - lang_section_flags_type flags; + int flags; } lang_memory_region_type ; typedef struct lang_statement_header_struct -{ -union lang_statement_union *next; - enum statement_enum { - lang_output_section_statement_enum, - lang_assignment_statement_enum, - lang_input_statement_enum, - lang_address_statement_enum, - lang_wild_statement_enum, - lang_input_section_enum, - lang_object_symbols_statement_enum, - lang_fill_statement_enum, - lang_data_statement_enum, - lang_target_statement_enum, - lang_output_statement_enum, - lang_padding_statement_enum, - - lang_afile_asection_pair_statement_enum - } type; - -} lang_statement_header_type; + { + union lang_statement_union *next; + enum statement_enum { + lang_output_section_statement_enum, + lang_assignment_statement_enum, + lang_input_statement_enum, + lang_address_statement_enum, + lang_wild_statement_enum, + lang_input_section_enum, + lang_object_symbols_statement_enum, + lang_fill_statement_enum, + lang_data_statement_enum, + lang_target_statement_enum, + lang_output_statement_enum, + lang_padding_statement_enum, + + lang_afile_asection_pair_statement_enum, + lang_constructors_statement_enum + } type; + + } lang_statement_header_type; typedef struct -{ - lang_statement_header_type header; - union etree_union *exp; -} lang_assignment_statement_type; + { + lang_statement_header_type header; + union etree_union *exp; + } lang_assignment_statement_type; typedef struct lang_target_statement_struct { @@ -93,22 +89,22 @@ typedef struct lang_output_statement_struct { typedef struct lang_output_section_statement_struct -{ - lang_statement_header_type header; - union etree_union *addr_tree; - lang_statement_list_type children; - CONST char *memspec; - union lang_statement_union *next; - CONST char *name; - unsigned long subsection_alignment; - boolean processed; - - asection *bfd_section; - lang_section_flags_type flags; - struct memory_region_struct *region; - size_t block_value; - fill_type fill; -} lang_output_section_statement_type; + { + lang_statement_header_type header; + union etree_union *addr_tree; + lang_statement_list_type children; + CONST char *memspec; + union lang_statement_union *next; + CONST char *name; + unsigned long subsection_alignment; + boolean processed; + + asection *bfd_section; + int flags; + struct memory_region_struct *region; + size_t block_value; + fill_type fill; + } lang_output_section_statement_type; typedef struct { @@ -145,63 +141,54 @@ typedef struct lang_input_statement_struct /* Usually the same as filename, but for a file spec'd with -l this is the -l switch itself rather than the filename. */ CONST char *local_sym_name; - - /* Describe the layout of the contents of the file */ - - /* The file's a.out header. */ - /* struct exec header;*/ - /* Offset in file of GDB symbol segment, or 0 if there is none. */ - int symseg_offset; - - /* Describe data from the file loaded into core */ - + bfd *the_bfd; - + boolean closed; file_ptr passive_position; - + /* Symbol table of the file. */ asymbol **asymbols; unsigned int symbol_count; - + /* For library members only */ - + /* For a library, points to chain of entries for the library members. */ struct lang_input_statement_struct *subfiles; /* For a library member, offset of the member within the archive. Zero for files that are not library members. */ /* int starting_offset;*/ /* Size of contents of this file, if library member. */ - int total_size; + bfd_size_type total_size; /* For library member, points to the library's own entry. */ struct lang_input_statement_struct *superfile; /* For library member, points to next entry for next member. */ struct lang_input_statement_struct *chain; /* Point to the next file - whatever it is, wanders up and down archives */ - + union lang_statement_union *next; /* Point to the next file, but skips archive contents */ union lang_statement_union *next_real_file; - + boolean is_archive; - + /* 1 means search a set of directories for this file. */ boolean search_dirs_flag; - + /* 1 means this is base file of incremental load. Do not load this file's text or data. Also default text_start to after this file's bss. */ - + boolean just_syms_flag; - + boolean loaded; - - + + /* unsigned int globals_in_this_file;*/ CONST char *target; boolean real; - + asection *common_section; asection *common_output_section; } lang_input_statement_type; @@ -210,7 +197,7 @@ typedef struct { lang_statement_header_type header; asection *section; lang_input_statement_type *ifile; - + } lang_input_section_type; @@ -222,8 +209,8 @@ typedef struct { typedef struct lang_wild_statement_struct { lang_statement_header_type header; -CONST char *section_name; -CONST char *filename; + CONST char *section_name; + CONST char *filename; lang_statement_list_type children; } lang_wild_statement_type; @@ -242,24 +229,24 @@ typedef struct { } lang_padding_statement_type; typedef union lang_statement_union -{ - lang_statement_header_type header; - union lang_statement_union *next; - lang_wild_statement_type wild_statement; - lang_data_statement_type data_statement; - lang_address_statement_type address_statement; - lang_output_section_statement_type output_section_statement; - lang_afile_asection_pair_statement_type afile_asection_pair_statement; - lang_assignment_statement_type assignment_statement; - lang_input_statement_type input_statement; - lang_target_statement_type target_statement; - lang_output_statement_type output_statement; - lang_input_section_type input_section; - lang_common_statement_type common_statement; - lang_object_symbols_statement_type object_symbols_statement; - lang_fill_statement_type fill_statement; - lang_padding_statement_type padding_statement; -} lang_statement_union_type; + { + lang_statement_header_type header; + union lang_statement_union *next; + lang_wild_statement_type wild_statement; + lang_data_statement_type data_statement; + lang_address_statement_type address_statement; + lang_output_section_statement_type output_section_statement; + lang_afile_asection_pair_statement_type afile_asection_pair_statement; + lang_assignment_statement_type assignment_statement; + lang_input_statement_type input_statement; + lang_target_statement_type target_statement; + lang_output_statement_type output_statement; + lang_input_section_type input_section; + lang_common_statement_type common_statement; + lang_object_symbols_statement_type object_symbols_statement; + lang_fill_statement_type fill_statement; + lang_padding_statement_type padding_statement; + } lang_statement_union_type; @@ -270,7 +257,7 @@ PROTO(struct memory_region_struct , PROTO(void ,lang_map,(FILE *)); -PROTO(void,lang_set_flags,(lang_section_flags_type *, CONST char *)); +PROTO(void,lang_set_flags,(int *, CONST char *)); PROTO(void,lang_add_output,(CONST char *)); PROTO(void,lang_final,(void)); @@ -285,47 +272,47 @@ PROTO(void,lang_add_fill,(int)); PROTO(void,lang_add_assignment,(union etree_union *)); PROTO(void,lang_add_attribute,(enum statement_enum)); PROTO(void,lang_startup,(CONST char *)); -PROTO(void,lang_float,(enum boolean)); +PROTO(void,lang_float,(enum bfd_boolean)); PROTO(void,lang_leave_output_section_statement,(bfd_vma, CONST char *)); PROTO(void,lang_abs_symbol_at_end_of,(CONST char *, CONST char *)); PROTO(void,lang_abs_symbol_at_beginning_of,(CONST char *, CONST char *)); PROTO(void,lang_statement_append,(struct statement_list *, union lang_statement_union *, union lang_statement_union **)); PROTO(void, lang_for_each_file,(void (*dothis)(lang_input_statement_type *))); - + #define LANG_FOR_EACH_INPUT_STATEMENT(statement) \ extern lang_statement_list_type file_chain; \ lang_input_statement_type *statement; \ for (statement = (lang_input_statement_type *)file_chain.head;\ statement != (lang_input_statement_type *)NULL; \ statement = (lang_input_statement_type *)statement->next)\ - + #define LANG_FOR_EACH_INPUT_SECTION(statement, abfd, section, x) \ -{ extern lang_statement_list_type file_chain; \ - lang_input_statement_type *statement; \ - for (statement = (lang_input_statement_type *)file_chain.head;\ - statement != (lang_input_statement_type *)NULL; \ - statement = (lang_input_statement_type *)statement->next)\ - { \ - asection *section; \ - bfd *abfd = statement->the_bfd; \ + { extern lang_statement_list_type file_chain; \ + lang_input_statement_type *statement; \ + for (statement = (lang_input_statement_type *)file_chain.head;\ + statement != (lang_input_statement_type *)NULL; \ + statement = (lang_input_statement_type *)statement->next)\ + { \ + asection *section; \ + bfd *abfd = statement->the_bfd; \ for (section = abfd->sections; \ section != (asection *)NULL; \ section = section->next) { \ - x; \ - } \ - } \ + x; \ + } \ + } \ } #define LANG_FOR_EACH_OUTPUT_SECTION(section, x) \ - { extern bfd *output_bfd; \ - asection *section; \ - for (section = output_bfd->sections; \ - section != (asection *)NULL; \ - section = section->next) \ - { x; } \ - } - + { extern bfd *output_bfd; \ + asection *section; \ + for (section = output_bfd->sections; \ + section != (asection *)NULL; \ + section = section->next) \ + { x; } \ + } + PROTO(void, lang_process,(void)); PROTO(void, ldlang_add_file,(lang_input_statement_type *)); @@ -334,11 +321,16 @@ PROTO(lang_output_section_statement_type *,lang_output_section_find,(CONST char * CONST)); PROTO(lang_input_statement_type *, - lang_add_input_file,(char *name, - lang_input_file_enum_type file_type, - char *target)); + lang_add_input_file,(char *name, + lang_input_file_enum_type file_type, + char *target)); PROTO(lang_output_section_statement_type *, -lang_output_section_statement_lookup,(CONST char * CONST name)); + lang_output_section_statement_lookup,(CONST char * CONST name)); PROTO(void, ldlang_add_undef,(CONST char *CONST name)); PROTO(void, lang_add_output_format,(CONST char *)); + + +void EXFUN(lang_list_init,( lang_statement_list_type*)); + +void EXFUN(lang_add_data,(int type, union etree_union *)); diff --git a/ld/ldmain.c b/ld/ldmain.c index 71ca4cf..99526a0 100644 --- a/ld/ldmain.c +++ b/ld/ldmain.c @@ -35,7 +35,9 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ldemul.h" #include "ldlex.h" #include "ldfile.h" - +#include "ldindr.h" +#include "ldwarn.h" +#include "ldctor.h" /* IMPORTS */ extern boolean lang_has_input_file; extern boolean trace_files; @@ -112,6 +114,7 @@ unsigned int total_symbols_seen; */ unsigned int total_files_seen; + /* IMPORTS */ args_type command_line; ld_config_type config; @@ -151,6 +154,8 @@ main (argc, argv) unix_relocate = 0; command_line.force_common_definition = false; + init_bfd_error_vector(); + ldfile_add_arch(""); ldfile_add_library_path("./"); config.make_executable = true; @@ -181,7 +186,7 @@ main (argc, argv) info("%P: mode %s\n", emulation); } if (lang_has_input_file == false) { - info("%P%F: No input files\n"); + einfo("%P%F: No input files\n"); } ldemul_after_parse(); @@ -190,35 +195,32 @@ main (argc, argv) /* Print error messages for any missing symbols, for any warning symbols, and possibly multiple definitions */ - /* Print a map, if requested. */ - - if (write_map) { - ldsym_print_symbol_table (); - lang_map(stdout); - } if (config.text_read_only) { /* Look for a text section and mark the readonly attribute in it */ asection *found = bfd_get_section_by_name(output_bfd, ".text"); if (found == (asection *)NULL) { - info("%P%F: text marked read only, but no text section present"); + einfo("%P%F: text marked read only, but no text section present"); } found->flags |= SEC_READONLY; } if (config.relocateable_output) { output_bfd->flags &= ~EXEC_P; - ldwrite(); + + ldwrite(write_map); bfd_close(output_bfd); } else { output_bfd->flags |= EXEC_P; - ldwrite(); - bfd_close(output_bfd); - if (config.make_executable == false && force_make_executable == false) { + ldwrite(write_map); + + if (config.make_executable == false && force_make_executable ==false) { + unlink(output_filename); } + else { bfd_close(output_bfd); }; return (!config.make_executable); } @@ -249,8 +251,8 @@ asymbol **nlist_p; { asymbol *sym = *nlist_p; sym->value = 0; - sym->flags = BSF_UNDEFINED; - sym->section = (asection *)NULL; + sym->flags = 0; + sym->section = &bfd_und_section; sym->udata =(PTR)( sp->srefs_chain); sp->srefs_chain = nlist_p; } @@ -277,6 +279,7 @@ Whilst all this is going on we keep a count of the number of multiple definitions seen, undefined global symbols and pending commons. */ +extern boolean relaxing; void Q_enter_global_ref (nlist_p) @@ -305,7 +308,7 @@ Q_enter_global_ref (nlist_p) } else { - if (flag_is_common(this_symbol_flags)) { + if (sym->section == &bfd_com_section) { /* If we have a definition of this symbol already then this common turns into a reference. Also we only ever point to the largest common, so if we @@ -351,7 +354,7 @@ Q_enter_global_ref (nlist_p) } } - else if (flag_is_defined(this_symbol_flags)) { + else if (sym->section != &bfd_und_section) { /* This is the definition of a symbol, add to def chain */ if (sp->sdefs_chain && (*(sp->sdefs_chain))->section != sym->section) { /* Multiple definition */ @@ -362,18 +365,11 @@ Q_enter_global_ref (nlist_p) asymbol ** stat_symbols = stat ? stat->asymbols:0; multiple_def_count++; - info("%C: multiple definition of `%T'\n", - sym->the_bfd, - sym->section, - stat1_symbols, - sym->value, - sym); + einfo("%C: multiple definition of `%T'\n", + sym->the_bfd, sym->section, stat1_symbols, sym->value, sym); - info("%C: first seen here\n", - sy->the_bfd, - sy->section, - stat_symbols, - sy->value); + einfo("%C: first seen here\n", + sy->the_bfd, sy->section, stat_symbols, sy->value); } else { sym->udata =(PTR)( sp->sdefs_chain); @@ -385,7 +381,7 @@ Q_enter_global_ref (nlist_p) sp->scoms_chain = 0; commons_pending--; } - else if (sp->srefs_chain) { + else if (sp->srefs_chain && relaxing == false) { /* If previously was undefined, then remember as defined */ undefined_global_sym_count--; } @@ -414,8 +410,9 @@ Q_enter_file_symbols (entry) lang_input_statement_type *entry; { asymbol **q ; + entry->common_section = - bfd_make_section(entry->the_bfd, "COMMON"); + bfd_make_section_old_way(entry->the_bfd, "COMMON"); ldlang_add_file(entry); @@ -430,7 +427,10 @@ lang_input_statement_type *entry; { asymbol *p = *q; - if (flag_is_undefined_or_global_or_common_or_constructor(p->flags)) + if (p->section == &bfd_und_section + || (p->flags & BSF_GLOBAL) + || p->section == &bfd_com_section + || (p->flags & BSF_CONSTRUCTOR)) { Q_enter_global_ref(q); } @@ -441,7 +441,7 @@ lang_input_statement_type *entry; if (p->flags & BSF_WARNING) { add_warning(p); } - ASSERT(p->flags != 0); + } } @@ -533,8 +533,8 @@ struct lang_input_statement_struct *entry; } else { - info("%F%B: malformed input file (not rel or archive) \n", - entry->the_bfd); + einfo("%F%B: malformed input file (not rel or archive) \n", + entry->the_bfd); } } @@ -658,9 +658,8 @@ symdef_library (entry) } if (archive_member_lang_input_statement_struct == 0) { - info ("%F%I contains invalid archive member %s\n", - entry, - sp->name); + einfo ("%F%I contains invalid archive member %s\n", + entry, sp->name); } if (archive_member_lang_input_statement_struct->loaded == false) @@ -779,7 +778,7 @@ struct lang_input_statement_struct *entry; add_indirect(q); } - if (p->flags & BSF_FORT_COMM + if (p->section == &bfd_com_section || p->flags & BSF_GLOBAL) { register ldsym_type *sp = ldsym_get_soft (p->name); @@ -795,7 +794,7 @@ struct lang_input_statement_struct *entry; /* This is a symbol we are looking for. It is either not yet defined or common. */ - if (flag_is_common(p->flags)) + if (p->section == &bfd_com_section) { /* If the symbol in the table is a constructor, we won't to @@ -824,7 +823,9 @@ struct lang_input_statement_struct *entry; (asymbol **)((*(sp->srefs_chain))->udata); (*(sp->scoms_chain))->udata = (PTR)NULL; - (*( sp->scoms_chain))->flags = BSF_FORT_COMM; + (*( sp->scoms_chain))->section = + &bfd_com_section; + (*( sp->scoms_chain))->flags = 0; /* Remember the size of this item */ sp->scoms_chain[0]->value = p->value; commons_pending++; @@ -836,7 +837,7 @@ struct lang_input_statement_struct *entry; (asection *)NULL) { ((lang_input_statement_type *) (com->the_bfd->usrdata))->common_section = - bfd_make_section(com->the_bfd, "COMMON"); + bfd_make_section_old_way(com->the_bfd, "COMMON"); } } } @@ -858,3 +859,4 @@ struct lang_input_statement_struct *entry; return false; } + diff --git a/ld/ldmisc.c b/ld/ldmisc.c index 9ae7515..f67f235 100644 --- a/ld/ldmisc.c +++ b/ld/ldmisc.c @@ -1,10 +1,13 @@ -/* Copyright (C) 1991 Free Software Foundation, Inc. +/* ldmisc.c + Copyright (C) 1991 Free Software Foundation, Inc. + + Written by Steve Chamberlain of Cygnus Support. This file is part of GLD, the Gnu Linker. GLD 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) +the Free Software Foundation; either version 2, or (at your option) any later version. GLD is distributed in the hope that it will be useful, @@ -17,17 +20,14 @@ along with GLD; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* - * $Id$ - */ +$Id$ -/* - ldmisc.c -*/ + */ +#include "bfd.h" #include "sysdep.h" #include <varargs.h> -#include "bfd.h" #include "ld.h" #include "ldmisc.h" @@ -45,7 +45,7 @@ void yyerror(arg) char *arg; { - info("%P%F: %S %s\n",arg); + einfo("%P%F: %S %s\n",arg); } extern int errno; @@ -63,19 +63,19 @@ extern char *sys_errlist[]; %X no object output, fail return %V hex bfd_vma %C Clever filename:linenumber + %R info about a relent % */ -void info(va_alist) -va_dcl +static void +vfinfo(fp, fmt, arg) + FILE *fp; + char *fmt; + va_list arg; { - char *fmt; boolean fatal = false; - va_list arg; - va_start(arg); - fmt = va_arg(arg, char *); while (*fmt) { while (*fmt != '%' && *fmt != '\0') { - fputc(*fmt, stderr); + putc(*fmt, fp); fmt++; } if (*fmt == '%') { @@ -85,24 +85,23 @@ va_dcl config.make_executable = false; break; case 'V': - fprintf(stderr,"%08lx", va_arg(arg, bfd_vma)); + { + bfd_vma value = va_arg(arg, bfd_vma); + fprintf_vma(fp, value); + } break; case 'T': { asymbol *symbol = va_arg(arg, asymbol *); - if (symbol) { + if (symbol) + { asection *section = symbol->section; - if ((symbol->flags & BSF_UNDEFINED) == 0) { - CONST char *section_name = section == (asection *)NULL ? - "absolute" : section->name; - fprintf(stderr,"%s (%s)", symbol->name, section_name); - } - else { - fprintf(stderr,"%s", symbol->name); - } + CONST char *section_name = section->name; + fprintf(fp,"%s (%s)", symbol->name, section_name); } - else { - fprintf(stderr,"no symbol"); + else + { + fprintf(fp,"no symbol"); } } break; @@ -110,11 +109,11 @@ va_dcl { bfd *abfd = va_arg(arg, bfd *); if (abfd->my_archive) { - fprintf(stderr,"%s(%s)", abfd->my_archive->filename, + fprintf(fp,"%s(%s)", abfd->my_archive->filename, abfd->filename); } else { - fprintf(stderr,"%s", abfd->filename); + fprintf(fp,"%s", abfd->filename); } } @@ -123,13 +122,13 @@ va_dcl fatal = true; break; case 'P': - fprintf(stderr,"%s", program_name); + fprintf(fp,"%s", program_name); break; case 'E': /* Replace with the most recent errno explanation */ - fprintf(stderr, bfd_errmsg(bfd_error)); + fprintf(fp, bfd_errmsg(bfd_error)); break; @@ -138,7 +137,7 @@ va_dcl lang_input_statement_type *i = va_arg(arg,lang_input_statement_type *); - fprintf(stderr,"%s", i->local_sym_name); + fprintf(fp,"%s", i->local_sym_name); } break; case 'S': @@ -147,26 +146,44 @@ va_dcl if (ldlex_input_stack) { extern unsigned int lineno; if (ldfile_input_filename == (char *)NULL) { - fprintf(stderr,"command line"); + fprintf(fp,"command line"); } else { - fprintf(stderr,"%s:%u", ldfile_input_filename, lineno ); + fprintf(fp,"%s:%u", ldfile_input_filename, lineno ); } } else { int ch; int n = 0; - fprintf(stderr,"command (just before \""); + fprintf(fp,"command (just before \""); ch = lex_input(); while (ch != 0 && n < 10) { - fprintf(stderr, "%c", ch); + fprintf(fp, "%c", ch); ch = lex_input(); n++; } - fprintf(stderr,"\")"); + fprintf(fp,"\")"); } break; + + case 'R': + /* Print all that's interesting about a relent */ + { + arelent *relent = va_arg(arg, arelent *); + + fprintf(fp,"%s+0x%x (type %s)", + (*(relent->sym_ptr_ptr))->name, + relent->addend, + relent->howto->name); + + + } + break; + + + + case 'C': { CONST char *filename; @@ -188,27 +205,31 @@ va_dcl if (filename == (char *)NULL) filename = abfd->filename; if (functionname != (char *)NULL) - fprintf(stderr,"%s:%u: (%s)", filename, linenumber, functionname); + fprintf(fp,"%s:%u: (%s)", filename, linenumber, functionname); else if (linenumber != 0) - fprintf(stderr,"%s:%u", filename, linenumber); + fprintf(fp,"%s:%u", filename, linenumber); else - fprintf(stderr,"%s", filename); + fprintf(fp,"%s(%s+%0x)", filename, + section->name, + offset); } else { - fprintf(stderr,"%s", abfd->filename); + fprintf(fp,"%s(%s+%0x)", abfd->filename, + section->name, + offset); } } break; case 's': - fprintf(stderr,"%s", va_arg(arg, char *)); + fprintf(fp,"%s", va_arg(arg, char *)); break; case 'd': - fprintf(stderr,"%d", va_arg(arg, int)); + fprintf(fp,"%d", va_arg(arg, int)); break; default: - fprintf(stderr,"%s", va_arg(arg, char *)); + fprintf(fp,"%s", va_arg(arg, char *)); break; } } @@ -219,16 +240,40 @@ va_dcl unlink(output_filename); exit(1); } +} + +/* Format info message and print on stdout. */ + +void info(va_alist) +va_dcl +{ + char *fmt; + va_list arg; + va_start(arg); + fmt = va_arg(arg, char *); + vfinfo(stdout, fmt, arg); va_end(arg); } +/* ('e' for error.) Format info message and print on stderr. */ + +void einfo(va_alist) +va_dcl +{ + char *fmt; + va_list arg; + va_start(arg); + fmt = va_arg(arg, char *); + vfinfo(stderr, fmt, arg); + va_end(arg); +} void info_assert(file, line) char *file; unsigned int line; { - info("%F%P internal error %s %d\n", file,line); + einfo("%F%P internal error %s %d\n", file,line); } /* Return a newly-allocated string @@ -240,9 +285,9 @@ DEFUN(concat, (s1, s2, s3), CONST char *s2 AND CONST char *s3) { - size_t len1 = strlen (s1); - size_t len2 = strlen (s2); - size_t len3 = strlen (s3); + bfd_size_type len1 = strlen (s1); + bfd_size_type len2 = strlen (s2); + bfd_size_type len3 = strlen (s3); char *result = ldmalloc (len1 + len2 + len3 + 1); if (len1 != 0) @@ -258,13 +303,14 @@ DEFUN(concat, (s1, s2, s3), -char *ldmalloc (size) -size_t size; +PTR +DEFUN(ldmalloc, (size), +bfd_size_type size) { - char * result = malloc (size); + PTR result = malloc ((int)size); if (result == (char *)NULL && size != 0) - info("%F%P virtual memory exhausted\n"); + einfo("%F%P virtual memory exhausted\n"); return result; } @@ -274,8 +320,30 @@ size_t size; char *DEFUN(buystring,(x), CONST char *CONST x) { - size_t l = strlen(x)+1; + bfd_size_type l = strlen(x)+1; char *r = ldmalloc(l); memcpy(r, x,l); return r; } + + +/*---------------------------------------------------------------------- + Functions to print the link map + */ + +void +DEFUN_VOID(print_space) +{ + printf(" "); +} +void +DEFUN_VOID(print_nl) +{ + printf("\n"); +} +void +DEFUN(print_address,(value), + bfd_vma value) +{ + printf_vma(value); +} @@ -214,32 +214,46 @@ lang_input_statement_type *f; { fprintf (stdout, " %s\n", f->filename); if (f->just_syms_flag) - { - fprintf (stdout, " symbols only\n"); - } + { + fprintf (stdout, " symbols only\n"); + } else - { - asection *s; - if (true || option_longmap) { - for (s = f->the_bfd->sections; - s != (asection *)NULL; - s = s->next) { + { + asection *s; + if (true || option_longmap) { + for (s = f->the_bfd->sections; + s != (asection *)NULL; + s = s->next) { print_address(s->output_offset); - printf (" %08x 2**%2ud %s\n", - (unsigned)s->size, s->alignment_power, s->name); + if (s->flags & SEC_HAS_CONTENTS) + { + printf (" %08x 2**%2ud %s\n", + (unsigned)bfd_get_section_size_after_reloc(s), + s->alignment_power, s->name); + } + + else + { + printf (" %08x 2**%2ud %s\n", + (unsigned)bfd_get_section_size_before_reloc(s), + s->alignment_power, s->name); + } + + + } - } - else { - for (s = f->the_bfd->sections; - s != (asection *)NULL; - s = s->next) { + } + else { + for (s = f->the_bfd->sections; + s != (asection *)NULL; + s = s->next) { printf("%s ", s->name); print_address(s->output_offset); - printf("(%x)", (unsigned)s->size); + printf("(%x)", (unsigned)bfd_get_section_size_after_reloc(s)); } - printf("hex \n"); - } + printf("hex \n"); } + } fprintf (stdout, "\n"); } @@ -345,7 +359,7 @@ LANG_FOR_EACH_INPUT_STATEMENT(entry) { asymbol *p = entry->asymbols[i]; - if (flag_is_global(p->flags) || flag_is_absolute(p->flags)) + if (flag_is_global(p->flags) ) { /* We are only interested in outputting globals at this stage in special circumstances */ @@ -376,10 +390,10 @@ LANG_FOR_EACH_INPUT_STATEMENT(entry) *output_buffer++ = p; } } - else if (flag_is_undefined(p->flags)) + else if (p->section == &bfd_und_section) { /* This must be global */ } - else if (flag_is_common(p->flags)) { + else if (p->section == &bfd_com_section) { /* And so must this */ } else if (p->flags & BSF_CTOR) { |