* 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:
Steve Chamberlain 1992-01-24 22:34:34 +00:00
parent 2cbe4c5f9e
commit 2e2bf962db
9 changed files with 492 additions and 123 deletions

View file

@ -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) Mon Dec 9 16:26:43 1991 Per Bothner (bothner at cygnus.com)
* Makefile.in: Pass -y to bison. (Again; * Makefile.in: Pass -y to bison. (Again;

View file

@ -17,9 +17,6 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# $Id$
#
srcdir = . srcdir = .
@ -166,7 +163,9 @@ LIBIBERTY=$(unsubdir)/../libiberty$(subdir)/libiberty.a
OFILES= ldgram.o ldlex.o ldlang.o ldctor.o ldmain.o ldindr.o \ 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 \ 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__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 \ HEADERS=config.h ldmain.h ldmain.h ldwarn.h ldmisc.h ldindr.h \
ldsym.h ldctor.h ldlang.h ldexp.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 \ 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 \ 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_SOURCES=ldgram.c ldlex.c ldgram.h ld__*.c
GENERATED_HEADERS=ldgram.h GENERATED_HEADERS=ldgram.h
@ -202,10 +202,6 @@ ldgram.h ldgram.c: ldgram.y
ldlex.c: ldlex.l ldlex.c: ldlex.l
lex -t $(VPATH)/ldlex.l >ldlex.c 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. # These all start with ld__ so 'make clean' can find them.
ld__gld.c: $(srcdir)/ldtemplate 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) $(HOSTING_EMU); ./ld.new -o ld1 $(HOSTING_CRT0) $(OFILES) $(BFDLIB) $(LIBIBERTY) $(HOSTING_LIBS)
ld2: ld1 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 ld3: ld2
$(HOSTING_EMU); ./ld2 -o ld3 $(HOSTING_CRT0) $(OFILES) $(BFDLIB) $(LIBIBERTY) $(HOSTING_LIBS) $(HOSTING_EMU); ./ld2 -o ld3 $(HOSTING_CRT0) $(OFILES) $(BFDLIB) $(LIBIBERTY) $(HOSTING_LIBS)

View file

@ -33,8 +33,15 @@
#define EBMON29K_EMULATION_NAME "ebmon29k" #define EBMON29K_EMULATION_NAME "ebmon29k"
#define GLDI386AOUT_EMULATION_NAME "gldi386aout" #define GLDI386AOUT_EMULATION_NAME "gldi386aout"
/* Otherwise default to this emulation */ /* 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 */ /* Look in this variable for a target format */

View file

@ -55,8 +55,7 @@ extern bfd_vma print_dot;
static void static void
DEFUN(exp_print_token,(outfile, code), DEFUN(exp_print_token,( code),
FILE *outfile AND
token_code_type code) token_code_type code)
{ {
static struct { static struct {
@ -110,12 +109,12 @@ DEFUN(exp_print_token,(outfile, code),
unsigned int idx; unsigned int idx;
for (idx = 0; table[idx].name != (char*)NULL; idx++) { for (idx = 0; table[idx].name != (char*)NULL; idx++) {
if (table[idx].code == code) { if (table[idx].code == code) {
fprintf(outfile, "%s", table[idx].name); fprintf(config.map_file, "%s", table[idx].name);
return; return;
} }
} }
/* Not in table, just print it alone */ /* Not in table, just print it alone */
fprintf(outfile, "%c",code); fprintf(config.map_file, "%c",code);
} }
static void static void
@ -710,8 +709,7 @@ DEFUN(exp_assop,(code, dst, src),
} }
void void
DEFUN(exp_print_tree,(outfile, tree), DEFUN(exp_print_tree,(tree),
FILE *outfile AND
etree_type *tree) etree_type *tree)
{ {
switch (tree->type.node_class) { switch (tree->type.node_class) {
@ -722,45 +720,45 @@ DEFUN(exp_print_tree,(outfile, tree),
case etree_assign: case etree_assign:
#if 0 #if 0
if (tree->assign.dst->sdefs != (asymbol *)NULL){ 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); tree->assign.dst->sdefs->value);
} }
else { else {
fprintf(outfile,"%s (UNDEFINED)",tree->assign.dst->name); fprintf(config.map_file,"%s (UNDEFINED)",tree->assign.dst->name);
} }
#endif #endif
fprintf(outfile,"%s ",tree->assign.dst); fprintf(config.map_file,"%s ",tree->assign.dst);
exp_print_token(outfile,tree->type.node_code); exp_print_token(tree->type.node_code);
exp_print_tree(outfile,tree->assign.src); exp_print_tree(tree->assign.src);
break; break;
case etree_binary: case etree_binary:
exp_print_tree(outfile,tree->binary.lhs); exp_print_tree(tree->binary.lhs);
exp_print_token(outfile,tree->type.node_code); exp_print_token(tree->type.node_code);
exp_print_tree(outfile,tree->binary.rhs); exp_print_tree(tree->binary.rhs);
break; break;
case etree_trinary: case etree_trinary:
exp_print_tree(outfile,tree->trinary.cond); exp_print_tree(tree->trinary.cond);
fprintf(outfile,"?"); fprintf(config.map_file,"?");
exp_print_tree(outfile,tree->trinary.lhs); exp_print_tree(tree->trinary.lhs);
fprintf(outfile,":"); fprintf(config.map_file,":");
exp_print_tree(outfile,tree->trinary.rhs); exp_print_tree(tree->trinary.rhs);
break; break;
case etree_unary: case etree_unary:
exp_print_token(outfile,tree->unary.type.node_code); exp_print_token(tree->unary.type.node_code);
fprintf(outfile,"("); fprintf(config.map_file,"(");
exp_print_tree(outfile,tree->unary.child); exp_print_tree(tree->unary.child);
fprintf(outfile,")"); fprintf(config.map_file,")");
break; break;
case etree_undef: case etree_undef:
fprintf(outfile,"????????"); fprintf(config.map_file,"????????");
break; break;
case etree_name: case etree_name:
if (tree->type.node_code == NAME) { if (tree->type.node_code == NAME) {
fprintf(outfile,"%s", tree->name.name); fprintf(config.map_file,"%s", tree->name.name);
} }
else { else {
exp_print_token(outfile,tree->type.node_code); exp_print_token(tree->type.node_code);
fprintf(outfile,"(%s)", tree->name.name); fprintf(config.map_file,"(%s)", tree->name.name);
} }
break; break;
default: default:

View file

@ -20,7 +20,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
%{ %{
/* /*
* $Id$
*/ */
#define DONTDECLARE_MALLOC #define DONTDECLARE_MALLOC
@ -137,6 +137,7 @@ boolean ldgram_had_equals = false;
%token <integer> SIZEOF NEXT ADDR %token <integer> SIZEOF NEXT ADDR
%token OPTION_d OPTION_dc OPTION_dp OPTION_x OPTION_X OPTION_defsym %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_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 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 <name> OPTION_l OPTION_L OPTION_T OPTION_Aarch OPTION_Tfile OPTION_Texp
%token OPTION_Ur %token OPTION_Ur
@ -185,6 +186,12 @@ command_line_option:
| OPTION_t { | OPTION_t {
trace_files = true; trace_files = true;
} }
| OPTION_Map NAME
{
write_map = true;
config.map_filename = $2;
}
| OPTION_M { | OPTION_M {
if (write_map) { if (write_map) {
option_longmap = true; option_longmap = true;

View file

@ -5,7 +5,7 @@ This file is part of GLD, the Gnu Linker.
GLD is free software; you can redistribute it and/or modify GLD is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by 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. any later version.
GLD is distributed in the hope that it will be useful, 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 529*/
/*SUPPRESS 26*/ /*SUPPRESS 26*/
/*SUPPRESS 29*/ /*SUPPRESS 29*/
#define LEXDEBUG 0 /*#define LEXDEBUG 0*/
#include "sysdep.h"
#include "bfd.h" #include "bfd.h"
#include "sysdep.h"
#include <ctype.h> #include <ctype.h>
#include "ldlex.h" #include "ldlex.h"
#include "ld.h" #include "ld.h"
#include "ldexp.h" #include "ldexp.h"
#include "ldgramtb.h" #include "ldgram.h"
#include "ldmisc.h" #include "ldmisc.h"
#undef input #undef input
#undef unput #undef unput
#define input lex_input #define input lex_input
#define unput lex_unput #define unput lex_unput
int debug; int debug;
@ -81,6 +82,7 @@ keyword_type keywords[] =
"INPUT",INPUT, "INPUT",INPUT,
"DEFINED",DEFINED, "DEFINED",DEFINED,
"CREATE_OBJECT_SYMBOLS",CREATE_OBJECT_SYMBOLS, "CREATE_OBJECT_SYMBOLS",CREATE_OBJECT_SYMBOLS,
"CONSTRUCTORS", CONSTRUCTORS,
"FORCE_COMMON_ALLOCATION",FORCE_COMMON_ALLOCATION, "FORCE_COMMON_ALLOCATION",FORCE_COMMON_ALLOCATION,
"SECTIONS",SECTIONS, "SECTIONS",SECTIONS,
"FILL",FILL, "FILL",FILL,
@ -94,6 +96,13 @@ keyword_type keywords[] =
"SHORT", SHORT, "SHORT", SHORT,
"BYTE", BYTE, "BYTE", BYTE,
"NOFLOAT",NOFLOAT, "NOFLOAT",NOFLOAT,
"NOLOAD",NOLOAD,
"DSECT",DSECT,
"COPY",COPY,
"INFO",INFO,
"OVERLAY",OVERLAY,
"o",ORIGIN, "o",ORIGIN,
"org",ORIGIN, "org",ORIGIN,
"l", LENGTH, "l", LENGTH,
@ -275,7 +284,9 @@ WHITE [ \t]+
"\ -sort_common\ " { return OPTION_sort_common;} "\ -sort_common\ " { return OPTION_sort_common;}
"\ -format\ " { return OPTION_format; } "\ -format\ " { return OPTION_format; }
"\ -n\ " { return OPTION_n; } "\ -n\ " { return OPTION_n; }
"\ -N\ " { return OPTION_N; }
"\ -r\ " { return OPTION_r; } "\ -r\ " { return OPTION_r; }
"\ -relax\ " { return OPTION_relax; }
"\ -i\ " { return OPTION_r; } "\ -i\ " { return OPTION_r; }
"\ -Ur\ " { return OPTION_Ur; } "\ -Ur\ " { return OPTION_Ur; }
"\ -o\ " { return OPTION_o; } "\ -o\ " { return OPTION_o; }
@ -286,7 +297,9 @@ WHITE [ \t]+
"\ -dp\ " { return OPTION_dp; } "\ -dp\ " { return OPTION_dp; }
"\ -d\ " { return OPTION_d; } "\ -d\ " { return OPTION_d; }
"\ -v\ " { return OPTION_v; } "\ -v\ " { return OPTION_v; }
"\ -V\ " { return OPTION_V; }
"\ -M\ " { return OPTION_M; } "\ -M\ " { return OPTION_M; }
"\ -Map\ " { return OPTION_Map;}
"\ -t\ " { return OPTION_t; } "\ -t\ " { return OPTION_t; }
"\ -X\ " { return OPTION_X; } "\ -X\ " { return OPTION_X; }
"\ -x\ " { return OPTION_x; } "\ -x\ " { return OPTION_x; }
@ -295,6 +308,7 @@ WHITE [ \t]+
"\ -u\ " { return OPTION_u; } "\ -u\ " { return OPTION_u; }
"\ -s\ " { return OPTION_s; } "\ -s\ " { return OPTION_s; }
"\ -S\ " { return OPTION_S; } "\ -S\ " { return OPTION_S; }
"\ -Bstatic" { return OPTION_Bstatic; }
"\ -B{FILENAME}\ " { /* Ignored */ } "\ -B{FILENAME}\ " { /* Ignored */ }
"\ -l"{FILENAME} { "\ -l"{FILENAME} {
yylval.name = buystring(yytext+3); yylval.name = buystring(yytext+3);
@ -382,7 +396,7 @@ WHITE [ \t]+
"]" { RTOKEN(']');} "]" { RTOKEN(']');}
"[" { RTOKEN('[');} "[" { RTOKEN('[');}
":" { RTOKEN(':'); } ":" { RTOKEN(':'); }
";" { RTOKEN('\;');} ";" { RTOKEN(';');}
"-" { RTOKEN('-');} "-" { RTOKEN('-');}

View file

@ -190,6 +190,17 @@ main (argc, argv)
} }
ldemul_after_parse(); 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(); lang_process();
/* Print error messages for any missing symbols, for any warning /* Print error messages for any missing symbols, for any warning

View file

@ -2,19 +2,19 @@
This file is part of GLD, the Gnu Linker. 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 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 of the License, or
any later version. (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 but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with GLD; see the file COPYING. If not, write to along with this program; if not, write to the Free Software
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* /*
* $Id$ * $Id$
@ -40,19 +40,19 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
*/ */
#include "sysdep.h"
#include "bfd.h" #include "bfd.h"
#include "sysdep.h"
#include "ldlang.h" #include "ldlang.h"
#include "ld.h" #include "ld.h"
#include "ldwrite.h" #include "ldwrite.h"
#include "ldmisc.h" #include "ldmisc.h"
#include "ldsym.h" #include "ldsym.h"
#include "ldgram.tab.h" #include "ldgram.h"
char *ldmalloc();
/* Static vars for do_warnings and subroutines of it */ /* Static vars for do_warnings and subroutines of it */
int list_unresolved_refs; /* List unresolved refs */ int list_unresolved_refs; /* List unresolved refs */
int list_warning_symbols; /* List warning syms */ int list_warning_symbols; /* List warning syms */
@ -74,26 +74,27 @@ void lang_for_each_statement(void (*func)());
void lang_for_each_statement(); void lang_for_each_statement();
#endif /* __STDC__ */ #endif /* __STDC__ */
extern size_t largest_section; extern bfd_size_type largest_section;
ld_config_type config; ld_config_type config;
extern unsigned int global_symbol_count; extern unsigned int global_symbol_count;
boolean trace_files; boolean trace_files;
static void perform_relocation(input_bfd, static void
DEFUN(perform_relocation,(input_bfd,
input_section, input_section,
data, data,
symbols) symbols),
bfd *input_bfd; bfd *input_bfd AND
asection *input_section; asection *input_section AND
PTR data; PTR data AND
asymbol **symbols; asymbol **symbols)
{ {
static asymbol *error_symbol = (asymbol *)NULL; static asymbol *error_symbol = (asymbol *)NULL;
static unsigned int error_count = 0; static unsigned int error_count = 0;
#define MAX_ERRORS_IN_A_ROW 5 #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 **reloc_vector = (arelent **)ldmalloc(reloc_size);
arelent **parent; arelent **parent;
@ -101,6 +102,9 @@ asymbol **symbols;
asection *os = input_section->output_section; asection *os = input_section->output_section;
if (config.relocateable_output == false) ob = (bfd *)NULL; 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, if (bfd_canonicalize_reloc(input_bfd,
input_section, input_section,
reloc_vector, reloc_vector,
@ -109,7 +113,7 @@ asymbol **symbols;
for (parent = reloc_vector; *parent; parent++) for (parent = reloc_vector; *parent; parent++)
{ {
bfd_reloc_status_enum_type r= bfd_reloc_status_type r=
bfd_perform_relocation(input_bfd, bfd_perform_relocation(input_bfd,
*parent, *parent,
data, data,
@ -119,6 +123,11 @@ asymbol **symbols;
if (r == bfd_reloc_ok) { if (r == bfd_reloc_ok) {
if (ob != (bfd *)NULL) { if (ob != (bfd *)NULL) {
/* A parital link, so keep the relocs */ /* 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->orelocation[os->reloc_count] = *parent;
os->reloc_count++; os->reloc_count++;
} }
@ -153,49 +162,35 @@ asymbol **symbols;
error_symbol = s; error_symbol = s;
} }
if (error_count < MAX_ERRORS_IN_A_ROW) { if (error_count < MAX_ERRORS_IN_A_ROW) {
info("%C: undefined reference to `%T'\n", einfo("%C: undefined reference to `%T'\n",
input_bfd, input_bfd, input_section, symbols,
input_section, (*parent)->address, s);
symbols,
(*parent)->address,
s);
config.make_executable = false; config.make_executable = false;
} }
else if (error_count == MAX_ERRORS_IN_A_ROW) { else if (error_count == MAX_ERRORS_IN_A_ROW) {
info("%C: more undefined references to `%T' follow\n", einfo("%C: more undefined references to `%T' follow\n",
input_bfd, input_bfd, input_section,
input_section, symbols, (*parent)->address, s);
symbols,
(*parent)->address,
s);
} }
else { else {
/* Don't print any more */ /* Don't print any more */
} }
break; break;
case bfd_reloc_dangerous: case bfd_reloc_dangerous:
info("%B: relocation may be wrong `%T'\n", einfo("%B: relocation may be wrong `%T'\n",
input_bfd, input_bfd, s);
s);
break; break;
case bfd_reloc_outofrange: case bfd_reloc_outofrange:
info("%B:%s relocation address out of range %T (%V)\n", einfo("%B:%s relocation address out of range %T (%V)\n",
input_bfd, input_bfd, input_section->name, s, p->address);
input_section->name,
s,
p->address);
break; break;
case bfd_reloc_overflow: case bfd_reloc_overflow:
info("%B:%s relocation overflow in %T reloc type %d\n", einfo("%B:%s relocation overflow in %T reloc type %d\n",
input_bfd, input_bfd, input_section->name, s, p->howto->type);
input_section->name,
s,
p->howto->type);
break; break;
default: default:
info("%F%B: relocation error, symbol `%T'\n", einfo("%F%B: relocation error, symbol `%T'\n",
input_bfd, input_bfd, s);
s);
break; break;
} }
} }
@ -212,8 +207,8 @@ asymbol **symbols;
PTR data_area; PTR data_area;
static void static void
copy_and_relocate(statement) DEFUN(copy_and_relocate,(statement),
lang_statement_union_type *statement; lang_statement_union_type *statement)
{ {
switch (statement->header.type) { switch (statement->header.type) {
case lang_fill_statement_enum: case lang_fill_statement_enum:
@ -252,18 +247,18 @@ lang_statement_union_type *statement;
{ {
bfd_vma value = statement->data_statement.value; bfd_vma value = statement->data_statement.value;
bfd_byte play_area[LONG_SIZE]; bfd_byte play_area[LONG_SIZE];
unsigned int size; unsigned int size = 0;
switch (statement->data_statement.type) { switch (statement->data_statement.type) {
case LONG: case LONG:
bfd_putlong(output_bfd, value, play_area); bfd_put_32(output_bfd, value, play_area);
size = LONG_SIZE; size = LONG_SIZE;
break; break;
case SHORT: case SHORT:
bfd_putshort(output_bfd, value, play_area); bfd_put_16(output_bfd, value, play_area);
size = SHORT_SIZE; size = SHORT_SIZE;
break; break;
case BYTE: case BYTE:
bfd_putchar(output_bfd, value, play_area); bfd_put_8(output_bfd, value, play_area);
size = BYTE_SIZE; size = BYTE_SIZE;
break; break;
} }
@ -289,17 +284,19 @@ lang_statement_union_type *statement;
if (ifile->just_syms_flag == false) { if (ifile->just_syms_flag == false) {
bfd *inbfd = ifile->the_bfd; 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, if(bfd_get_section_contents(inbfd,
i, i,
data_area, data_area,
0L, (file_ptr)0,
i->size) == false) bfd_get_section_size_before_reloc(i)) == false)
{ {
info("%F%B error reading section contents %E\n", einfo("%F%B error reading section contents %E\n", inbfd);
inbfd);
} }
/* Set the reloc bit */
perform_relocation (inbfd, i, data_area, ifile->asymbols); perform_relocation (inbfd, i, data_area, ifile->asymbols);
@ -307,9 +304,9 @@ lang_statement_union_type *statement;
output_section, output_section,
data_area, data_area,
(file_ptr)i->output_offset, (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); output_bfd);
} }
@ -327,22 +324,23 @@ lang_statement_union_type *statement;
} }
void void
write_norel() DEFUN_VOID(write_norel)
{ {
/* Output the text and data segments, relocating as we go. */ /* Output the text and data segments, relocating as we go. */
lang_for_each_statement(copy_and_relocate); lang_for_each_statement(copy_and_relocate);
} }
static void read_relocs(abfd, section, symbols) static void
bfd *abfd; DEFUN(read_relocs,(abfd, section, symbols),
asection *section; bfd *abfd AND
asymbol **symbols; asection *section AND
asymbol **symbols)
{ {
/* Work out the output section ascociated with this input section */ /* Work out the output section ascociated with this input section */
asection *output_section = section->output_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); arelent **reloc_vector = (arelent **)ldmalloc(reloc_size);
if (bfd_canonicalize_reloc(abfd, if (bfd_canonicalize_reloc(abfd,
@ -355,7 +353,7 @@ asymbol **symbols;
static void static void
write_rel() DEFUN_VOID(write_rel)
{ {
/* /*
Run through each section of each file and work work out the total Run through each section of each file and work work out the total
@ -376,7 +374,7 @@ write_rel()
LANG_FOR_EACH_OUTPUT_SECTION LANG_FOR_EACH_OUTPUT_SECTION
(section, (section,
(section->orelocation = (section->orelocation =
(arelent **)ldmalloc((size_t)(sizeof(arelent **)* (arelent **)ldmalloc((bfd_size_type)(sizeof(arelent **)*
section->reloc_count)), section->reloc_count)),
section->reloc_count = 0, section->reloc_count = 0,
section->flags |= SEC_HAS_CONTENTS)); section->flags |= SEC_HAS_CONTENTS));
@ -389,7 +387,8 @@ write_rel()
} }
void void
ldwrite () DEFUN(ldwrite, (write_map),
boolean write_map)
{ {
data_area = (PTR) ldmalloc(largest_section); data_area = (PTR) ldmalloc(largest_section);
if (config.relocateable_output == true) if (config.relocateable_output == true)
@ -398,10 +397,18 @@ ldwrite ()
} }
else else
{ {
write_norel(); write_relaxnorel(output_bfd);
} }
free(data_area); free(data_area);
/* Output the symbol table (both globals and locals). */ /* 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 (); ldsym_write ();
} }

299
ld/relax.c Normal file
View 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;
}