/* Object file "section" support for the BFD library.
- Copyright (C) 1990-2019 Free Software Foundation, Inc.
+ Copyright (C) 1990-2021 Free Software Foundation, Inc.
Written by Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
. {* A unique sequence number. *}
. unsigned int id;
.
+. {* A unique section number which can be used by assembler to
+. distinguish different sections with the same section name. *}
+. unsigned int section_id;
+.
. {* Which section in the bfd; 0..n-1 as sections are created in a bfd. *}
. unsigned int index;
.
. else up the line will take care of it later. *}
.#define SEC_LINKER_CREATED 0x100000
.
+. {* This section contains a section ID to distinguish different
+. sections with the same section name. *}
+.#define SEC_ASSEMBLER_SECTION_ID 0x100000
+.
. {* 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. *}
. {* This section contains vliw code. This is for Toshiba MeP only. *}
.#define SEC_MEP_VLIW 0x20000000
.
+. {* All symbols, sizes and relocations in this section are octets
+. instead of bytes. Required for DWARF debug sections as DWARF
+. information is organized in octets, not bytes. *}
+.#define SEC_ELF_OCTETS 0x40000000
+.
. {* Indicate that section has the no read flag set. This happens
. when memory read flag isn't set. *}
.#define SEC_COFF_NOREAD 0x40000000
. {* 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. *}
+. structs. The linked_to_symbol_name field is for ELF assembler
+. internal use. *}
. union {
. struct bfd_link_order *link_order;
. struct bfd_section *s;
+. const char *linked_to_symbol_name;
. } map_head, map_tail;
+. {* Points to the output section this section is already assigned to, if any.
+. This is used when support for non-contiguous memory regions is enabled. *}
+. struct bfd_section *already_assigned;
+.
.} asection;
.
.{* Relax table contains information about instructions which can
. int size;
.};
.
+.static inline const char *
+.bfd_section_name (const asection *sec)
+.{
+. return sec->name;
+.}
+.
+.static inline bfd_size_type
+.bfd_section_size (const asection *sec)
+.{
+. return sec->size;
+.}
+.
+.static inline bfd_vma
+.bfd_section_vma (const asection *sec)
+.{
+. return sec->vma;
+.}
+.
+.static inline bfd_vma
+.bfd_section_lma (const asection *sec)
+.{
+. return sec->lma;
+.}
+.
+.static inline unsigned int
+.bfd_section_alignment (const asection *sec)
+.{
+. return sec->alignment_power;
+.}
+.
+.static inline flagword
+.bfd_section_flags (const asection *sec)
+.{
+. return sec->flags;
+.}
+.
+.static inline void *
+.bfd_section_userdata (const asection *sec)
+.{
+. return sec->userdata;
+.}
+.static inline bool
+.bfd_is_com_section (const asection *sec)
+.{
+. return (sec->flags & SEC_IS_COMMON) != 0;
+.}
+.
.{* Note: the following are provided as inline functions rather than macros
. because not all callers use the return value. A macro implementation
. would use a comma expression, eg: "((ptr)->foo = val, TRUE)" and some
. compilers will complain about comma expressions that have no effect. *}
-.static inline bfd_boolean
+.static inline bool
.bfd_set_section_userdata (asection *sec, void *val)
.{
. sec->userdata = val;
-. return TRUE;
+. return true;
.}
.
-.static inline bfd_boolean
+.static inline bool
.bfd_set_section_vma (asection *sec, bfd_vma val)
.{
. sec->vma = sec->lma = val;
-. sec->user_set_vma = TRUE;
-. return TRUE;
+. sec->user_set_vma = true;
+. return true;
.}
.
-.static inline bfd_boolean
+.static inline bool
.bfd_set_section_lma (asection *sec, bfd_vma val)
.{
. sec->lma = val;
-. return TRUE;
+. return true;
.}
.
-.static inline bfd_boolean
+.static inline bool
.bfd_set_section_alignment (asection *sec, unsigned int val)
.{
. sec->alignment_power = val;
-. return TRUE;
+. return true;
.}
.
.{* These sections are global, and are managed by BFD. The application
.{* Pointer to the indirect section. *}
.#define bfd_ind_section_ptr (&_bfd_std_section[3])
.
-.#define bfd_is_und_section(sec) ((sec) == bfd_und_section_ptr)
-.#define bfd_is_abs_section(sec) ((sec) == bfd_abs_section_ptr)
-.#define bfd_is_ind_section(sec) ((sec) == bfd_ind_section_ptr)
-.
-.#define bfd_is_const_section(SEC) \
-. ( ((SEC) == bfd_abs_section_ptr) \
-. || ((SEC) == bfd_und_section_ptr) \
-. || ((SEC) == bfd_com_section_ptr) \
-. || ((SEC) == bfd_ind_section_ptr))
-.
-.{* 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_list_remove(ABFD, S) \
-. do \
-. { \
-. asection *_s = S; \
-. asection *_next = _s->next; \
-. asection *_prev = _s->prev; \
-. if (_prev) \
-. _prev->next = _next; \
-. else \
-. (ABFD)->sections = _next; \
-. if (_next) \
-. _next->prev = _prev; \
-. else \
-. (ABFD)->section_last = _prev; \
-. } \
-. while (0)
-.#define bfd_section_list_append(ABFD, S) \
-. do \
-. { \
-. asection *_s = S; \
-. bfd *_abfd = ABFD; \
-. _s->next = NULL; \
-. if (_abfd->section_last) \
-. { \
-. _s->prev = _abfd->section_last; \
-. _abfd->section_last->next = _s; \
-. } \
-. else \
-. { \
-. _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 \
-. { \
-. asection *_a = A; \
-. asection *_s = S; \
-. asection *_next = _a->next; \
-. _s->next = _next; \
-. _s->prev = _a; \
-. _a->next = _s; \
-. if (_next) \
-. _next->prev = _s; \
-. else \
-. (ABFD)->section_last = _s; \
-. } \
-. while (0)
-.#define bfd_section_list_insert_before(ABFD, B, S) \
-. do \
-. { \
-. asection *_b = B; \
-. asection *_s = S; \
-. asection *_prev = _b->prev; \
-. _s->prev = _prev; \
-. _s->next = _b; \
-. _b->prev = _s; \
-. if (_prev) \
-. _prev->next = _s; \
-. else \
-. (ABFD)->sections = _s; \
-. } \
-. while (0)
-.#define bfd_section_removed_from_list(ABFD, S) \
-. ((S)->next == NULL ? (ABFD)->section_last != (S) : (S)->next->prev != (S))
+.static inline bool
+.bfd_is_und_section (const asection *sec)
+.{
+. return sec == bfd_und_section_ptr;
+.}
+.
+.static inline bool
+.bfd_is_abs_section (const asection *sec)
+.{
+. return sec == bfd_abs_section_ptr;
+.}
+.
+.static inline bool
+.bfd_is_ind_section (const asection *sec)
+.{
+. return sec == bfd_ind_section_ptr;
+.}
+.
+.static inline bool
+.bfd_is_const_section (const asection *sec)
+.{
+. return (sec >= _bfd_std_section
+. && sec < _bfd_std_section + (sizeof (_bfd_std_section)
+. / sizeof (_bfd_std_section[0])));
+.}
+.
+.{* Return TRUE if input section SEC has been discarded. *}
+.static inline bool
+.discarded_section (const asection *sec)
+.{
+. return (!bfd_is_abs_section (sec)
+. && bfd_is_abs_section (sec->output_section)
+. && sec->sec_info_type != SEC_INFO_TYPE_MERGE
+. && sec->sec_info_type != SEC_INFO_TYPE_JUST_SYMS);
+.}
.
.#define BFD_FAKE_SECTION(SEC, SYM, NAME, IDX, FLAGS) \
-. {* name, id, index, next, prev, flags, user_set_vma, *} \
-. { NAME, IDX, 0, NULL, NULL, FLAGS, 0, \
+. {* name, id, section_id, index, next, prev, flags, user_set_vma, *} \
+. { NAME, IDX, 0, 0, NULL, NULL, FLAGS, 0, \
. \
-. {* linker_mark, linker_has_input, gc_mark, decompress_status, *} \
+. {* linker_mark, linker_has_input, gc_mark, decompress_status, *} \
. 0, 0, 1, 0, \
. \
-. {* segment_mark, sec_info_type, use_rela_p, *} \
+. {* segment_mark, sec_info_type, use_rela_p, *} \
. 0, 0, 0, \
. \
-. {* sec_flg0, sec_flg1, sec_flg2, sec_flg3, sec_flg4, sec_flg5, *} \
+. {* sec_flg0, sec_flg1, sec_flg2, sec_flg3, sec_flg4, sec_flg5, *} \
. 0, 0, 0, 0, 0, 0, \
. \
-. {* vma, lma, size, rawsize, compressed_size, relax, relax_count, *} \
+. {* vma, lma, size, rawsize, compressed_size, relax, relax_count, *} \
. 0, 0, 0, 0, 0, 0, 0, \
. \
-. {* output_offset, output_section, alignment_power, *} \
+. {* output_offset, output_section, alignment_power, *} \
. 0, &SEC, 0, \
. \
-. {* relocation, orelocation, reloc_count, filepos, rel_filepos, *} \
+. {* relocation, orelocation, reloc_count, filepos, rel_filepos, *} \
. NULL, NULL, 0, 0, 0, \
. \
-. {* line_filepos, userdata, contents, lineno, lineno_count, *} \
+. {* line_filepos, userdata, contents, lineno, lineno_count, *} \
. 0, NULL, NULL, NULL, 0, \
. \
-. {* entsize, kept_section, moving_line_filepos, *} \
-. 0, NULL, 0, \
+. {* entsize, kept_section, moving_line_filepos, *} \
+. 0, NULL, 0, \
. \
-. {* target_index, used_by_bfd, constructor_chain, owner, *} \
+. {* target_index, used_by_bfd, constructor_chain, owner, *} \
. 0, NULL, NULL, NULL, \
. \
-. {* symbol, symbol_ptr_ptr, *} \
+. {* symbol, symbol_ptr_ptr, *} \
. (struct bfd_symbol *) SYM, &SEC.symbol, \
. \
-. {* map_head, map_tail *} \
-. { NULL }, { NULL } \
+. {* map_head, map_tail, already_assigned *} \
+. { NULL }, { NULL }, NULL \
+. \
. }
.
.{* We use a macro to initialize the static asymbol structures because
is useful for things like relocs which are relative to the base
of a section. */
-bfd_boolean
+bool
_bfd_generic_new_section_hook (bfd *abfd, asection *newsect)
{
newsect->symbol = bfd_make_empty_symbol (abfd);
if (newsect->symbol == NULL)
- return FALSE;
+ 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;
+ return true;
}
unsigned int _bfd_section_id = 0x10; /* id 0 to 3 used by STD_SECTION. */
{
struct section_hash_entry *sh;
- sh = section_hash_lookup (&abfd->section_htab, name, FALSE, FALSE);
+ if (name == NULL)
+ return NULL;
+
+ sh = section_hash_lookup (&abfd->section_htab, name, false, false);
if (sh != NULL)
return &sh->section;
asection *bfd_get_section_by_name_if
(bfd *abfd,
const char *name,
- bfd_boolean (*func) (bfd *abfd, asection *sect, void *obj),
+ bool (*func) (bfd *abfd, asection *sect, void *obj),
void *obj);
DESCRIPTION
asection *
bfd_get_section_by_name_if (bfd *abfd, const char *name,
- bfd_boolean (*operation) (bfd *,
- asection *,
- void *),
+ bool (*operation) (bfd *, asection *, void *),
void *user_storage)
{
struct section_hash_entry *sh;
unsigned long hash;
- sh = section_hash_lookup (&abfd->section_htab, name, FALSE, FALSE);
+ if (name == NULL)
+ return NULL;
+
+ sh = section_hash_lookup (&abfd->section_htab, name, false, false);
if (sh == NULL)
return NULL;
abort ();
sprintf (sname + len, ".%d", num++);
}
- while (section_hash_lookup (&abfd->section_htab, sname, FALSE, FALSE));
+ while (section_hash_lookup (&abfd->section_htab, sname, false, false));
if (count != NULL)
*count = num;
{
struct section_hash_entry *sh;
- sh = section_hash_lookup (&abfd->section_htab, name, TRUE, FALSE);
+ sh = section_hash_lookup (&abfd->section_htab, name, true, false);
if (sh == NULL)
return NULL;
return NULL;
}
- sh = section_hash_lookup (&abfd->section_htab, name, TRUE, FALSE);
+ sh = section_hash_lookup (&abfd->section_htab, name, true, false);
if (sh == NULL)
return NULL;
|| strcmp (name, BFD_IND_SECTION_NAME) == 0)
return NULL;
- sh = section_hash_lookup (&abfd->section_htab, name, TRUE, FALSE);
+ sh = section_hash_lookup (&abfd->section_htab, name, true, false);
if (sh == NULL)
return NULL;
bfd_set_section_flags
SYNOPSIS
- bfd_boolean bfd_set_section_flags (asection *sec, flagword flags);
+ bool bfd_set_section_flags (asection *sec, flagword flags);
DESCRIPTION
Set the attributes of the section @var{sec} to the value @var{flags}.
*/
-bfd_boolean
+bool
bfd_set_section_flags (asection *section, flagword flags)
{
section->flags = flags;
- return TRUE;
+ return true;
}
/*
SYNOPSIS
asection *bfd_sections_find_if
(bfd *abfd,
- bfd_boolean (*operation) (bfd *abfd, asection *sect, void *obj),
+ bool (*operation) (bfd *abfd, asection *sect, void *obj),
void *obj);
DESCRIPTION
asection *
bfd_sections_find_if (bfd *abfd,
- bfd_boolean (*operation) (bfd *, asection *, void *),
+ bool (*operation) (bfd *, asection *, void *),
void *user_storage)
{
asection *sect;
bfd_set_section_size
SYNOPSIS
- bfd_boolean bfd_set_section_size (asection *sec, bfd_size_type val);
+ bool bfd_set_section_size (asection *sec, bfd_size_type val);
DESCRIPTION
Set @var{sec} to the size @var{val}. If the operation is
*/
-bfd_boolean
+bool
bfd_set_section_size (asection *sec, bfd_size_type val)
{
/* Once you've started writing to any section you cannot create or change
if (sec->owner == NULL || sec->owner->output_has_begun)
{
bfd_set_error (bfd_error_invalid_operation);
- return FALSE;
+ return false;
}
sec->size = val;
- return TRUE;
+ return true;
}
/*
bfd_set_section_contents
SYNOPSIS
- bfd_boolean bfd_set_section_contents
+ bool bfd_set_section_contents
(bfd *abfd, asection *section, const void *data,
file_ptr offset, bfd_size_type count);
*/
-bfd_boolean
+bool
bfd_set_section_contents (bfd *abfd,
sec_ptr section,
const void *location,
if (!(bfd_section_flags (section) & SEC_HAS_CONTENTS))
{
bfd_set_error (bfd_error_no_contents);
- return FALSE;
+ return false;
}
sz = section->size;
if ((bfd_size_type) offset > sz
- || count > sz
- || offset + count > sz
+ || count > sz - offset
|| count != (size_t) count)
{
bfd_set_error (bfd_error_bad_value);
- return FALSE;
+ return false;
}
if (!bfd_write_p (abfd))
{
bfd_set_error (bfd_error_invalid_operation);
- return FALSE;
+ return false;
}
/* Record a copy of the data in memory if desired. */
if (BFD_SEND (abfd, _bfd_set_section_contents,
(abfd, section, location, offset, count)))
{
- abfd->output_has_begun = TRUE;
- return TRUE;
+ abfd->output_has_begun = true;
+ return true;
}
- return FALSE;
+ return false;
}
/*
bfd_get_section_contents
SYNOPSIS
- bfd_boolean bfd_get_section_contents
+ bool bfd_get_section_contents
(bfd *abfd, asection *section, void *location, file_ptr offset,
bfd_size_type count);
<<FALSE>>.
*/
-bfd_boolean
+bool
bfd_get_section_contents (bfd *abfd,
sec_ptr section,
void *location,
if (section->flags & SEC_CONSTRUCTOR)
{
memset (location, 0, (size_t) count);
- return TRUE;
+ return true;
}
if (abfd->direction != write_direction && section->rawsize != 0)
else
sz = section->size;
if ((bfd_size_type) offset > sz
- || count > sz
- || offset + count > sz
+ || count > sz - offset
|| count != (size_t) count)
{
bfd_set_error (bfd_error_bad_value);
- return FALSE;
+ return false;
}
if (count == 0)
/* Don't bother. */
- return TRUE;
+ return true;
if ((section->flags & SEC_HAS_CONTENTS) == 0)
{
memset (location, 0, (size_t) count);
- return TRUE;
+ return true;
}
if ((section->flags & SEC_IN_MEMORY) != 0)
error code. */
section->flags &= ~ SEC_IN_MEMORY;
bfd_set_error (bfd_error_invalid_operation);
- return FALSE;
+ return false;
}
memmove (location, section->contents + offset, (size_t) count);
- return TRUE;
+ return true;
}
return BFD_SEND (abfd, _bfd_get_section_contents,
bfd_malloc_and_get_section
SYNOPSIS
- bfd_boolean bfd_malloc_and_get_section
+ bool bfd_malloc_and_get_section
(bfd *abfd, asection *section, bfd_byte **buf);
DESCRIPTION
into a buffer, *@var{buf}, malloc'd by this function.
*/
-bfd_boolean
+bool
bfd_malloc_and_get_section (bfd *abfd, sec_ptr sec, bfd_byte **buf)
{
*buf = NULL;
bfd_copy_private_section_data
SYNOPSIS
- bfd_boolean bfd_copy_private_section_data
+ bool bfd_copy_private_section_data
(bfd *ibfd, asection *isec, bfd *obfd, asection *osec);
DESCRIPTION
bfd_generic_is_group_section
SYNOPSIS
- bfd_boolean bfd_generic_is_group_section (bfd *, const asection *sec);
+ bool bfd_generic_is_group_section (bfd *, const asection *sec);
DESCRIPTION
Returns TRUE if @var{sec} is a member of a group.
*/
-bfd_boolean
+bool
bfd_generic_is_group_section (bfd *abfd ATTRIBUTE_UNUSED,
const asection *sec ATTRIBUTE_UNUSED)
{
- return FALSE;
+ return false;
}
/*
bfd_generic_discard_group
SYNOPSIS
- bfd_boolean bfd_generic_discard_group (bfd *abfd, asection *group);
+ bool bfd_generic_discard_group (bfd *abfd, asection *group);
DESCRIPTION
Remove all members of @var{group} from the output.
*/
-bfd_boolean
+bool
bfd_generic_discard_group (bfd *abfd ATTRIBUTE_UNUSED,
asection *group ATTRIBUTE_UNUSED)
{
- return TRUE;
+ return true;
}
-bfd_boolean
+bool
_bfd_nowrite_set_section_contents (bfd *abfd,
sec_ptr section ATTRIBUTE_UNUSED,
const void *location ATTRIBUTE_UNUSED,