/* Linker command language support.
- Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 1999
+ Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 99, 2000
Free Software Foundation, Inc.
This file is part of GLD, the Gnu Linker.
static boolean map_option_f;
static bfd_vma print_dot;
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 lang_statement_list_type statement_list;
/* EXPORTS */
lang_output_section_statement_type *abs_output_section;
+lang_statement_list_type lang_output_section_statement;
lang_statement_list_type *stat_ptr = &statement_list;
lang_statement_list_type file_chain = { NULL, NULL };
const char *entry_symbol = NULL;
void *data;
{
/* Don't process sections from files which were excluded. */
- if (ptr->exclude_filename != NULL)
+ if (ptr->exclude_filename_list != NULL)
{
- boolean match;
+ struct name_list *list_tmp;
+ for (list_tmp = ptr->exclude_filename_list; list_tmp; list_tmp = list_tmp->next)
+ {
+ boolean match;
- if (wildcardp (ptr->exclude_filename))
- match = fnmatch (ptr->exclude_filename, file->filename, 0) == 0 ? true : false;
- else
- match = strcmp (ptr->exclude_filename, file->filename) == 0 ? true : false;
+ if (wildcardp (list_tmp->name))
+ match = fnmatch (list_tmp->name, file->filename, 0) == 0 ? true : false;
+ else
+ match = strcmp (list_tmp->name, file->filename) == 0 ? true : false;
- if (match)
- return;
+ if (match)
+ return;
+ }
}
if (file->just_syms_flag == false)
lookup = (lang_output_section_statement_type *)
new_stat (lang_output_section_statement, stat_ptr);
lookup->region = (lang_memory_region_type *) NULL;
+ lookup->lma_region = (lang_memory_region_type *) NULL;
lookup->fill = 0;
lookup->block_value = 1;
lookup->name = name;
{
asection *i = in->section;
bfd_size_type size = i->_cooked_size != 0 ? i->_cooked_size : i->_raw_size;
-
+ unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
+ ldfile_output_machine);
if (size != 0)
{
print_space ();
}
minfo ("0x%V %W %B\n",
- i->output_section->vma + i->output_offset, size,
+ i->output_section->vma + i->output_offset, size / opb,
i->owner);
if (i->_cooked_size != 0 && i->_cooked_size != i->_raw_size)
bfd_link_hash_traverse (link_info.hash, print_one_symbol, (PTR) i);
- print_dot = i->output_section->vma + i->output_offset + size;
+ print_dot = i->output_section->vma + i->output_offset + size / opb;
}
}
}
bfd_vma addr;
bfd_size_type size;
const char *name;
+ unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
+ ldfile_output_machine);
for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++)
print_space ();
print_nl ();
- print_dot = addr + size;
+ print_dot = addr + size / opb;
+
}
/* Print an address statement. These are generated by options like
int i;
bfd_vma addr;
bfd_size_type size;
+ unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
+ ldfile_output_machine);
for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++)
print_space ();
print_nl ();
- print_dot = addr + size;
+ print_dot = addr + size / opb;
}
static void
{
int len;
bfd_vma addr;
+ unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
+ ldfile_output_machine);
minfo (" *fill*");
print_nl ();
- print_dot = addr + s->size;
+ print_dot = addr + s->size / opb;
}
static void
if (w->filenames_sorted)
minfo ("SORT(");
- if (w->exclude_filename != NULL)
- minfo ("EXCLUDE_FILE ( %s )", w->exclude_filename);
- if (w->filename != NULL)
+ if (w->exclude_filename_list != NULL)
+ {
+ name_list *tmp;
+ minfo ("EXCLUDE_FILE ( %s", w->exclude_filename_list->name);
+ for (tmp=w->exclude_filename_list->next; tmp; tmp = tmp->next)
+ minfo (", %s", tmp->name);
+ minfo (")");
+ }
+ if (w->filename != NULL)
minfo ("%s", w->filename);
else
minfo ("*");
inserting a magic 'padding' statement.
*/
+ unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
+ ldfile_output_machine);
unsigned int alignment_needed = align_power (dot, power) - dot;
if (alignment_needed != 0)
new->padding_statement.output_offset =
dot - output_section_statement->vma;
new->padding_statement.fill = fill;
- new->padding_statement.size = alignment_needed;
+ new->padding_statement.size = alignment_needed * opb;
}
{
output_section_statement->alignment_power = power;
}
- output_section_statement->_raw_size += alignment_needed;
- return alignment_needed + dot;
+ output_section_statement->_raw_size += alignment_needed * opb;
+ return dot + alignment_needed;
}
/* Work out how much this section will move the dot point */
{
lang_input_section_type *is = &((*this_ptr)->input_section);
asection *i = is->section;
+ unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
+ ldfile_output_machine);
if (is->ifile->just_syms_flag == false)
{
/* Mark how big the output section must be to contain this now
*/
if (i->_cooked_size != 0)
- dot += i->_cooked_size;
+ dot += i->_cooked_size / opb;
else
- dot += i->_raw_size;
- output_section_statement->bfd_section->_raw_size = dot - output_section_statement->bfd_section->vma;
+ dot += i->_raw_size / opb;
+ output_section_statement->bfd_section->_raw_size =
+ (dot - output_section_statement->bfd_section->vma) * opb;
}
else
{
}
#define IGNORE_SECTION(bfd, s) \
- (((bfd_get_section_flags (bfd, s) & (SEC_ALLOC | SEC_LOAD)) == 0) \
+ (((bfd_get_section_flags (bfd, s) & (SEC_ALLOC | SEC_LOAD)) != (SEC_ALLOC | SEC_LOAD)) \
|| bfd_section_size (bfd, s) == 0)
/* Check to see if any allocated sections overlap with other allocated
lang_check_section_addresses ()
{
asection * s;
+ unsigned opb = bfd_octets_per_byte (output_bfd);
/* Scan all sections in the output list. */
for (s = output_bfd->sections; s != NULL; s = s->next)
overlapping VMAs but they must have distinct LMAs. */
s_start = bfd_section_lma (output_bfd, s);
os_start = bfd_section_lma (output_bfd, os);
- s_end = s_start + bfd_section_size (output_bfd, s) - 1;
- os_end = os_start + bfd_section_size (output_bfd, os) - 1;
+ s_end = s_start + bfd_section_size (output_bfd, s) / opb - 1;
+ os_end = os_start + bfd_section_size (output_bfd, os) / opb - 1;
/* Look for an overlap. */
if ((s_end < os_start) || (s_start > os_end))
static boolean relax_again;
+/* Make sure the new address is within the region. We explicitly permit the
+ current address to be at the exact end of the region when the address is
+ non-zero, in case the region is at the end of addressable memory and the
+ calculation wraps around. */
+
+static void
+os_region_check (os, region, tree, base)
+ lang_output_section_statement_type *os;
+ struct memory_region_struct *region;
+ etree_type *tree;
+ bfd_vma base;
+{
+ if ((region->current < region->origin
+ || (region->current - region->origin > region->length))
+ && ((region->current != region->origin + region->length)
+ || base == 0))
+ {
+ if (tree != (etree_type *) NULL)
+ {
+ einfo (_("%X%P: address 0x%v of %B section %s is not within region %s\n"),
+ region->current,
+ os->bfd_section->owner,
+ os->bfd_section->name,
+ region->name);
+ }
+ else
+ {
+ einfo (_("%X%P: region %s is full (%B section %s)\n"),
+ region->name,
+ os->bfd_section->owner,
+ os->bfd_section->name);
+ }
+ /* Reset the region pointer. */
+ region->current = region->origin;
+ }
+}
+
/* Set the sizes for all the output sections. */
bfd_vma
bfd_vma dot;
boolean relax;
{
+ unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
+ ldfile_output_machine);
+
/* Size up the sections from their constituent parts. */
for (; s != (lang_statement_union_type *) NULL; s = s->next)
{
(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,
+ /* put the section within the requested block size, or align at
+ the block boundary */
+ after = ALIGN_N (os->bfd_section->vma
+ + os->bfd_section->_raw_size / opb,
/* The coercion here is important, see ld.h. */
(bfd_vma) os->block_value);
if (bfd_is_abs_section (os->bfd_section))
ASSERT (after == os->bfd_section->vma);
else
- os->bfd_section->_raw_size = after - os->bfd_section->vma;
- dot = os->bfd_section->vma + os->bfd_section->_raw_size;
+ os->bfd_section->_raw_size =
+ (after - os->bfd_section->vma) * opb;
+ dot = os->bfd_section->vma + os->bfd_section->_raw_size / opb;
os->processed = true;
/* Update dot in the region ?
We only do this if the section is going to be allocated,
since unallocated sections do not contribute to the region's
- overall size in memory. */
+ overall size in memory.
+
+ If the SEC_NEVER_LOAD bit is not set, it will affect the
+ addresses of sections after it. We have to update
+ dot. */
if (os->region != (lang_memory_region_type *) NULL
- && (bfd_get_section_flags (output_bfd, os->bfd_section)
- & (SEC_ALLOC | SEC_LOAD)))
+ && ((bfd_get_section_flags (output_bfd, os->bfd_section)
+ & SEC_NEVER_LOAD) == 0
+ || (bfd_get_section_flags (output_bfd, os->bfd_section)
+ & (SEC_ALLOC | SEC_LOAD))))
{
os->region->current = dot;
- /* Make sure the new address is within the region. We
- explicitly permit the current address to be at the
- exact end of the region when the VMA is non-zero,
- in case the region is at the end of addressable
- memory and the calculation wraps around. */
- if ((os->region->current < os->region->origin
- || (os->region->current - os->region->origin
- > os->region->length))
- && ((os->region->current
- != os->region->origin + os->region->length)
- || os->bfd_section->vma == 0))
-
- {
- if (os->addr_tree != (etree_type *) NULL)
- {
- einfo (_("%X%P: address 0x%v of %B section %s is not within region %s\n"),
- os->region->current,
- os->bfd_section->owner,
- os->bfd_section->name,
- os->region->name);
- }
- else
- {
- 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 = os->region->origin;
- }
+ /* Make sure the new address is within the region. */
+ os_region_check (os, os->region, os->addr_tree,
+ os->bfd_section->vma);
+
+ /* if there's no load address specified, use the run region as
+ the load region */
+ if (os->lma_region == NULL && os->load_base == NULL)
+ os->lma_region = os->region;
+
+ if (os->lma_region != NULL)
+ {
+ if (os->load_base != NULL)
+ {
+ einfo (_("%X%P: use an absolute load address or a load memory region, not both\n"));
+ }
+ else
+ {
+ /* don't allocate twice */
+ if (os->lma_region != os->region)
+ {
+ /* set load_base, which will be handled later */
+ os->load_base = exp_intop (os->lma_region->current);
+ os->lma_region->current +=
+ os->bfd_section->_raw_size / opb;
+ os_region_check (os, os->lma_region, NULL,
+ os->bfd_section->lma);
+ }
+ }
+ }
}
}
break;
switch (s->data_statement.type)
{
+ default:
+ abort();
case QUAD:
case SQUAD:
size = QUAD_SIZE;
size = BYTE_SIZE;
break;
}
-
- dot += size;
+ if (size < opb)
+ size = opb;
+ dot += size / opb;
output_section_statement->bfd_section->_raw_size += size;
/* The output section gets contents, and then we inspect for
any flags set in the input script which override any ALLOC. */
s->reloc_statement.output_section =
output_section_statement->bfd_section;
size = bfd_get_reloc_size (s->reloc_statement.howto);
- dot += size;
+ dot += size / opb;
output_section_statement->bfd_section->_raw_size += size;
}
break;
new->padding_statement.output_offset =
dot - output_section_statement->bfd_section->vma;
new->padding_statement.fill = fill;
- new->padding_statement.size = newdot - dot;
+ new->padding_statement.size = (newdot - dot) * opb;
output_section_statement->bfd_section->_raw_size +=
new->padding_statement.size;
}
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;
+ dot += s->padding_statement.size / opb;
output_section_statement->bfd_section->_raw_size +=
s->padding_statement.size;
break;
fill_type fill;
bfd_vma dot;
{
+ unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
+ ldfile_output_machine);
+
for (; s != (lang_statement_union_type *) NULL; s = s->next)
{
switch (s->header.type)
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;
+ dot = os->bfd_section->vma + os->bfd_section->_raw_size / opb;
+
}
if (os->load_base)
{
if (value.valid_p == false)
einfo (_("%F%P: invalid data statement\n"));
}
- switch (s->data_statement.type)
- {
- case QUAD:
- case SQUAD:
- dot += QUAD_SIZE;
- break;
- case LONG:
- dot += LONG_SIZE;
- break;
- case SHORT:
- dot += SHORT_SIZE;
- break;
- case BYTE:
- dot += BYTE_SIZE;
- break;
- }
+ {
+ unsigned int size;
+ switch (s->data_statement.type)
+ {
+ default:
+ abort();
+ case QUAD:
+ case SQUAD:
+ size = QUAD_SIZE;
+ break;
+ case LONG:
+ size = LONG_SIZE;
+ break;
+ case SHORT:
+ size = SHORT_SIZE;
+ break;
+ case BYTE:
+ size = BYTE_SIZE;
+ break;
+ }
+ if (size < opb)
+ size = opb;
+ dot += size / opb;
+ }
break;
case lang_reloc_statement_enum:
if (value.valid_p == false)
einfo (_("%F%P: invalid reloc statement\n"));
}
- dot += bfd_get_reloc_size (s->reloc_statement.howto);
+ dot += bfd_get_reloc_size (s->reloc_statement.howto) / opb;
break;
case lang_input_section_enum:
asection *in = s->input_section.section;
if (in->_cooked_size != 0)
- dot += in->_cooked_size;
+ dot += in->_cooked_size / opb;
else
- dot += in->_raw_size;
+ dot += in->_raw_size / opb;
}
break;
break;
case lang_padding_statement_enum:
- dot += s->padding_statement.size;
+ dot += s->padding_statement.size / opb;
break;
case lang_group_statement_enum:
h = bfd_link_hash_lookup (link_info.hash, buf, false, false, true);
if (h != NULL && h->type == bfd_link_hash_undefined)
{
+ unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
+ ldfile_output_machine);
h->type = bfd_link_hash_defined;
if (s->_cooked_size != 0)
- h->u.def.value = s->_cooked_size;
+ h->u.def.value = s->_cooked_size / opb;
else
- h->u.def.value = s->_raw_size;
+ h->u.def.value = s->_raw_size / opb;
h->u.def.section = bfd_abs_section_ptr;
}
unsigned int power_of_two;
bfd_vma size;
asection *section;
+ unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
+ ldfile_output_machine);
if (h->type != bfd_link_hash_common)
return true;
section = h->u.c.p->section;
/* Increase the size of the section. */
- section->_cooked_size = ALIGN_N (section->_cooked_size,
- (bfd_size_type) (1 << power_of_two));
+ section->_cooked_size = ALIGN_N ((section->_cooked_size + opb - 1) / opb,
+ (bfd_size_type) (1 << power_of_two)) * opb;
/* Adjust the alignment if necessary. */
if (power_of_two > section->alignment_power)
return 0;
}
-void
+lang_output_section_statement_type *
lang_enter_output_section_statement (output_section_statement_name,
address_exp, sectype, block_value,
align, subalign, ebase)
"section alignment", 0));
os->load_base = ebase;
+ return os;
}
void
lang_add_wild (section_name, sections_sorted, filename, filenames_sorted,
- keep_sections, exclude_filename)
+ keep_sections, exclude_filename_list)
const char *const section_name;
boolean sections_sorted;
const char *const filename;
boolean filenames_sorted;
boolean keep_sections;
- const char *exclude_filename;
+ struct name_list *exclude_filename_list;
{
lang_wild_statement_type *new = new_stat (lang_wild_statement,
stat_ptr);
new->filename = filename;
new->filenames_sorted = filenames_sorted;
new->keep_sections = keep_sections;
- new->exclude_filename = exclude_filename;
+ new->exclude_filename_list = exclude_filename_list;
lang_list_init (&new->children);
}
}
void
-lang_leave_output_section_statement (fill, memspec, phdrs)
+lang_leave_output_section_statement (fill, memspec, phdrs, lma_memspec)
bfd_vma fill;
const char *memspec;
struct lang_output_section_phdr_list *phdrs;
+ const char *lma_memspec;
{
current_section->fill = fill;
current_section->region = lang_memory_region_lookup (memspec);
+ if (strcmp (lma_memspec, "*default*") != 0)
+ {
+ current_section->lma_region = lang_memory_region_lookup (lma_memspec);
+ /* if no runtime region has been given, but the load region has been,
+ use the load region */
+ if (strcmp (memspec, "*default*") == 0)
+ current_section->region = lang_memory_region_lookup (lma_memspec);
+ }
current_section->phdrs = phdrs;
stat_ptr = &statement_list;
}
h->u.def.value = 0;
else
h->u.def.value = (bfd_get_section_vma (output_bfd, sec)
- + bfd_section_size (output_bfd, sec));
+ + bfd_section_size (output_bfd, sec) /
+ bfd_octets_per_byte (output_bfd));
h->u.def.section = bfd_abs_section_ptr;
}
name = current_section->name;
- lang_leave_output_section_statement (fill, "*default*", phdrs);
+ lang_leave_output_section_statement (fill, "*default*",
+ phdrs, "*default*");
/* Define the magic symbols. */
looks through all the sections in the overlay and sets them. */
void
-lang_leave_overlay (fill, memspec, phdrs)
+lang_leave_overlay (fill, memspec, phdrs, lma_memspec)
bfd_vma fill;
const char *memspec;
struct lang_output_section_phdr_list *phdrs;
+ const char *lma_memspec;
{
lang_memory_region_type *region;
+ lang_memory_region_type *lma_region;
struct overlay_list *l;
struct lang_nocrossref *nocrossref;
else
region = lang_memory_region_lookup (memspec);
+ if (lma_memspec == NULL)
+ lma_region = NULL;
+ else
+ lma_region = lang_memory_region_lookup (lma_memspec);
+
nocrossref = NULL;
l = overlay_list;
l->os->fill = fill;
if (region != NULL && l->os->region == NULL)
l->os->region = region;
+ if (lma_region != NULL && l->os->lma_region == NULL)
+ l->os->lma_region = lma_region;
if (phdrs != NULL && l->os->phdrs == NULL)
l->os->phdrs = phdrs;