* Makefile.in: added relax, also made three stage go through a
partial link stage. * relax.c : added * config.h: if GNU960 defined, then default emulation mode is GLD960 * ldexp.h, ldexp.c: map to file hooks * ldlang.c: map to file hooks * ldgram.y: added -Map -relax * ldlex.l: added -relax, -Map * ldmain.c: open map file * ldmisc.c: support for map file * ldwrite.c: new relax magic
This commit is contained in:
parent
2cbe4c5f9e
commit
2e2bf962db
9 changed files with 492 additions and 123 deletions
28
ld/ChangeLog
28
ld/ChangeLog
|
@ -1,3 +1,31 @@
|
|||
Fri Jan 24 14:23:46 1992 Steve Chamberlain (sac at rtl.cygnus.com)
|
||||
|
||||
* Makefile.in: added relax, also made three stage go through a
|
||||
partial link stage.
|
||||
* relax.c : added
|
||||
* config.h: if GNU960 defined, then default emulation mode is
|
||||
GLD960
|
||||
* ldexp.h, ldexp.c: map to file hooks
|
||||
* ldlang.c: map to file hooks
|
||||
* ldgram.y: added -Map -relax
|
||||
* ldlex.l: added -relax, -Map
|
||||
* ldmain.c: open map file
|
||||
* ldmisc.c: support for map file
|
||||
* ldwrite.c: new relax magic
|
||||
|
||||
Thu Dec 19 18:49:51 1991 John Gilmore (gnu at cygnus.com)
|
||||
|
||||
* Makefile.in, config/tm-*.h: Clean up make output, only
|
||||
pass DEFAULT_EMULATION to ldmain.c.
|
||||
|
||||
Wed Dec 18 15:02:47 1991 Per Bothner (bothner at cygnus.com)
|
||||
|
||||
* ldver.c: Bump to version 1.94.
|
||||
|
||||
Tue Dec 10 04:07:23 1991 K. Richard Pixley (rich at rtl.cygnus.com)
|
||||
|
||||
* Makefile.in: infodir belongs in datadir.
|
||||
|
||||
Mon Dec 9 16:26:43 1991 Per Bothner (bothner at cygnus.com)
|
||||
|
||||
* Makefile.in: Pass -y to bison. (Again;
|
||||
|
|
|
@ -17,9 +17,6 @@
|
|||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
srcdir = .
|
||||
|
||||
|
@ -166,7 +163,9 @@ LIBIBERTY=$(unsubdir)/../libiberty$(subdir)/libiberty.a
|
|||
OFILES= ldgram.o ldlex.o ldlang.o ldctor.o ldmain.o ldindr.o \
|
||||
ldwarn.o ldwrite.o ldexp.o ldlnk960.o ld__gld68k.o ld__i386aout.o \
|
||||
ld__m88k.o ld__glda29k.o ld__news.o h8300hds.o ld__ebmon29k.o \
|
||||
ld__gld.o ldgld960.o ldemul.o ldver.o ldmisc.o ldsym.o ldvanilla.o ldfile.o
|
||||
ld__gld.o ldgld960.o ldemul.o ldver.o ldmisc.o ldsym.o \
|
||||
ldvanilla.o ldfile.o \
|
||||
relax.o lderror.o
|
||||
|
||||
HEADERS=config.h ldmain.h ldmain.h ldwarn.h ldmisc.h ldindr.h \
|
||||
ldsym.h ldctor.h ldlang.h ldexp.h \
|
||||
|
@ -176,7 +175,8 @@ MANSOURCES=ld.tex
|
|||
|
||||
LDCSOURCES=ldlang.c ldctor.c ldindr.c ldmain.c ldwrite.c ldwarn.c ldlnk960.c \
|
||||
ld__gld.c ld__gld68k.c ld__m88k.c ld__ebmon29k.c \
|
||||
ldgld960.c ldemul.c ldver.c ldmisc.c ldexp.c ldsym.c ldfile.c ldvanilla.c
|
||||
ldgld960.c ldemul.c ldver.c ldmisc.c ldexp.c ldsym.c ldfile.c \
|
||||
ldvanilla.c relax.c lderror.c
|
||||
|
||||
GENERATED_SOURCES=ldgram.c ldlex.c ldgram.h ld__*.c
|
||||
GENERATED_HEADERS=ldgram.h
|
||||
|
@ -202,10 +202,6 @@ ldgram.h ldgram.c: ldgram.y
|
|||
ldlex.c: ldlex.l
|
||||
lex -t $(VPATH)/ldlex.l >ldlex.c
|
||||
|
||||
# Main needs to know the default emulation type, too.
|
||||
ldmain.o: ldmain.c
|
||||
$(CC) $(CFLAGS) -DDEFAULT_EMULATION=$(EMUL) -c $<
|
||||
|
||||
# These all start with ld__ so 'make clean' can find them.
|
||||
|
||||
ld__gld.c: $(srcdir)/ldtemplate
|
||||
|
@ -269,7 +265,9 @@ ld1: ld.new
|
|||
$(HOSTING_EMU); ./ld.new -o ld1 $(HOSTING_CRT0) $(OFILES) $(BFDLIB) $(LIBIBERTY) $(HOSTING_LIBS)
|
||||
|
||||
ld2: ld1
|
||||
$(HOSTING_EMU); ./ld1 -o ld2 $(HOSTING_CRT0) $(OFILES) $(BFDLIB) $(LIBIBERTY) $(HOSTING_LIBS)
|
||||
#try and make life a bit harder
|
||||
$(HOSTING_EMU); ./ld1 -o foo.o -r $(OFILES)
|
||||
$(HOSTING_EMU); ./ld1 -o ld2 $(HOSTING_CRT0) foo.o $(BFDLIB) $(LIBIBERTY) $(HOSTING_LIBS)
|
||||
|
||||
ld3: ld2
|
||||
$(HOSTING_EMU); ./ld2 -o ld3 $(HOSTING_CRT0) $(OFILES) $(BFDLIB) $(LIBIBERTY) $(HOSTING_LIBS)
|
||||
|
|
|
@ -33,8 +33,15 @@
|
|||
#define EBMON29K_EMULATION_NAME "ebmon29k"
|
||||
#define GLDI386AOUT_EMULATION_NAME "gldi386aout"
|
||||
/* Otherwise default to this emulation */
|
||||
/* 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 */
|
||||
|
|
52
ld/ldexp.c
52
ld/ldexp.c
|
@ -55,8 +55,7 @@ extern bfd_vma print_dot;
|
|||
|
||||
|
||||
static void
|
||||
DEFUN(exp_print_token,(outfile, code),
|
||||
FILE *outfile AND
|
||||
DEFUN(exp_print_token,( code),
|
||||
token_code_type code)
|
||||
{
|
||||
static struct {
|
||||
|
@ -110,12 +109,12 @@ DEFUN(exp_print_token,(outfile, code),
|
|||
unsigned int idx;
|
||||
for (idx = 0; table[idx].name != (char*)NULL; idx++) {
|
||||
if (table[idx].code == code) {
|
||||
fprintf(outfile, "%s", table[idx].name);
|
||||
fprintf(config.map_file, "%s", table[idx].name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Not in table, just print it alone */
|
||||
fprintf(outfile, "%c",code);
|
||||
fprintf(config.map_file, "%c",code);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -710,8 +709,7 @@ DEFUN(exp_assop,(code, dst, src),
|
|||
}
|
||||
|
||||
void
|
||||
DEFUN(exp_print_tree,(outfile, tree),
|
||||
FILE *outfile AND
|
||||
DEFUN(exp_print_tree,(tree),
|
||||
etree_type *tree)
|
||||
{
|
||||
switch (tree->type.node_class) {
|
||||
|
@ -722,45 +720,45 @@ DEFUN(exp_print_tree,(outfile, tree),
|
|||
case etree_assign:
|
||||
#if 0
|
||||
if (tree->assign.dst->sdefs != (asymbol *)NULL){
|
||||
fprintf(outfile,"%s (%x) ",tree->assign.dst->name,
|
||||
fprintf(config.map_file,"%s (%x) ",tree->assign.dst->name,
|
||||
tree->assign.dst->sdefs->value);
|
||||
}
|
||||
else {
|
||||
fprintf(outfile,"%s (UNDEFINED)",tree->assign.dst->name);
|
||||
fprintf(config.map_file,"%s (UNDEFINED)",tree->assign.dst->name);
|
||||
}
|
||||
#endif
|
||||
fprintf(outfile,"%s ",tree->assign.dst);
|
||||
exp_print_token(outfile,tree->type.node_code);
|
||||
exp_print_tree(outfile,tree->assign.src);
|
||||
fprintf(config.map_file,"%s ",tree->assign.dst);
|
||||
exp_print_token(tree->type.node_code);
|
||||
exp_print_tree(tree->assign.src);
|
||||
break;
|
||||
case etree_binary:
|
||||
exp_print_tree(outfile,tree->binary.lhs);
|
||||
exp_print_token(outfile,tree->type.node_code);
|
||||
exp_print_tree(outfile,tree->binary.rhs);
|
||||
exp_print_tree(tree->binary.lhs);
|
||||
exp_print_token(tree->type.node_code);
|
||||
exp_print_tree(tree->binary.rhs);
|
||||
break;
|
||||
case etree_trinary:
|
||||
exp_print_tree(outfile,tree->trinary.cond);
|
||||
fprintf(outfile,"?");
|
||||
exp_print_tree(outfile,tree->trinary.lhs);
|
||||
fprintf(outfile,":");
|
||||
exp_print_tree(outfile,tree->trinary.rhs);
|
||||
exp_print_tree(tree->trinary.cond);
|
||||
fprintf(config.map_file,"?");
|
||||
exp_print_tree(tree->trinary.lhs);
|
||||
fprintf(config.map_file,":");
|
||||
exp_print_tree(tree->trinary.rhs);
|
||||
break;
|
||||
case etree_unary:
|
||||
exp_print_token(outfile,tree->unary.type.node_code);
|
||||
fprintf(outfile,"(");
|
||||
exp_print_tree(outfile,tree->unary.child);
|
||||
fprintf(outfile,")");
|
||||
exp_print_token(tree->unary.type.node_code);
|
||||
fprintf(config.map_file,"(");
|
||||
exp_print_tree(tree->unary.child);
|
||||
fprintf(config.map_file,")");
|
||||
break;
|
||||
case etree_undef:
|
||||
fprintf(outfile,"????????");
|
||||
fprintf(config.map_file,"????????");
|
||||
break;
|
||||
case etree_name:
|
||||
if (tree->type.node_code == NAME) {
|
||||
fprintf(outfile,"%s", tree->name.name);
|
||||
fprintf(config.map_file,"%s", tree->name.name);
|
||||
}
|
||||
else {
|
||||
exp_print_token(outfile,tree->type.node_code);
|
||||
fprintf(outfile,"(%s)", tree->name.name);
|
||||
exp_print_token(tree->type.node_code);
|
||||
fprintf(config.map_file,"(%s)", tree->name.name);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -20,7 +20,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
|
||||
%{
|
||||
/*
|
||||
* $Id$
|
||||
|
||||
*/
|
||||
|
||||
#define DONTDECLARE_MALLOC
|
||||
|
@ -137,6 +137,7 @@ boolean ldgram_had_equals = false;
|
|||
%token <integer> SIZEOF NEXT ADDR
|
||||
%token OPTION_d OPTION_dc OPTION_dp OPTION_x OPTION_X OPTION_defsym
|
||||
%token OPTION_v OPTION_V OPTION_M OPTION_t STARTUP HLL SYSLIB FLOAT NOFLOAT
|
||||
%token OPTION_Map
|
||||
%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
|
||||
|
@ -185,6 +186,12 @@ command_line_option:
|
|||
| OPTION_t {
|
||||
trace_files = true;
|
||||
}
|
||||
| OPTION_Map NAME
|
||||
{
|
||||
write_map = true;
|
||||
config.map_filename = $2;
|
||||
}
|
||||
|
||||
| OPTION_M {
|
||||
if (write_map) {
|
||||
option_longmap = true;
|
||||
|
|
24
ld/ldlex.l
24
ld/ldlex.l
|
@ -5,7 +5,7 @@ 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,
|
||||
|
@ -28,22 +28,23 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
/*SUPPRESS 529*/
|
||||
/*SUPPRESS 26*/
|
||||
/*SUPPRESS 29*/
|
||||
#define LEXDEBUG 0
|
||||
#include "sysdep.h"
|
||||
/*#define LEXDEBUG 0*/
|
||||
#include "bfd.h"
|
||||
#include "sysdep.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include "ldlex.h"
|
||||
|
||||
#include "ld.h"
|
||||
#include "ldexp.h"
|
||||
#include "ldgramtb.h"
|
||||
#include "ldgram.h"
|
||||
#include "ldmisc.h"
|
||||
|
||||
#undef input
|
||||
#undef unput
|
||||
#define input lex_input
|
||||
#define unput lex_unput
|
||||
|
||||
int debug;
|
||||
|
||||
|
||||
|
@ -81,6 +82,7 @@ keyword_type keywords[] =
|
|||
"INPUT",INPUT,
|
||||
"DEFINED",DEFINED,
|
||||
"CREATE_OBJECT_SYMBOLS",CREATE_OBJECT_SYMBOLS,
|
||||
"CONSTRUCTORS", CONSTRUCTORS,
|
||||
"FORCE_COMMON_ALLOCATION",FORCE_COMMON_ALLOCATION,
|
||||
"SECTIONS",SECTIONS,
|
||||
"FILL",FILL,
|
||||
|
@ -94,6 +96,13 @@ keyword_type keywords[] =
|
|||
"SHORT", SHORT,
|
||||
"BYTE", BYTE,
|
||||
"NOFLOAT",NOFLOAT,
|
||||
|
||||
"NOLOAD",NOLOAD,
|
||||
"DSECT",DSECT,
|
||||
"COPY",COPY,
|
||||
"INFO",INFO,
|
||||
"OVERLAY",OVERLAY,
|
||||
|
||||
"o",ORIGIN,
|
||||
"org",ORIGIN,
|
||||
"l", LENGTH,
|
||||
|
@ -275,7 +284,9 @@ WHITE [ \t]+
|
|||
"\ -sort_common\ " { return OPTION_sort_common;}
|
||||
"\ -format\ " { return OPTION_format; }
|
||||
"\ -n\ " { return OPTION_n; }
|
||||
"\ -N\ " { return OPTION_N; }
|
||||
"\ -r\ " { return OPTION_r; }
|
||||
"\ -relax\ " { return OPTION_relax; }
|
||||
"\ -i\ " { return OPTION_r; }
|
||||
"\ -Ur\ " { return OPTION_Ur; }
|
||||
"\ -o\ " { return OPTION_o; }
|
||||
|
@ -286,7 +297,9 @@ WHITE [ \t]+
|
|||
"\ -dp\ " { return OPTION_dp; }
|
||||
"\ -d\ " { return OPTION_d; }
|
||||
"\ -v\ " { return OPTION_v; }
|
||||
"\ -V\ " { return OPTION_V; }
|
||||
"\ -M\ " { return OPTION_M; }
|
||||
"\ -Map\ " { return OPTION_Map;}
|
||||
"\ -t\ " { return OPTION_t; }
|
||||
"\ -X\ " { return OPTION_X; }
|
||||
"\ -x\ " { return OPTION_x; }
|
||||
|
@ -295,6 +308,7 @@ WHITE [ \t]+
|
|||
"\ -u\ " { return OPTION_u; }
|
||||
"\ -s\ " { return OPTION_s; }
|
||||
"\ -S\ " { return OPTION_S; }
|
||||
"\ -Bstatic" { return OPTION_Bstatic; }
|
||||
"\ -B{FILENAME}\ " { /* Ignored */ }
|
||||
"\ -l"{FILENAME} {
|
||||
yylval.name = buystring(yytext+3);
|
||||
|
@ -382,7 +396,7 @@ WHITE [ \t]+
|
|||
"]" { RTOKEN(']');}
|
||||
"[" { RTOKEN('[');}
|
||||
":" { RTOKEN(':'); }
|
||||
";" { RTOKEN('\;');}
|
||||
";" { RTOKEN(';');}
|
||||
"-" { RTOKEN('-');}
|
||||
|
||||
|
||||
|
|
11
ld/ldmain.c
11
ld/ldmain.c
|
@ -190,6 +190,17 @@ main (argc, argv)
|
|||
}
|
||||
|
||||
ldemul_after_parse();
|
||||
if (config.map_filename)
|
||||
{
|
||||
config.map_file = fopen(config.map_filename, FOPEN_WT);
|
||||
if (config.map_file == (FILE *)NULL)
|
||||
{
|
||||
einfo("%P%F: can't open map file %s\n",
|
||||
config.map_filename);
|
||||
}
|
||||
}
|
||||
else config.map_file = stdout;
|
||||
|
||||
lang_process();
|
||||
|
||||
/* Print error messages for any missing symbols, for any warning
|
||||
|
|
145
ld/ldwrite.c
145
ld/ldwrite.c
|
@ -2,19 +2,19 @@
|
|||
|
||||
This file is part of GLD, the Gnu Linker.
|
||||
|
||||
GLD is free software; you can redistribute it and/or modify
|
||||
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 1, or (at your option)
|
||||
any later version.
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GLD is distributed in the hope that it will be useful,
|
||||
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 GLD; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
|
@ -40,19 +40,19 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
*/
|
||||
|
||||
|
||||
#include "sysdep.h"
|
||||
#include "bfd.h"
|
||||
#include "sysdep.h"
|
||||
|
||||
#include "ldlang.h"
|
||||
#include "ld.h"
|
||||
#include "ldwrite.h"
|
||||
#include "ldmisc.h"
|
||||
#include "ldsym.h"
|
||||
#include "ldgram.tab.h"
|
||||
#include "ldgram.h"
|
||||
|
||||
|
||||
|
||||
|
||||
char *ldmalloc();
|
||||
/* Static vars for do_warnings and subroutines of it */
|
||||
int list_unresolved_refs; /* List unresolved refs */
|
||||
int list_warning_symbols; /* List warning syms */
|
||||
|
@ -74,26 +74,27 @@ void lang_for_each_statement(void (*func)());
|
|||
void lang_for_each_statement();
|
||||
#endif /* __STDC__ */
|
||||
|
||||
extern size_t largest_section;
|
||||
extern bfd_size_type largest_section;
|
||||
ld_config_type config;
|
||||
|
||||
extern unsigned int global_symbol_count;
|
||||
|
||||
boolean trace_files;
|
||||
|
||||
static void perform_relocation(input_bfd,
|
||||
static void
|
||||
DEFUN(perform_relocation,(input_bfd,
|
||||
input_section,
|
||||
data,
|
||||
symbols)
|
||||
bfd *input_bfd;
|
||||
asection *input_section;
|
||||
PTR data;
|
||||
asymbol **symbols;
|
||||
symbols),
|
||||
bfd *input_bfd AND
|
||||
asection *input_section AND
|
||||
PTR data AND
|
||||
asymbol **symbols)
|
||||
{
|
||||
static asymbol *error_symbol = (asymbol *)NULL;
|
||||
static unsigned int error_count = 0;
|
||||
#define MAX_ERRORS_IN_A_ROW 5
|
||||
size_t reloc_size = get_reloc_upper_bound(input_bfd, input_section);
|
||||
bfd_size_type reloc_size = bfd_get_reloc_upper_bound(input_bfd, input_section);
|
||||
|
||||
arelent **reloc_vector = (arelent **)ldmalloc(reloc_size);
|
||||
arelent **parent;
|
||||
|
@ -101,6 +102,9 @@ asymbol **symbols;
|
|||
asection *os = input_section->output_section;
|
||||
if (config.relocateable_output == false) ob = (bfd *)NULL;
|
||||
|
||||
input_section->_cooked_size = input_section->_raw_size;
|
||||
input_section->reloc_done = 1;
|
||||
|
||||
if (bfd_canonicalize_reloc(input_bfd,
|
||||
input_section,
|
||||
reloc_vector,
|
||||
|
@ -109,7 +113,7 @@ asymbol **symbols;
|
|||
for (parent = reloc_vector; *parent; parent++)
|
||||
{
|
||||
|
||||
bfd_reloc_status_enum_type r=
|
||||
bfd_reloc_status_type r=
|
||||
bfd_perform_relocation(input_bfd,
|
||||
*parent,
|
||||
data,
|
||||
|
@ -119,6 +123,11 @@ asymbol **symbols;
|
|||
if (r == bfd_reloc_ok) {
|
||||
if (ob != (bfd *)NULL) {
|
||||
/* A parital link, so keep the relocs */
|
||||
|
||||
/* Add to each relocation the offset of where it lives
|
||||
in the output section */
|
||||
/* (*parent)->address += input_section->output_offset;*/
|
||||
|
||||
os->orelocation[os->reloc_count] = *parent;
|
||||
os->reloc_count++;
|
||||
}
|
||||
|
@ -153,49 +162,35 @@ asymbol **symbols;
|
|||
error_symbol = s;
|
||||
}
|
||||
if (error_count < MAX_ERRORS_IN_A_ROW) {
|
||||
info("%C: undefined reference to `%T'\n",
|
||||
input_bfd,
|
||||
input_section,
|
||||
symbols,
|
||||
(*parent)->address,
|
||||
s);
|
||||
einfo("%C: undefined reference to `%T'\n",
|
||||
input_bfd, input_section, symbols,
|
||||
(*parent)->address, s);
|
||||
config.make_executable = false;
|
||||
}
|
||||
else if (error_count == MAX_ERRORS_IN_A_ROW) {
|
||||
info("%C: more undefined references to `%T' follow\n",
|
||||
input_bfd,
|
||||
input_section,
|
||||
symbols,
|
||||
(*parent)->address,
|
||||
s);
|
||||
einfo("%C: more undefined references to `%T' follow\n",
|
||||
input_bfd, input_section,
|
||||
symbols, (*parent)->address, s);
|
||||
}
|
||||
else {
|
||||
/* Don't print any more */
|
||||
}
|
||||
break;
|
||||
case bfd_reloc_dangerous:
|
||||
info("%B: relocation may be wrong `%T'\n",
|
||||
input_bfd,
|
||||
s);
|
||||
einfo("%B: relocation may be wrong `%T'\n",
|
||||
input_bfd, s);
|
||||
break;
|
||||
case bfd_reloc_outofrange:
|
||||
info("%B:%s relocation address out of range %T (%V)\n",
|
||||
input_bfd,
|
||||
input_section->name,
|
||||
s,
|
||||
p->address);
|
||||
einfo("%B:%s relocation address out of range %T (%V)\n",
|
||||
input_bfd, input_section->name, s, p->address);
|
||||
break;
|
||||
case bfd_reloc_overflow:
|
||||
info("%B:%s relocation overflow in %T reloc type %d\n",
|
||||
input_bfd,
|
||||
input_section->name,
|
||||
s,
|
||||
p->howto->type);
|
||||
einfo("%B:%s relocation overflow in %T reloc type %d\n",
|
||||
input_bfd, input_section->name, s, p->howto->type);
|
||||
break;
|
||||
default:
|
||||
info("%F%B: relocation error, symbol `%T'\n",
|
||||
input_bfd,
|
||||
s);
|
||||
einfo("%F%B: relocation error, symbol `%T'\n",
|
||||
input_bfd, s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -212,8 +207,8 @@ asymbol **symbols;
|
|||
PTR data_area;
|
||||
|
||||
static void
|
||||
copy_and_relocate(statement)
|
||||
lang_statement_union_type *statement;
|
||||
DEFUN(copy_and_relocate,(statement),
|
||||
lang_statement_union_type *statement)
|
||||
{
|
||||
switch (statement->header.type) {
|
||||
case lang_fill_statement_enum:
|
||||
|
@ -252,18 +247,18 @@ lang_statement_union_type *statement;
|
|||
{
|
||||
bfd_vma value = statement->data_statement.value;
|
||||
bfd_byte play_area[LONG_SIZE];
|
||||
unsigned int size;
|
||||
unsigned int size = 0;
|
||||
switch (statement->data_statement.type) {
|
||||
case LONG:
|
||||
bfd_putlong(output_bfd, value, play_area);
|
||||
bfd_put_32(output_bfd, value, play_area);
|
||||
size = LONG_SIZE;
|
||||
break;
|
||||
case SHORT:
|
||||
bfd_putshort(output_bfd, value, play_area);
|
||||
bfd_put_16(output_bfd, value, play_area);
|
||||
size = SHORT_SIZE;
|
||||
break;
|
||||
case BYTE:
|
||||
bfd_putchar(output_bfd, value, play_area);
|
||||
bfd_put_8(output_bfd, value, play_area);
|
||||
size = BYTE_SIZE;
|
||||
break;
|
||||
}
|
||||
|
@ -289,17 +284,19 @@ lang_statement_union_type *statement;
|
|||
if (ifile->just_syms_flag == false) {
|
||||
bfd *inbfd = ifile->the_bfd;
|
||||
|
||||
if (output_section->flags & SEC_LOAD && i->size != 0)
|
||||
if (output_section->flags & SEC_LOAD &&
|
||||
output_section->flags & SEC_ALLOC
|
||||
&& bfd_get_section_size_before_reloc(i) != 0)
|
||||
{
|
||||
if(bfd_get_section_contents(inbfd,
|
||||
i,
|
||||
data_area,
|
||||
0L,
|
||||
i->size) == false)
|
||||
(file_ptr)0,
|
||||
bfd_get_section_size_before_reloc(i)) == false)
|
||||
{
|
||||
info("%F%B error reading section contents %E\n",
|
||||
inbfd);
|
||||
einfo("%F%B error reading section contents %E\n", inbfd);
|
||||
}
|
||||
/* Set the reloc bit */
|
||||
perform_relocation (inbfd, i, data_area, ifile->asymbols);
|
||||
|
||||
|
||||
|
@ -307,9 +304,9 @@ lang_statement_union_type *statement;
|
|||
output_section,
|
||||
data_area,
|
||||
(file_ptr)i->output_offset,
|
||||
i->size) == false)
|
||||
bfd_get_section_size_after_reloc(i)) == false)
|
||||
{
|
||||
info("%F%B error writing section contents of %E\n",
|
||||
einfo("%F%B error writing section contents of %E\n",
|
||||
output_bfd);
|
||||
}
|
||||
|
||||
|
@ -327,22 +324,23 @@ lang_statement_union_type *statement;
|
|||
}
|
||||
|
||||
void
|
||||
write_norel()
|
||||
DEFUN_VOID(write_norel)
|
||||
{
|
||||
/* Output the text and data segments, relocating as we go. */
|
||||
lang_for_each_statement(copy_and_relocate);
|
||||
}
|
||||
|
||||
|
||||
static void read_relocs(abfd, section, symbols)
|
||||
bfd *abfd;
|
||||
asection *section;
|
||||
asymbol **symbols;
|
||||
static void
|
||||
DEFUN(read_relocs,(abfd, section, symbols),
|
||||
bfd *abfd AND
|
||||
asection *section AND
|
||||
asymbol **symbols)
|
||||
{
|
||||
/* Work out the output section ascociated with this input section */
|
||||
asection *output_section = section->output_section;
|
||||
|
||||
size_t reloc_size = get_reloc_upper_bound(abfd, section);
|
||||
bfd_size_type reloc_size = bfd_get_reloc_upper_bound(abfd, section);
|
||||
arelent **reloc_vector = (arelent **)ldmalloc(reloc_size);
|
||||
|
||||
if (bfd_canonicalize_reloc(abfd,
|
||||
|
@ -355,7 +353,7 @@ asymbol **symbols;
|
|||
|
||||
|
||||
static void
|
||||
write_rel()
|
||||
DEFUN_VOID(write_rel)
|
||||
{
|
||||
/*
|
||||
Run through each section of each file and work work out the total
|
||||
|
@ -376,7 +374,7 @@ write_rel()
|
|||
LANG_FOR_EACH_OUTPUT_SECTION
|
||||
(section,
|
||||
(section->orelocation =
|
||||
(arelent **)ldmalloc((size_t)(sizeof(arelent **)*
|
||||
(arelent **)ldmalloc((bfd_size_type)(sizeof(arelent **)*
|
||||
section->reloc_count)),
|
||||
section->reloc_count = 0,
|
||||
section->flags |= SEC_HAS_CONTENTS));
|
||||
|
@ -389,7 +387,8 @@ write_rel()
|
|||
}
|
||||
|
||||
void
|
||||
ldwrite ()
|
||||
DEFUN(ldwrite, (write_map),
|
||||
boolean write_map)
|
||||
{
|
||||
data_area = (PTR) ldmalloc(largest_section);
|
||||
if (config.relocateable_output == true)
|
||||
|
@ -398,10 +397,18 @@ ldwrite ()
|
|||
}
|
||||
else
|
||||
{
|
||||
write_norel();
|
||||
write_relaxnorel(output_bfd);
|
||||
}
|
||||
free(data_area);
|
||||
/* Output the symbol table (both globals and locals). */
|
||||
|
||||
/* Print a map, if requested. */
|
||||
|
||||
if (write_map) {
|
||||
ldsym_print_symbol_table ();
|
||||
lang_map(stdout);
|
||||
}
|
||||
|
||||
ldsym_write ();
|
||||
|
||||
}
|
||||
|
|
299
ld/relax.c
Normal file
299
ld/relax.c
Normal file
|
@ -0,0 +1,299 @@
|
|||
|
||||
|
||||
/*
|
||||
|
||||
new age linking
|
||||
|
||||
|
||||
Tie together all the interseting blocks
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "bfd.h"
|
||||
#include "../bfd/seclet.h"
|
||||
#include "coff/internal.h"
|
||||
#include "sysdep.h"
|
||||
|
||||
#include "ldlang.h"
|
||||
#include "ld.h"
|
||||
#include "ldwrite.h"
|
||||
#include "ldmisc.h"
|
||||
#include "ldsym.h"
|
||||
#include "ldgram.h"
|
||||
|
||||
static void
|
||||
DEFUN(build_it,(statement),
|
||||
lang_statement_union_type *statement)
|
||||
{
|
||||
switch (statement->header.type) {
|
||||
case lang_fill_statement_enum:
|
||||
{
|
||||
#if 0
|
||||
bfd_byte play_area[SHORT_SIZE];
|
||||
unsigned int i;
|
||||
bfd_putshort(output_bfd, statement->fill_statement.fill, play_area);
|
||||
/* Write out all entire shorts */
|
||||
for (i = 0;
|
||||
i < statement->fill_statement.size - SHORT_SIZE + 1;
|
||||
i+= SHORT_SIZE)
|
||||
{
|
||||
bfd_set_section_contents(output_bfd,
|
||||
statement->fill_statement.output_section,
|
||||
play_area,
|
||||
statement->data_statement.output_offset +i,
|
||||
SHORT_SIZE);
|
||||
|
||||
}
|
||||
|
||||
/* Now write any remaining byte */
|
||||
if (i < statement->fill_statement.size)
|
||||
{
|
||||
bfd_set_section_contents(output_bfd,
|
||||
statement->fill_statement.output_section,
|
||||
play_area,
|
||||
statement->data_statement.output_offset +i,
|
||||
1);
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case lang_data_statement_enum:
|
||||
{
|
||||
abort();
|
||||
|
||||
#if 0
|
||||
bfd_vma value = statement->data_statement.value;
|
||||
bfd_byte play_area[LONG_SIZE];
|
||||
unsigned int size = 0;
|
||||
switch (statement->data_statement.type) {
|
||||
case LONG:
|
||||
bfd_put_32(output_bfd, value, play_area);
|
||||
size = LONG_SIZE;
|
||||
break;
|
||||
case SHORT:
|
||||
bfd_put_16(output_bfd, value, play_area);
|
||||
size = SHORT_SIZE;
|
||||
break;
|
||||
case BYTE:
|
||||
bfd_put_8(output_bfd, value, play_area);
|
||||
size = BYTE_SIZE;
|
||||
break;
|
||||
}
|
||||
|
||||
bfd_set_section_contents(output_bfd,
|
||||
statement->data_statement.output_section,
|
||||
play_area,
|
||||
statement->data_statement.output_vma,
|
||||
size);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
break;
|
||||
case lang_input_section_enum:
|
||||
{
|
||||
/* Create a new seclet in the output section with this
|
||||
attached */
|
||||
|
||||
asection *i = statement->input_section.section;
|
||||
|
||||
asection *output_section = i->output_section;
|
||||
|
||||
bfd_seclet_type *seclet = bfd_new_seclet(output_section->owner,output_section);
|
||||
|
||||
seclet->type = bfd_indirect_seclet;
|
||||
seclet->u.indirect.section = i;
|
||||
seclet->u.indirect.symbols = statement->input_section.ifile->asymbols;
|
||||
seclet->size = bfd_get_section_size_before_reloc(i);
|
||||
seclet->offset = i->output_offset;
|
||||
seclet->next = 0;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* All the other ones fall through */
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DEFUN(write_relaxnorel,(output_bfd),
|
||||
bfd *output_bfd)
|
||||
{
|
||||
/* Tie up all the statements to generate an output bfd structure which
|
||||
bfd can mull over */
|
||||
|
||||
|
||||
lang_for_each_statement(build_it);
|
||||
|
||||
seclet_dump(output_bfd);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
DEFUN(perform_slip,(s, slip, input_section, value),
|
||||
asymbol **s AND
|
||||
unsigned int slip AND
|
||||
asection *input_section AND
|
||||
bfd_vma value)
|
||||
{
|
||||
|
||||
/* Find all symbols past this point, and make them know
|
||||
what's happened */
|
||||
while (*s)
|
||||
{
|
||||
asymbol *p = *s;
|
||||
if (p->section == input_section)
|
||||
{
|
||||
/* This was pointing into this section, so mangle it */
|
||||
if (p->value > value)
|
||||
{
|
||||
p->value -=2;
|
||||
}
|
||||
}
|
||||
s++;
|
||||
|
||||
}
|
||||
}
|
||||
static int
|
||||
DEFUN(movb1,(input_section, symbols, r, shrink),
|
||||
asection *input_section AND
|
||||
asymbol **symbols AND
|
||||
arelent *r AND
|
||||
unsigned int shrink)
|
||||
{
|
||||
|
||||
|
||||
bfd_vma value = get_value(r, input_section);
|
||||
|
||||
if (value >= 0xff00)
|
||||
{
|
||||
|
||||
/* Change the reloc type from 16bit, possible 8 to 8bit
|
||||
possible 16 */
|
||||
r->howto = r->howto + 1;
|
||||
/* The place to relc moves back by one */
|
||||
r->address -=1;
|
||||
|
||||
/* This will be two bytes smaller in the long run */
|
||||
shrink +=2 ;
|
||||
perform_slip(symbols, 2, input_section, r->address - shrink +1);
|
||||
|
||||
|
||||
}
|
||||
return shrink;
|
||||
}
|
||||
|
||||
static int
|
||||
DEFUN(jmp1,(input_section, symbols, r, shrink),
|
||||
asection *input_section AND
|
||||
asymbol **symbols AND
|
||||
arelent *r AND
|
||||
unsigned int shrink)
|
||||
{
|
||||
|
||||
|
||||
bfd_vma value = get_value(r, 0);
|
||||
|
||||
bfd_vma dot = input_section->output_section->vma +
|
||||
input_section->output_offset + r->address;
|
||||
bfd_vma gap;
|
||||
|
||||
/* See if the address we're looking at within 127 bytes of where
|
||||
we are, if so then we can use a small branch rather than the
|
||||
jump we were going to */
|
||||
|
||||
gap = value - (dot - shrink);
|
||||
|
||||
|
||||
if (-120 < (long)gap && (long)gap < 120 )
|
||||
{
|
||||
|
||||
/* Change the reloc type from 16bit, possible 8 to 8bit
|
||||
possible 16 */
|
||||
r->howto = r->howto + 1;
|
||||
/* The place to relc moves back by one */
|
||||
r->address -=1;
|
||||
|
||||
/* This will be two bytes smaller in the long run */
|
||||
shrink +=2 ;
|
||||
perform_slip(symbols, 2, input_section, r->address-shrink +1);
|
||||
|
||||
|
||||
}
|
||||
return shrink;
|
||||
}
|
||||
|
||||
|
||||
/* See if we can change the size of this section by shrinking the
|
||||
relocations in it. If this happens, then we'll have to renumber the
|
||||
symbols in it, and shift around the data too.
|
||||
*/
|
||||
boolean
|
||||
DEFUN(relax_section,(this_ptr),
|
||||
lang_statement_union_type **this_ptr)
|
||||
{
|
||||
|
||||
lang_input_section_type *is = &((*this_ptr)->input_section);
|
||||
asection *i = is->section;
|
||||
|
||||
|
||||
/* Get enough memory to hold the stuff */
|
||||
bfd *input_bfd = i->owner;
|
||||
asection *input_section = i;
|
||||
int shrink = 0 ;
|
||||
int new = 0;
|
||||
|
||||
bfd_size_type reloc_size = bfd_get_reloc_upper_bound(input_bfd,
|
||||
input_section);
|
||||
arelent **reloc_vector = (arelent **)ldmalloc(reloc_size);
|
||||
|
||||
/* Get the relocs and think about them */
|
||||
if (bfd_canonicalize_reloc(input_bfd,
|
||||
input_section,
|
||||
reloc_vector,
|
||||
is->ifile->asymbols) )
|
||||
{
|
||||
arelent **parent;
|
||||
asymbol **symbols = is->ifile->asymbols;
|
||||
for (parent = reloc_vector; *parent; parent++)
|
||||
{
|
||||
arelent *r = *parent;
|
||||
switch (r->howto->type) {
|
||||
case R_MOVB2:
|
||||
case R_JMP2:
|
||||
|
||||
shrink+=2;
|
||||
break;
|
||||
|
||||
case R_MOVB1:
|
||||
shrink = movb1(input_section, symbols, r, shrink);
|
||||
new = 1;
|
||||
|
||||
break;
|
||||
case R_JMP1:
|
||||
shrink = jmp1(input_section, symbols, r, shrink);
|
||||
new = 1;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
input_section->_cooked_size -= shrink;
|
||||
free((char *)reloc_vector);
|
||||
return new;
|
||||
|
||||
}
|
||||
|
Loading…
Reference in a new issue