/* 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, 2006
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, 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"
.
. {* If SEC_LINK_ONCE is set, this bitfield describes how the linker
. should handle duplicate sections. *}
-.#define SEC_LINK_DUPLICATES 0x40000
+.#define SEC_LINK_DUPLICATES 0xc0000
.
. {* This value for SEC_LINK_DUPLICATES means that duplicate
. sections with the same name should simply be discarded. *}
. {* This value for SEC_LINK_DUPLICATES means that the linker
. should warn if there are any duplicate sections, although
. it should still only link one copy. *}
-.#define SEC_LINK_DUPLICATES_ONE_ONLY 0x80000
+.#define SEC_LINK_DUPLICATES_ONE_ONLY 0x40000
.
. {* This value for SEC_LINK_DUPLICATES means that the linker
. should warn if any duplicate sections are a different size. *}
-.#define SEC_LINK_DUPLICATES_SAME_SIZE 0x100000
+.#define SEC_LINK_DUPLICATES_SAME_SIZE 0x80000
.
. {* This value for SEC_LINK_DUPLICATES means that the linker
. should warn if any duplicate sections contain different
. relocation or other arcane processing. It is skipped when
. going through the first-pass output, trusting that someone
. else up the line will take care of it later. *}
-.#define SEC_LINKER_CREATED 0x200000
+.#define SEC_LINKER_CREATED 0x100000
.
-. {* This section should not be subject to garbage collection. *}
-.#define SEC_KEEP 0x400000
+. {* 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 0x200000
.
. {* This section contains "short" data, and should be placed
. "near" the GP. *}
-.#define SEC_SMALL_DATA 0x800000
+.#define SEC_SMALL_DATA 0x400000
.
. {* Attempt to merge identical entities in the section.
. Entity size is given in the entsize field. *}
-.#define SEC_MERGE 0x1000000
+.#define SEC_MERGE 0x800000
.
. {* If given with SEC_MERGE, entities to merge are zero terminated
. strings where entsize specifies character size instead of fixed
. size entries. *}
-.#define SEC_STRINGS 0x2000000
+.#define SEC_STRINGS 0x1000000
.
. {* This section contains data about section groups. *}
-.#define SEC_GROUP 0x4000000
+.#define SEC_GROUP 0x2000000
.
. {* The section is a COFF shared library section. This flag is
. only for the linker. If this type of section appears in
. might be cleaner to have some more general mechanism to
. allow the back end to control what the linker does with
. sections. *}
-.#define SEC_COFF_SHARED_LIBRARY 0x10000000
+.#define SEC_COFF_SHARED_LIBRARY 0x4000000
.
. {* This section contains data which may be shared with other
. executables or shared objects. This is for COFF only. *}
-.#define SEC_COFF_SHARED 0x20000000
+.#define SEC_COFF_SHARED 0x8000000
.
. {* When a section with this flag is being linked, then if the size of
. the input section is less than a page, it should not cross a page
. boundary. If the size of the input section is one page or more,
. it should be aligned on a page boundary. This is for TI
. TMS320C54X only. *}
-.#define SEC_TIC54X_BLOCK 0x40000000
+.#define SEC_TIC54X_BLOCK 0x10000000
.
. {* Conditionally link this section; do not link if there are no
. references found to any symbol in the section. This is for TI
. TMS320C54X only. *}
-.#define SEC_TIC54X_CLINK 0x80000000
+.#define SEC_TIC54X_CLINK 0x20000000
+.
+. {* Indicate that section has the no read flag set. This happens
+. when memory read flag isn't set. *}
+.#define SEC_COFF_NOREAD 0x40000000
.
. {* End of section flags. *}
.
. output sections that have an input section. *}
. unsigned int linker_has_input : 1;
.
-. {* Mark flags used by some linker backends for garbage collection. *}
+. {* Mark flag used by some linker backends for garbage collection. *}
. unsigned int gc_mark : 1;
-. unsigned int gc_mark_from_eh : 1;
.
. {* The following flags are used by the ELF linker. *}
.
. {* Nonzero if this section has TLS related relocations. *}
. unsigned int has_tls_reloc:1;
.
+. {* Nonzero if this section has a call to __tls_get_addr. *}
+. unsigned int has_tls_get_addr_call:1;
+.
. {* Nonzero if this section has a gp reloc. *}
. unsigned int has_gp_reloc:1;
.
. 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;
.
+. {* Relaxation table. *}
+. struct relax_table *relax;
+.
+. {* Count of used relaxation table entries. *}
+. int relax_count;
+.
+.
. {* If this section is going to be output, then this value is the
. offset in *bytes* into the output section of the first byte in the
. input section (byte ==> smallest addressable unit on the
. } map_head, map_tail;
.} asection;
.
+.{* Relax table contains information about instructions which can
+. be removed by relaxation -- replacing a long address with a
+. short address. *}
+.struct relax_table {
+. {* Address where bytes may be deleted. *}
+. bfd_vma addr;
+.
+. {* Number of bytes to be deleted. *}
+. int size;
+.};
+.
.{* These sections are global, and are managed by BFD. The application
. and target back end are not permitted to change the values in
. these sections. New code should use the section_ptr macros rather
. || ((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. *}
.#define bfd_section_removed_from_list(ABFD, S) \
. ((S)->next == NULL ? (ABFD)->section_last != (S) : (S)->next->prev != (S))
.
-.#define BFD_FAKE_SECTION(SEC, FLAGS, SYM, SYM_PTR, NAME, IDX) \
+.#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, gc_mark_from_eh, *} \
-. 0, 0, 1, 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, \
+. {* has_tls_get_addr_call, has_gp_reloc, need_finalize_relax, *} \
+. 0, 0, 0, \
. \
-. {* vma, lma, size, rawsize *} \
-. 0, 0, 0, 0, \
+. {* reloc_done, vma, lma, size, rawsize, relax, relax_count, *} \
+. 0, 0, 0, 0, 0, 0, 0, \
. \
. {* output_offset, output_section, alignment_power, *} \
. 0, (struct bfd_section *) &SEC, 0, \
. {* target_index, used_by_bfd, constructor_chain, owner, *} \
. 0, NULL, NULL, NULL, \
. \
-. {* symbol, *} \
-. (struct bfd_symbol *) SYM, \
-. \
-. {* symbol_ptr_ptr, *} \
-. (struct bfd_symbol **) SYM_PTR, \
+. {* 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 = BFD_FAKE_SECTION(SEC, FLAGS, &global_syms[IDX], &SYM, \
+#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
/* Initialize an entry in the section hash table. */
((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;
char *sname;
len = strlen (templat);
- sname = bfd_malloc (len + 8);
+ sname = (char *) bfd_malloc (len + 8);
if (sname == NULL)
return NULL;
memcpy (sname, templat, len);
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;
}
/*
if ((section->flags & SEC_IN_MEMORY) != 0)
{
+ if (section->contents == NULL)
+ {
+ /* This can happen because of errors earlier on in the linking process.
+ We do not want to seg-fault here, so clear the flag and return an
+ error code. */
+ section->flags &= ~ SEC_IN_MEMORY;
+ bfd_set_error (bfd_error_invalid_operation);
+ return FALSE;
+ }
+
memcpy (location, section->contents + offset, (size_t) count);
return TRUE;
}
if (sz == 0)
return TRUE;
- p = bfd_malloc (sec->rawsize > sec->size ? sec->rawsize : sec->size);
+ p = (bfd_byte *)
+ bfd_malloc (sec->rawsize > sec->size ? sec->rawsize : sec->size);
if (p == NULL)
return FALSE;
*buf = p;