diff options
Diffstat (limited to 'contrib/binutils/bfd/section.c')
-rw-r--r-- | contrib/binutils/bfd/section.c | 196 |
1 files changed, 174 insertions, 22 deletions
diff --git a/contrib/binutils/bfd/section.c b/contrib/binutils/bfd/section.c index 787855c..b3b7608 100644 --- a/contrib/binutils/bfd/section.c +++ b/contrib/binutils/bfd/section.c @@ -1,5 +1,5 @@ /* Object file "section" support for the BFD library. - Copyright (C) 1990, 91, 92, 93, 94, 95, 96, 1997 + Copyright (C) 1990, 91, 92, 93, 94, 95, 96, 97, 98, 1999 Free Software Foundation, Inc. Written by Cygnus Support. @@ -137,7 +137,7 @@ SUBSECTION #include "bfd.h" #include "sysdep.h" #include "libbfd.h" - +#include "bfdlink.h" /* DOCDD @@ -150,6 +150,27 @@ SUBSECTION CODE_FRAGMENT . +. {* This structure is used for a comdat section, as in PE. A comdat +. section is associated with a particular symbol. When the linker +. sees a comdat section, it keeps only one of the sections with a +. given name and associated with a given symbol. *} +. +.struct bfd_comdat_info +.{ +. {* The name of the symbol associated with a comdat section. *} +. const char *name; +. +. {* The local symbol table index of the symbol associated with a +. comdat section. This is only meaningful to the object file format +. specific code; it is not an index into the list returned by +. bfd_canonicalize_symtab. *} +. long symbol; +. +. {* If this section is being discarded, the linker uses this field +. to point to the input section which is being kept. *} +. struct sec *sec; +.}; +. .typedef struct sec .{ . {* The name of the section; the name isn't a copy, the pointer is @@ -215,7 +236,7 @@ CODE_FRAGMENT . standard data. *} .#define SEC_CONSTRUCTOR 0x100 . -. {* The section is a constuctor, and should be placed at the +. {* The section is a constructor, and should be placed at the . end of the text, data, or bss section(?). *} .#define SEC_CONSTRUCTOR_TEXT 0x1100 .#define SEC_CONSTRUCTOR_DATA 0x2100 @@ -304,6 +325,17 @@ CODE_FRAGMENT . else up the line will take care of it later. *} .#define SEC_LINKER_CREATED 0x800000 . +. {* This section should not be subject to garbage collection. *} +.#define SEC_KEEP 0x1000000 +. +. {* This section contains "short" data, and should be placed +. "near" the GP. *} +.#define SEC_SMALL_DATA 0x2000000 +. +. {* This section contains data which may be shared with other +. executables or shared objects. *} +.#define SEC_SHARED 0x4000000 +. . {* End of section flags. *} . . {* Some internal packed boolean fields. *} @@ -317,6 +349,9 @@ CODE_FRAGMENT . {* A mark flag used by some of the linker backends. *} . unsigned int linker_mark : 1; . +. {* A mark flag used by some linker backends for garbage collection. *} +. unsigned int gc_mark : 1; +. . {* End of internal packed boolean fields. *} . . {* The virtual memory address of the section - where it will be @@ -334,22 +369,25 @@ CODE_FRAGMENT . . bfd_vma lma; . -. {* The size of the section in bytes, as it will be output. -. contains a value even if the section has no contents (e.g., the -. size of <<.bss>>). This will be filled in after relocation *} +. {* The size of the section in octets, as it will be output. +. Contains a value even if the section has no contents (e.g., the +. size of <<.bss>>). This will be filled in after relocation. *} . . bfd_size_type _cooked_size; . -. {* The original size on disk of the section, in bytes. Normally this +. {* The original size on disk of the section, in octets. Normally this . value is the same as the size, but if some relaxing has . been done, then this value will be bigger. *} . . bfd_size_type _raw_size; . . {* If this section is going to be output, then this value is the -. offset into the output section of the first byte in the input -. section. E.g., if this was going to start at the 100th byte in -. the output section, this value would be 100. *} +. offset in *bytes* into the output section of the first byte in the +. input section (byte ==> smallest addressable unit on the +. target). In most cases, if this was going to start at the +. 100th octet (8-bit quantity) in the output section, this value +. would be 100. However, if the target byte size is 16 bits +. (bfd_octets_per_byte is "2"), this value would be 50. *} . . bfd_vma output_offset; . @@ -407,6 +445,10 @@ CODE_FRAGMENT . . unsigned int lineno_count; . +. {* Optional information about a COMDAT entry; NULL if not COMDAT *} +. +. struct bfd_comdat_info *comdat; +. . {* When a section is being output, this value changes as more . linenumbers are written out *} . @@ -466,28 +508,60 @@ CODE_FRAGMENT .extern const struct symbol_cache_entry * const bfd_und_symbol; .extern const struct symbol_cache_entry * const bfd_ind_symbol; .#define bfd_get_section_size_before_reloc(section) \ -. (section->reloc_done ? (abort(),1): (section)->_raw_size) +. ((section)->reloc_done ? (abort (), (bfd_size_type) 1) \ +. : (section)->_raw_size) .#define bfd_get_section_size_after_reloc(section) \ -. ((section->reloc_done) ? (section)->_cooked_size: (abort(),1)) +. ((section)->reloc_done ? (section)->_cooked_size \ +. : (abort (), (bfd_size_type) 1)) */ +/* We use a macro to initialize the static asymbol structures because + traditional C does not permit us to initialize a union member while + gcc warns if we don't initialize it. */ + /* the_bfd, name, value, attr, section [, udata] */ +#ifdef __STDC__ +#define GLOBAL_SYM_INIT(NAME, SECTION) \ + { 0, NAME, 0, BSF_SECTION_SYM, (asection *) SECTION, { 0 }} +#else +#define GLOBAL_SYM_INIT(NAME, SECTION) \ + { 0, NAME, 0, BSF_SECTION_SYM, (asection *) SECTION } +#endif + /* These symbols are global, not specific to any BFD. Therefore, anything that tries to change them is broken, and should be repaired. */ + static const asymbol global_syms[] = { - /* the_bfd, name, value, attr, section [, udata] */ - {0, BFD_COM_SECTION_NAME, 0, BSF_SECTION_SYM, (asection *) &bfd_com_section}, - {0, BFD_UND_SECTION_NAME, 0, BSF_SECTION_SYM, (asection *) &bfd_und_section}, - {0, BFD_ABS_SECTION_NAME, 0, BSF_SECTION_SYM, (asection *) &bfd_abs_section}, - {0, BFD_IND_SECTION_NAME, 0, BSF_SECTION_SYM, (asection *) &bfd_ind_section}, + GLOBAL_SYM_INIT (BFD_COM_SECTION_NAME, &bfd_com_section), + GLOBAL_SYM_INIT (BFD_UND_SECTION_NAME, &bfd_und_section), + GLOBAL_SYM_INIT (BFD_ABS_SECTION_NAME, &bfd_abs_section), + 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]; \ const asection SEC = \ - { NAME, 0, 0, FLAGS, 0, 0, 0, 0, 0, 0, 0, 0, (asection *) &SEC, \ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ - (asymbol *) &global_syms[IDX], (asymbol **) &SYM, 0, 0 } + /* name, index, next, flags, set_vma, reloc_done, linker_mark, gc_mark */ \ + { NAME, 0, 0, FLAGS, 0, 0, 0, 0, \ + \ + /* vma, lma, _cooked_size, _raw_size, output_offset, output_section, */ \ + 0, 0, 0, 0, 0, (struct sec *) &SEC, \ + \ + /* alig..., reloc..., orel..., reloc_count, filepos, rel_..., line_... */ \ + 0, 0, 0, 0, 0, 0, 0, \ + \ + /* userdata, contents, lineno, lineno_count */ \ + 0, 0, 0, 0, \ + \ + /* comdat_info, moving_line_filepos, target_index, used_by_bfd, */ \ + NULL, 0, 0, 0, \ + \ + /* cons..., owner, symbol */ \ + 0, 0, (struct symbol_cache_entry *) &global_syms[IDX], \ + \ + /* symbol_ptr_ptr, link_order_head, ..._tail */ \ + (struct symbol_cache_entry **) &SYM, 0, 0 \ + } STD_SECTION (bfd_com_section, SEC_IS_COMMON, bfd_com_symbol, BFD_COM_SECTION_NAME, 0); @@ -630,6 +704,7 @@ bfd_make_section_anyway (abfd, name) newsect->reloc_count = 0; newsect->line_filepos = 0; newsect->owner = abfd; + newsect->comdat = NULL; /* Create a symbol whos only job is to point to this section. This is useful for things like relocs which are relative to the base of a @@ -727,7 +802,7 @@ DESCRIPTION /*ARGSUSED*/ boolean bfd_set_section_flags (abfd, section, flags) - bfd *abfd; + bfd *abfd ATTRIBUTE_UNUSED; sec_ptr section; flagword flags; { @@ -850,7 +925,7 @@ DESCRIPTION Sets the contents of the section @var{section} in BFD @var{abfd} to the data starting in memory at @var{data}. The data is written to the output section starting at offset - @var{offset} for @var{count} bytes. + @var{offset} for @var{count} octets. @@ -1020,3 +1095,80 @@ DESCRIPTION . BFD_SEND (obfd, _bfd_copy_private_section_data, \ . (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. @var{info} may + be NULL; if it is not, it is used to decide whether the output + section is empty. +*/ +void +_bfd_strip_section_from_output (info, s) + struct bfd_link_info *info; + asection *s; +{ + asection **spp, *os; + struct bfd_link_order *p, *pp; + boolean keep_os; + + /* Excise the input section from the link order. + + FIXME: For all calls that I can see to this function, the link + orders have not yet been set up. So why are we checking them? -- + Ian */ + os = s->output_section; + for (p = os->link_order_head, pp = NULL; p != NULL; pp = p, p = p->next) + if (p->type == bfd_indirect_link_order + && p->u.indirect.section == s) + { + if (pp) + pp->next = p->next; + else + os->link_order_head = p->next; + if (!p->next) + os->link_order_tail = pp; + break; + } + + keep_os = os->link_order_head != NULL; + + if (! keep_os && info != NULL) + { + bfd *abfd; + for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link_next) + { + asection *is; + for (is = abfd->sections; is != NULL; is = is->next) + { + if (is != s && is->output_section == os) + break; + } + if (is != NULL) + break; + } + if (abfd != NULL) + keep_os = true; + } + + /* If the output section is empty, remove it too. Careful about sections + that have been discarded in the link script -- they are mapped to + bfd_abs_section, which has no owner. */ + if (!keep_os && os->owner != NULL) + { + for (spp = &os->owner->sections; *spp; spp = &(*spp)->next) + if (*spp == os) + { + *spp = os->next; + os->owner->section_count--; + break; + } + } +} |