aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ld/ChangeLog28
-rw-r--r--ld/Makefile.in18
-rw-r--r--ld/config.h9
-rw-r--r--ld/ldexp.c52
-rw-r--r--ld/ldgram.y11
-rw-r--r--ld/ldlex.l24
-rw-r--r--ld/ldmain.c11
-rw-r--r--ld/ldwrite.c163
-rw-r--r--ld/relax.c299
9 files changed, 492 insertions, 123 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog
index d2154ff..8a0ee1d 100644
--- a/ld/ChangeLog
+++ b/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;
diff --git a/ld/Makefile.in b/ld/Makefile.in
index 62db9e2..d82aa44 100644
--- a/ld/Makefile.in
+++ b/ld/Makefile.in
@@ -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)
diff --git a/ld/config.h b/ld/config.h
index 50cc3ca..b128156 100644
--- a/ld/config.h
+++ b/ld/config.h
@@ -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 */
diff --git a/ld/ldexp.c b/ld/ldexp.c
index 849f235..247de62 100644
--- a/ld/ldexp.c
+++ b/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:
diff --git a/ld/ldgram.y b/ld/ldgram.y
index a5b1731..d342da1 100644
--- a/ld/ldgram.y
+++ b/ld/ldgram.y
@@ -20,7 +20,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
%{
/*
- * $Id$
+
*/
#define DONTDECLARE_MALLOC
@@ -136,7 +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_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 <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;
diff --git a/ld/ldlex.l b/ld/ldlex.l
index 9967b69..cf7fd47 100644
--- a/ld/ldlex.l
+++ b/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('-');}
diff --git a/ld/ldmain.c b/ld/ldmain.c
index 99526a0..a83385e 100644
--- a/ld/ldmain.c
+++ b/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
diff --git a/ld/ldwrite.c b/ld/ldwrite.c
index 6e1603a..0f545d0 100644
--- a/ld/ldwrite.c
+++ b/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,
- input_section,
- data,
- symbols)
-bfd *input_bfd;
-asection *input_section;
-PTR data;
-asymbol **symbols;
+static void
+DEFUN(perform_relocation,(input_bfd,
+ input_section,
+ data,
+ 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,10 +304,10 @@ 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",
- output_bfd);
+ 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,
@@ -354,8 +352,8 @@ asymbol **symbols;
}
-static void
-write_rel()
+static void
+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,19 +387,28 @@ write_rel()
}
void
-ldwrite ()
+DEFUN(ldwrite, (write_map),
+ boolean write_map)
{
data_area = (PTR) ldmalloc(largest_section);
if (config.relocateable_output == true)
- {
- write_rel();
- }
+ {
+ write_rel();
+ }
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 ();
}
diff --git a/ld/relax.c b/ld/relax.c
new file mode 100644
index 0000000..6db5590
--- /dev/null
+++ b/ld/relax.c
@@ -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;
+
+}
+