aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ld/config.h11
-rw-r--r--ld/ldexp.c537
-rw-r--r--ld/ldgram.y54
-rw-r--r--ld/ldlang.c545
-rw-r--r--ld/ldlang.h242
-rw-r--r--ld/ldmain.c84
-rw-r--r--ld/ldmisc.c176
-rw-r--r--ld/ldsym.c58
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"
diff --git a/ld/ldexp.c b/ld/ldexp.c
index c91af29..849f235 100644
--- a/ld/ldexp.c
+++ b/ld/ldexp.c
@@ -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);
+}
diff --git a/ld/ldsym.c b/ld/ldsym.c
index 4ad9476..5d75c69 100644
--- a/ld/ldsym.c
+++ b/ld/ldsym.c
@@ -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) {