X-Git-Url: https://repo.jachan.dev/binutils.git/blobdiff_plain/f177a611f1cf28a94a906e4338e49688b5e21fc1..416b47c64d9cf8cbfac2c3461456b466f5bb9298:/ld/ldlang.c diff --git a/ld/ldlang.c b/ld/ldlang.c index b7596a0cec..36a85534b0 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -1,5 +1,6 @@ -/* Copyright (C) 1991 Free Software Foundation, Inc. - +/* Linker command language support. + Copyright (C) 1991, 92, 93, 94 Free Software Foundation, Inc. + This file is part of GLD, the Gnu Linker. GLD is free software; you can redistribute it and/or modify @@ -16,40 +17,43 @@ 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. */ -/* $Id$ - * -*/ - #include "bfd.h" -#include "sysdep.h" +#include "sysdep.h" +#include "libiberty.h" +#include "bfdlink.h" #include "ld.h" #include "ldmain.h" -#include "ldsym.h" #include "ldgram.h" -#include "ldwarn.h" -#include "ldlang.h" #include "ldexp.h" +#include "ldlang.h" #include "ldemul.h" #include "ldlex.h" #include "ldmisc.h" +#include "ldctor.h" +#include "ldfile.h" + /* FORWARDS */ -PROTO(static void, print_statements,(void)); -PROTO(static void, print_statement,(lang_statement_union_type *, - lang_output_section_statement_type *)); +static void print_statements PARAMS ((void)); +static void print_statement PARAMS ((lang_statement_union_type *, + lang_output_section_statement_type *)); +static lang_statement_union_type *new_statement PARAMS ((enum statement_enum, + size_t, + lang_statement_list_type*)); /* LOCALS */ -static CONST char *startup_file; +static struct obstack stat_obstack; + +#define obstack_chunk_alloc xmalloc +#define obstack_chunk_free free +static CONST char *startup_file; static lang_statement_list_type input_file_chain; /* Points to the last statement in the .data section, so we can add stuff to the data section without pain */ static lang_statement_list_type end_of_data_section_statement_list; -/* List of statements needed to handle consxtructors */ -static lang_statement_list_type constructor_list; - static boolean placed_commons = false; static lang_output_section_statement_type *default_common_section; static boolean map_option_f; @@ -58,40 +62,96 @@ static lang_input_statement_type *first_file; static lang_statement_list_type lang_output_section_statement; static CONST char *current_target; static CONST char *output_target; -static size_t longest_section_name = 8; -static asection common_section; -static section_userdata_type common_section_userdata; +static int longest_section_name = 8; static lang_statement_list_type statement_list; -/* EXPORTS */ +static void print_size PARAMS ((size_t value)); +static void print_alignment PARAMS ((unsigned int value)); +static void print_fill PARAMS ((fill_type value)); +static void print_section PARAMS ((const char *name)); +static void lang_for_each_statement_worker + PARAMS ((void (*func) (lang_statement_union_type *), + lang_statement_union_type *s)); +static lang_input_statement_type *new_afile + PARAMS ((const char *name, lang_input_file_enum_type file_type, + const char *target, boolean add_to_list)); +static void print_flags PARAMS ((int *ignore_flags)); +static void init_os PARAMS ((lang_output_section_statement_type *s)); +static void wild_doit PARAMS ((lang_statement_list_type *ptr, + asection *section, + lang_output_section_statement_type *output, + lang_input_statement_type *file)); +static void wild_section PARAMS ((lang_wild_statement_type *ptr, + const char *section, + lang_input_statement_type *file, + lang_output_section_statement_type *output)); +static lang_input_statement_type *lookup_name PARAMS ((const char *name)); +static void load_symbols PARAMS ((lang_input_statement_type *entry)); +static void wild PARAMS ((lang_wild_statement_type *s, + const char *section, const char *file, + const char *target, + lang_output_section_statement_type *output)); +static bfd *open_output PARAMS ((const char *name)); +static void ldlang_open_output PARAMS ((lang_statement_union_type *statement)); +static void open_input_bfds PARAMS ((lang_statement_union_type *statement)); +static void lang_reasonable_defaults PARAMS ((void)); +static void lang_place_undefineds PARAMS ((void)); +static void map_input_to_output_sections + PARAMS ((lang_statement_union_type *s, + const char *target, + lang_output_section_statement_type *output_section_statement)); +static void print_output_section_statement + PARAMS ((lang_output_section_statement_type *output_section_statement)); +static void print_assignment + PARAMS ((lang_assignment_statement_type *assignment, + lang_output_section_statement_type *output_section)); +static void print_input_statement PARAMS ((lang_input_statement_type *statm)); +static void print_input_section PARAMS ((lang_input_section_type *in)); +static void print_fill_statement PARAMS ((lang_fill_statement_type *fill)); +static void print_data_statement PARAMS ((lang_data_statement_type *data)); +static void print_reloc_statement PARAMS ((lang_reloc_statement_type *reloc)); +static void print_padding_statement PARAMS ((lang_padding_statement_type *s)); +static void print_wild_statement + PARAMS ((lang_wild_statement_type *w, + lang_output_section_statement_type *os)); +static void print_statement PARAMS ((lang_statement_union_type *s, + lang_output_section_statement_type *os)); +static void print_statements PARAMS ((void)); +static bfd_vma insert_pad PARAMS ((lang_statement_union_type **this_ptr, + fill_type fill, unsigned int power, + asection *output_section_statement, + bfd_vma dot)); +static bfd_vma size_input_section + PARAMS ((lang_statement_union_type **this_ptr, + lang_output_section_statement_type *output_section_statement, + fill_type fill, bfd_vma dot, boolean relax)); +static bfd_vma lang_do_assignments + PARAMS ((lang_statement_union_type * s, + lang_output_section_statement_type *output_section_statement, + fill_type fill, + bfd_vma dot)); +static void lang_finish PARAMS ((void)); +static void lang_check PARAMS ((void)); +static void lang_common PARAMS ((void)); +static boolean lang_one_common PARAMS ((struct bfd_link_hash_entry *, PTR)); +static void lang_place_orphans PARAMS ((void)); +static int topower PARAMS ((int)); +static void reset_memory_regions PARAMS ((void)); + +/* EXPORTS */ +lang_output_section_statement_type *abs_output_section; lang_statement_list_type *stat_ptr = &statement_list; -lang_input_statement_type *script_file = 0; -boolean option_longmap = false; -lang_statement_list_type file_chain = {0}; -CONST char *entry_symbol = 0; -bfd_size_type largest_section = 0; +lang_statement_list_type file_chain = { 0 }; +static const char *entry_symbol = 0; boolean lang_has_input_file = false; -lang_output_section_statement_type *create_object_symbols = 0; boolean had_output_filename = false; boolean lang_float_flag = false; -/* IMPORTS */ -extern char *default_target; - -extern unsigned int undefined_global_sym_count; -extern char *current_file; -extern bfd *output_bfd; -extern enum bfd_architecture ldfile_output_architecture; -extern unsigned long ldfile_output_machine; -extern char *ldfile_output_machine_name; -extern ldsym_type *symbol_head; -extern unsigned int commons_pending; -extern args_type command_line; -extern ld_config_type config; -extern boolean had_script; -extern boolean write_map; - - -#ifdef __STDC__ +boolean delete_output_file_on_failure = false; + +etree_type *base; /* Relocation base - or null */ + + +#if defined(__STDC__) || defined(ALMOST_STDC) #define cat(a,b) a##b #else #define cat(a,b) a/**/b @@ -103,33 +163,39 @@ extern boolean write_map; #define outside_symbol_address(q) ((q)->value + outside_section_address(q->section)) -void EXFUN(lang_add_data,( int type , union etree_union *exp)); - -static void -DEFUN(print_size,(value), - size_t value) +PTR +stat_alloc (size) + size_t size; { - printf("%5x", (unsigned)value); + return obstack_alloc (&stat_obstack, size); } -static void -DEFUN(print_alignment,(value), - unsigned int value) + +static void +print_size (value) + size_t value; { - printf("2**%1u",value); + fprintf (config.map_file, "%5x", (unsigned) value); } -static void -DEFUN(print_fill,(value), - fill_type value) + +static void +print_alignment (value) + unsigned int value; { - printf("%04x",(unsigned)value); + fprintf (config.map_file, "2**%1u", value); } +static void +print_fill (value) + fill_type value; +{ + fprintf (config.map_file, "%04x", (unsigned) value); +} -static void -DEFUN(print_section,(name), - CONST char *CONST name) +static void +print_section (name) + CONST char *name; { - printf("%*s", -longest_section_name, name); + fprintf (config.map_file, "%*s", -longest_section_name, name); } /*---------------------------------------------------------------------- @@ -137,82 +203,84 @@ DEFUN(print_section,(name), function for each node */ -static void -DEFUN(lang_for_each_statement_worker,(func, s), - void (*func)() AND - lang_statement_union_type *s) +static void +lang_for_each_statement_worker (func, s) + void (*func) PARAMS ((lang_statement_union_type *)); + lang_statement_union_type *s; { - for (; s != (lang_statement_union_type *)NULL ; s = s->next) - { - func(s); + for (; s != (lang_statement_union_type *) NULL; s = s->next) + { + func (s); - switch (s->header.type) { + switch (s->header.type) + { case lang_constructors_statement_enum: - lang_for_each_statement_worker(func, constructor_list.head); + lang_for_each_statement_worker (func, constructor_list.head); break; case lang_output_section_statement_enum: lang_for_each_statement_worker - (func, + (func, s->output_section_statement.children.head); break; case lang_wild_statement_enum: lang_for_each_statement_worker - (func, + (func, s->wild_statement.children.head); break; case lang_data_statement_enum: + case lang_reloc_statement_enum: case lang_object_symbols_statement_enum: case lang_output_statement_enum: case lang_target_statement_enum: case lang_input_section_enum: case lang_input_statement_enum: - case lang_fill_statement_enum: case lang_assignment_statement_enum: case lang_padding_statement_enum: case lang_address_statement_enum: break; default: - FAIL(); + FAIL (); break; } - } + } } void -DEFUN(lang_for_each_statement,(func), - void (*func)()) +lang_for_each_statement (func) + void (*func) PARAMS ((lang_statement_union_type *)); { - lang_for_each_statement_worker(func, - statement_list.head); + lang_for_each_statement_worker (func, + statement_list.head); } + /*----------------------------------------------------------------------*/ -static void -DEFUN(lang_list_init,(list), - lang_statement_list_type *list) +void +lang_list_init (list) + lang_statement_list_type *list; { -list->head = (lang_statement_union_type *)NULL; -list->tail = &list->head; + list->head = (lang_statement_union_type *) NULL; + list->tail = &list->head; } - /*---------------------------------------------------------------------- - + build a new statement node for the parse tree */ static -lang_statement_union_type* -DEFUN(new_statement,(type, size, list), - enum statement_enum type AND - bfd_size_type size AND - lang_statement_list_type *list) +lang_statement_union_type * +new_statement (type, size, list) + enum statement_enum type; + size_t size; + lang_statement_list_type * list; { lang_statement_union_type *new = (lang_statement_union_type *) - ldmalloc(size); + stat_alloc (size); + new->header.type = type; - new->header.next = (lang_statement_union_type *)NULL; - lang_statement_append(list, new, &new->header.next); + new->header.next = (lang_statement_union_type *) NULL; + lang_statement_append (list, new, &new->header.next); return new; } @@ -228,121 +296,128 @@ DEFUN(new_statement,(type, size, list), */ static lang_input_statement_type * -DEFUN(new_afile, (name, file_type, target), - CONST char *CONST name AND - CONST lang_input_file_enum_type file_type AND - CONST char *CONST target) +new_afile (name, file_type, target, add_to_list) + CONST char *name; + lang_input_file_enum_type file_type; + CONST char *target; + boolean add_to_list; { - lang_input_statement_type *p = new_stat(lang_input_statement, - stat_ptr); + lang_input_statement_type *p; + + if (add_to_list) + p = new_stat (lang_input_statement, stat_ptr); + else + { + p = ((lang_input_statement_type *) + stat_alloc (sizeof (lang_input_statement_type))); + p->header.next = NULL; + } + lang_has_input_file = true; p->target = target; - switch (file_type) { - case lang_input_file_is_symbols_only_enum: - p->filename = name; - p->is_archive =false; - p->real = true; - p->local_sym_name= name; - p->just_syms_flag = true; - p->search_dirs_flag = false; - break; - case lang_input_file_is_fake_enum: - p->filename = name; - p->is_archive =false; - p->real = false; - p->local_sym_name= name; - p->just_syms_flag = false; - p->search_dirs_flag =false; - break; - case lang_input_file_is_l_enum: - p->is_archive = true; - p->filename = name; - p->real = true; - p->local_sym_name = concat("-l",name,""); - p->just_syms_flag = false; - p->search_dirs_flag = true; - break; - case lang_input_file_is_search_file_enum: - case lang_input_file_is_marker_enum: - p->filename = name; - p->is_archive =false; - p->real = true; - p->local_sym_name= name; - p->just_syms_flag = false; - p->search_dirs_flag =true; - break; - case lang_input_file_is_file_enum: - p->filename = name; - p->is_archive =false; - p->real = true; - p->local_sym_name= name; - p->just_syms_flag = false; - p->search_dirs_flag =false; - break; - default: - FAIL(); - } - p->asymbols = (asymbol **)NULL; - p->superfile = (lang_input_statement_type *)NULL; - p->next_real_file = (lang_statement_union_type*)NULL; - p->next = (lang_statement_union_type*)NULL; + p->complained = false; + switch (file_type) + { + case lang_input_file_is_symbols_only_enum: + p->filename = name; + p->is_archive = false; + p->real = true; + p->local_sym_name = name; + p->just_syms_flag = true; + p->search_dirs_flag = false; + break; + case lang_input_file_is_fake_enum: + p->filename = name; + p->is_archive = false; + p->real = false; + p->local_sym_name = name; + p->just_syms_flag = false; + p->search_dirs_flag = false; + break; + case lang_input_file_is_l_enum: + p->is_archive = true; + p->filename = name; + p->real = true; + p->local_sym_name = concat ("-l", name, (const char *) NULL); + p->just_syms_flag = false; + p->search_dirs_flag = true; + break; + case lang_input_file_is_marker_enum: + p->filename = name; + p->is_archive = false; + p->real = false; + p->local_sym_name = name; + p->just_syms_flag = false; + p->search_dirs_flag = true; + break; + case lang_input_file_is_search_file_enum: + p->filename = name; + p->is_archive = false; + p->real = true; + p->local_sym_name = name; + p->just_syms_flag = false; + p->search_dirs_flag = true; + break; + case lang_input_file_is_file_enum: + p->filename = name; + p->is_archive = false; + p->real = true; + p->local_sym_name = name; + p->just_syms_flag = false; + p->search_dirs_flag = false; + break; + default: + FAIL (); + } + p->the_bfd = (bfd *) NULL; + p->asymbols = (asymbol **) NULL; + p->next_real_file = (lang_statement_union_type *) NULL; + p->next = (lang_statement_union_type *) NULL; p->symbol_count = 0; - p->common_output_section = (asection *)NULL; - lang_statement_append(&input_file_chain, - (lang_statement_union_type *)p, - &p->next_real_file); + p->common_output_section = (asection *) NULL; + p->loaded = false; + lang_statement_append (&input_file_chain, + (lang_statement_union_type *) p, + &p->next_real_file); return p; } - - lang_input_statement_type * -DEFUN(lang_add_input_file,(name, file_type, target), - char *name AND - lang_input_file_enum_type file_type AND - char *target) +lang_add_input_file (name, file_type, target) + CONST char *name; + lang_input_file_enum_type file_type; + CONST char *target; { - /* Look it up or build a new one */ lang_has_input_file = true; -#if 0 - lang_input_statement_type *p; - - for (p = (lang_input_statement_type *)input_file_chain.head; - p != (lang_input_statement_type *)NULL; - p = (lang_input_statement_type *)(p->next_real_file)) - { - /* Sometimes we have incomplete entries in here */ - if (p->filename != (char *)NULL) { - if(strcmp(name,p->filename) == 0) return p; - } - - } -#endif - return new_afile(name, file_type, target); + return new_afile (name, file_type, target, true); } - /* Build enough state so that the parser can build its tree */ void -DEFUN_VOID(lang_init) +lang_init () { + obstack_begin (&stat_obstack, 1000); + + stat_ptr = &statement_list; - stat_ptr= &statement_list; - lang_list_init(stat_ptr); + lang_list_init (stat_ptr); - lang_list_init(&input_file_chain); - lang_list_init(&lang_output_section_statement); - lang_list_init(&file_chain); - first_file = lang_add_input_file((char *)NULL, - lang_input_file_is_marker_enum, - (char *)NULL); -} + lang_list_init (&input_file_chain); + lang_list_init (&lang_output_section_statement); + lang_list_init (&file_chain); + first_file = lang_add_input_file ((char *) NULL, + lang_input_file_is_marker_enum, + (char *) NULL); + abs_output_section = lang_output_section_statement_lookup (BFD_ABS_SECTION_NAME); + abs_output_section->bfd_section = &bfd_abs_section; + +} /*---------------------------------------------------------------------- - A region is an area of memory declared with the - MEMORY { name:org=exp, len=exp ... } - syntax. + A region is an area of memory declared with the + MEMORY { name:org=exp, len=exp ... } + syntax. We maintain a list of all the regions here @@ -354,161 +429,192 @@ static lang_memory_region_type *lang_memory_region_list; static lang_memory_region_type **lang_memory_region_list_tail = &lang_memory_region_list; lang_memory_region_type * -DEFUN(lang_memory_region_lookup,(name), - CONST char *CONST name) +lang_memory_region_lookup (name) + CONST char *CONST name; { - lang_memory_region_type *p = lang_memory_region_list; + lang_memory_region_type *p = lang_memory_region_list; + for (p = lang_memory_region_list; - p != ( lang_memory_region_type *)NULL; - p = p->next) { - if (strcmp(p->name, name) == 0) { - return p; - } - } - if (strcmp(name,"*default*")==0) { - /* This is the default region, dig out first one on the list */ - if (lang_memory_region_list != (lang_memory_region_type*)NULL){ - return lang_memory_region_list; + p != (lang_memory_region_type *) NULL; + p = p->next) + { + if (strcmp (p->name, name) == 0) + { + return p; + } } - } + if (strcmp (name, "*default*") == 0) { - lang_memory_region_type *new = - (lang_memory_region_type *)ldmalloc((bfd_size_type)(sizeof(lang_memory_region_type))); - new->name = buystring(name); - new->next = (lang_memory_region_type *)NULL; - - *lang_memory_region_list_tail = new; - lang_memory_region_list_tail = &new->next; - new->origin = 0; - new->length = ~0; - new->current = 0; - return new; + /* This is the default region, dig out first one on the list */ + if (lang_memory_region_list != (lang_memory_region_type *) NULL) + { + return lang_memory_region_list; + } } + { + lang_memory_region_type *new = + (lang_memory_region_type *) stat_alloc ((bfd_size_type) (sizeof (lang_memory_region_type))); + + new->name = buystring (name); + new->next = (lang_memory_region_type *) NULL; + + *lang_memory_region_list_tail = new; + lang_memory_region_list_tail = &new->next; + new->origin = 0; + new->length = ~(bfd_size_type)0; + new->current = 0; + new->had_full_message = false; + + return new; + } } lang_output_section_statement_type * -DEFUN(lang_output_section_find,(name), - CONST char * CONST name) +lang_output_section_find (name) + CONST char *CONST name; { lang_statement_union_type *u; lang_output_section_statement_type *lookup; for (u = lang_output_section_statement.head; - u != (lang_statement_union_type *)NULL; + u != (lang_statement_union_type *) NULL; u = lookup->next) - { - lookup = &u->output_section_statement; - if (strcmp(name, lookup->name)==0) { + { + lookup = &u->output_section_statement; + if (strcmp (name, lookup->name) == 0) + { return lookup; } - } - return (lang_output_section_statement_type *)NULL; + } + return (lang_output_section_statement_type *) NULL; } lang_output_section_statement_type * -DEFUN(lang_output_section_statement_lookup,(name), - CONST char * CONST name) +lang_output_section_statement_lookup (name) + CONST char *CONST name; { lang_output_section_statement_type *lookup; - lookup =lang_output_section_find(name); - if (lookup == (lang_output_section_statement_type *)NULL) { - - lookup =(lang_output_section_statement_type *) - new_stat(lang_output_section_statement, stat_ptr); - lookup->region = (lang_memory_region_type *)NULL; - lookup->fill = 0; - lookup->block_value = 1; - lookup->name = name; - - lookup->next = (lang_statement_union_type*)NULL; - lookup->bfd_section = (asection *)NULL; - lookup->processed = false; - lookup->addr_tree = (etree_type *)NULL; - lang_list_init(&lookup->children); - - lang_statement_append(&lang_output_section_statement, - (lang_statement_union_type *)lookup, - &lookup->next); - } - return lookup; -} - - + lookup = lang_output_section_find (name); + if (lookup == (lang_output_section_statement_type *) NULL) + { + lookup = (lang_output_section_statement_type *) + new_stat (lang_output_section_statement, stat_ptr); + lookup->region = (lang_memory_region_type *) NULL; + lookup->fill = 0; + lookup->block_value = 1; + lookup->name = name; + + lookup->next = (lang_statement_union_type *) NULL; + lookup->bfd_section = (asection *) NULL; + lookup->processed = false; + lookup->loadable = 1; + lookup->addr_tree = (etree_type *) NULL; + lang_list_init (&lookup->children); + + lookup->memspec = (CONST char *) NULL; + lookup->flags = 0; + lookup->subsection_alignment = -1; + lookup->section_alignment = -1; + lookup->load_base = (union etree_union *) NULL; + + lang_statement_append (&lang_output_section_statement, + (lang_statement_union_type *) lookup, + &lookup->next); + } + return lookup; +} +/*ARGSUSED*/ static void -DEFUN(print_flags, (outfile, ignore_flags), - FILE *outfile AND - int *ignore_flags) +print_flags (ignore_flags) + int *ignore_flags; { - fprintf(outfile,"("); + fprintf (config.map_file, "("); #if 0 - if (flags->flag_read) fprintf(outfile,"R"); - if (flags->flag_write) fprintf(outfile,"W"); - if (flags->flag_executable) fprintf(outfile,"X"); - if (flags->flag_loadable) fprintf(outfile,"L"); + if (flags->flag_read) + fprintf (outfile, "R"); + if (flags->flag_write) + fprintf (outfile, "W"); + if (flags->flag_executable) + fprintf (outfile, "X"); + if (flags->flag_loadable) + fprintf (outfile, "L"); #endif - fprintf(outfile,")"); + fprintf (config.map_file, ")"); } void -DEFUN(lang_map,(outfile), - FILE *outfile) +lang_map () { lang_memory_region_type *m; - fprintf(outfile,"**MEMORY CONFIGURATION**\n\n"); + + fprintf (config.map_file, "**MEMORY CONFIGURATION**\n\n"); #ifdef HOST_64_BIT - fprintf(outfile,"name\t\torigin\t\tlength\t\tattributes\n"); + fprintf (config.map_file, "name\t\torigin\t\tlength\t\tattributes\n"); #else - fprintf(outfile,"name\t\torigin length\t\tattributes\n"); + fprintf (config.map_file, + "name\t\torigin length r_size c_size is attributes\n"); + #endif for (m = lang_memory_region_list; - m != (lang_memory_region_type *)NULL; - m = m->next) + m != (lang_memory_region_type *) NULL; + m = m->next) { - fprintf(outfile,"%-16s", m->name); - print_address(m->origin); + fprintf (config.map_file, "%-16s", m->name); + print_address (m->origin); + print_space (); + print_address ((bfd_vma)m->length); + print_space (); + print_address ((bfd_vma)m->old_length); print_space(); - print_address(m->length); + print_address (m->current - m->origin); print_space(); - print_flags(outfile, &m->flags); - fprintf(outfile,"\n"); + if (m->old_length) + fprintf (config.map_file, " %2d%% ", + (int) ((m->current - m->origin) * 100 / m->old_length)); + print_flags (&m->flags); + fprintf (config.map_file, "\n"); } - fprintf(outfile,"\n\n**LINK EDITOR MEMORY MAP**\n\n"); - fprintf(outfile,"output input virtual\n"); - fprintf(outfile,"section section address tsize\n\n"); + fprintf (config.map_file, "\n\n**LINK EDITOR MEMORY MAP**\n\n"); + fprintf (config.map_file, "output input virtual\n"); + fprintf (config.map_file, "section section address tsize\n\n"); - print_statements(); + print_statements (); } /* * */ -static void -DEFUN(init_os,(s), - lang_output_section_statement_type *s) +static void +init_os (s) + lang_output_section_statement_type * s; { +/* asection *section = bfd_get_section_by_name(output_bfd, s->name);*/ section_userdata_type *new = - (section_userdata_type *) - ldmalloc((bfd_size_type)(sizeof(section_userdata_type))); - - s->bfd_section = bfd_make_section(output_bfd, s->name); - if (s->bfd_section == (asection *)NULL) { - info("%P%F output format %s cannot represent section called %s\n", - output_bfd->xvec->name, - s->name); - } + (section_userdata_type *) + stat_alloc ((bfd_size_type) (sizeof (section_userdata_type))); + + s->bfd_section = bfd_get_section_by_name (output_bfd, s->name); + if (s->bfd_section == (asection *) NULL) + s->bfd_section = bfd_make_section (output_bfd, s->name); + if (s->bfd_section == (asection *) NULL) + { + einfo ("%P%F: output format %s cannot represent section called %s\n", + output_bfd->xvec->name, s->name); + } s->bfd_section->output_section = s->bfd_section; -/* s->bfd_section->flags = s->flags;*/ +/* s->bfd_section->flags = s->flags;*/ /* We initialize an output sections output offset to minus its own */ /* vma to allow us to output a section through itself */ s->bfd_section->output_offset = 0; - get_userdata( s->bfd_section) = (PTR)new; + get_userdata (s->bfd_section) = (PTR) new; + } /*********************************************************************** @@ -524,66 +630,86 @@ DEFUN(init_os,(s), each part of the expanstion, and placed after the statement provided. */ - -static void -DEFUN(wild_doit,(ptr, section, output, file), - lang_statement_list_type *ptr AND - asection *section AND - lang_output_section_statement_type *output AND - lang_input_statement_type *file) -{ - if(output->bfd_section == (asection *)NULL) - { - init_os(output); - } - if (section != (asection *)NULL - && section->output_section == (asection *)NULL) { +static void +wild_doit (ptr, section, output, file) + lang_statement_list_type * ptr; + asection * section; + lang_output_section_statement_type * output; + lang_input_statement_type * file; +{ + if (output->bfd_section == (asection *) NULL) + init_os (output); + + if (section != (asection *) NULL + && section->output_section == (asection *) NULL) + { /* Add a section reference to the list */ - lang_input_section_type *new = new_stat(lang_input_section, ptr); + lang_input_section_type *new = new_stat (lang_input_section, ptr); new->section = section; new->ifile = file; section->output_section = output->bfd_section; - section->output_section->flags |= section->flags; - if (section->alignment_power > output->bfd_section->alignment_power) { - output->bfd_section->alignment_power = section->alignment_power; - } - } -} -static asection * -DEFUN(our_bfd_get_section_by_name,(abfd, section), -bfd *abfd AND -CONST char *section) -{ - return bfd_get_section_by_name(abfd, section); -} + /* We don't copy the SEC_NEVER_LOAD flag from an input section to + an output section, because we want to be able to include a + SEC_NEVER_LOAD section in the middle of an otherwise loaded + section (I don't know why we want to do this, but we do). + build_link_order in ldwrite.c handles this case by turning the + embedded SEC_NEVER_LOAD section into a fill. */ + section->output_section->flags |= + section->flags & (flagword) (~ SEC_NEVER_LOAD); -static void -DEFUN(wild_section,(ptr, section, file , output), - lang_wild_statement_type *ptr AND - CONST char *section AND - lang_input_statement_type *file AND - lang_output_section_statement_type *output) -{ - asection *s; - if (file->just_syms_flag == false) { - if (section == (char *)NULL) { - /* Do the creation to all sections in the file */ - for (s = file->the_bfd->sections; s != (asection *)NULL; s=s->next) { - wild_doit(&ptr->children, s, output, file); - } + if (!output->loadable) + { + /* Turn off load flag */ + output->bfd_section->flags &= ~SEC_LOAD; + output->bfd_section->flags |= SEC_NEVER_LOAD; + } + if (section->alignment_power > output->bfd_section->alignment_power) + { + output->bfd_section->alignment_power = section->alignment_power; } - else { - /* Do the creation to the named section only */ - wild_doit(&ptr->children, - our_bfd_get_section_by_name(file->the_bfd, section), - output, file); + /* If supplied an aligmnet, then force it */ + if (output->section_alignment != -1) + { + output->bfd_section->alignment_power = output->section_alignment; } } } +static void +wild_section (ptr, section, file, output) + lang_wild_statement_type * ptr; + CONST char *section; + lang_input_statement_type * file; + lang_output_section_statement_type * output; +{ + asection *s; + + if (file->just_syms_flag == false) + { + if (section == (char *) NULL) + { + /* Do the creation to all sections in the file */ + for (s = file->the_bfd->sections; s != NULL; s = s->next) + { + /* except for bss */ + if ((s->flags & SEC_IS_COMMON) == 0) + { + wild_doit (&ptr->children, s, output, file); + } + } + } + else + { + /* Do the creation to the named section only */ + s = bfd_get_section_by_name (file->the_bfd, section); + if (s != NULL) + wild_doit (&ptr->children, s, output, file); + } + } +} /* passed a file name (which must have been seen already and added to the statement tree. We will see if it has been opened already and @@ -593,96 +719,152 @@ DEFUN(wild_section,(ptr, section, file , output), not define anything we need at the time, they won't have all their symbols read. If we need them later, we'll have to redo it. */ -static -lang_input_statement_type * -DEFUN(lookup_name,(name), - CONST char * CONST name) +static lang_input_statement_type * +lookup_name (name) + CONST char *name; { lang_input_statement_type *search; - for(search = (lang_input_statement_type *)input_file_chain.head; - search != (lang_input_statement_type *)NULL; - search = (lang_input_statement_type *)search->next_real_file) - { - if (search->filename == (char *)NULL && name == (char *)NULL) { - return search; - } - if (search->filename != (char *)NULL && name != (char *)NULL) { - if (strcmp(search->filename, name) == 0) { - ldmain_open_file_read_symbol(search); - return search; - } - } - } - /* There isn't an afile entry for this file yet, this must be - because the name has only appeared inside a load script and not - on the command line */ - search = new_afile(name, lang_input_file_is_file_enum, default_target); - ldmain_open_file_read_symbol(search); + for (search = (lang_input_statement_type *) input_file_chain.head; + search != (lang_input_statement_type *) NULL; + search = (lang_input_statement_type *) search->next_real_file) + { + if (search->filename == (char *) NULL && name == (char *) NULL) + return search; + if (search->filename != (char *) NULL + && name != (char *) NULL + && strcmp (search->filename, name) == 0) + break; + } + + if (search == (lang_input_statement_type *) NULL) + search = new_afile (name, lang_input_file_is_file_enum, default_target, + false); + + /* If we have already added this file, or this file is not real + (FIXME: can that ever actually happen?) or the name is NULL + (FIXME: can that ever actually happen?) don't add this file. */ + if (search->loaded + || ! search->real + || search->filename == (const char *) NULL) + return search; + + load_symbols (search); + return search; +} + +/* Get the symbols for an input file. */ + +static void +load_symbols (entry) + lang_input_statement_type *entry; +{ + if (entry->loaded) + return; + + ldfile_open_file (entry); + + if (bfd_check_format (entry->the_bfd, bfd_object)) + { + ldlang_add_file (entry); + if (trace_files || trace_file_tries) + info_msg ("%I\n", entry); + } + else if (bfd_check_format (entry->the_bfd, bfd_archive)) + { + /* There is nothing to do here; the add_symbols routine will + call ldlang_add_file (via the add_archive_element callback) + for each element of the archive which is used. */ + } + else + einfo ("%F%B: file not recognized: %E\n", entry->the_bfd); + if (bfd_link_add_symbols (entry->the_bfd, &link_info) == false) + einfo ("%F%B: could not read symbols: %E\n", entry->the_bfd); + entry->loaded = true; } static void -DEFUN(wild,(s, section, file, target, output), - lang_wild_statement_type *s AND - CONST char *CONST section AND - CONST char *CONST file AND - CONST char *CONST target AND - lang_output_section_statement_type *output) +wild (s, section, file, target, output) + lang_wild_statement_type * s; + CONST char *section; + CONST char *file; + CONST char *target; + lang_output_section_statement_type * output; { lang_input_statement_type *f; - if (file == (char *)NULL) { - /* Perform the iteration over all files in the list */ - for (f = (lang_input_statement_type *)file_chain.head; - f != (lang_input_statement_type *)NULL; - f = (lang_input_statement_type *)f->next) { - wild_section(s, section, f, output); + + if (file == (char *) NULL) + { + /* Perform the iteration over all files in the list */ + for (f = (lang_input_statement_type *) file_chain.head; + f != (lang_input_statement_type *) NULL; + f = (lang_input_statement_type *) f->next) + { + wild_section (s, section, f, output); + } + } + else + { + /* Perform the iteration over a single file */ + wild_section (s, section, lookup_name (file), output); + } + if (section != (char *) NULL + && strcmp (section, "COMMON") == 0 + && default_common_section == (lang_output_section_statement_type *) NULL) + { + /* Remember the section that common is going to incase we later + get something which doesn't know where to put it */ + default_common_section = output; } - } - else { - /* Perform the iteration over a single file */ - wild_section( s, section, lookup_name(file), output); - } - if (section != (char *)NULL - && strcmp(section,"COMMON") == 0 - && default_common_section == (lang_output_section_statement_type*)NULL) - { - /* Remember the section that common is going to incase we later - get something which doesn't know where to put it */ - default_common_section = output; - } } /* - read in all the files + read in all the files */ -static bfd * -DEFUN(open_output,(name), - CONST char *CONST name) + +static bfd * +open_output (name) + CONST char *name; { - extern CONST char *output_filename; bfd *output; - if (output_target == (char *)NULL) { - if (current_target != (char *)NULL) - output_target = current_target; - else - output_target = default_target; - } - output = bfd_openw(name, output_target); - output_filename = name; - if (output == (bfd *)NULL) - { - if (bfd_error == invalid_target) { - info("%P%F target %s not found\n", output_target); + if (output_target == (char *) NULL) + { + if (current_target != (char *) NULL) + output_target = current_target; + else + output_target = default_target; + } + output = bfd_openw (name, output_target); + + if (output == (bfd *) NULL) + { + if (bfd_get_error () == bfd_error_invalid_target) + { + einfo ("%P%F: target %s not found\n", output_target); } - info("%P%F problem opening output file %s, %E", name); - } - - output->flags |= D_PAGED; - bfd_set_format(output, bfd_object); + einfo ("%P%F: cannot open output file %s: %E\n", name); + } + + delete_output_file_on_failure = 1; + + /* output->flags |= D_PAGED;*/ + + if (! bfd_set_format (output, bfd_object)) + einfo ("%P%F:%s: can not make object file: %E\n", name); + if (! bfd_set_arch_mach (output, + ldfile_output_architecture, + ldfile_output_machine)) + einfo ("%P%F:%s: can not set architecture: %E\n", name); + + link_info.hash = bfd_link_hash_table_create (output); + if (link_info.hash == (struct bfd_link_hash_table *) NULL) + einfo ("%P%F: can not create link hash table: %E\n"); + + bfd_set_gp_size (output, g_switch_value); return output; } @@ -690,72 +872,88 @@ DEFUN(open_output,(name), static void -DEFUN(ldlang_open_output,(statement), - lang_statement_union_type *statement) +ldlang_open_output (statement) + lang_statement_union_type * statement; { - switch (statement->header.type) - { - case lang_output_statement_enum: - output_bfd = open_output(statement->output_statement.name); - ldemul_set_output_arch(); - break; + switch (statement->header.type) + { + case lang_output_statement_enum: + ASSERT (output_bfd == (bfd *) NULL); + output_bfd = open_output (statement->output_statement.name); + ldemul_set_output_arch (); + if (config.magic_demand_paged && !link_info.relocateable) + output_bfd->flags |= D_PAGED; + else + output_bfd->flags &= ~D_PAGED; + if (config.text_read_only) + output_bfd->flags |= WP_TEXT; + else + output_bfd->flags &= ~WP_TEXT; + if (config.traditional_format) + output_bfd->flags |= BFD_TRADITIONAL_FORMAT; + else + output_bfd->flags &= ~BFD_TRADITIONAL_FORMAT; + break; - case lang_target_statement_enum: - current_target = statement->target_statement.target; - break; - default: - break; - } + case lang_target_statement_enum: + current_target = statement->target_statement.target; + break; + default: + break; + } } static void -DEFUN(open_input_bfds,(statement), - lang_statement_union_type *statement) +open_input_bfds (statement) + lang_statement_union_type * statement; { - switch (statement->header.type) - { + switch (statement->header.type) + { case lang_target_statement_enum: - current_target = statement->target_statement.target; - break; - case lang_wild_statement_enum: - /* Maybe we should load the file's symbols */ - if (statement->wild_statement.filename) - { - (void) lookup_name(statement->wild_statement.filename); - } - break; - case lang_input_statement_enum: - if (statement->input_statement.real == true) - { - statement->input_statement.target = current_target; - lookup_name(statement->input_statement.filename); - } - break; - default: - break; - } + current_target = statement->target_statement.target; + break; + case lang_wild_statement_enum: + /* Maybe we should load the file's symbols */ + if (statement->wild_statement.filename) + { + (void) lookup_name (statement->wild_statement.filename); + } + break; + case lang_input_statement_enum: + if (statement->input_statement.real == true) + { + statement->input_statement.target = current_target; + load_symbols (&statement->input_statement); + } + break; + default: + break; + } } + /* If there are [COMMONS] statements, put a wild one into the bss section */ static void -lang_reasonable_defaults() +lang_reasonable_defaults () { #if 0 - lang_output_section_statement_lookup(".text"); - lang_output_section_statement_lookup(".data"); + lang_output_section_statement_lookup (".text"); + lang_output_section_statement_lookup (".data"); - default_common_section = - lang_output_section_statement_lookup(".bss"); + default_common_section = + lang_output_section_statement_lookup (".bss"); - if (placed_commons == false) { - lang_wild_statement_type *new = - new_stat(lang_wild_statement, - &default_common_section->children); - new->section_name = "COMMON"; - new->filename = (char *)NULL; - lang_list_init(&new->children); - } + if (placed_commons == false) + { + lang_wild_statement_type *new = + new_stat (lang_wild_statement, + &default_common_section->children); + + new->section_name = "COMMON"; + new->filename = (char *) NULL; + lang_list_init (&new->children); + } #endif } @@ -764,484 +962,543 @@ lang_reasonable_defaults() Add the supplied name to the symbol table as an undefined reference. Remove items from the chain as we open input bfds */ -typedef struct ldlang_undef_chain_list { +typedef struct ldlang_undef_chain_list +{ struct ldlang_undef_chain_list *next; char *name; -} ldlang_undef_chain_list_type; +} ldlang_undef_chain_list_type; static ldlang_undef_chain_list_type *ldlang_undef_chain_list_head; void -DEFUN(ldlang_add_undef,(name), - CONST char *CONST name) +ldlang_add_undef (name) + CONST char *CONST name; { ldlang_undef_chain_list_type *new = - (ldlang_undef_chain_list_type - *)ldmalloc((bfd_size_type)(sizeof(ldlang_undef_chain_list_type))); + (ldlang_undef_chain_list_type + *) stat_alloc ((bfd_size_type) (sizeof (ldlang_undef_chain_list_type))); new->next = ldlang_undef_chain_list_head; ldlang_undef_chain_list_head = new; - new->name = buystring(name); + new->name = buystring (name); } + /* Run through the list of undefineds created above and place them into the linker hash table as undefined symbols belonging to the script file. */ static void -DEFUN_VOID(lang_place_undefineds) -{ - ldlang_undef_chain_list_type *ptr = ldlang_undef_chain_list_head; - while (ptr != (ldlang_undef_chain_list_type*)NULL) { - ldsym_type *sy = ldsym_get(ptr->name); - asymbol *def; - asymbol **def_ptr = (asymbol **)ldmalloc((bfd_size_type)(sizeof(asymbol **))); - def = (asymbol *)bfd_make_empty_symbol(script_file->the_bfd); - *def_ptr= def; - def->name = ptr->name; - def->flags = BSF_UNDEFINED; - def->section = (asection *)NULL; - Q_enter_global_ref(def_ptr); - ptr = ptr->next; - } -} - - - -/* Copy important data from out internal form to the bfd way. Also - create a section for the dummy file - */ +lang_place_undefineds () +{ + ldlang_undef_chain_list_type *ptr; -static void -DEFUN_VOID(lang_create_output_section_statements) -{ - lang_statement_union_type*os; - for (os = lang_output_section_statement.head; - os != (lang_statement_union_type*)NULL; - os = os->output_section_statement.next) { - lang_output_section_statement_type *s = - &os->output_section_statement; - init_os(s); - } + for (ptr = ldlang_undef_chain_list_head; + ptr != (ldlang_undef_chain_list_type *) NULL; + ptr = ptr->next) + { + struct bfd_link_hash_entry *h; + h = bfd_link_hash_lookup (link_info.hash, ptr->name, true, false, true); + if (h == (struct bfd_link_hash_entry *) NULL) + einfo ("%P%F: bfd_link_hash_lookup failed: %E"); + if (h->type == bfd_link_hash_new) + { + h->type = bfd_link_hash_undefined; + h->u.undef.abfd = NULL; + bfd_link_add_undef (link_info.hash, h); + } + } } +/* Open input files and attatch to output sections */ static void -DEFUN_VOID(lang_init_script_file) +map_input_to_output_sections (s, target, output_section_statement) + lang_statement_union_type * s; + CONST char *target; + lang_output_section_statement_type * output_section_statement; { - script_file = lang_add_input_file("script file", - lang_input_file_is_fake_enum, - (char *)NULL); - script_file->the_bfd = bfd_create("script file", output_bfd); - script_file->symbol_count = 0; - script_file->the_bfd->sections = output_bfd->sections; -} - + for (; s != (lang_statement_union_type *) NULL; s = s->next) + { + switch (s->header.type) + { + case lang_wild_statement_enum: + wild (&s->wild_statement, s->wild_statement.section_name, + s->wild_statement.filename, target, + output_section_statement); -/* Open input files and attatch to output sections */ -static void -DEFUN(map_input_to_output_sections,(s, target, output_section_statement), - lang_statement_union_type *s AND - CONST char *target AND - lang_output_section_statement_type *output_section_statement) -{ - for (; s != (lang_statement_union_type *)NULL ; s = s->next) - { - switch (s->header.type) { - - - case lang_wild_statement_enum: - wild(&s->wild_statement, s->wild_statement.section_name, - s->wild_statement.filename, target, - output_section_statement); + break; + case lang_constructors_statement_enum: + map_input_to_output_sections (constructor_list.head, + target, + output_section_statement); + break; + case lang_output_section_statement_enum: + map_input_to_output_sections (s->output_section_statement.children.head, + target, + &s->output_section_statement); + break; + case lang_output_statement_enum: + break; + case lang_target_statement_enum: + target = s->target_statement.target; + break; + case lang_fill_statement_enum: + case lang_input_section_enum: + case lang_object_symbols_statement_enum: + case lang_data_statement_enum: + case lang_reloc_statement_enum: + case lang_assignment_statement_enum: + case lang_padding_statement_enum: + case lang_input_statement_enum: + if (output_section_statement != NULL + && output_section_statement->bfd_section == NULL) + init_os (output_section_statement); + break; + case lang_afile_asection_pair_statement_enum: + FAIL (); + break; + case lang_address_statement_enum: + /* Mark the specified section with the supplied address */ + { + lang_output_section_statement_type *os = + lang_output_section_statement_lookup + (s->address_statement.section_name); - break; - case lang_constructors_statement_enum: - map_input_to_output_sections(constructor_list.head, - target, - output_section_statement); - break; - case lang_output_section_statement_enum: - map_input_to_output_sections(s->output_section_statement.children.head, - target, - &s->output_section_statement); - break; - case lang_output_statement_enum: - break; - case lang_target_statement_enum: - target = s->target_statement.target; - break; - case lang_fill_statement_enum: - case lang_input_section_enum: - case lang_object_symbols_statement_enum: - case lang_data_statement_enum: - case lang_assignment_statement_enum: - case lang_padding_statement_enum: - break; - case lang_afile_asection_pair_statement_enum: - FAIL(); - break; - case lang_address_statement_enum: - /* Mark the specified section with the supplied address */ - { - lang_output_section_statement_type *os = - lang_output_section_statement_lookup - (s->address_statement.section_name); - os->addr_tree = s->address_statement.address; - if (os->bfd_section == (asection *)NULL) { - info("%P%F can't set the address of undefined section %s\n", - s->address_statement.section_name); + if (os->bfd_section == NULL) + init_os (os); + os->addr_tree = s->address_statement.address; } + break; } - break; - case lang_input_statement_enum: - /* A standard input statement, has no wildcards */ - /* ldmain_open_file_read_symbol(&s->input_statement);*/ - break; - } } } - - - - -static void -DEFUN(print_output_section_statement,(output_section_statement), - lang_output_section_statement_type *output_section_statement) +static void +print_output_section_statement (output_section_statement) + lang_output_section_statement_type * output_section_statement; { asection *section = output_section_statement->bfd_section; - print_nl(); - print_section(output_section_statement->name); - if (section) { + print_nl (); + print_section (output_section_statement->name); + + + if (section) + { print_dot = section->vma; + print_space (); + print_section (""); + print_space (); + print_address (section->vma); + print_space (); + print_size (section->_raw_size); print_space(); - print_section(""); - print_space(); - print_address(section->vma); - print_space(); - print_size(section->size); - print_space(); - print_alignment(section->alignment_power); - print_space(); + print_size(section->_cooked_size); + print_space (); + print_alignment (section->alignment_power); + print_space (); #if 0 - printf("%s flags", output_section_statement->region->name); - print_flags(stdout, &output_section_statement->flags); + fprintf (config.map_file, "%s flags", output_section_statement->region->name); + print_flags (stdout, &output_section_statement->flags); #endif if (section->flags & SEC_LOAD) - printf("load "); + fprintf (config.map_file, "load "); if (section->flags & SEC_ALLOC) - printf("alloc "); + fprintf (config.map_file, "alloc "); if (section->flags & SEC_RELOC) - printf("reloc "); + fprintf (config.map_file, "reloc "); if (section->flags & SEC_HAS_CONTENTS) - printf("contents "); + fprintf (config.map_file, "contents "); } - else { - printf("No attached output section"); + else + { + fprintf (config.map_file, " (no attached output section)"); + } + print_nl (); + if (output_section_statement->load_base) + { + int b = exp_get_value_int(output_section_statement->load_base, + 0, "output base", lang_final_phase_enum); + printf("Output address %08x\n", b); + } + if (output_section_statement->section_alignment >= 0 + || output_section_statement->section_alignment >= 0) + { + printf("\t\t\t\t\tforced alignment "); + if ( output_section_statement->section_alignment >= 0) + { + printf("section 2**%d ",output_section_statement->section_alignment ); + } + if ( output_section_statement->subsection_alignment >= 0) + { + printf("subsection 2**%d ",output_section_statement->subsection_alignment ); + } + + print_nl (); } - print_nl(); - print_statement(output_section_statement->children.head, - output_section_statement); + print_statement (output_section_statement->children.head, + output_section_statement); } -static void -DEFUN(print_assignment,(assignment, output_section), - lang_assignment_statement_type *assignment AND - lang_output_section_statement_type *output_section) +static void +print_assignment (assignment, output_section) + lang_assignment_statement_type * assignment; + lang_output_section_statement_type * output_section; { etree_value_type result; - print_section(""); - print_space(); - print_section(""); - print_space(); - print_address(print_dot); - print_space(); - result = exp_fold_tree(assignment->exp->assign.src, - output_section, - lang_final_phase_enum, - print_dot, - &print_dot); - - if (result.valid) { - print_address(result.value); - } - else - { - printf("*undefined*"); - } - print_space(); - exp_print_tree(stdout, assignment->exp); - printf("\n"); + + print_section (""); + print_space (); + print_section (""); + print_space (); + print_address (print_dot); + print_space (); + result = exp_fold_tree (assignment->exp->assign.src, + output_section, + lang_final_phase_enum, + print_dot, + &print_dot); + + if (result.valid) + { + print_address (result.value); + } + else + { + fprintf (config.map_file, "*undefined*"); + } + print_space (); + exp_print_tree (assignment->exp); + + fprintf (config.map_file, "\n"); } static void -DEFUN(print_input_statement,(statm), - lang_input_statement_type *statm) +print_input_statement (statm) + lang_input_statement_type * statm; { - if (statm->filename != (char *)NULL) { - printf("LOAD %s\n",statm->filename); - } + if (statm->filename != (char *) NULL) + { + fprintf (config.map_file, "LOAD %s\n", statm->filename); + } } -static void -DEFUN(print_symbol,(q), - asymbol *q) +/* Print all the defined symbols for the abfd provided by in the supplied + section. +*/ + +static boolean +print_one_symbol (hash_entry, ptr) +struct bfd_link_hash_entry *hash_entry; +PTR ptr; { - print_section(""); - printf(" "); - print_section(""); - printf(" "); - print_address(outside_symbol_address(q)); - printf(" %s", q->name ? q->name : " "); - print_nl(); + asection * sec = (asection *)ptr; + + if (hash_entry->type == bfd_link_hash_defined) + { + if (sec == hash_entry->u.def.section) { + print_section (""); + fprintf (config.map_file, " "); + print_section (""); + fprintf (config.map_file, " "); + print_address (hash_entry->u.def.value + outside_section_address (sec)); + fprintf (config.map_file, " %s", hash_entry->root.string); + print_nl (); + } + } + + return true; } -static void -DEFUN(print_input_section,(in), - lang_input_section_type *in) +static void +print_input_section (in) + lang_input_section_type * in; { asection *i = in->section; + bfd_size_type size = i->_cooked_size != 0 ? i->_cooked_size : i->_raw_size; - if(i->size != 0) { - print_section(""); - printf(" "); - print_section(i->name); - printf(" "); - if (i->output_section) { - print_address(i->output_section->vma + i->output_offset); - printf(" "); - print_size(i->size); - printf(" "); - print_alignment(i->alignment_power); - printf(" "); - if (in->ifile) { - - bfd *abfd = in->ifile->the_bfd; - if (in->ifile->just_syms_flag == true) { - printf("symbols only "); - } + if (size != 0) + { + print_section (""); + fprintf (config.map_file, " "); + print_section (i->name); + fprintf (config.map_file, " "); + if (i->output_section) + { + print_address (i->output_section->vma + i->output_offset); + fprintf (config.map_file, " "); + print_size (i->_raw_size); + fprintf (config.map_file, " "); + print_size(i->_cooked_size); + fprintf (config.map_file, " "); + print_alignment (i->alignment_power); + fprintf (config.map_file, " "); + if (in->ifile) + { - printf(" %s ",abfd->xvec->name); - if(abfd->my_archive != (bfd *)NULL) { - printf("[%s]%s", abfd->my_archive->filename, - abfd->filename); - } - else { - printf("%s", abfd->filename); - } - printf("(overhead %d bytes)", (int)bfd_alloc_size(abfd)); - print_nl(); + bfd *abfd = in->ifile->the_bfd; - /* Find all the symbols in this file defined in this section */ - { - asymbol **p; - for (p = in->ifile->asymbols; *p; p++) { - asymbol *q = *p; - - if (bfd_get_section(q) == i && q->flags & BSF_GLOBAL) { - print_symbol(q); - } + if (in->ifile->just_syms_flag == true) + { + fprintf (config.map_file, "symbols only "); + } + + fprintf (config.map_file, " %s ", abfd->xvec->name); + if (abfd->my_archive != (bfd *) NULL) + { + fprintf (config.map_file, "[%s]%s", abfd->my_archive->filename, + abfd->filename); + } + else + { + fprintf (config.map_file, "%s", abfd->filename); + } + fprintf (config.map_file, "(overhead %d bytes)", (int) bfd_alloc_size (abfd)); + print_nl (); + + /* Print all the symbols */ + bfd_link_hash_traverse (link_info.hash, print_one_symbol, (PTR) i); + } + else + { + print_nl (); } - } - } - else { - print_nl(); - } - print_dot = outside_section_address(i) + i->size; - } - else { - printf("No output section allocated\n"); + print_dot = outside_section_address (i) + size; + } + else + { + fprintf (config.map_file, "No output section allocated\n"); + } } - } } static void -DEFUN(print_fill_statement,(fill), - lang_fill_statement_type *fill) +print_fill_statement (fill) + lang_fill_statement_type * fill; { - printf("FILL mask "); - print_fill( fill->fill); + fprintf (config.map_file, "FILL mask "); + print_fill (fill->fill); } static void -DEFUN(print_data_statement,(data), - lang_data_statement_type *data) +print_data_statement (data) + lang_data_statement_type * data; { /* bfd_vma value; */ - print_section(""); - print_space(); - print_section(""); - print_space(); + print_section (""); + print_space (); + print_section (""); + print_space (); /* ASSERT(print_dot == data->output_vma);*/ - print_address(data->output_vma); - print_space(); - print_address(data->value); - print_space(); - switch (data->type) { - case BYTE : - printf("BYTE "); - print_dot += BYTE_SIZE; - break; - case SHORT: - printf("SHORT "); - print_dot += SHORT_SIZE; - break; - case LONG: - printf("LONG "); - print_dot += LONG_SIZE; - break; - } + print_address (data->output_vma + data->output_section->vma); + print_space (); + print_address (data->value); + print_space (); + switch (data->type) + { + case BYTE: + fprintf (config.map_file, "BYTE "); + print_dot += BYTE_SIZE; + break; + case SHORT: + fprintf (config.map_file, "SHORT "); + print_dot += SHORT_SIZE; + break; + case LONG: + fprintf (config.map_file, "LONG "); + print_dot += LONG_SIZE; + break; + case QUAD: + fprintf (config.map_file, "QUAD "); + print_dot += QUAD_SIZE; + break; + } - exp_print_tree(stdout, data->exp); - - printf("\n"); + exp_print_tree (data->exp); + + fprintf (config.map_file, "\n"); } +/* Print a reloc statement. */ static void -DEFUN(print_padding_statement,(s), - lang_padding_statement_type *s) -{ - print_section(""); - print_space(); - print_section("*fill*"); - print_space(); - print_address(s->output_offset + s->output_section->vma); - print_space(); - print_size(s->size); - print_space(); - print_fill(s->fill); - print_nl(); -} - -static void -DEFUN(print_wild_statement,(w,os), - lang_wild_statement_type *w AND - lang_output_section_statement_type *os) -{ - printf(" from "); - if (w->filename != (char *)NULL) { - printf("%s",w->filename); - } - else { - printf("*"); - } - if (w->section_name != (char *)NULL) { - printf("(%s)",w->section_name); - } - else { - printf("(*)"); - } - print_nl(); - print_statement(w->children.head, os); +print_reloc_statement (reloc) + lang_reloc_statement_type *reloc; +{ + print_section (""); + print_space (); + print_section (""); + print_space (); + +/* ASSERT(print_dot == data->output_vma);*/ + + print_address (reloc->output_vma + reloc->output_section->vma); + print_space (); + print_address (reloc->addend_value); + print_space (); + + fprintf (config.map_file, "RELOC %s ", reloc->howto->name); + + print_dot += bfd_get_reloc_size (reloc->howto); + + exp_print_tree (reloc->addend_exp); + + fprintf (config.map_file, "\n"); +} -} static void -DEFUN(print_statement,(s, os), - lang_statement_union_type *s AND - lang_output_section_statement_type *os) +print_padding_statement (s) + lang_padding_statement_type * s; { - while (s) { - switch (s->header.type) { - case lang_constructors_statement_enum: - printf("constructors:\n"); -print_statement(constructor_list.head, os); -break; + print_section (""); + print_space (); + print_section ("*fill*"); + print_space (); + print_address (s->output_offset + s->output_section->vma); + print_space (); + print_size (s->size); + print_space (); + print_fill (s->fill); + print_nl (); - case lang_wild_statement_enum: - print_wild_statement(&s->wild_statement, os); - break; - default: - printf("Fail with %d\n",s->header.type); - FAIL(); - break; - case lang_address_statement_enum: - printf("address\n"); - break; - break; - case lang_object_symbols_statement_enum: - printf("object symbols\n"); - break; - case lang_fill_statement_enum: - print_fill_statement(&s->fill_statement); - break; - case lang_data_statement_enum: - print_data_statement(&s->data_statement); - break; - case lang_input_section_enum: - print_input_section(&s->input_section); - break; - case lang_padding_statement_enum: - print_padding_statement(&s->padding_statement); - break; - case lang_output_section_statement_enum: - print_output_section_statement(&s->output_section_statement); - break; - case lang_assignment_statement_enum: - print_assignment(&s->assignment_statement, - os); - break; + print_dot = s->output_offset + s->output_section->vma + s->size; +} - case lang_target_statement_enum: - printf("TARGET(%s)\n", s->target_statement.target); - break; - case lang_output_statement_enum: - printf("OUTPUT(%s %s)\n", - s->output_statement.name, - output_target); - break; - case lang_input_statement_enum: - print_input_statement(&s->input_statement); - break; - case lang_afile_asection_pair_statement_enum: - FAIL(); - break; +static void +print_wild_statement (w, os) + lang_wild_statement_type * w; + lang_output_section_statement_type * os; +{ + fprintf (config.map_file, " from "); + if (w->filename != (char *) NULL) + { + fprintf (config.map_file, "%s", w->filename); + } + else + { + fprintf (config.map_file, "*"); + } + if (w->section_name != (char *) NULL) + { + fprintf (config.map_file, "(%s)", w->section_name); + } + else + { + fprintf (config.map_file, "(*)"); + } + print_nl (); + print_statement (w->children.head, os); + +} +static void +print_statement (s, os) + lang_statement_union_type * s; + lang_output_section_statement_type * os; +{ + while (s) + { + switch (s->header.type) + { + case lang_constructors_statement_enum: + fprintf (config.map_file, "constructors:\n"); + print_statement (constructor_list.head, os); + break; + case lang_wild_statement_enum: + print_wild_statement (&s->wild_statement, os); + break; + default: + fprintf (config.map_file, "Fail with %d\n", s->header.type); + FAIL (); + break; + case lang_address_statement_enum: + fprintf (config.map_file, "address\n"); + break; + case lang_object_symbols_statement_enum: + fprintf (config.map_file, "object symbols\n"); + break; + case lang_fill_statement_enum: + print_fill_statement (&s->fill_statement); + break; + case lang_data_statement_enum: + print_data_statement (&s->data_statement); + break; + case lang_reloc_statement_enum: + print_reloc_statement (&s->reloc_statement); + break; + case lang_input_section_enum: + print_input_section (&s->input_section); + break; + case lang_padding_statement_enum: + print_padding_statement (&s->padding_statement); + break; + case lang_output_section_statement_enum: + print_output_section_statement (&s->output_section_statement); + break; + case lang_assignment_statement_enum: + print_assignment (&s->assignment_statement, + os); + break; + case lang_target_statement_enum: + fprintf (config.map_file, "TARGET(%s)\n", s->target_statement.target); + break; + case lang_output_statement_enum: + fprintf (config.map_file, "OUTPUT(%s %s)\n", + s->output_statement.name, + output_target ? output_target : ""); + break; + case lang_input_statement_enum: + print_input_statement (&s->input_statement); + break; + case lang_afile_asection_pair_statement_enum: + FAIL (); + break; + } + s = s->next; } - s = s->next; - } } static void -DEFUN_VOID(print_statements) +print_statements () { - print_statement(statement_list.head, - (lang_output_section_statement_type *)NULL); + print_statement (statement_list.head, + abs_output_section); + } static bfd_vma -DEFUN(insert_pad,(this_ptr, fill, power, output_section_statement, dot), - lang_statement_union_type **this_ptr AND - fill_type fill AND - unsigned int power AND - asection * output_section_statement AND - bfd_vma dot) -{ - /* Align this section first to the +insert_pad (this_ptr, fill, power, output_section_statement, dot) + lang_statement_union_type ** this_ptr; + fill_type fill; + unsigned int power; + asection * output_section_statement; + bfd_vma dot; +{ + /* Align this section first to the input sections requirement, then to the output section's requirement. - If this alignment is > than any seen before, + If this alignment is > than any seen before, then record it too. Perform the alignment by inserting a magic 'padding' statement. */ - unsigned int alignment_needed = align_power(dot, power) - dot; + unsigned int alignment_needed = align_power (dot, power) - dot; - if (alignment_needed != 0) + if (alignment_needed != 0) { - lang_statement_union_type *new = - (lang_statement_union_type *) - ldmalloc((bfd_size_type)(sizeof(lang_padding_statement_type))); + lang_statement_union_type *new = + (lang_statement_union_type *) + stat_alloc ((bfd_size_type) (sizeof (lang_padding_statement_type))); + /* Link into existing chain */ new->header.next = *this_ptr; *this_ptr = new; @@ -1255,1072 +1512,1270 @@ DEFUN(insert_pad,(this_ptr, fill, power, output_section_statement, dot), /* Remember the most restrictive alignment */ - if (power > output_section_statement->alignment_power) { - output_section_statement->alignment_power = power; - } - output_section_statement->size += alignment_needed; + if (power > output_section_statement->alignment_power) + { + output_section_statement->alignment_power = power; + } + output_section_statement->_raw_size += alignment_needed; return alignment_needed + dot; } /* Work out how much this section will move the dot point */ -static bfd_vma -DEFUN(size_input_section, (this_ptr, output_section_statement, fill, dot), - lang_statement_union_type **this_ptr AND - lang_output_section_statement_type*output_section_statement AND - unsigned short fill AND - bfd_vma dot) +static bfd_vma +size_input_section (this_ptr, output_section_statement, fill, dot, relax) + lang_statement_union_type ** this_ptr; + lang_output_section_statement_type * output_section_statement; + fill_type fill; + bfd_vma dot; + boolean relax; { lang_input_section_type *is = &((*this_ptr)->input_section); asection *i = is->section; - - if (is->ifile->just_syms_flag == false) { - dot = insert_pad(this_ptr, fill, i->alignment_power, - output_section_statement->bfd_section, dot); - /* remember the largest size so we can malloc the largest area - needed for the output stage. Only remember the size of sections - which we will actually allocate */ - if (((i->flags & - (SEC_HAS_CONTENTS | SEC_LOAD)) == (SEC_HAS_CONTENTS | SEC_LOAD)) - && (i->size > largest_section)) { - largest_section = i->size; - } + if (is->ifile->just_syms_flag == false) + { + if (output_section_statement->subsection_alignment != -1) + i->alignment_power = + output_section_statement->subsection_alignment; - /* Remember where in the output section this input section goes */ + dot = insert_pad (this_ptr, fill, i->alignment_power, + output_section_statement->bfd_section, dot); - i->output_offset = dot - output_section_statement->bfd_section->vma; + /* Remember where in the output section this input section goes */ - /* Mark how big the output section must be to contain this now */ - dot += i->size; - output_section_statement->bfd_section->size = - dot - output_section_statement->bfd_section->vma; - } + i->output_offset = dot - output_section_statement->bfd_section->vma; + + /* Mark how big the output section must be to contain this now + */ + if (i->_cooked_size != 0) + dot += i->_cooked_size; + else + dot += i->_raw_size; + output_section_statement->bfd_section->_raw_size = dot - output_section_statement->bfd_section->vma; + } else - { - i->output_offset = i->vma - output_section_statement->bfd_section->vma; - } + { + i->output_offset = i->vma - output_section_statement->bfd_section->vma; + } - return dot ; + return dot; } +/* This variable indicates whether bfd_relax_section should be called + again. */ -/* Work out the size of the output sections - from the sizes of the input sections */ -static bfd_vma -DEFUN(lang_size_sections,(s, output_section_statement, prev, fill, dot), - lang_statement_union_type *s AND - lang_output_section_statement_type * output_section_statement AND - lang_statement_union_type **prev AND - unsigned short fill AND - bfd_vma dot) +static boolean relax_again; + +/* Set the sizes for all the output sections. */ + +bfd_vma +lang_size_sections (s, output_section_statement, prev, fill, dot, relax) + lang_statement_union_type * s; + lang_output_section_statement_type * output_section_statement; + lang_statement_union_type ** prev; + fill_type fill; + bfd_vma dot; + boolean relax; { /* Size up the sections from their constituent parts */ - for (; s != (lang_statement_union_type *)NULL ; s = s->next) - { - switch (s->header.type) { + for (; s != (lang_statement_union_type *) NULL; s = s->next) + { + switch (s->header.type) + { - - case lang_output_section_statement_enum: - { - bfd_vma after; - lang_output_section_statement_type *os = - &(s->output_section_statement); - /* The start of a section */ - - if (os->addr_tree == (etree_type *)NULL) { - /* No address specified for this section, get one - from the region specification - */ - if (os->region == (lang_memory_region_type *)NULL) { - os->region = lang_memory_region_lookup("*default*"); - } - dot = os->region->current; - } - else { - etree_value_type r ; - r = exp_fold_tree(os->addr_tree, - (lang_output_section_statement_type *)NULL, - lang_allocating_phase_enum, - dot, &dot); - if (r.valid == false) { - info("%F%S: non constant address expression for section %s\n", - os->name); - } - dot = r.value; - } - /* The section starts here */ - /* First, align to what the section needs */ + case lang_output_section_statement_enum: + { + bfd_vma after; + lang_output_section_statement_type *os = &s->output_section_statement; + + if (os->bfd_section == NULL) + { + /* This section was never actually created. */ + break; + } + + /* If this is a COFF shared library section, use the size and + address from the input section. FIXME: This is COFF + specific; it would be cleaner if there were some other way + to do this, but nothing simple comes to mind. */ + if ((os->bfd_section->flags & SEC_COFF_SHARED_LIBRARY) != 0) + { + asection *input; + + if (os->children.head == NULL + || os->children.head->next != NULL + || os->children.head->header.type != lang_input_section_enum) + einfo ("%P%X: Internal error on COFF shared library section %s", + os->name); + + input = os->children.head->input_section.section; + bfd_set_section_vma (os->bfd_section->owner, + os->bfd_section, + bfd_section_vma (input->owner, input)); + os->bfd_section->_raw_size = input->_raw_size; + break; + } + + if (os->bfd_section == &bfd_abs_section) + { + /* No matter what happens, an abs section starts at zero */ + bfd_set_section_vma (0, os->bfd_section, 0); + } + else + { + if (os->addr_tree == (etree_type *) NULL) + { + /* No address specified for this section, get one + from the region specification + */ + if (os->region == (lang_memory_region_type *) NULL) + { + os->region = lang_memory_region_lookup ("*default*"); + } + dot = os->region->current; + if (os->section_alignment == -1) + dot = align_power (dot, os->bfd_section->alignment_power); + } + else + { + etree_value_type r; + + r = exp_fold_tree (os->addr_tree, + abs_output_section, + lang_allocating_phase_enum, + dot, &dot); + if (r.valid == false) + { + einfo ("%F%S: non constant address expression for section %s\n", + os->name); + } + dot = r.value; + } + /* The section starts here */ + /* First, align to what the section needs */ + + if (os->section_alignment != -1) + dot = align_power (dot, os->section_alignment); + + bfd_set_section_vma (0, os->bfd_section, dot); + + if (os->load_base) { + os->bfd_section->lma + = exp_get_value_int(os->load_base, 0,"load base", lang_final_phase_enum); + } + } + + + os->bfd_section->output_offset = 0; + + (void) lang_size_sections (os->children.head, os, &os->children.head, + os->fill, dot, relax); + /* Ignore the size of the input sections, use the vma and size to */ + /* align against */ + + after = ALIGN_N (os->bfd_section->vma + + os->bfd_section->_raw_size, + /* The coercion here is important, see ld.h. */ + (bfd_vma) os->block_value); + + os->bfd_section->_raw_size = after - os->bfd_section->vma; + dot = os->bfd_section->vma + os->bfd_section->_raw_size; + os->processed = true; + + /* Replace into region ? */ + if (os->addr_tree == (etree_type *) NULL + && os->region != (lang_memory_region_type *) NULL) + { + os->region->current = dot; + /* Make sure this isn't silly */ + if (( os->region->current + > os->region->origin + os->region->length) + || ( os->region->origin > os->region->current )) + { + einfo ("%X%P: region %s is full (%B section %s)\n", + os->region->name, + os->bfd_section->owner, + os->bfd_section->name); + /* Reset the region pointer */ + os->region->current = 0; + + } + + } + } - dot = align_power(dot, os->bfd_section->alignment_power); - os->bfd_section->vma = dot; - os->bfd_section->output_offset = 0; + break; + case lang_constructors_statement_enum: + dot = lang_size_sections (constructor_list.head, + output_section_statement, + &s->wild_statement.children.head, + fill, + dot, relax); + break; - (void) lang_size_sections(os->children.head, os, &os->children.head, - os->fill, dot); - /* Ignore the size of the input sections, use the vma and size to */ - /* align against */ + case lang_data_statement_enum: + { + unsigned int size = 0; + s->data_statement.output_vma = dot - output_section_statement->bfd_section->vma; + s->data_statement.output_section = + output_section_statement->bfd_section; - after = ALIGN(os->bfd_section->vma + - os->bfd_section->size, - os->block_value) ; + switch (s->data_statement.type) + { + case QUAD: + size = QUAD_SIZE; + break; + case LONG: + size = LONG_SIZE; + break; + case SHORT: + size = SHORT_SIZE; + break; + case BYTE: + size = BYTE_SIZE; + break; + } + dot += size; + output_section_statement->bfd_section->_raw_size += size; + } + break; - os->bfd_section->size = after - os->bfd_section->vma; - dot = os->bfd_section->vma + os->bfd_section->size; - os->processed = true; + case lang_reloc_statement_enum: + { + int size; + + s->reloc_statement.output_vma = + dot - output_section_statement->bfd_section->vma; + s->reloc_statement.output_section = + output_section_statement->bfd_section; + size = bfd_get_reloc_size (s->reloc_statement.howto); + dot += size; + output_section_statement->bfd_section->_raw_size += size; + } + break; + + case lang_wild_statement_enum: - /* Replace into region ? */ - if (os->addr_tree == (etree_type *)NULL - && os->region !=(lang_memory_region_type*)NULL ) { - os->region->current = dot; - } - } + dot = lang_size_sections (s->wild_statement.children.head, + output_section_statement, + &s->wild_statement.children.head, - break; - case lang_constructors_statement_enum: - dot = lang_size_sections(constructor_list.head, - output_section_statement, - &s->wild_statement.children.head, - fill, - dot); - break; - - case lang_data_statement_enum: - { - unsigned int size; - s->data_statement.output_vma = dot - output_section_statement->bfd_section->vma; - s->data_statement.output_section = - output_section_statement->bfd_section; - - switch (s->data_statement.type) { - case LONG: - size = LONG_SIZE; - break; - case SHORT: - size = SHORT_SIZE; - break; - case BYTE: - size = BYTE_SIZE; - break; + fill, dot, relax); - } - dot += size; - output_section_statement->bfd_section->size += size; - } - break; + break; - case lang_wild_statement_enum: + case lang_object_symbols_statement_enum: + link_info.create_object_symbols_section = + output_section_statement->bfd_section; + break; + case lang_output_statement_enum: + case lang_target_statement_enum: + break; + case lang_input_section_enum: + { + asection *i; - dot = lang_size_sections(s->wild_statement.children.head, - output_section_statement, - &s->wild_statement.children.head, + i = (*prev)->input_section.section; + if (! relax) + i->_cooked_size = i->_raw_size; + else + { + boolean again; - fill, dot); + if (! bfd_relax_section (i->owner, i, &link_info, &again)) + einfo ("%P%F: can't relax section: %E\n"); + if (again) + relax_again = true; + } + dot = size_input_section (prev, + output_section_statement, + output_section_statement->fill, + dot, relax); + } + break; + case lang_input_statement_enum: + break; + case lang_fill_statement_enum: + s->fill_statement.output_section = output_section_statement->bfd_section; - break; + fill = s->fill_statement.fill; + break; + case lang_assignment_statement_enum: + { + bfd_vma newdot = dot; + + exp_fold_tree (s->assignment_statement.exp, + output_section_statement, + lang_allocating_phase_enum, + dot, + &newdot); + + if (newdot != dot && !relax) + { + /* The assignment changed dot. Insert a pad. */ + if (output_section_statement == abs_output_section) + { + /* If we don't have an output section, then just adjust + the default memory address. */ + lang_memory_region_lookup ("*default*")->current = newdot; + } + else + { + lang_statement_union_type *new = + ((lang_statement_union_type *) + stat_alloc (sizeof (lang_padding_statement_type))); + + /* Link into existing chain */ + new->header.next = *prev; + *prev = new; + new->header.type = lang_padding_statement_enum; + new->padding_statement.output_section = + output_section_statement->bfd_section; + new->padding_statement.output_offset = + dot - output_section_statement->bfd_section->vma; + new->padding_statement.fill = fill; + new->padding_statement.size = newdot - dot; + output_section_statement->bfd_section->_raw_size += + new->padding_statement.size; + } + + dot = newdot; + } + } + break; + + case lang_padding_statement_enum: + /* If we are relaxing, and this is not the first pass, some + padding statements may have been inserted during previous + passes. We may have to move the padding statement to a new + location if dot has a different value at this point in this + pass than it did at this point in the previous pass. */ + s->padding_statement.output_offset = + dot - output_section_statement->bfd_section->vma; + dot += s->padding_statement.size; + break; + + default: + FAIL (); + break; - case lang_object_symbols_statement_enum: - create_object_symbols = output_section_statement; - break; - case lang_output_statement_enum: - case lang_target_statement_enum: - break; - case lang_input_section_enum: - dot = size_input_section(prev, - output_section_statement, - output_section_statement->fill, dot); - break; - case lang_input_statement_enum: - break; - case lang_fill_statement_enum: - fill = s->fill_statement.fill; - break; - case lang_assignment_statement_enum: - { - bfd_vma newdot = dot; - exp_fold_tree(s->assignment_statement.exp, - output_section_statement, - lang_allocating_phase_enum, - dot, - &newdot); - - if (newdot != dot) - /* We've been moved ! so insert a pad */ - { - lang_statement_union_type *new = - (lang_statement_union_type *) - ldmalloc((bfd_size_type)(sizeof(lang_padding_statement_type))); - /* Link into existing chain */ - new->header.next = *prev; - *prev = new; - new->header.type = lang_padding_statement_enum; - new->padding_statement.output_section = - output_section_statement->bfd_section; - new->padding_statement.output_offset = - dot - output_section_statement->bfd_section->vma; - new->padding_statement.fill = fill; - new->padding_statement.size = newdot - dot; - output_section_statement->bfd_section->size += - new->padding_statement.size; - dot = newdot; - } - } + /* This can only get here when relaxing is turned on */ - break; - case lang_padding_statement_enum: - FAIL(); - break; - default: - FAIL(); - break; - case lang_address_statement_enum: - break; - } - prev = &s->header.next; - } + case lang_address_statement_enum: + break; + } + prev = &s->header.next; + } return dot; } - static bfd_vma -DEFUN(lang_do_assignments,(s, output_section_statement, fill, dot), - lang_statement_union_type *s AND - lang_output_section_statement_type * output_section_statement AND - unsigned short fill AND - bfd_vma dot) +lang_do_assignments (s, output_section_statement, fill, dot) + lang_statement_union_type * s; + lang_output_section_statement_type * output_section_statement; + fill_type fill; + bfd_vma dot; { - - for (; s != (lang_statement_union_type *)NULL ; s = s->next) + for (; s != (lang_statement_union_type *) NULL; s = s->next) { - switch (s->header.type) { - case lang_constructors_statement_enum: - dot = lang_do_assignments(constructor_list.head, - output_section_statement, - fill, - dot); - break; - - case lang_output_section_statement_enum: + switch (s->header.type) { - lang_output_section_statement_type *os = - &(s->output_section_statement); - dot = os->bfd_section->vma; - (void) lang_do_assignments(os->children.head, os, os->fill, dot); - dot = os->bfd_section->vma + os->bfd_section->size; - } - break; - case lang_wild_statement_enum: + case lang_constructors_statement_enum: + dot = lang_do_assignments (constructor_list.head, + output_section_statement, + fill, + dot); + break; - dot = lang_do_assignments(s->wild_statement.children.head, - output_section_statement, - fill, dot); + case lang_output_section_statement_enum: + { + lang_output_section_statement_type *os = + &(s->output_section_statement); - break; + if (os->bfd_section != NULL) + { + dot = os->bfd_section->vma; + (void) lang_do_assignments (os->children.head, os, + os->fill, dot); + dot = os->bfd_section->vma + os->bfd_section->_raw_size; + } + } + break; + case lang_wild_statement_enum: - case lang_object_symbols_statement_enum: - case lang_output_statement_enum: - case lang_target_statement_enum: + dot = lang_do_assignments (s->wild_statement.children.head, + output_section_statement, + fill, dot); + + break; + + case lang_object_symbols_statement_enum: + case lang_output_statement_enum: + case lang_target_statement_enum: #if 0 - case lang_common_statement_enum: + case lang_common_statement_enum: #endif - break; - case lang_data_statement_enum: - { - etree_value_type value ; - value = exp_fold_tree(s->data_statement.exp, - 0, lang_final_phase_enum, dot, &dot); - s->data_statement.value = value.value; - if (value.valid == false) info("%F%P: Invalid data statement\n"); - } - switch (s->data_statement.type) { - case LONG: - dot += LONG_SIZE; - break; - case SHORT: - dot += SHORT_SIZE; break; - case BYTE: - dot += BYTE_SIZE; + case lang_data_statement_enum: + { + etree_value_type value; + + value = exp_fold_tree (s->data_statement.exp, + abs_output_section, + lang_final_phase_enum, dot, &dot); + s->data_statement.value = value.value; + if (value.valid == false) + einfo ("%F%P: invalid data statement\n"); + } + switch (s->data_statement.type) + { + case QUAD: + dot += QUAD_SIZE; + break; + case LONG: + dot += LONG_SIZE; + break; + case SHORT: + dot += SHORT_SIZE; + break; + case BYTE: + dot += BYTE_SIZE; + break; + } break; - } - break; - case lang_input_section_enum: - { - asection *in = s->input_section.section; - dot += in->size; - } - break; - - case lang_input_statement_enum: - break; - case lang_fill_statement_enum: - fill = s->fill_statement.fill; - break; - case lang_assignment_statement_enum: - { - exp_fold_tree(s->assignment_statement.exp, - output_section_statement, - lang_final_phase_enum, - dot, - &dot); - } - break; - case lang_padding_statement_enum: - dot += s->padding_statement.size; - break; - default: - FAIL(); - break; - case lang_address_statement_enum: - break; - } - - } - return dot; -} - - - -static void -DEFUN_VOID(lang_relocate_globals) -{ + case lang_reloc_statement_enum: + { + etree_value_type value; + + value = exp_fold_tree (s->reloc_statement.addend_exp, + abs_output_section, + lang_final_phase_enum, dot, &dot); + s->reloc_statement.addend_value = value.value; + if (value.valid == false) + einfo ("%F%P: invalid reloc statement\n"); + } + dot += bfd_get_reloc_size (s->reloc_statement.howto); + break; - /* - Each ldsym_type maintains a chain of pointers to asymbols which - references the definition. Replace each pointer to the referenence - with a pointer to only one place, preferably the definition. If - the defintion isn't available then the common symbol, and if - there isn't one of them then choose one reference. - */ + case lang_input_section_enum: + { + asection *in = s->input_section.section; - FOR_EACH_LDSYM(lgs) { - asymbol *it; - if (lgs->sdefs_chain) { - it = *(lgs->sdefs_chain); - } - else if (lgs->scoms_chain != (asymbol **)NULL) { - it = *(lgs->scoms_chain); - } - else if (lgs->srefs_chain != (asymbol **)NULL) { - it = *(lgs->srefs_chain); - } - else { - /* This can happen when the command line asked for a symbol to - be -u */ - it = (asymbol *)NULL; - } - if (it != (asymbol *)NULL) - { - asymbol **ptr = lgs->srefs_chain;; - if (lgs->flags & SYM_WARNING) - { - produce_warnings(lgs, it); - } + if (in->_cooked_size != 0) + dot += in->_cooked_size; + else + dot += in->_raw_size; + } + break; - while (ptr != (asymbol **)NULL) { - asymbol *ref = *ptr; - *ptr = it; - ptr = (asymbol **)(ref->udata); + case lang_input_statement_enum: + break; + case lang_fill_statement_enum: + fill = s->fill_statement.fill; + break; + case lang_assignment_statement_enum: + { + exp_fold_tree (s->assignment_statement.exp, + output_section_statement, + lang_final_phase_enum, + dot, + &dot); } + + break; + case lang_padding_statement_enum: + dot += s->padding_statement.size; + break; + default: + FAIL (); + break; + case lang_address_statement_enum: + break; } - } -} - + } + return dot; +} static void -DEFUN_VOID(lang_finish) +lang_finish () { - ldsym_type *lgs; + struct bfd_link_hash_entry *h; + boolean warn = link_info.relocateable ? false : true; - if (entry_symbol == (char *)NULL) { - /* No entry has been specified, look for start */ - entry_symbol = "start"; - } - lgs = ldsym_get_soft(entry_symbol); - if (lgs && lgs->sdefs_chain) { - asymbol *sy = *(lgs->sdefs_chain); - /* We can set the entry address*/ - bfd_set_start_address(output_bfd, - outside_symbol_address(sy)); + if (entry_symbol == (char *) NULL) + { + /* No entry has been specified. Look for start, but don't warn + if we don't find it. */ + entry_symbol = "start"; + warn = false; + } - } - else { - /* Can't find anything reasonable, - use the first address in the text section - */ - asection *ts = bfd_get_section_by_name(output_bfd, ".text"); - if (ts) { - bfd_set_start_address(output_bfd, ts->vma); + h = bfd_link_hash_lookup (link_info.hash, entry_symbol, false, false, true); + if (h != (struct bfd_link_hash_entry *) NULL + && h->type == bfd_link_hash_defined) + { + bfd_vma val; + + val = (h->u.def.value + + bfd_get_section_vma (output_bfd, + h->u.def.section->output_section) + + h->u.def.section->output_offset); + if (! bfd_set_start_address (output_bfd, val)) + einfo ("%P%F:%s: can't set start address\n", entry_symbol); + } + else + { + asection *ts; + + /* Can't find the entry symbol. Use the first address in the + text section. */ + ts = bfd_get_section_by_name (output_bfd, ".text"); + if (ts != (asection *) NULL) + { + if (warn) + einfo ("%P: warning: cannot find entry symbol %s; defaulting to %V\n", + entry_symbol, bfd_get_section_vma (output_bfd, ts)); + if (! bfd_set_start_address (output_bfd, + bfd_get_section_vma (output_bfd, ts))) + einfo ("%P%F: can't set start address\n"); + } + else + { + if (warn) + einfo ("%P: warning: cannot find entry symbol %s; not setting start address\n", + entry_symbol); + } } - } } /* By now we know the target architecture, and we may have an */ /* ldfile_output_machine_name */ static void -DEFUN_VOID(lang_check) +lang_check () { lang_statement_union_type *file; - - bfd * input_bfd; + bfd *input_bfd; unsigned long input_machine; enum bfd_architecture input_architecture; - - CONST bfd_arch_info_type *compatible; + CONST bfd_arch_info_type *compatible; for (file = file_chain.head; - file != (lang_statement_union_type *)NULL; - file=file->input_statement.next) - { - unsigned long ldfile_new_output_machine = 0; - enum bfd_architecture ldfile_new_output_architecture = bfd_arch_unknown; + file != (lang_statement_union_type *) NULL; + file = file->input_statement.next) + { + input_bfd = file->input_statement.the_bfd; - input_bfd = file->input_statement.the_bfd; + input_machine = bfd_get_mach (input_bfd); + input_architecture = bfd_get_arch (input_bfd); - input_machine = bfd_get_mach(input_bfd); - input_architecture = bfd_get_arch(input_bfd); + /* Inspect the architecture and ensure we're linking like with + like */ + + compatible = bfd_arch_get_compatible (input_bfd, + output_bfd); - /* Inspect the architecture and ensure we're linking like with - like */ + if (compatible) + { + ldfile_output_machine = compatible->mach; + ldfile_output_architecture = compatible->arch; + } + else + { - compatible=bfd_arch_get_compatible(input_bfd, - output_bfd); + einfo ("%P: warning: %s architecture of input file `%B' is incompatible with %s output\n", + bfd_printable_name (input_bfd), input_bfd, + bfd_printable_name (output_bfd)); - if (compatible) - { - ldfile_output_machine = compatible->mach; - ldfile_output_architecture = compatible->arch; - } - else - { + if (! bfd_set_arch_mach (output_bfd, + input_architecture, + input_machine)) + einfo ("%P%F:%s: can't set architecture: %E\n", + bfd_get_filename (output_bfd)); + } - info("%P: warning, %s architecture of input file `%B' incompatible with %s output\n", - bfd_printable_name(input_bfd), input_bfd, - bfd_printable_name(output_bfd)); + } +} - bfd_set_arch_mach(output_bfd, - ldfile_new_output_architecture, - ldfile_new_output_machine); - } +/* Look through all the global common symbols and attach them to the + correct section. The -sort-common command line switch may be used + to roughly sort the entries by size. */ - } +static void +lang_common () +{ + if (link_info.relocateable + && ! command_line.force_common_definition) + return; + + if (! config.sort_common) + bfd_link_hash_traverse (link_info.hash, lang_one_common, (PTR) NULL); + else + { + unsigned int power; + + for (power = 1; power <= 16; power <<= 1) + bfd_link_hash_traverse (link_info.hash, lang_one_common, + (PTR) &power); + } } +/* Place one common symbol in the correct section. */ -/* - * run through all the global common symbols and tie them - * to the output section requested. - * - As an experiment we do this 4 times, once for all the byte sizes, - then all the two bytes, all the four bytes and then everything else - */ +static boolean +lang_one_common (h, info) + struct bfd_link_hash_entry *h; + PTR info; +{ + unsigned int power_of_two; + bfd_vma size; + size_t align; + asection *section; -static void -DEFUN_VOID(lang_common) -{ - ldsym_type *lgs; - size_t power; - if (config.relocateable_output == false || - command_line.force_common_definition== true) { - for (power = 1; (config.sort_common == true && power == 1) || (power <= 16); power <<=1) { - for (lgs = symbol_head; - lgs != (ldsym_type *)NULL; - lgs=lgs->next) - { - asymbol *com ; - unsigned int power_of_two; - size_t size; - size_t align; - if (lgs->scoms_chain != (asymbol **)NULL) { - com = *(lgs->scoms_chain); - size = com->value; - switch (size) { - case 0: - case 1: - align = 1; - power_of_two = 0; - break; - case 2: - power_of_two = 1; - align = 2; - break; - case 3: - case 4: - power_of_two =2; - align = 4; - break; - case 5: - case 6: - case 7: - case 8: - power_of_two = 3; - align = 8; - break; - default: - power_of_two = 4; - align = 16; - break; - } - if (config.sort_common == false || align == power) { - /* Change from a common symbol into a definition of - a symbol */ - lgs->sdefs_chain = lgs->scoms_chain; - lgs->scoms_chain = (asymbol **)NULL; - commons_pending--; - /* Point to the correct common section */ - com->section = - ((lang_input_statement_type *) - (com->the_bfd->usrdata))->common_section; - /* Fix the size of the common section */ - com->section->size = ALIGN(com->section->size, align); - - /* Remember if this is the biggest alignment ever seen */ - if (power_of_two > com->section->alignment_power) { - com->section->alignment_power = power_of_two; - } + if (h->type != bfd_link_hash_common) + return true; - /* Symbol stops being common and starts being global, but - we remember that it was common once. */ + size = h->u.c.size; + switch (size) + { + case 0: + case 1: + power_of_two = 0; + align = 1; + break; + case 2: + power_of_two = 1; + align = 2; + break; + case 3: + case 4: + power_of_two = 2; + align = 4; + break; + case 5: + case 6: + case 7: + case 8: + power_of_two = 3; + align = 8; + break; + default: + power_of_two = 4; + align = 16; + break; + } + + if (config.sort_common && align != *(unsigned int *) info) + return true; - com->flags = BSF_EXPORT | BSF_GLOBAL | BSF_OLD_COMMON; - com->value = com->section->size; + section = h->u.c.section; - if (write_map) - { - printf ("Allocating common %s: %x at %x %s\n", - lgs->name, - (unsigned) size, - (unsigned) com->value, - com->the_bfd->filename); - } + /* Increase the size of the section. */ + section->_raw_size = ALIGN_N (section->_raw_size, align); - com->section->size += size; + /* Adjust the alignment if necessary. */ + if (power_of_two > section->alignment_power) + section->alignment_power = power_of_two; - } - } + /* Change the symbol from common to defined. */ + h->type = bfd_link_hash_defined; + h->u.def.section = section; + h->u.def.value = section->_raw_size; - } - } - } + /* Increase the size of the section. */ + section->_raw_size += size; + if (config.map_file != NULL) + fprintf (config.map_file, "Allocating common %s: %lx at %lx %s\n", + h->root.string, (unsigned long) size, + (unsigned long) h->u.def.value, section->owner->filename); + return true; } /* -run through the input files and ensure that every input +run through the input files and ensure that every input section has somewhere to go. If one is found without a destination then create an input request and place it into the statement tree. */ -static void -DEFUN_VOID(lang_place_orphans) +static void +lang_place_orphans () { lang_input_statement_type *file; - for (file = (lang_input_statement_type*)file_chain.head; - file != (lang_input_statement_type*)NULL; - file = (lang_input_statement_type*)file->next) { - asection *s; - for (s = file->the_bfd->sections; - s != (asection *)NULL; - s = s->next) { - if ( s->output_section == (asection *)NULL) { - /* This section of the file is not attatched, root - around for a sensible place for it to go */ - - if (file->common_section == s) { - /* This is a lonely common section which must - have come from an archive. We attatch to the - section with the wildcard */ - if (config.relocateable_output != true - && command_line.force_common_definition == false) { - if (default_common_section == - (lang_output_section_statement_type *)NULL) { - info("%P: No [COMMON] command, defaulting to .bss\n"); - - default_common_section = - lang_output_section_statement_lookup(".bss"); - } - wild_doit(&default_common_section->children, s, - default_common_section, file); - } - } - else { - lang_output_section_statement_type *os = - lang_output_section_statement_lookup(s->name); + for (file = (lang_input_statement_type *) file_chain.head; + file != (lang_input_statement_type *) NULL; + file = (lang_input_statement_type *) file->next) + { + asection *s; + + if (file->just_syms_flag) + continue; + + for (s = file->the_bfd->sections; + s != (asection *) NULL; + s = s->next) + { + if (s->output_section == (asection *) NULL) + { + /* This section of the file is not attatched, root + around for a sensible place for it to go */ + + if (file->common_section == s) + { + /* This is a lonely common section which must + have come from an archive. We attatch to the + section with the wildcard */ + if (! link_info.relocateable + && ! command_line.force_common_definition) + { + if (default_common_section == + (lang_output_section_statement_type *) NULL) + { + info_msg ("%P: no [COMMON] command, defaulting to .bss\n"); + + default_common_section = + lang_output_section_statement_lookup (".bss"); + + } + wild_doit (&default_common_section->children, s, + default_common_section, file); + } + } + else + { + lang_output_section_statement_type *os = + lang_output_section_statement_lookup (s->name); - wild_doit(&os->children, s, os, file); + wild_doit (&os->children, s, os, file); + } + } } - } } - } } void -DEFUN(lang_set_flags,(ptr, flags), - int *ptr AND - CONST char *flags) +lang_set_flags (ptr, flags) + int *ptr; + CONST char *flags; { - boolean state = true; -*ptr= 0; + boolean state = false; + + *ptr = 0; while (*flags) - { - if (*flags == '!') { + { + if (*flags == '!') + { state = false; flags++; } - else state = true; - switch (*flags) { + else + state = true; + switch (*flags) + { case 'R': -/* ptr->flag_read = state; */ + /* ptr->flag_read = state; */ break; case 'W': -/* ptr->flag_write = state; */ + /* ptr->flag_write = state; */ break; case 'X': -/* ptr->flag_executable= state;*/ + /* ptr->flag_executable= state;*/ break; case 'L': case 'I': -/* ptr->flag_loadable= state;*/ + /* ptr->flag_loadable= state;*/ break; default: - info("%P%F illegal syntax in flags\n"); + einfo ("%P%F: invalid syntax in flags\n"); break; } - flags++; - } + flags++; + } } - +/* Call a function on each input file. This function will be called + on an archive, but not on the elements. */ void -DEFUN(lang_for_each_file,(func), - PROTO(void, (*func),(lang_input_statement_type *))) +lang_for_each_input_file (func) + void (*func) PARAMS ((lang_input_statement_type *)); { lang_input_statement_type *f; - for (f = (lang_input_statement_type *)file_chain.head; - f != (lang_input_statement_type *)NULL; - f = (lang_input_statement_type *)f->next) - { - func(f); - } + + for (f = (lang_input_statement_type *) input_file_chain.head; + f != NULL; + f = (lang_input_statement_type *) f->next_real_file) + func (f); } +/* Call a function on each file. The function will be called on all + the elements of an archive which are included in the link, but will + not be called on the archive file itself. */ void -DEFUN(lang_for_each_input_section, (func), - PROTO(void ,(*func),(bfd *ab, asection*as))) +lang_for_each_file (func) + void (*func) PARAMS ((lang_input_statement_type *)); { lang_input_statement_type *f; - for (f = (lang_input_statement_type *)file_chain.head; - f != (lang_input_statement_type *)NULL; - f = (lang_input_statement_type *)f->next) + + for (f = (lang_input_statement_type *) file_chain.head; + f != (lang_input_statement_type *) NULL; + f = (lang_input_statement_type *) f->next) { - asection *s; - for (s = f->the_bfd->sections; - s != (asection *)NULL; - s = s->next) { - func(f->the_bfd, s); - } + func (f); } } +#if 0 +/* Not used. */ -void -DEFUN(ldlang_add_file,(entry), - lang_input_statement_type *entry) +void +lang_for_each_input_section (func) + void (*func) PARAMS ((bfd * ab, asection * as)); { + lang_input_statement_type *f; + + for (f = (lang_input_statement_type *) file_chain.head; + f != (lang_input_statement_type *) NULL; + f = (lang_input_statement_type *) f->next) + { + asection *s; - lang_statement_append(&file_chain, - (lang_statement_union_type *)entry, - &entry->next); + for (s = f->the_bfd->sections; + s != (asection *) NULL; + s = s->next) + { + func (f->the_bfd, s); + } + } } +#endif + +void +ldlang_add_file (entry) + lang_input_statement_type * entry; +{ + bfd **pp; + lang_statement_append (&file_chain, + (lang_statement_union_type *) entry, + &entry->next); + + /* The BFD linker needs to have a list of all input BFDs involved in + a link. */ + ASSERT (entry->the_bfd->link_next == (bfd *) NULL); + ASSERT (entry->the_bfd != output_bfd); + for (pp = &link_info.input_bfds; + *pp != (bfd *) NULL; + pp = &(*pp)->link_next) + ; + *pp = entry->the_bfd; + entry->the_bfd->usrdata = (PTR) entry; + bfd_set_gp_size (entry->the_bfd, g_switch_value); +} void -DEFUN(lang_add_output,(name), - CONST char *name) +lang_add_output (name, from_script) + CONST char *name; + int from_script; { - lang_output_statement_type *new = new_stat(lang_output_statement, - stat_ptr); - new->name = name; - had_output_filename = true; + /* Make -o on command line override OUTPUT in script. */ + if (had_output_filename == false || !from_script) + { + output_filename = name; + had_output_filename = true; + } } static lang_output_section_statement_type *current_section; +static int topower(x) + int x; +{ + unsigned int i = 1; + int l; + if (x < 0) return -1; + for (l = 0; l < 32; l++) + { + if (i >= x) return l; + i<<=1; + } + return 0; +} void -DEFUN(lang_enter_output_section_statement, - (output_section_statement_name, - address_exp, - flags, - block_value), - char *output_section_statement_name AND - etree_type *address_exp AND - int flags AND - bfd_vma block_value) +lang_enter_output_section_statement (output_section_statement_name, + address_exp, flags, block_value, + align, subalign, ebase) + const char *output_section_statement_name; + etree_type * address_exp; + int flags; + bfd_vma block_value; + etree_type *align; + etree_type *subalign; + etree_type *ebase; { lang_output_section_statement_type *os; - current_section = - os = - lang_output_section_statement_lookup(output_section_statement_name); - - + current_section = + os = + lang_output_section_statement_lookup (output_section_statement_name); + + + /* Add this statement to tree */ /* add_statement(lang_output_section_statement_enum, output_section_statement);*/ /* Make next things chain into subchain of this */ if (os->addr_tree == - (etree_type *)NULL) { + (etree_type *) NULL) + { os->addr_tree = - address_exp; + address_exp; } os->flags = flags; - os->block_value = block_value; - stat_ptr = & os->children; - -} + if (flags & SEC_NEVER_LOAD) + os->loadable = 0; + else + os->loadable = 1; + os->block_value = block_value ? block_value : 1; + stat_ptr = &os->children; + os->subsection_alignment = topower( + exp_get_value_int(subalign, -1, + "subsection alignment", + 0)); + os->section_alignment = topower( + exp_get_value_int(align, -1, + "section alignment", 0)); -void -DEFUN_VOID(lang_final) -{ - if (had_output_filename == false) { - extern CONST char *output_filename; - lang_add_output(output_filename); - } + os->load_base = ebase; } - - - -asymbol * -DEFUN(create_symbol,(name, flags, section), - CONST char *name AND - flagword flags AND - asection *section) +void +lang_final () { - extern lang_input_statement_type *script_file; - asymbol **def_ptr = (asymbol **)ldmalloc((bfd_size_type)(sizeof(asymbol **))); - /* Add this definition to script file */ - asymbol *def = (asymbol *)bfd_make_empty_symbol(script_file->the_bfd); - def->name = buystring(name); - def->udata = 0; - def->flags = flags; - def->section = section; + lang_output_statement_type *new = + new_stat (lang_output_statement, stat_ptr); - *def_ptr = def; - Q_enter_global_ref(def_ptr); - return def; + new->name = output_filename; } -/* run through the symbol table, find all the symbols which are - constructors and for each one, create statements to do something - like.. - - for - __CTOR_LIST__, foo - - __CTOR_LIST__ = . ; - LONG(__CTOR_LIST_END - . / 4 - 2) - *(foo) - __CTOR_LIST_END= . - - Put these statements onto a special list. - -*/ - -typedef struct constructor_list -{ -ldsym_type *sym; - struct constructor_list *next; -} constructor_list_type; - -static constructor_list_type *constructor_name_list; - -void -DEFUN(ldlang_add_constructor,(name), -ldsym_type *name) +/* Reset the current counters in the regions */ +static void +reset_memory_regions () { + lang_memory_region_type *p = lang_memory_region_list; - constructor_list_type *next = constructor_name_list; - - if (name->flags & SYM_CONSTRUCTOR) return; - - next = (constructor_list_type *) ldmalloc(sizeof(constructor_list_type)); - next->next= constructor_name_list; - next->sym= name; - name->flags |= SYM_CONSTRUCTOR; - constructor_name_list = next; - + for (p = lang_memory_region_list; + p != (lang_memory_region_type *) NULL; + p = p->next) + { + p->old_length = (bfd_size_type) (p->current - p->origin); + p->current = p->origin; + } } void -DEFUN_VOID(find_constructors) +lang_process () { - lang_statement_list_type *old = stat_ptr; - constructor_list_type *p = constructor_name_list; - stat_ptr = & constructor_list; - lang_list_init(stat_ptr); - while (p != (constructor_list_type *)NULL) - { - /* Have we already done this one ? */ - CONST char *name = p->sym->name; - int len = strlen(name); - char *end = ldmalloc(len+3); - strcpy(end, name); - strcat(end,"$e"); - - lang_add_assignment - ( exp_assop('=',name, exp_nameop(NAME,"."))); - - lang_add_data - (LONG, exp_binop('-', - exp_binop ( '/', - exp_binop ( '-', - exp_nameop(NAME, end), - exp_nameop(NAME,".")), - exp_intop(4)), - - exp_intop(2))); - - - lang_add_wild(name, (char *)NULL); - lang_add_data(LONG, exp_intop(0)); - lang_add_assignment - (exp_assop('=', end, exp_nameop(NAME,"."))); -p = p->next; - } - - - - - stat_ptr = old; -} -void -DEFUN_VOID(lang_process) -{ - if (had_script == false) { - parse_line(ldemul_get_script()); - } - lang_reasonable_defaults(); + lang_reasonable_defaults (); current_target = default_target; - lang_for_each_statement(ldlang_open_output); /* Open the output file */ - /* For each output section statement, create a section in the output - file */ - lang_create_output_section_statements(); + lang_for_each_statement (ldlang_open_output); /* Open the output file */ - /* Create a dummy bfd for the script */ - lang_init_script_file(); + ldemul_create_output_section_statements (); /* Add to the hash table all undefineds on the command line */ - lang_place_undefineds(); + lang_place_undefineds (); /* Create a bfd for each input file */ current_target = default_target; - lang_for_each_statement(open_input_bfds); + lang_for_each_statement (open_input_bfds); - common_section.userdata = (PTR)&common_section_userdata; + /* Build all sets based on the information gathered from the input + files. */ + ldctor_build_sets (); + /* Size up the common data */ + lang_common (); /* Run through the contours of the script and attatch input sections - to the correct output sections + to the correct output sections */ - find_constructors(); - map_input_to_output_sections(statement_list.head, (char *)NULL, - ( lang_output_section_statement_type *)NULL); + map_input_to_output_sections (statement_list.head, (char *) NULL, + (lang_output_section_statement_type *) NULL); /* Find any sections not attatched explicitly and handle them */ - lang_place_orphans(); + lang_place_orphans (); - /* Size up the common data */ - lang_common(); + ldemul_before_allocation (); + + /* Now run around and relax if we can */ + if (command_line.relax) + { + /* First time round is a trial run to get the 'worst case' + addresses of the objects if there was no relaxing. */ + lang_size_sections (statement_list.head, + abs_output_section, + &(statement_list.head), 0, (bfd_vma) 0, false); - ldemul_before_allocation(); - /* Size up the sections */ - lang_size_sections(statement_list.head, - (lang_output_section_statement_type *)NULL, - &(statement_list.head), 0, (bfd_vma)0); + reset_memory_regions (); + + /* Keep relaxing until bfd_relax_section gives up. */ + do + { + relax_again = false; + + /* Do all the assignments with our current guesses as to + section sizes. */ + lang_do_assignments (statement_list.head, + abs_output_section, + (fill_type) 0, (bfd_vma) 0); + + /* Perform another relax pass - this time we know where the + globals are, so can make better guess. */ + lang_size_sections (statement_list.head, + abs_output_section, + &(statement_list.head), 0, (bfd_vma) 0, true); + } + while (relax_again); + } + else + { + /* Size up the sections. */ + lang_size_sections (statement_list.head, + abs_output_section, + &(statement_list.head), 0, (bfd_vma) 0, false); + } /* See if anything special should be done now we know how big - everything is */ - ldemul_after_allocation(); + everything is. */ + ldemul_after_allocation (); /* Do all the assignments, now that we know the final restingplaces of all the symbols */ - lang_do_assignments(statement_list.head, - (lang_output_section_statement_type *)NULL, - 0, (bfd_vma)0); + lang_do_assignments (statement_list.head, + abs_output_section, + (fill_type) 0, (bfd_vma) 0); /* Make sure that we're not mixing architectures */ - lang_check(); - - /* Move the global symbols around */ - lang_relocate_globals(); + lang_check (); /* Final stuffs */ - lang_finish(); -} + ldemul_finish (); + lang_finish (); +} /* EXPORTED TO YACC */ void -DEFUN(lang_add_wild,(section_name, filename), - CONST char *CONST section_name AND - CONST char *CONST filename) +lang_add_wild (section_name, filename) + CONST char *CONST section_name; + CONST char *CONST filename; { - lang_wild_statement_type *new = new_stat(lang_wild_statement, - stat_ptr); + lang_wild_statement_type *new = new_stat (lang_wild_statement, + stat_ptr); - if (section_name != (char *)NULL && strcmp(section_name,"COMMON") == 0) - { - placed_commons = true; - } - if (filename != (char *)NULL) { - lang_has_input_file = true; - } + if (section_name != (char *) NULL && strcmp (section_name, "COMMON") == 0) + { + placed_commons = true; + } + if (filename != (char *) NULL) + { + lang_has_input_file = true; + } new->section_name = section_name; new->filename = filename; - lang_list_init(&new->children); + lang_list_init (&new->children); } + void -DEFUN(lang_section_start,(name, address), - CONST char *name AND - etree_type *address) +lang_section_start (name, address) + CONST char *name; + etree_type * address; { - lang_address_statement_type *ad =new_stat(lang_address_statement, stat_ptr); + lang_address_statement_type *ad = new_stat (lang_address_statement, stat_ptr); + ad->section_name = name; ad->address = address; } -void -DEFUN(lang_add_entry,(name), - CONST char *name) -{ - entry_symbol = name; -} +/* Set the start symbol to NAME. CMDLINE is nonzero if this is called + because of a -e argument on the command line, or zero if this is + called by ENTRY in a linker script. Command line arguments take + precedence. */ void -DEFUN(lang_add_target,(name), - CONST char *name) +lang_add_entry (name, cmdline) + CONST char *name; + int cmdline; { - lang_target_statement_type *new = new_stat(lang_target_statement, - stat_ptr); - new->target = name; + static int from_cmdline; + if (entry_symbol == NULL + || cmdline + || ! from_cmdline) + { + entry_symbol = name; + from_cmdline = cmdline; + } } +void +lang_add_target (name) + CONST char *name; +{ + lang_target_statement_type *new = new_stat (lang_target_statement, + stat_ptr); + new->target = name; +} void -DEFUN(lang_add_map,(name), - CONST char *name) +lang_add_map (name) + CONST char *name; { - while (*name) { - switch (*name) { - case 'F': - map_option_f = true; - break; + while (*name) + { + switch (*name) + { + case 'F': + map_option_f = true; + break; + } + name++; } - name++; - } } -void -DEFUN(lang_add_fill,(exp), - int exp) +void +lang_add_fill (exp) + int exp; { - lang_fill_statement_type *new = new_stat(lang_fill_statement, - stat_ptr); + lang_fill_statement_type *new = new_stat (lang_fill_statement, + stat_ptr); + new->fill = exp; } -void -DEFUN(lang_add_data,(type, exp), - int type AND - union etree_union *exp) +void +lang_add_data (type, exp) + int type; + union etree_union *exp; { - lang_data_statement_type *new = new_stat(lang_data_statement, + lang_data_statement_type *new = new_stat (lang_data_statement, stat_ptr); - new->exp = exp; - new->type = type; + + new->exp = exp; + new->type = type; } + +/* Create a new reloc statement. RELOC is the BFD relocation type to + generate. HOWTO is the corresponding howto structure (we could + look this up, but the caller has already done so). SECTION is the + section to generate a reloc against, or NAME is the name of the + symbol to generate a reloc against. Exactly one of SECTION and + NAME must be NULL. ADDEND is an expression for the addend. */ + +void +lang_add_reloc (reloc, howto, section, name, addend) + bfd_reloc_code_real_type reloc; + const reloc_howto_type *howto; + asection *section; + const char *name; + union etree_union *addend; +{ + lang_reloc_statement_type *p = new_stat (lang_reloc_statement, stat_ptr); + + p->reloc = reloc; + p->howto = howto; + p->section = section; + p->name = name; + p->addend_exp = addend; + + p->addend_value = 0; + p->output_section = NULL; + p->output_vma = 0; +} + void -DEFUN(lang_add_assignment,(exp), - etree_type *exp) +lang_add_assignment (exp) + etree_type * exp; { - lang_assignment_statement_type *new = new_stat(lang_assignment_statement, - stat_ptr); + lang_assignment_statement_type *new = new_stat (lang_assignment_statement, + stat_ptr); + new->exp = exp; } void -DEFUN(lang_add_attribute,(attribute), - enum statement_enum attribute) +lang_add_attribute (attribute) + enum statement_enum attribute; { - new_statement(attribute, sizeof(lang_statement_union_type),stat_ptr); + new_statement (attribute, sizeof (lang_statement_union_type), stat_ptr); } - - -void -DEFUN(lang_startup,(name), - CONST char *name) +void +lang_startup (name) + CONST char *name; { - if (startup_file != (char *)NULL) { - info("%P%FMultiple STARTUP files\n"); - } + if (startup_file != (char *) NULL) + { + einfo ("%P%Fmultiple STARTUP files\n"); + } first_file->filename = name; first_file->local_sym_name = name; + first_file->real = true; - startup_file= name; + startup_file = name; } -void -DEFUN(lang_float,(maybe), - boolean maybe) + +void +lang_float (maybe) + boolean maybe; { lang_float_flag = maybe; } -void -DEFUN(lang_leave_output_section_statement,(fill, memspec), - bfd_vma fill AND - CONST char *memspec) +void +lang_leave_output_section_statement (fill, memspec) + bfd_vma fill; + CONST char *memspec; { current_section->fill = fill; - current_section->region = lang_memory_region_lookup(memspec); + current_section->region = lang_memory_region_lookup (memspec); stat_ptr = &statement_list; /* We remember if we are closing a .data section, since we use it to store constructors in */ - if (strcmp(current_section->name, ".data") ==0) { - end_of_data_section_statement_list = statement_list; + if (strcmp (current_section->name, ".data") == 0) + { + end_of_data_section_statement_list = statement_list; - } + } } + /* Create an absolute symbol with the given name with the value of the address of first byte of the section named. @@ -2328,25 +2783,31 @@ DEFUN(lang_leave_output_section_statement,(fill, memspec), If the symbol already exists, then do nothing. */ void -DEFUN(lang_abs_symbol_at_beginning_of,(section, name), - CONST char *section AND - CONST char *name) -{ - if (ldsym_undefined(name)) { - extern bfd *output_bfd; - extern asymbol *create_symbol(); - asection *s = bfd_get_section_by_name(output_bfd, section); - asymbol *def = create_symbol(name, - BSF_GLOBAL | BSF_EXPORT | - BSF_ABSOLUTE, - (asection *)NULL); - if (s != (asection *)NULL) { - def->value = s->vma; - } - else { - def->value = 0; +lang_abs_symbol_at_beginning_of (secname, name) + const char *secname; + const char *name; +{ + struct bfd_link_hash_entry *h; + + h = bfd_link_hash_lookup (link_info.hash, name, true, true, true); + if (h == (struct bfd_link_hash_entry *) NULL) + einfo ("%P%F: bfd_link_hash_lookup failed: %E\n"); + + if (h->type == bfd_link_hash_new + || h->type == bfd_link_hash_undefined) + { + asection *sec; + + h->type = bfd_link_hash_defined; + + sec = bfd_get_section_by_name (output_bfd, secname); + if (sec == (asection *) NULL) + h->u.def.value = 0; + else + h->u.def.value = bfd_get_section_vma (output_bfd, sec); + + h->u.def.section = &bfd_abs_section; } - } } /* @@ -2356,43 +2817,50 @@ DEFUN(lang_abs_symbol_at_beginning_of,(section, name), If the symbol already exists, then do nothing. */ void -DEFUN(lang_abs_symbol_at_end_of,(section, name), - CONST char *section AND - CONST char *name) -{ - if (ldsym_undefined(name)){ - extern bfd *output_bfd; - extern asymbol *create_symbol(); - asection *s = bfd_get_section_by_name(output_bfd, section); - /* Add a symbol called _end */ - asymbol *def = create_symbol(name, - BSF_GLOBAL | BSF_EXPORT | - BSF_ABSOLUTE, - (asection *)NULL); - if (s != (asection *)NULL) { - def->value = s->vma + s->size; - } - else { - def->value = 0; +lang_abs_symbol_at_end_of (secname, name) + const char *secname; + const char *name; +{ + struct bfd_link_hash_entry *h; + + h = bfd_link_hash_lookup (link_info.hash, name, true, true, true); + if (h == (struct bfd_link_hash_entry *) NULL) + einfo ("%P%F: bfd_link_hash_lookup failed: %E\n"); + + if (h->type == bfd_link_hash_new + || h->type == bfd_link_hash_undefined) + { + asection *sec; + + h->type = bfd_link_hash_defined; + + sec = bfd_get_section_by_name (output_bfd, secname); + if (sec == (asection *) NULL) + h->u.def.value = 0; + else + h->u.def.value = (bfd_get_section_vma (output_bfd, sec) + + bfd_section_size (output_bfd, sec)); + + h->u.def.section = &bfd_abs_section; } - } } -void -DEFUN(lang_statement_append,(list, element, field), - lang_statement_list_type *list AND - lang_statement_union_type *element AND - lang_statement_union_type **field) +void +lang_statement_append (list, element, field) + lang_statement_list_type * list; + lang_statement_union_type * element; + lang_statement_union_type ** field; { *(list->tail) = element; list->tail = field; } -/* Set the output format type */ +/* Set the output format type. -oformat overrides scripts. */ void -DEFUN(lang_add_output_format,(format), -CONST char *format) +lang_add_output_format (format, from_script) + CONST char *format; + int from_script; { - output_target = format; + if (output_target == NULL || !from_script) + output_target = format; } -