*
*/
-
-
-#include "sysdep.h"
#include "bfd.h"
+#include "sysdep.h"
#include "ld.h"
#include "ldmain.h"
#include "ldsym.h"
-#include "ldgram.tab.h"
-#include "ldmisc.h"
+#include "ldgram.h"
+#include "ldwarn.h"
#include "ldlang.h"
#include "ldexp.h"
#include "ldemul.h"
#include "ldlex.h"
-
+#include "ldmisc.h"
+#include "ldindr.h"
+#include "ldctor.h"
/* FORWARDS */
PROTO(static void, print_statements,(void));
PROTO(static void, print_statement,(lang_statement_union_type *,
/* LOCALS */
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 constructors */
+extern 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;
static asection common_section;
static section_userdata_type common_section_userdata;
static lang_statement_list_type statement_list;
-/* EXPORTS */
+/* EXPORTS */
+boolean relaxing;
+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;
-size_t largest_section = 0;
+bfd_size_type largest_section = 0;
boolean lang_has_input_file = false;
lang_output_section_statement_type *create_object_symbols = 0;
boolean had_output_filename = false;
#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)
+{
+ fprintf(config.map_file, "%5x", (unsigned)value);
+}
+static void
+DEFUN(print_alignment,(value),
+ unsigned int value)
+{
+ fprintf(config.map_file, "2**%1u",value);
+}
+static void
+DEFUN(print_fill,(value),
+ fill_type value)
+{
+ fprintf(config.map_file, "%04x",(unsigned)value);
+}
+static void
+DEFUN(print_section,(name),
+ CONST char *CONST name)
+{
+ fprintf(config.map_file, "%*s", -longest_section_name, name);
+}
+
/*----------------------------------------------------------------------
lang_for_each_statement walks the parse tree and calls the provided
function for each node
func(s);
switch (s->header.type) {
+ case lang_constructors_statement_enum:
+ lang_for_each_statement_worker(func, constructor_list.head);
+ break;
case lang_output_section_statement_enum:
lang_for_each_statement_worker
(func,
statement_list.head);
}
/*----------------------------------------------------------------------*/
-static void
+void
DEFUN(lang_list_init,(list),
lang_statement_list_type *list)
{
list->tail = &list->head;
}
-/*----------------------------------------------------------------------
- Functions to print the link map
- */
-
-static void
-DEFUN(print_section,(name),
- CONST char *CONST name)
-{
- printf("%*s", -longest_section_name, name);
-}
-static void
-DEFUN_VOID(print_space)
-{
- printf(" ");
-}
-static void
-DEFUN_VOID(print_nl)
-{
- printf("\n");
-}
-static void
-DEFUN(print_address,(value),
- bfd_vma value)
-{
- printf("%8lx", value);
-}
-static void
-DEFUN(print_size,(value),
- size_t value)
-{
- printf("%5x", (unsigned)value);
-}
-static void
-DEFUN(print_alignment,(value),
- unsigned int value)
-{
- printf("2**%2u",value);
-}
-
-static void
-DEFUN(print_fill,(value),
- fill_type value)
-{
- printf("%04x",(unsigned)value);
-}
/*----------------------------------------------------------------------
lang_statement_union_type*
DEFUN(new_statement,(type, size, list),
enum statement_enum type AND
- size_t size AND
+ bfd_size_type size AND
lang_statement_list_type *list)
{
lang_statement_union_type *new = (lang_statement_union_type *)
lang_input_statement_type *
DEFUN(lang_add_input_file,(name, file_type, target),
- char *name AND
+ CONST char *name AND
lang_input_file_enum_type file_type AND
- char *target)
+ CONST char *target)
{
/* Look it up or build a new one */
lang_has_input_file = true;
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;
+
}
}
{
lang_memory_region_type *new =
- (lang_memory_region_type *)ldmalloc(sizeof(lang_memory_region_type));
+ (lang_memory_region_type *)ldmalloc((bfd_size_type)(sizeof(lang_memory_region_type)));
new->name = buystring(name);
new->next = (lang_memory_region_type *)NULL;
new->origin = 0;
new->length = ~0;
new->current = 0;
+ new->had_full_message = false;
+
return new;
}
}
-
+/*ARGSUSED*/
static void
-DEFUN(print_flags, (outfile, ignore_flags),
- FILE *outfile AND
- lang_section_flags_type *ignore_flags)
+DEFUN(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");
#endif
- fprintf(outfile,")");
+ fprintf(config.map_file, ")");
}
void
-DEFUN(lang_map,(outfile),
- FILE *outfile)
+DEFUN_VOID(lang_map)
{
lang_memory_region_type *m;
- fprintf(outfile,"**MEMORY CONFIGURATION**\n\n");
-
- fprintf(outfile,"name\t\torigin\t\tlength\t\tattributes\n");
+ fprintf(config.map_file,"**MEMORY CONFIGURATION**\n\n");
+#ifdef HOST_64_BIT
+ fprintf(config.map_file,"name\t\torigin\t\tlength\t\tattributes\n");
+#else
+ fprintf(config.map_file,"name\t\torigin length\t\tattributes\n");
+#endif
for (m = lang_memory_region_list;
m != (lang_memory_region_type *)NULL;
m = m->next)
{
- fprintf(outfile,"%-16s", m->name);
-
- fprintf(outfile,"%08lx\t%08lx\t", m->origin, m->length);
- print_flags(outfile, &m->flags);
- fprintf(outfile,"\n");
+ fprintf(config.map_file,"%-16s", m->name);
+ print_address(m->origin);
+ print_space();
+ print_address(m->length);
+ print_space();
+ print_flags( &m->flags);
+ fprintf(config.map_file,"\n");
}
- fprintf(outfile,"\n\n**LINK EDITOR MEMORY MAP**\n\n");
- fprintf(outfile,"output\t\tinput\t\tvirtual\n");
- fprintf(outfile,"section\t\tsection\t\taddress\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();
DEFUN(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(sizeof(section_userdata_type));
-
- s->bfd_section = bfd_make_section(output_bfd, s->name);
+ (section_userdata_type *)
+ ldmalloc((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 = SEC_NO_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;
+
}
/***********************************************************************
if (output == (bfd *)NULL)
{
if (bfd_error == invalid_target) {
- info("%P%F target %s not found\n", output_target);
+ einfo("%P%F target %s not found\n", output_target);
}
- info("%P%F problem opening output file %s, %E", name);
+ einfo("%P%F problem opening output file %s, %E", name);
}
- output->flags |= D_PAGED;
+/* output->flags |= D_PAGED;*/
bfd_set_format(output, bfd_object);
return output;
}
case lang_output_statement_enum:
output_bfd = open_output(statement->output_statement.name);
ldemul_set_output_arch();
+ if (config.magic_demand_paged && !config.relocateable_output)
+ 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;
break;
case lang_target_statement_enum:
static void
lang_reasonable_defaults()
{
+
+
+
#if 0
lang_output_section_statement_lookup(".text");
lang_output_section_statement_lookup(".data");
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_struct {
- struct ldlang_undef_chain_list_struct *next;
+typedef struct ldlang_undef_chain_list {
+ struct ldlang_undef_chain_list *next;
char *name;
} ldlang_undef_chain_list_type;
{
ldlang_undef_chain_list_type *new =
(ldlang_undef_chain_list_type
- *)ldmalloc(sizeof(ldlang_undef_chain_list_type));
+ *)ldmalloc((bfd_size_type)(sizeof(ldlang_undef_chain_list_type)));
new->next = ldlang_undef_chain_list_head;
ldlang_undef_chain_list_head = new;
while (ptr != (ldlang_undef_chain_list_type*)NULL) {
ldsym_type *sy = ldsym_get(ptr->name);
asymbol *def;
- asymbol **def_ptr = (asymbol **)ldmalloc(sizeof(asymbol **));
+ 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;
+ def->section = &bfd_und_section;
Q_enter_global_ref(def_ptr);
ptr = ptr->next;
}
script_file->the_bfd = bfd_create("script file", output_bfd);
script_file->symbol_count = 0;
script_file->the_bfd->sections = output_bfd->sections;
+abs_output_section = lang_output_section_statement_lookup(BFD_ABS_SECTION_NAME);
+
+abs_output_section->bfd_section = &bfd_abs_section;
+
}
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,
lang_output_section_statement_lookup
(s->address_statement.section_name);
os->addr_tree = s->address_statement.address;
+ if (os->bfd_section == (asection *)NULL) {
+ einfo("%P%F can't set the address of undefined section %s\n",
+ s->address_statement.section_name);
+ }
}
break;
case lang_input_statement_enum:
print_space();
print_address(section->vma);
print_space();
- print_size(section->size);
+ print_size(bfd_get_section_size_before_reloc(section));
print_space();
print_alignment(section->alignment_power);
print_space();
#if 0
- printf("%s flags", output_section_statement->region->name);
+ fprintf(config.map_file, "%s flags", output_section_statement->region->name);
print_flags(stdout, &output_section_statement->flags);
#endif
+ if (section->flags & SEC_LOAD)
+ fprintf(config.map_file, "load ");
+ if (section->flags & SEC_ALLOC)
+ fprintf(config.map_file, "alloc ");
+ if (section->flags & SEC_RELOC)
+ fprintf(config.map_file, "reloc ");
+ if (section->flags & SEC_HAS_CONTENTS)
+ fprintf(config.map_file, "contents ");
}
else {
- printf("No attached output section");
+ fprintf(config.map_file, "No attached output section");
}
print_nl();
print_statement(output_section_statement->children.head,
}
else
{
- printf("*undefined*");
+ fprintf(config.map_file, "*undefined*");
}
print_space();
- exp_print_tree(stdout, assignment->exp);
- printf("\n");
+ exp_print_tree(assignment->exp);
+
+ fprintf(config.map_file, "\n");
}
static void
lang_input_statement_type *statm)
{
if (statm->filename != (char *)NULL) {
- printf("LOAD %s\n",statm->filename);
+ fprintf(config.map_file, "LOAD %s\n",statm->filename);
}
}
asymbol *q)
{
print_section("");
- printf(" ");
+ fprintf(config.map_file, " ");
print_section("");
- printf(" ");
+ fprintf(config.map_file, " ");
print_address(outside_symbol_address(q));
- printf(" %s", q->name ? q->name : " ");
+ fprintf(config.map_file, " %s", q->name ? q->name : " ");
print_nl();
}
lang_input_section_type *in)
{
asection *i = in->section;
+ int size = i->reloc_done ?
+ bfd_get_section_size_after_reloc(i) :
+ bfd_get_section_size_before_reloc(i);
+
- if(i->size != 0) {
+ if(size != 0) {
print_section("");
- printf(" ");
+ fprintf(config.map_file, " ");
print_section(i->name);
- printf(" ");
+ fprintf(config.map_file, " ");
if (i->output_section) {
print_address(i->output_section->vma + i->output_offset);
- printf(" ");
- print_size(i->size);
- printf(" ");
+ fprintf(config.map_file, " ");
+ print_size(size);
+ fprintf(config.map_file, " ");
print_alignment(i->alignment_power);
- printf(" ");
+ fprintf(config.map_file, " ");
if (in->ifile) {
bfd *abfd = in->ifile->the_bfd;
if (in->ifile->just_syms_flag == true) {
- printf("symbols only ");
+ fprintf(config.map_file, "symbols only ");
}
- printf(" %s ",abfd->xvec->name);
+ fprintf(config.map_file, " %s ",abfd->xvec->name);
if(abfd->my_archive != (bfd *)NULL) {
- printf("[%s]%s", abfd->my_archive->filename,
+ fprintf(config.map_file, "[%s]%s", abfd->my_archive->filename,
abfd->filename);
}
else {
- printf("%s", abfd->filename);
+ fprintf(config.map_file, "%s", abfd->filename);
}
- printf("(%d bytes)", bfd_alloc_size(abfd));
+ fprintf(config.map_file, "(overhead %d bytes)", (int)bfd_alloc_size(abfd));
print_nl();
/* Find all the symbols in this file defined in this section */
}
- print_dot = outside_section_address(i) + i->size;
+ print_dot = outside_section_address(i) + size;
}
else {
- printf("No output section allocated\n");
+ fprintf(config.map_file, "No output section allocated\n");
}
}
}
DEFUN(print_fill_statement,(fill),
lang_fill_statement_type *fill)
{
- printf("FILL mask ");
+ fprintf(config.map_file, "FILL mask ");
print_fill( fill->fill);
}
print_space();
/* ASSERT(print_dot == data->output_vma);*/
- print_address(data->output_vma);
+ print_address(data->output_vma + data->output_section->vma);
print_space();
print_address(data->value);
print_space();
switch (data->type) {
case BYTE :
- printf("BYTE ");
+ fprintf(config.map_file, "BYTE ");
print_dot += BYTE_SIZE;
break;
case SHORT:
- printf("SHORT ");
+ fprintf(config.map_file, "SHORT ");
print_dot += SHORT_SIZE;
break;
case LONG:
- printf("LONG ");
+ fprintf(config.map_file, "LONG ");
print_dot += LONG_SIZE;
break;
}
- exp_print_tree(stdout, data->exp);
+ exp_print_tree(data->exp);
- printf("\n");
+ fprintf(config.map_file, "\n");
}
print_space();
print_fill(s->fill);
print_nl();
+
+ print_dot = s->output_offset + s->output_section->vma + s->size;
+
}
static void
lang_wild_statement_type *w AND
lang_output_section_statement_type *os)
{
+ fprintf(config.map_file, " from ");
if (w->filename != (char *)NULL) {
- printf("%s",w->filename);
+ fprintf(config.map_file, "%s",w->filename);
}
else {
- printf("*");
+ fprintf(config.map_file, "*");
}
if (w->section_name != (char *)NULL) {
- printf("(%s)",w->section_name);
+ fprintf(config.map_file, "(%s)",w->section_name);
}
else {
- printf("(*)");
+ fprintf(config.map_file, "(*)");
}
print_nl();
print_statement(w->children.head, os);
lang_statement_union_type *s AND
lang_output_section_statement_type *os)
{
- while (s) {
- switch (s->header.type) {
- 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;
-
-
- 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;
+ 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;
+ 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_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);
+ 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;
- }
}
DEFUN_VOID(print_statements)
{
print_statement(statement_list.head,
- (lang_output_section_statement_type *)NULL);
+ abs_output_section);
+
}
static bfd_vma
{
lang_statement_union_type *new =
(lang_statement_union_type *)
- ldmalloc(sizeof(lang_padding_statement_type));
+ ldmalloc((bfd_size_type)(sizeof(lang_padding_statement_type)));
/* Link into existing chain */
new->header.next = *this_ptr;
*this_ptr = new;
if (power > output_section_statement->alignment_power) {
output_section_statement->alignment_power = power;
}
- output_section_statement->size += alignment_needed;
+ output_section_statement->_raw_size += alignment_needed;
return alignment_needed + dot;
}
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 */
- if (i->size > largest_section) {
- largest_section = i->size;
+ /* 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))
+ && (bfd_get_section_size_before_reloc(i) > largest_section)) {
+ largest_section = bfd_get_section_size_before_reloc(i);
}
/* Remember where in the output section this input section goes */
i->output_offset = dot - output_section_statement->bfd_section->vma;
/* Mark how big the output section must be to contain this now */
- dot += i->size;
- output_section_statement->bfd_section->size =
+ dot += bfd_get_section_size_before_reloc(i);
+output_section_statement->bfd_section->_raw_size =
dot - output_section_statement->bfd_section->vma;
}
else
}
-/* Work out the size of the output sections
- from the sizes of the input sections */
+/* Sizing happens in two passes, first pass we allocate worst case
+ stuff. The second pass (if relaxing), we use what we learnt to
+ change the size of some relocs from worst case to better
+ */
+static boolean had_relax;
+
static bfd_vma
-DEFUN(lang_size_sections,(s, output_section_statement, prev, fill, dot),
+DEFUN(lang_size_sections,(s, output_section_statement, prev, fill,
+ dot, relax),
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)
+ bfd_vma dot AND
+ boolean relax)
{
/* Size up the sections from their constituent parts */
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 */
+ {
+ switch (s->header.type) {
- 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;
+ case lang_output_section_statement_enum:
+ {
+ bfd_vma after;
+ lang_output_section_statement_type *os =&(s->output_section_statement);
+
+ if (os->bfd_section == &bfd_abs_section)
+ {
+ /* No matter what happens, an abs section starts at zero */
+ os->bfd_section->vma = 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*");
}
- /* The section starts here */
- /* First, align to what the section needs */
+ dot = os->region->current;
+ }
+ 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 */
- dot = align_power(dot, os->bfd_section->alignment_power);
- os->bfd_section->vma = dot;
- os->bfd_section->output_offset = 0;
- (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 */
+ dot = align_power(dot, os->bfd_section->alignment_power);
+ os->bfd_section->vma = dot;
+ }
+
+
+ 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(os->bfd_section->vma +
- os->bfd_section->size,
- os->block_value) ;
+ after = ALIGN(os->bfd_section->vma +
+ os->bfd_section->_raw_size,
+ os->block_value) ;
- os->bfd_section->size = after - os->bfd_section->vma;
- dot = os->bfd_section->vma + os->bfd_section->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;
- }
- }
+ os->bfd_section->_raw_size = after - os->bfd_section->vma;
+ dot = os->bfd_section->vma + os->bfd_section->_raw_size;
+ os->processed = true;
- break;
-
- case lang_data_statement_enum:
+ /* 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)
{
- 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;
+ 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 += size;
- output_section_statement->bfd_section->size += size;
}
- break;
+
+ }
+ }
- case lang_wild_statement_enum:
+ 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;
+
+ 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;
+
+ switch (s->data_statement.type) {
+ 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;
+
+ case lang_wild_statement_enum:
- dot = lang_size_sections(s->wild_statement.children.head,
+ dot = lang_size_sections(s->wild_statement.children.head,
output_section_statement,
&s->wild_statement.children.head,
- fill, dot);
+ fill, dot, relax);
- break;
+ 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,
+ 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:
+ if (relax)
+ {
+ relaxing = true;
+
+
+ had_relax |= relax_section(prev);
+ relaxing = false;
+
+ }
+
+ 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(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;
- }
- }
-
- break;
- case lang_padding_statement_enum:
- FAIL();
- break;
- default:
- FAIL();
- break;
- case lang_address_statement_enum:
- break;
+ 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 && !relax)
+ /* 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->_raw_size +=
+ new->padding_statement.size;
+ dot = newdot;
}
- prev = &s->header.next;
}
+
+ break;
+ default:
+ FAIL();
+ break;
+ /* This can only get here when relaxing is turned on */
+ case lang_padding_statement_enum:
+
+ case lang_address_statement_enum:
+ break;
+ }
+ prev = &s->header.next;
+ }
return dot;
}
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:
{
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;
+ dot = os->bfd_section->vma + os->bfd_section->_raw_size;
}
break;
case lang_wild_statement_enum:
{
etree_value_type value ;
value = exp_fold_tree(s->data_statement.exp,
- 0, lang_final_phase_enum, dot, &dot);
+ abs_output_section,
+ lang_final_phase_enum, dot, &dot);
s->data_statement.value = value.value;
- if (value.valid == false) info("%F%P: Invalid data statement\n");
+ if (value.valid == false) einfo("%F%P: Invalid data statement\n");
}
switch (s->data_statement.type) {
case LONG:
case lang_input_section_enum:
{
asection *in = s->input_section.section;
- dot += in->size;
+ dot += bfd_get_section_size_before_reloc(in);
}
break;
}
if (it != (asymbol *)NULL)
{
- asymbol **ptr= lgs->srefs_chain;
+ asymbol **ptr = lgs->srefs_chain;;
+ if (lgs->flags & SYM_WARNING)
+ {
+ produce_warnings(lgs, it);
+ }
while (ptr != (asymbol **)NULL) {
asymbol *ref = *ptr;
{
lang_statement_union_type *file;
-
+ bfd * input_bfd;
+ unsigned long input_machine;
+ enum bfd_architecture input_architecture;
+
+ CONST bfd_arch_info_type *compatible;
+
for (file = file_chain.head;
file != (lang_statement_union_type *)NULL;
file=file->input_statement.next)
{
- /* Inspect the architecture and ensure we're linking like
- with like
- */
-
- if (bfd_arch_compatible( file->input_statement.the_bfd,
- output_bfd,
- &ldfile_output_architecture,
- &ldfile_output_machine)) {
- bfd_set_arch_mach(output_bfd,
- ldfile_output_architecture, ldfile_output_machine);
- }
- else {
- enum bfd_architecture this_architecture =
- bfd_get_architecture(file->input_statement.the_bfd);
- unsigned long this_machine =
- bfd_get_machine(file->input_statement.the_bfd);
-
- info("%I: architecture %s",
- file,
- bfd_printable_arch_mach(this_architecture, this_machine));
- info(" incompatible with output %s\n",
- bfd_printable_arch_mach(ldfile_output_architecture,
- ldfile_output_machine));
- ldfile_output_architecture = this_architecture;
- ldfile_output_machine = this_machine;
- bfd_set_arch_mach(output_bfd,
- ldfile_output_architecture,
- ldfile_output_machine);
+ unsigned long ldfile_new_output_machine = 0;
+ enum bfd_architecture ldfile_new_output_architecture = bfd_arch_unknown;
+ input_bfd = file->input_statement.the_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);
+
+ if (compatible)
+ {
+ ldfile_output_machine = compatible->mach;
+ ldfile_output_architecture = compatible->arch;
+ }
+ else
+ {
+
+ 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);
+ }
- }
}
}
((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);
+
+ com->section->_raw_size =
+ ALIGN(com->section->_raw_size, align);
/* Remember if this is the biggest alignment ever seen */
if (power_of_two > com->section->alignment_power) {
we remember that it was common once. */
com->flags = BSF_EXPORT | BSF_GLOBAL | BSF_OLD_COMMON;
- com->value = com->section->size;
+ com->value = com->section->_raw_size;
if (write_map)
{
- printf ("Allocating common %s: %x at %x %s\n",
+ fprintf (config.map_file, "Allocating common %s: %x at %x %s\n",
lgs->name,
(unsigned) size,
(unsigned) com->value,
com->the_bfd->filename);
}
- com->section->size += size;
+ com->section->_raw_size += size;
}
}
void
DEFUN(lang_set_flags,(ptr, flags),
- lang_section_flags_type *ptr AND
+ int *ptr AND
CONST char *flags)
{
boolean state = true;
- ptr->flag_read = false;
- ptr->flag_write = false;
- ptr->flag_executable = false;
- ptr->flag_loadable= false;
+*ptr= 0;
while (*flags)
{
if (*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 illegal syntax in flags\n");
break;
}
flags++;
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_output_section_statement_type *os;
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);*/
os->addr_tree =
address_exp;
}
+ os->flags = flags;
os->block_value = block_value;
stat_ptr = & os->children;
+/* Reset the current counters in the regions */
+static void
+ DEFUN_VOID(reset_memory_regions)
+{
+ lang_memory_region_type *p = lang_memory_region_list;
+ for (p = lang_memory_region_list;
+ p != ( lang_memory_region_type *)NULL;
+ p = p->next)
+ {
+ p->current = p->origin;
+ }
+}
asymbol *
asection *section)
{
extern lang_input_statement_type *script_file;
- asymbol **def_ptr = (asymbol **)ldmalloc(sizeof(asymbol **));
+ 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);
}
+
void
DEFUN_VOID(lang_process)
{
+
if (had_script == false) {
- parse_line(ldemul_get_script());
- }
+ parse_line(ldemul_get_script(),1);
+ }
lang_reasonable_defaults();
current_target = default_target;
common_section.userdata = (PTR)&common_section_userdata;
+
/* Run through the contours of the script and attatch input sections
to the correct output sections
*/
+ find_constructors();
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();
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);
+ abs_output_section,
+ &(statement_list.head), 0, (bfd_vma)0, false);
+
+
+ /* Now run around and relax if we can */
+ if (command_line.relax)
+ {
+ reset_memory_regions();
+
+ /* Move the global symbols around */
+ lang_relocate_globals();
+
+ had_relax = true;
+ while (had_relax)
+ {
+
+ had_relax = false;
+
+ lang_size_sections(statement_list.head,
+ (lang_output_section_statement_type *)NULL,
+ &(statement_list.head), 0, (bfd_vma)0, true);
+ /* FIXME. Until the code in relax is fixed so that it only reads in
+ stuff once, we cant iterate since there is no way for the linker to
+ know what has been patched and what hasn't */
+ break;
+
+ }
+
+
+
+
+ }
+
/* See if anything special should be done now we know how big
everything is */
of all the symbols */
lang_do_assignments(statement_list.head,
- (lang_output_section_statement_type *)NULL,
+ abs_output_section,
0, (bfd_vma)0);
- /* Make sure that we're not mixing architectures */
-
- lang_check();
/* Move the global symbols around */
lang_relocate_globals();
+ /* Make sure that we're not mixing architectures */
+
+ lang_check();
+
/* Final stuffs */
lang_finish();
}
CONST char *name)
{
if (startup_file != (char *)NULL) {
- info("%P%FMultiple STARTUP files\n");
+ einfo("%P%FMultiple STARTUP files\n");
}
first_file->filename = name;
first_file->local_sym_name = name;
current_section->fill = fill;
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;
+
+ }
}
/*
Create an absolute symbol with the given name with the value of the
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);
+ BSF_GLOBAL | BSF_EXPORT ,
+ &bfd_abs_section);
+
+
if (s != (asection *)NULL) {
def->value = s->vma;
}
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);
+ BSF_GLOBAL | BSF_EXPORT ,
+ &bfd_abs_section);
+
if (s != (asection *)NULL) {
- def->value = s->vma + s->size;
+ def->value = s->vma + s->_raw_size;
}
else {
def->value = 0;