* 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)
* Makefile.in: Pass -y to bison. (Again;

View file

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

View file

@ -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 */

View file

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

View file

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

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
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('-');}

View file

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

View file

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

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