Merging from VMS port. Doc to follow..

This commit is contained in:
Steve Chamberlain 1992-01-24 18:41:32 +00:00
parent f5e8a8f9c7
commit c611e285bd
8 changed files with 992 additions and 709 deletions

View File

@ -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"

View File

@ -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.
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.
*/
/*
* Written by Steve Chamberlain
* steve@cygnus.com
*
* This module handles expression trees.
*/
#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",
{
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} ;
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");
}
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 {
unsigned long nextdot =result.value +
current_section->bfd_section->vma;
if (nextdot < dot) {
info("%F%S cannot move location counter backwards");
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 {
*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;
{
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->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;
}
def->udata = (PTR)NULL;
def->name = sy->name;
Q_enter_global_ref(def_ptr);
}
else {
def->section = &bfd_abs_section;
def->flags = BSF_GLOBAL | BSF_EXPORT ;
}
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);
}

View File

@ -1,18 +1,27 @@
/* 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 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.
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$
*
*
*/
/*
This is a YACC grammer intended to parse a superset of the AT&T
linker scripting languaue.
Written by Steve Chamberlain steve@cygnus.com
*/
* $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;

View File

@ -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;

View File

@ -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 *));

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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) {