-/* Copyright (C) 1991 Free Software Foundation, Inc.
+/* Linker command language support.
+ Copyright 1991, 1992 Free Software Foundation, Inc.
This file is part of GLD, the Gnu Linker.
#include "ldindr.h"
#include "ldctor.h"
/* FORWARDS */
-PROTO (static void, print_statements, (void));
-PROTO (static void, print_statement, (lang_statement_union_type *,
+static void print_statements PARAMS ((void));
+static void print_statement PARAMS ((lang_statement_union_type *,
lang_output_section_statement_type *));
/* LOCALS */
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 lang_statement_list_type statement_list;
extern ld_config_type config;
extern boolean had_script;
extern boolean write_map;
+extern int g_switch_value;
+
+
+etree_type *base; /* Relocation base - or null */
+
#ifdef __STDC__
#define cat(a,b) a##b
#define outside_symbol_address(q) ((q)->value + outside_section_address(q->section))
-void EXFUN (lang_add_data, (int type, union etree_union * exp));
+void lang_add_data PARAMS ((int type, union etree_union * exp));
PTR
DEFUN (stat_alloc, (size),
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);
new->section = section;
new->ifile = file;
section->output_section = output->bfd_section;
- section->output_section->flags |= section->flags;
+
+ /* Be selective about what the output section inherits from the
+ input section */
+
+ section->output_section->flags |= section->flags & ~SEC_NEVER_LOAD;
+
if (!output->loadable)
{
- /* Turn of load flag */
+ /* 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;
}
+ /* If supplied an aligmnet, then force it */
+ if (output->section_alignment != -1)
+ {
+ output->bfd_section->alignment_power = output->section_alignment;
+ }
}
}
{
/* Do the creation to all sections in the file */
for (s = file->the_bfd->sections; s != (asection *) NULL; s = s->next)
+ {
+ /* except for bss */
+ if ((s->flags & SEC_IS_COMMON) == 0)
{
wild_doit (&ptr->children, s, output, file);
}
+ }
}
else
{
{
wild_section (s, section, f, output);
}
+ /* Once more for the script file */
+ wild_section(s, section, script_file, output);
}
else
{
bfd_set_arch_mach (output,
ldfile_output_architecture,
ldfile_output_machine);
+ bfd_set_gp_size (output, g_switch_value);
return output;
}
static void
DEFUN_VOID (lang_init_script_file)
{
- script_file = lang_add_input_file ("script file",
+ script_file = lang_add_input_file ("command line",
lang_input_file_is_fake_enum,
(char *) NULL);
- script_file->the_bfd = bfd_create ("script file", output_bfd);
+ script_file->the_bfd = bfd_create ("command line", 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);
+ script_file->the_bfd->sections = 0;
+
+ /* The user data of a bfd points to the input statement attatched */
+ script_file->the_bfd->usrdata = (void *)script_file;
+ script_file->common_section =
+ bfd_make_section(script_file->the_bfd,"COMMON");
+
+ abs_output_section =
+ lang_output_section_statement_lookup (BFD_ABS_SECTION_NAME);
abs_output_section->bfd_section = &bfd_abs_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_size(section->_cooked_size);
- print_space ();
- print_alignment (section->alignment_power);
- print_space ();
+ {
+ print_dot = section->vma;
+ print_space ();
+ print_section ("");
+ print_space ();
+ print_address (section->vma);
+ print_space ();
+ print_size (section->_raw_size);
+ print_space();
+ print_size(section->_cooked_size);
+ print_space ();
+ print_alignment (section->alignment_power);
+ print_space ();
#if 0
- fprintf (config.map_file, "%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)
- 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 ");
+ 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
+ {
+ fprintf (config.map_file, "No attached output section");
+ }
+ print_nl ();
+ if (output_section_statement->load_base)
{
- fprintf (config.map_file, "No attached output section");
+ int b = exp_get_value_int(output_section_statement->load_base,
+ 0, "output base", lang_final_phase_enum);
+ printf("Output address %08x\n", b);
}
- print_nl ();
+ 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_statement (output_section_statement->children.head,
output_section_statement);
case lang_output_statement_enum:
fprintf (config.map_file, "OUTPUT(%s %s)\n",
s->output_statement.name,
- output_target);
+ output_target ? output_target : "");
break;
case lang_input_statement_enum:
print_input_statement (&s->input_statement);
if (is->ifile->just_syms_flag == false)
{
+ if (output_section_statement->subsection_alignment != -1)
+ i->alignment_power =
+ output_section_statement->subsection_alignment;
+
dot = insert_pad (this_ptr, fill, i->alignment_power,
output_section_statement->bfd_section, dot);
bfd_vma after;
lang_output_section_statement_type *os = &s->output_section_statement;
- /* If this section is never loaded, don't change the size and
- address. */
- if (os->bfd_section->flags & SEC_NEVER_LOAD)
+ /* If this is a shared library section, don't change the size
+ and address. */
+ if (os->bfd_section->flags & SEC_SHARED_LIBRARY)
break;
if (os->bfd_section == &bfd_abs_section)
dot = align_power (dot, os->bfd_section->alignment_power);
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->region->current = dot;
/* Make sure this isn't silly */
- if (os->region->current >
- os->region->origin +
- os->region->length)
- {
- 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;
+ 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;
- }
+ }
}
}
}
if (it != (asymbol *) NULL)
{
+ asymbol **prev = 0;
asymbol **ptr = lgs->srefs_chain;;
if (lgs->flags & SYM_WARNING)
{
produce_warnings (lgs, it);
}
- while (ptr != (asymbol **) NULL)
+ while (ptr != (asymbol **) NULL
+ && ptr != prev)
{
asymbol *ref = *ptr;
-
+ prev = ptr;
*ptr = it;
ptr = (asymbol **) (ref->udata);
}
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;
-
input_bfd = file->input_statement.the_bfd;
input_machine = bfd_get_mach (input_bfd);
}
if (config.sort_common == false || align == power)
{
+ bfd *symbfd;
+
/* 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;
+ symbfd = bfd_asymbol_bfd (com);
+ if (com->section == &bfd_com_section)
+ com->section =
+ ((lang_input_statement_type *) symbfd->usrdata)
+ ->common_section;
+ else
+ {
+ CONST char *name;
+ asection *newsec;
+
+ name = bfd_get_section_name (symbfd,
+ com->section);
+ newsec = bfd_get_section_by_name (symbfd,
+ name);
+ /* BFD backend must provide this section. */
+ if (newsec == (asection *) NULL)
+ einfo ("%P%F: No output section %s", name);
+ com->section = newsec;
+ }
+
/* Fix the size of the common section */
com->section->_raw_size =
com->flags = BSF_EXPORT | BSF_GLOBAL | BSF_OLD_COMMON;
com->value = com->section->_raw_size;
- if (write_map)
+ if (write_map && config.map_file)
{
fprintf (config.map_file, "Allocating common %s: %x at %x %s\n",
lgs->name,
(unsigned) size,
(unsigned) com->value,
- com->the_bfd->filename);
+ bfd_asymbol_bfd(com)->filename);
}
com->section->_raw_size += size;
void
DEFUN (lang_for_each_file, (func),
- PROTO (void, (*func), (lang_input_statement_type *)))
+ void (*func) PARAMS ((lang_input_statement_type *)))
{
lang_input_statement_type *f;
void
DEFUN (lang_for_each_input_section, (func),
- PROTO (void, (*func), (bfd * ab, asection * as)))
+ void (*func) PARAMS ((bfd * ab, asection * as)))
{
lang_input_statement_type *f;
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),
+ block_value,
+ align, subalign, base),
char *output_section_statement_name AND
etree_type * address_exp AND
int flags AND
- bfd_vma block_value)
+ bfd_vma block_value AND
+ etree_type *align AND
+ etree_type *subalign AND
+ etree_type *base)
{
lang_output_section_statement_type *os;
current_section =
- os =
+ os =
lang_output_section_statement_lookup (output_section_statement_name);
if (os->addr_tree ==
(etree_type *) NULL)
- {
- os->addr_tree =
- address_exp;
- }
+ {
+ os->addr_tree =
+ address_exp;
+ }
os->flags = flags;
if (flags & SEC_NEVER_LOAD)
os->loadable = 0;
else
os->loadable = 1;
- os->block_value = block_value;
+ 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));
+
+ os->load_base = base;
}
+
void
DEFUN_VOID (lang_final)
{
/* 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;
-
*def_ptr = def;
Q_enter_global_ref (def_ptr, name);
return def;
current_target = default_target;
lang_for_each_statement (open_input_bfds);
- common_section.userdata = (PTR) & common_section_userdata;
-
-
/* Run through the contours of the script and attatch input sections
to the correct output sections
*/
{
output_target = format;
}
+