Merging from VMS port. Doc to follow..
This commit is contained in:
parent
f5e8a8f9c7
commit
c611e285bd
11
ld/config.h
11
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"
|
||||
|
|
525
ld/ldexp.c
525
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.
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
58
ld/ldgram.y
58
ld/ldgram.y
|
@ -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;
|
||||
|
|
545
ld/ldlang.c
545
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;
|
||||
|
|
242
ld/ldlang.h
242
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 *));
|
||||
|
|
84
ld/ldmain.c
84
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;
|
||||
}
|
||||
|
||||
|
||||
|
|
178
ld/ldmisc.c
178
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);
|
||||
}
|
||||
|
|
58
ld/ldsym.c
58
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) {
|
||||
|
|
Loading…
Reference in New Issue