/* Object file "section" support for the BFD library.
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
Written by Cygnus Support.
-This file is part of BFD, the Binary File Descriptor library.
+ This file is part of BFD, the Binary File Descriptor library.
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
/*
SECTION
*/
-#include "bfd.h"
#include "sysdep.h"
+#include "bfd.h"
#include "libbfd.h"
#include "bfdlink.h"
. else up the line will take care of it later. *}
.#define SEC_LINKER_CREATED 0x200000
.
-. {* This section should not be subject to garbage collection. *}
+. {* This section should not be subject to garbage collection.
+. Also set to inform the linker that this section should not be
+. listed in the link map as discarded. *}
.#define SEC_KEEP 0x400000
.
. {* This section contains "short" data, and should be placed
. output sections that have an input section. *}
. unsigned int linker_has_input : 1;
.
-. {* A mark flag used by some linker backends for garbage collection. *}
+. {* Mark flag used by some linker backends for garbage collection. *}
. unsigned int gc_mark : 1;
.
. {* The following flags are used by the ELF linker. *}
. bfd_size_type size;
.
. {* For input sections, the original size on disk of the section, in
-. octets. This field is used by the linker relaxation code. It is
-. currently only set for sections where the linker relaxation scheme
-. doesn't cache altered section and reloc contents (stabs, eh_frame,
-. SEC_MERGE, some coff relaxing targets), and thus the original size
-. needs to be kept to read the section multiple times.
-. For output sections, rawsize holds the section size calculated on
-. a previous linker relaxation pass. *}
+. octets. This field should be set for any section whose size is
+. changed by linker relaxation. It is required for sections where
+. the linker relaxation scheme doesn't cache altered section and
+. reloc contents (stabs, eh_frame, SEC_MERGE, some coff relaxing
+. targets), and thus the original size needs to be kept to read the
+. section multiple times. For output sections, rawsize holds the
+. section size calculated on a previous linker relaxation pass. *}
. bfd_size_type rawsize;
.
. {* If this section is going to be output, then this value is the
. struct bfd_symbol *symbol;
. struct bfd_symbol **symbol_ptr_ptr;
.
-. struct bfd_link_order *link_order_head;
-. struct bfd_link_order *link_order_tail;
+. {* Early in the link process, map_head and map_tail are used to build
+. a list of input sections attached to an output section. Later,
+. output sections use these fields for a list of bfd_link_order
+. structs. *}
+. union {
+. struct bfd_link_order *link_order;
+. struct bfd_section *s;
+. } map_head, map_tail;
.} asection;
.
.{* These sections are global, and are managed by BFD. The application
. || ((SEC) == bfd_com_section_ptr) \
. || ((SEC) == bfd_ind_section_ptr))
.
-.extern const struct bfd_symbol * const bfd_abs_symbol;
-.extern const struct bfd_symbol * const bfd_com_symbol;
-.extern const struct bfd_symbol * const bfd_und_symbol;
-.extern const struct bfd_symbol * const bfd_ind_symbol;
-.
.{* Macros to handle insertion and deletion of a bfd's sections. These
. only handle the list pointers, ie. do not adjust section_count,
. target_index etc. *}
. else \
. (ABFD)->sections = _next; \
. if (_next) \
-. { \
-. _next->prev = _prev; \
-. _s->next = NULL; \
-. } \
+. _next->prev = _prev; \
. else \
. (ABFD)->section_last = _prev; \
. } \
. _abfd->section_last->next = _s; \
. } \
. else \
-. _abfd->sections = _s; \
+. { \
+. _s->prev = NULL; \
+. _abfd->sections = _s; \
+. } \
. _abfd->section_last = _s; \
. } \
. while (0)
+.#define bfd_section_list_prepend(ABFD, S) \
+. do \
+. { \
+. asection *_s = S; \
+. bfd *_abfd = ABFD; \
+. _s->prev = NULL; \
+. if (_abfd->sections) \
+. { \
+. _s->next = _abfd->sections; \
+. _abfd->sections->prev = _s; \
+. } \
+. else \
+. { \
+. _s->next = NULL; \
+. _abfd->section_last = _s; \
+. } \
+. _abfd->sections = _s; \
+. } \
+. while (0)
.#define bfd_section_list_insert_after(ABFD, A, S) \
. do \
. { \
. _s->prev = _a; \
. _a->next = _s; \
. if (_next) \
-. _s->next->prev = _s; \
+. _next->prev = _s; \
. else \
. (ABFD)->section_last = _s; \
. } \
. } \
. while (0)
.#define bfd_section_removed_from_list(ABFD, S) \
-. ((S)->next == NULL && (S) != (ABFD)->section_last)
+. ((S)->next == NULL ? (ABFD)->section_last != (S) : (S)->next->prev != (S))
+.
+.#define BFD_FAKE_SECTION(SEC, FLAGS, SYM, NAME, IDX) \
+. {* name, id, index, next, prev, flags, user_set_vma, *} \
+. { NAME, IDX, 0, NULL, NULL, FLAGS, 0, \
+. \
+. {* linker_mark, linker_has_input, gc_mark, *} \
+. 0, 0, 1, \
+. \
+. {* segment_mark, sec_info_type, use_rela_p, has_tls_reloc, *} \
+. 0, 0, 0, 0, \
+. \
+. {* has_gp_reloc, need_finalize_relax, reloc_done, *} \
+. 0, 0, 0, \
+. \
+. {* vma, lma, size, rawsize *} \
+. 0, 0, 0, 0, \
+. \
+. {* output_offset, output_section, alignment_power, *} \
+. 0, (struct bfd_section *) &SEC, 0, \
+. \
+. {* relocation, orelocation, reloc_count, filepos, rel_filepos, *} \
+. NULL, NULL, 0, 0, 0, \
+. \
+. {* line_filepos, userdata, contents, lineno, lineno_count, *} \
+. 0, NULL, NULL, NULL, 0, \
+. \
+. {* entsize, kept_section, moving_line_filepos, *} \
+. 0, NULL, 0, \
+. \
+. {* target_index, used_by_bfd, constructor_chain, owner, *} \
+. 0, NULL, NULL, NULL, \
+. \
+. {* symbol, symbol_ptr_ptr, *} \
+. (struct bfd_symbol *) SYM, &SEC.symbol, \
+. \
+. {* map_head, map_tail *} \
+. { NULL }, { NULL } \
+. }
.
*/
GLOBAL_SYM_INIT (BFD_IND_SECTION_NAME, &bfd_ind_section)
};
-#define STD_SECTION(SEC, FLAGS, SYM, NAME, IDX) \
- const asymbol * const SYM = (asymbol *) &global_syms[IDX]; \
- asection SEC = \
- /* name, id, index, next, prev, flags, user_set_vma, */ \
- { NAME, IDX, 0, NULL, NULL, FLAGS, 0, \
- \
- /* linker_mark, linker_has_input, gc_mark, segment_mark, */ \
- 0, 0, 1, 0, \
- \
- /* sec_info_type, use_rela_p, has_tls_reloc, has_gp_reloc, */ \
- 0, 0, 0, 0, \
- \
- /* need_finalize_relax, reloc_done, */ \
- 0, 0, \
- \
- /* vma, lma, size, rawsize */ \
- 0, 0, 0, 0, \
- \
- /* output_offset, output_section, alignment_power, */ \
- 0, (struct bfd_section *) &SEC, 0, \
- \
- /* relocation, orelocation, reloc_count, filepos, rel_filepos, */ \
- NULL, NULL, 0, 0, 0, \
- \
- /* line_filepos, userdata, contents, lineno, lineno_count, */ \
- 0, NULL, NULL, NULL, 0, \
- \
- /* entsize, kept_section, moving_line_filepos, */ \
- 0, NULL, 0, \
- \
- /* target_index, used_by_bfd, constructor_chain, owner, */ \
- 0, NULL, NULL, NULL, \
- \
- /* symbol, */ \
- (struct bfd_symbol *) &global_syms[IDX], \
- \
- /* symbol_ptr_ptr, */ \
- (struct bfd_symbol **) &SYM, \
- \
- /* link_order_head, link_order_tail */ \
- NULL, NULL \
- }
+#define STD_SECTION(SEC, FLAGS, NAME, IDX) \
+ asection SEC = BFD_FAKE_SECTION(SEC, FLAGS, &global_syms[IDX], \
+ NAME, IDX)
-STD_SECTION (bfd_com_section, SEC_IS_COMMON, bfd_com_symbol,
- BFD_COM_SECTION_NAME, 0);
-STD_SECTION (bfd_und_section, 0, bfd_und_symbol, BFD_UND_SECTION_NAME, 1);
-STD_SECTION (bfd_abs_section, 0, bfd_abs_symbol, BFD_ABS_SECTION_NAME, 2);
-STD_SECTION (bfd_ind_section, 0, bfd_ind_symbol, BFD_IND_SECTION_NAME, 3);
+STD_SECTION (bfd_com_section, SEC_IS_COMMON, BFD_COM_SECTION_NAME, 0);
+STD_SECTION (bfd_und_section, 0, BFD_UND_SECTION_NAME, 1);
+STD_SECTION (bfd_abs_section, 0, BFD_ABS_SECTION_NAME, 2);
+STD_SECTION (bfd_ind_section, 0, BFD_IND_SECTION_NAME, 3);
#undef STD_SECTION
-struct section_hash_entry
-{
- struct bfd_hash_entry root;
- asection section;
-};
-
/* Initialize an entry in the section hash table. */
struct bfd_hash_entry *
((struct section_hash_entry *) \
bfd_hash_lookup ((table), (string), (create), (copy)))
-/* Initializes a new section. NEWSECT->NAME is already set. */
+/* Create a symbol whose only job is to point to this section. This
+ is useful for things like relocs which are relative to the base
+ of a section. */
-static asection *
-bfd_section_init (bfd *abfd, asection *newsect)
+bfd_boolean
+_bfd_generic_new_section_hook (bfd *abfd, asection *newsect)
{
- static int section_id = 0x10; /* id 0 to 3 used by STD_SECTION. */
-
- newsect->id = section_id;
- newsect->index = abfd->section_count;
- newsect->owner = abfd;
-
- /* Create a symbol whose only job is to point to this section. This
- is useful for things like relocs which are relative to the base
- of a section. */
newsect->symbol = bfd_make_empty_symbol (abfd);
if (newsect->symbol == NULL)
- return NULL;
+ return FALSE;
newsect->symbol->name = newsect->name;
newsect->symbol->value = 0;
newsect->symbol->flags = BSF_SECTION_SYM;
newsect->symbol_ptr_ptr = &newsect->symbol;
+ return TRUE;
+}
+
+/* Initializes a new section. NEWSECT->NAME is already set. */
+
+static asection *
+bfd_section_init (bfd *abfd, asection *newsect)
+{
+ static int section_id = 0x10; /* id 0 to 3 used by STD_SECTION. */
+
+ newsect->id = section_id;
+ newsect->index = abfd->section_count;
+ newsect->owner = abfd;
if (! BFD_SEND (abfd, _new_section_hook, (abfd, newsect)))
return NULL;
asection *
bfd_make_section_old_way (bfd *abfd, const char *name)
{
- struct section_hash_entry *sh;
asection *newsect;
if (abfd->output_has_begun)
}
if (strcmp (name, BFD_ABS_SECTION_NAME) == 0)
- return bfd_abs_section_ptr;
-
- if (strcmp (name, BFD_COM_SECTION_NAME) == 0)
- return bfd_com_section_ptr;
-
- if (strcmp (name, BFD_UND_SECTION_NAME) == 0)
- return bfd_und_section_ptr;
+ newsect = bfd_abs_section_ptr;
+ else if (strcmp (name, BFD_COM_SECTION_NAME) == 0)
+ newsect = bfd_com_section_ptr;
+ else if (strcmp (name, BFD_UND_SECTION_NAME) == 0)
+ newsect = bfd_und_section_ptr;
+ else if (strcmp (name, BFD_IND_SECTION_NAME) == 0)
+ newsect = bfd_ind_section_ptr;
+ else
+ {
+ struct section_hash_entry *sh;
- if (strcmp (name, BFD_IND_SECTION_NAME) == 0)
- return bfd_ind_section_ptr;
+ sh = section_hash_lookup (&abfd->section_htab, name, TRUE, FALSE);
+ if (sh == NULL)
+ return NULL;
- sh = section_hash_lookup (&abfd->section_htab, name, TRUE, FALSE);
- if (sh == NULL)
- return NULL;
+ newsect = &sh->section;
+ if (newsect->name != NULL)
+ {
+ /* Section already exists. */
+ return newsect;
+ }
- newsect = &sh->section;
- if (newsect->name != NULL)
- {
- /* Section already exists. */
- return newsect;
+ newsect->name = name;
+ return bfd_section_init (abfd, newsect);
}
- newsect->name = name;
- return bfd_section_init (abfd, newsect);
+ /* Call new_section_hook when "creating" the standard abs, com, und
+ and ind sections to tack on format specific section data.
+ Also, create a proper section symbol. */
+ if (! BFD_SEND (abfd, _new_section_hook, (abfd, newsect)))
+ return NULL;
+ return newsect;
}
/*
FUNCTION
- bfd_make_section_anyway
+ bfd_make_section_anyway_with_flags
SYNOPSIS
- asection *bfd_make_section_anyway (bfd *abfd, const char *name);
+ asection *bfd_make_section_anyway_with_flags
+ (bfd *abfd, const char *name, flagword flags);
DESCRIPTION
Create a new empty section called @var{name} and attach it to the end of
the chain of sections for @var{abfd}. Create a new section even if there
- is already a section with that name.
+ is already a section with that name. Also set the attributes of the
+ new section to the value @var{flags}.
Return <<NULL>> and set <<bfd_error>> on error; possible errors are:
o <<bfd_error_invalid_operation>> - If output has already started for @var{abfd}.
*/
sec_ptr
-bfd_make_section_anyway (bfd *abfd, const char *name)
+bfd_make_section_anyway_with_flags (bfd *abfd, const char *name,
+ flagword flags)
{
struct section_hash_entry *sh;
asection *newsect;
newsect = &new_sh->section;
}
+ newsect->flags = flags;
newsect->name = name;
return bfd_section_init (abfd, newsect);
}
/*
FUNCTION
- bfd_make_section
+ bfd_make_section_anyway
SYNOPSIS
- asection *bfd_make_section (bfd *, const char *name);
+ asection *bfd_make_section_anyway (bfd *abfd, const char *name);
+
+DESCRIPTION
+ Create a new empty section called @var{name} and attach it to the end of
+ the chain of sections for @var{abfd}. Create a new section even if there
+ is already a section with that name.
+
+ Return <<NULL>> and set <<bfd_error>> on error; possible errors are:
+ o <<bfd_error_invalid_operation>> - If output has already started for @var{abfd}.
+ o <<bfd_error_no_memory>> - If memory allocation fails.
+*/
+
+sec_ptr
+bfd_make_section_anyway (bfd *abfd, const char *name)
+{
+ return bfd_make_section_anyway_with_flags (abfd, name, 0);
+}
+
+/*
+FUNCTION
+ bfd_make_section_with_flags
+
+SYNOPSIS
+ asection *bfd_make_section_with_flags
+ (bfd *, const char *name, flagword flags);
DESCRIPTION
Like <<bfd_make_section_anyway>>, but return <<NULL>> (without calling
bfd_set_error ()) without changing the section chain if there is already a
- section named @var{name}. If there is an error, return <<NULL>> and set
+ section named @var{name}. Also set the attributes of the new section to
+ the value @var{flags}. If there is an error, return <<NULL>> and set
<<bfd_error>>.
*/
asection *
-bfd_make_section (bfd *abfd, const char *name)
+bfd_make_section_with_flags (bfd *abfd, const char *name,
+ flagword flags)
{
struct section_hash_entry *sh;
asection *newsect;
}
newsect->name = name;
+ newsect->flags = flags;
return bfd_section_init (abfd, newsect);
}
+/*
+FUNCTION
+ bfd_make_section
+
+SYNOPSIS
+ asection *bfd_make_section (bfd *, const char *name);
+
+DESCRIPTION
+ Like <<bfd_make_section_anyway>>, but return <<NULL>> (without calling
+ bfd_set_error ()) without changing the section chain if there is already a
+ section named @var{name}. If there is an error, return <<NULL>> and set
+ <<bfd_error>>.
+*/
+
+asection *
+bfd_make_section (bfd *abfd, const char *name)
+{
+ return bfd_make_section_with_flags (abfd, name, 0);
+}
+
/*
FUNCTION
bfd_set_section_flags
return FALSE;
}
- switch (abfd->direction)
+ if (!bfd_write_p (abfd))
{
- case read_direction:
- case no_direction:
bfd_set_error (bfd_error_invalid_operation);
return FALSE;
-
- case write_direction:
- break;
-
- case both_direction:
- /* File is opened for update. `output_has_begun' some time ago when
- the file was created. Do not recompute sections sizes or alignments
- in _bfd_set_section_content. */
- abfd->output_has_begun = TRUE;
- break;
}
/* Record a copy of the data in memory if desired. */
. (ibfd, isection, obfd, osection))
*/
-/*
-FUNCTION
- _bfd_strip_section_from_output
-
-SYNOPSIS
- void _bfd_strip_section_from_output
- (struct bfd_link_info *info, asection *section);
-
-DESCRIPTION
- Remove @var{section} from the output. If the output section
- becomes empty, remove it from the output bfd.
-
- This function won't actually do anything except twiddle flags
- if called too late in the linking process, when it's not safe
- to remove sections.
-*/
-void
-_bfd_strip_section_from_output (struct bfd_link_info *info, asection *s)
-{
- asection *os;
- asection *is;
- bfd *abfd;
-
- s->flags |= SEC_EXCLUDE;
-
- /* If the section wasn't assigned to an output section, or the
- section has been discarded by the linker script, there's nothing
- more to do. */
- os = s->output_section;
- if (os == NULL || os->owner == NULL)
- return;
-
- /* If the output section has other (non-excluded) input sections, we
- can't remove it. */
- for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link_next)
- for (is = abfd->sections; is != NULL; is = is->next)
- if (is->output_section == os && (is->flags & SEC_EXCLUDE) == 0)
- return;
-
- /* If the output section is empty, flag it for removal too.
- See ldlang.c:strip_excluded_output_sections for the action. */
- os->flags |= SEC_EXCLUDE;
-}
-
/*
FUNCTION
bfd_generic_is_group_section