diff options
-rw-r--r-- | ld/ChangeLog | 28 | ||||
-rw-r--r-- | ld/Makefile.in | 18 | ||||
-rw-r--r-- | ld/config.h | 9 | ||||
-rw-r--r-- | ld/ldexp.c | 52 | ||||
-rw-r--r-- | ld/ldgram.y | 11 | ||||
-rw-r--r-- | ld/ldlex.l | 24 | ||||
-rw-r--r-- | ld/ldmain.c | 11 | ||||
-rw-r--r-- | ld/ldwrite.c | 163 | ||||
-rw-r--r-- | ld/relax.c | 299 |
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 */ @@ -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; @@ -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; + +} + |