diff options
author | Ian Lance Taylor <ian@airs.com> | 1995-11-28 22:02:13 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 1995-11-28 22:02:13 +0000 |
commit | fd0198f02371c0d604ec7c3162cf60a0a84c0ef0 (patch) | |
tree | 7f92823e70416a077c31b4db5ce30fa9cee0084f /bfd/elf.c | |
parent | 6d2d98d31340d6a5e8eca291a70c59d507a8125e (diff) | |
download | gdb-fd0198f02371c0d604ec7c3162cf60a0a84c0ef0.zip gdb-fd0198f02371c0d604ec7c3162cf60a0a84c0ef0.tar.gz gdb-fd0198f02371c0d604ec7c3162cf60a0a84c0ef0.tar.bz2 |
* elf-bfd.h (struct elf_obj_tdata): Add segment_map field.
* elf.c (make_mapping): New static function.
(map_sections_to_segments): New static function.
(elf_sort_sections): New static function.
(assign_file_positions_for_segments): New static function.
(map_program_segments): Remove.
(get_program_header_size): Remove sorted_hdrs, count, and
maxpagesize parameters. Simplify.
(assign_file_positions_except_relocs): When generating an
executable, use assign_file_positions_for_segments.
(elf_sort_hdrs): Remove.
(_bfd_elf_sizeof_headers): Remove eliminated parameters from call
to get_program_header_size.
Diffstat (limited to 'bfd/elf.c')
-rw-r--r-- | bfd/elf.c | 1214 |
1 files changed, 698 insertions, 516 deletions
@@ -38,11 +38,11 @@ SECTION #define ARCH_SIZE 0 #include "elf-bfd.h" -static file_ptr map_program_segments PARAMS ((bfd *, file_ptr, - Elf_Internal_Shdr *, - Elf_Internal_Shdr **, - bfd_size_type)); -static boolean assign_file_positions_except_relocs PARAMS ((bfd *, boolean)); +static INLINE struct elf_segment_map *make_mapping + PARAMS ((bfd *, asection **, unsigned int, unsigned int)); +static int elf_sort_sections PARAMS ((const PTR, const PTR)); +static boolean assign_file_positions_for_segments PARAMS ((bfd *)); +static boolean assign_file_positions_except_relocs PARAMS ((bfd *)); static boolean prep_headers PARAMS ((bfd *)); static boolean swap_out_syms PARAMS ((bfd *, struct bfd_strtab_hash **)); @@ -219,6 +219,26 @@ _bfd_elf_make_section_from_shdr (abfd, hdr, name) if (! bfd_set_section_flags (abfd, newsect, flags)) return false; + if ((flags & SEC_ALLOC) != 0) + { + Elf_Internal_Phdr *phdr; + unsigned int i; + + /* Look through the phdrs to see if we need to adjust the lma. */ + phdr = elf_tdata (abfd)->phdr; + for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++) + { + if (phdr->p_type == PT_LOAD + && phdr->p_vaddr != phdr->p_paddr + && phdr->p_vaddr <= hdr->sh_addr + && phdr->p_vaddr + phdr->p_memsz >= hdr->sh_addr + hdr->sh_size) + { + newsect->lma += phdr->p_paddr - phdr->p_vaddr; + break; + } + } + } + hdr->bfd_section = newsect; elf_section_data (newsect)->this_hdr = *hdr; @@ -521,7 +541,7 @@ bfd_section_from_shdr (abfd, shindex) BFD_ASSERT (elf_onesymtab (abfd) == 0); elf_onesymtab (abfd) = shindex; elf_tdata (abfd)->symtab_hdr = *hdr; - elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->symtab_hdr; + elf_elfsections (abfd)[shindex] = hdr = &elf_tdata (abfd)->symtab_hdr; abfd->flags |= HAS_SYMS; /* Sometimes a shared object will map in the symbol table. If @@ -545,7 +565,7 @@ bfd_section_from_shdr (abfd, shindex) BFD_ASSERT (elf_dynsymtab (abfd) == 0); elf_dynsymtab (abfd) = shindex; elf_tdata (abfd)->dynsymtab_hdr = *hdr; - elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->dynsymtab_hdr; + elf_elfsections (abfd)[shindex] = hdr = &elf_tdata (abfd)->dynsymtab_hdr; abfd->flags |= HAS_SYMS; /* Besides being a symbol table, we also treat this as a regular @@ -581,7 +601,7 @@ bfd_section_from_shdr (abfd, shindex) if (elf_dynsymtab (abfd) == i) { elf_tdata (abfd)->dynstrtab_hdr = *hdr; - elf_elfsections (abfd)[shindex] = + elf_elfsections (abfd)[shindex] = hdr = &elf_tdata (abfd)->dynstrtab_hdr; /* We also treat this as a regular section, so that objcopy can handle it. */ @@ -867,27 +887,17 @@ elf_fake_sections (abfd, asect, failedptrarg) this_hdr->sh_flags = 0; - /* FIXME: This should really use vma, rather than lma. However, - that would mean that the lma information was lost, which would - mean that the AT keyword in linker scripts would not work. - Fortunately, native scripts do not use the AT keyword, so we can - get away with using lma here. The right way to handle this is to - 1) read the program headers as well as the section headers, and - set the lma fields of the BFD sections based on the p_paddr - fields of the program headers, and 2) set the p_paddr fields of - the program headers based on the section lma fields when writing - them out. */ if ((asect->flags & SEC_ALLOC) != 0) - this_hdr->sh_addr = asect->lma; + this_hdr->sh_addr = asect->vma; else this_hdr->sh_addr = 0; this_hdr->sh_offset = 0; this_hdr->sh_size = asect->_raw_size; this_hdr->sh_link = 0; - this_hdr->sh_info = 0; this_hdr->sh_addralign = 1 << asect->alignment_power; - this_hdr->sh_entsize = 0; + /* The sh_entsize and sh_info fields may have been set already by + copy_private_section_data. */ this_hdr->bfd_section = asect; this_hdr->contents = NULL; @@ -1220,7 +1230,7 @@ elf_map_symbols (abfd) for (idx = 0; idx < symcount; idx++) { if ((syms[idx]->flags & BSF_SECTION_SYM) != 0 - && syms[idx]->value == 0) + && (syms[idx]->value + syms[idx]->section->vma) == 0) { asection *sec; @@ -1333,6 +1343,43 @@ elf_map_symbols (abfd) return true; } +/* Align to the maximum file alignment that could be required for any + ELF data structure. */ + +static INLINE file_ptr align_file_position PARAMS ((file_ptr, int)); +static INLINE file_ptr +align_file_position (off, align) + file_ptr off; + int align; +{ + return (off + align - 1) & ~(align - 1); +} + +/* Assign a file position to a section, optionally aligning to the + required section alignment. */ + +INLINE file_ptr +_bfd_elf_assign_file_position_for_section (i_shdrp, offset, align) + Elf_Internal_Shdr *i_shdrp; + file_ptr offset; + boolean align; +{ + if (align) + { + unsigned int al; + + al = i_shdrp->sh_addralign; + if (al > 1) + offset = BFD_ALIGN (offset, al); + } + i_shdrp->sh_offset = offset; + if (i_shdrp->bfd_section != NULL) + i_shdrp->bfd_section->filepos = offset; + if (i_shdrp->sh_type != SHT_NOBITS) + offset += i_shdrp->sh_size; + return offset; +} + /* Compute the file positions we are going to put the sections at, and otherwise prepare to begin writing out the ELF file. If LINK_INFO is not NULL, this is being called by the ELF backend linker. */ @@ -1366,7 +1413,7 @@ _bfd_elf_compute_section_file_positions (abfd, link_info) return false; /* The backend linker builds symbol table information itself. */ - if (link_info == NULL) + if (link_info == NULL && abfd->symcount > 0) { if (! swap_out_syms (abfd, &strtab)) return false; @@ -1381,19 +1428,30 @@ _bfd_elf_compute_section_file_positions (abfd, link_info) shstrtab_hdr->sh_entsize = 0; shstrtab_hdr->sh_link = 0; shstrtab_hdr->sh_info = 0; - /* sh_offset is set in assign_file_positions_for_symtabs_and_strtabs. */ + /* sh_offset is set in assign_file_positions_except_relocs. */ shstrtab_hdr->sh_addralign = 1; - if (!assign_file_positions_except_relocs (abfd, - link_info == NULL ? true : false)) + if (!assign_file_positions_except_relocs (abfd)) return false; - if (link_info == NULL) + if (link_info == NULL && abfd->symcount > 0) { + file_ptr off; + Elf_Internal_Shdr *hdr; + + off = elf_tdata (abfd)->next_file_pos; + + hdr = &elf_tdata (abfd)->symtab_hdr; + off = _bfd_elf_assign_file_position_for_section (hdr, off, true); + + hdr = &elf_tdata (abfd)->strtab_hdr; + off = _bfd_elf_assign_file_position_for_section (hdr, off, true); + + elf_tdata (abfd)->next_file_pos = off; + /* Now that we know where the .strtab section goes, write it out. */ - if ((bfd_seek (abfd, elf_tdata (abfd)->strtab_hdr.sh_offset, SEEK_SET) - != 0) + if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0 || ! _bfd_stringtab_emit (abfd, strtab)) return false; _bfd_stringtab_free (strtab); @@ -1404,428 +1462,542 @@ _bfd_elf_compute_section_file_positions (abfd, link_info) return true; } +/* Create a mapping from a set of sections to a program segment. */ -/* Align to the maximum file alignment that could be required for any - ELF data structure. */ - -static INLINE file_ptr align_file_position PARAMS ((file_ptr, int)); -static INLINE file_ptr -align_file_position (off, align) - file_ptr off; - int align; +static INLINE struct elf_segment_map * +make_mapping (abfd, sections, from, to) + bfd *abfd; + asection **sections; + unsigned int from; + unsigned int to; { - return (off + align - 1) & ~(align - 1); + struct elf_segment_map *m; + unsigned int i; + asection **hdrpp; + + m = ((struct elf_segment_map *) + bfd_zalloc (abfd, + (sizeof (struct elf_segment_map) + + (to - from - 1) * sizeof (asection *)))); + if (m == NULL) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } + m->next = NULL; + m->p_type = PT_LOAD; + for (i = from, hdrpp = sections + from; i < to; i++, hdrpp++) + m->sections[i - from] = *hdrpp; + m->count = to - from; + + return m; } -/* Assign a file position to a section, optionally aligning to the - required section alignment. */ +/* Set up a mapping from BFD sections to program segments. */ -INLINE file_ptr -_bfd_elf_assign_file_position_for_section (i_shdrp, offset, align) - Elf_Internal_Shdr *i_shdrp; - file_ptr offset; - boolean align; +static boolean +map_sections_to_segments (abfd) + bfd *abfd; { - if (align) + asection **sections = NULL; + asection *s; + unsigned int i; + unsigned int count; + struct elf_segment_map *mfirst; + struct elf_segment_map **pm; + struct elf_segment_map *m; + asection *last_hdr; + unsigned int phdr_index; + bfd_vma maxpagesize; + asection **hdrpp; + + if (elf_tdata (abfd)->segment_map != NULL) + return true; + + if (bfd_count_sections (abfd) == 0) + return true; + + /* Select the allocated sections, and sort them. */ + + sections = (asection **) malloc (bfd_count_sections (abfd) + * sizeof (asection *)); + if (sections == NULL) { - unsigned int al; + bfd_set_error (bfd_error_no_memory); + goto error_return; + } - al = i_shdrp->sh_addralign; - if (al > 1) - offset = BFD_ALIGN (offset, al); + i = 0; + for (s = abfd->sections; s != NULL; s = s->next) + { + if ((s->flags & SEC_ALLOC) != 0) + { + sections[i] = s; + ++i; + } } - i_shdrp->sh_offset = offset; - if (i_shdrp->bfd_section != NULL) - i_shdrp->bfd_section->filepos = offset; - if (i_shdrp->sh_type != SHT_NOBITS) - offset += i_shdrp->sh_size; - return offset; -} + BFD_ASSERT (i <= bfd_count_sections (abfd)); + count = i; -/* Get the size of the program header. + qsort (sections, (size_t) count, sizeof (asection *), elf_sort_sections); - SORTED_HDRS, if non-NULL, is an array of COUNT pointers to headers sorted - by VMA. Non-allocated sections (!SHF_ALLOC) must appear last. All - section VMAs and sizes are known so we can compute the correct value. - (??? This may not be perfectly true. What cases do we miss?) + /* Build the mapping. */ - If SORTED_HDRS is NULL we assume there are two segments: text and data - (exclusive of .interp and .dynamic). + mfirst = NULL; + pm = &mfirst; - If this is called by the linker before any of the section VMA's are set, it - can't calculate the correct value for a strange memory layout. This only - happens when SIZEOF_HEADERS is used in a linker script. In this case, - SORTED_HDRS is NULL and we assume the normal scenario of one text and one - data segment (exclusive of .interp and .dynamic). + /* If we have a .interp section, then create a PT_PHDR segment for + the program headers and a PT_INTERP segment for the .interp + section. */ + s = bfd_get_section_by_name (abfd, ".interp"); + if (s != NULL && (s->flags & SEC_LOAD) != 0) + { + m = ((struct elf_segment_map *) + bfd_zalloc (abfd, sizeof (struct elf_segment_map))); + if (m == NULL) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + m->next = NULL; + m->p_type = PT_PHDR; + /* FIXME: UnixWare and Solaris set PF_X, Irix 5 does not. */ + m->p_flags = PF_R | PF_X; + m->p_flags_valid = 1; - ??? User written scripts must either not use SIZEOF_HEADERS, or assume there - will be two segments. */ + *pm = m; + pm = &m->next; -static bfd_size_type -get_program_header_size (abfd, sorted_hdrs, count, maxpagesize) - bfd *abfd; - Elf_Internal_Shdr **sorted_hdrs; - unsigned int count; - bfd_vma maxpagesize; -{ - size_t segs; - asection *s; - struct elf_backend_data *bed = get_elf_backend_data (abfd); + m = ((struct elf_segment_map *) + bfd_zalloc (abfd, sizeof (struct elf_segment_map))); + if (m == NULL) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + m->next = NULL; + m->p_type = PT_INTERP; + m->count = 1; + m->sections[0] = s; - /* We can't return a different result each time we're called. */ - if (elf_tdata (abfd)->program_header_size != 0) - return elf_tdata (abfd)->program_header_size; + *pm = m; + pm = &m->next; + } - if (sorted_hdrs != NULL) + /* Look through the sections. We put sections in the same program + segment when the start of the second section can be placed within + a few bytes of the end of the first section. */ + last_hdr = NULL; + phdr_index = 0; + maxpagesize = get_elf_backend_data (abfd)->maxpagesize; + for (i = 0, hdrpp = sections; i < count; i++, hdrpp++) { - unsigned int i; - unsigned int last_type; - Elf_Internal_Shdr **hdrpp; - /* What we think the current segment's offset is. */ - bfd_vma p_offset; - /* What we think the current segment's address is. */ - bfd_vma p_vaddr; - /* How big we think the current segment is. */ - bfd_vma p_memsz; - /* What we think the current file offset is. */ - bfd_vma file_offset; - bfd_vma next_offset; - - /* Scan the headers and compute the number of segments required. This - code is intentionally similar to the code in map_program_segments. - - The `sh_offset' field isn't valid at this point, so we keep our own - running total in `file_offset'. - - This works because section VMAs are already known. */ - - segs = 1; - /* Make sure the first section goes in the first segment. */ - file_offset = p_offset = sorted_hdrs[0]->sh_addr % maxpagesize; - p_vaddr = sorted_hdrs[0]->sh_addr; - p_memsz = 0; - last_type = SHT_PROGBITS; - - for (i = 0, hdrpp = sorted_hdrs; i < count; i++, hdrpp++) - { - Elf_Internal_Shdr *hdr; + asection *hdr; - hdr = *hdrpp; + hdr = *hdrpp; - /* Ignore any section which will not be part of the process - image. */ - if ((hdr->sh_flags & SHF_ALLOC) == 0) - continue; - - /* Keep track of where this and the next sections go. - The section VMA must equal the file position modulo - the page size. */ - file_offset += (hdr->sh_addr - file_offset) % maxpagesize; - next_offset = file_offset; - if (hdr->sh_type != SHT_NOBITS) - next_offset = file_offset + hdr->sh_size; - - /* If this section fits in the segment we are constructing, add - it in. */ - if ((file_offset - (p_offset + p_memsz) - == hdr->sh_addr - (p_vaddr + p_memsz)) - && (last_type != SHT_NOBITS || hdr->sh_type == SHT_NOBITS)) - { - bfd_size_type adjust; + /* See if this section and the last one will fit in the same + segment. */ + if (last_hdr == NULL + || ((BFD_ALIGN (last_hdr->lma + last_hdr->_raw_size, maxpagesize) + >= hdr->lma) + && ((last_hdr->flags & SEC_LOAD) != 0 + || (hdr->flags & SEC_LOAD) == 0))) + { + last_hdr = hdr; + continue; + } - adjust = hdr->sh_addr - (p_vaddr + p_memsz); - p_memsz += hdr->sh_size + adjust; - file_offset = next_offset; - last_type = hdr->sh_type; - continue; - } + /* This section won't fit in the program segment. We must + create a new program header holding all the sections from + phdr_index until hdr. */ - /* The section won't fit, start a new segment. */ - ++segs; + m = make_mapping (abfd, sections, phdr_index, i); + if (m == NULL) + goto error_return; - /* Initialize the segment. */ - p_vaddr = hdr->sh_addr; - p_memsz = hdr->sh_size; - p_offset = file_offset; - file_offset = next_offset; + *pm = m; + pm = &m->next; - last_type = hdr->sh_type; - } + last_hdr = hdr; + phdr_index = i; } - else + + /* Create a final PT_LOAD program segment. */ + if (last_hdr != NULL) { - /* Assume we will need exactly two PT_LOAD segments: one for text - and one for data. */ - segs = 2; + m = make_mapping (abfd, sections, phdr_index, i); + if (m == NULL) + goto error_return; + + *pm = m; + pm = &m->next; } - s = bfd_get_section_by_name (abfd, ".interp"); + /* If there is a .dynamic section, throw in a PT_DYNAMIC segment. */ + s = bfd_get_section_by_name (abfd, ".dynamic"); if (s != NULL && (s->flags & SEC_LOAD) != 0) { - /* If we have a loadable interpreter section, we need a - PT_INTERP segment. In this case, assume we also need a - PT_PHDR segment, although that may not be true for all - targets. */ - segs += 2; - } + m = ((struct elf_segment_map *) + bfd_zalloc (abfd, sizeof (struct elf_segment_map))); + if (m == NULL) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + m->next = NULL; + m->p_type = PT_DYNAMIC; + m->count = 1; + m->sections[0] = s; - if (bfd_get_section_by_name (abfd, ".dynamic") != NULL) - { - /* We need a PT_DYNAMIC segment. */ - ++segs; + *pm = m; + pm = &m->next; } - /* Let the backend count up any program headers it might need. */ - if (bed->elf_backend_create_program_headers) - segs = ((*bed->elf_backend_create_program_headers) - (abfd, (Elf_Internal_Phdr *) NULL, segs)); + free (sections); + sections = NULL; - elf_tdata (abfd)->program_header_size = segs * bed->s->sizeof_phdr; - return elf_tdata (abfd)->program_header_size; + elf_tdata (abfd)->segment_map = mfirst; + return true; + + error_return: + if (sections != NULL) + free (sections); + return false; } -/* Create the program header. OFF is the file offset where the - program header should be written. FIRST is the first loadable ELF - section. SORTED_HDRS is the ELF sections sorted by section - address. PHDR_SIZE is the size of the program header as returned - by get_program_header_size. */ +/* Sort sections by VMA. */ -static file_ptr -map_program_segments (abfd, off, first, sorted_hdrs, phdr_size) - bfd *abfd; - file_ptr off; - Elf_Internal_Shdr *first; - Elf_Internal_Shdr **sorted_hdrs; - bfd_size_type phdr_size; +static int +elf_sort_sections (arg1, arg2) + const PTR arg1; + const PTR arg2; { - Elf_Internal_Phdr phdrs[10]; - unsigned int phdr_count; - Elf_Internal_Phdr *phdr; - int phdr_size_adjust; - unsigned int i; - Elf_Internal_Shdr **hdrpp; - asection *sinterp, *sdyn; - unsigned int last_type; - Elf_Internal_Ehdr *i_ehdrp; - struct elf_backend_data *bed = get_elf_backend_data (abfd); + const asection *sec1 = *(const asection **) arg1; + const asection *sec2 = *(const asection **) arg2; - BFD_ASSERT ((abfd->flags & (EXEC_P | DYNAMIC)) != 0); - BFD_ASSERT (phdr_size / sizeof (Elf_Internal_Phdr) - <= sizeof phdrs / sizeof (phdrs[0])); + if (sec1->vma < sec2->vma) + return -1; + else if (sec1->vma > sec2->vma) + return 1; - phdr_count = 0; - phdr = phdrs; + /* Put !SEC_LOAD sections after SEC_LOAD ones. */ - if (bed->want_hdr_in_seg) - phdr_size_adjust = first->sh_offset - phdr_size; - else - phdr_size_adjust = 0; +#define TOEND(x) (((x)->flags & SEC_LOAD) == 0) - /* If we have a loadable .interp section, we must create a PT_INTERP - segment which must precede all PT_LOAD segments. We assume that - we must also create a PT_PHDR segment, although that may not be - true for all targets. */ - sinterp = bfd_get_section_by_name (abfd, ".interp"); - if (sinterp != NULL && (sinterp->flags & SEC_LOAD) != 0) - { - BFD_ASSERT (first != NULL); + if (TOEND (sec1)) + if (TOEND (sec2)) + return sec1->target_index - sec2->target_index; + else + return 1; - phdr->p_type = PT_PHDR; + if (TOEND (sec2)) + return -1; - phdr->p_offset = off; +#undef TOEND - /* Account for any adjustment made because of the alignment of - the first loadable section. */ - phdr_size_adjust = (first->sh_offset - phdr_size) - off; - BFD_ASSERT (phdr_size_adjust >= 0 && phdr_size_adjust < 128); + /* Sort by size, to put zero sized sections before others at the + same address. */ - /* The program header precedes all loadable sections. This lets - us compute its loadable address. This depends on the linker - script. */ - phdr->p_vaddr = first->sh_addr - (phdr_size + phdr_size_adjust); + if (sec1->_raw_size < sec2->_raw_size) + return -1; + if (sec1->_raw_size > sec2->_raw_size) + return 1; - phdr->p_paddr = 0; - phdr->p_filesz = phdr_size; - phdr->p_memsz = phdr_size; + return sec1->target_index - sec2->target_index; +} - /* FIXME: UnixWare and Solaris set PF_X, Irix 5 does not. */ - phdr->p_flags = PF_R | PF_X; +/* Assign file positions to the sections based on the mapping from + sections to segments. This function also sets up some fields in + the file header, and writes out the program headers. */ - phdr->p_align = bed->s->file_align; - BFD_ASSERT ((phdr->p_vaddr - phdr->p_offset) % bed->s->file_align == 0); +static boolean +assign_file_positions_for_segments (abfd) + bfd *abfd; +{ + const struct elf_backend_data *bed = get_elf_backend_data (abfd); + unsigned int count; + struct elf_segment_map *m; + unsigned int alloc; + Elf_Internal_Phdr *phdrs; + file_ptr off; + boolean found_load; + Elf_Internal_Phdr *p; + + if (elf_tdata (abfd)->segment_map == NULL) + { + if (! map_sections_to_segments (abfd)) + return false; + } - /* Include the ELF header in the first loadable segment. */ - phdr_size_adjust += off; + count = 0; + for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next) + ++count; - ++phdr_count; - ++phdr; + elf_elfheader (abfd)->e_phoff = bed->s->sizeof_ehdr; + elf_elfheader (abfd)->e_phentsize = bed->s->sizeof_phdr; + elf_elfheader (abfd)->e_phnum = count; - phdr->p_type = PT_INTERP; - phdr->p_offset = sinterp->filepos; - phdr->p_vaddr = sinterp->vma; - phdr->p_paddr = 0; - phdr->p_filesz = sinterp->_raw_size; - phdr->p_memsz = sinterp->_raw_size; - phdr->p_flags = PF_R; - phdr->p_align = 1 << bfd_get_section_alignment (abfd, sinterp); + if (count == 0) + return true; - ++phdr_count; - ++phdr; + /* Let the backend count up any program headers it might need. */ + if (bed->elf_backend_create_program_headers) + count = ((*bed->elf_backend_create_program_headers) + (abfd, (Elf_Internal_Phdr *) NULL, count)); + + /* If we already counted the number of program segments, make sure + that we allocated enough space. This happens when SIZEOF_HEADERS + is used in a linker script. */ + alloc = elf_tdata (abfd)->program_header_size / bed->s->sizeof_phdr; + if (alloc != 0 && count > alloc) + { + ((*_bfd_error_handler) + ("%s: Not enough room for program headers (allocated %u, need %u)", + bfd_get_filename (abfd), alloc, count)); + bfd_set_error (bfd_error_bad_value); + return false; } - /* Look through the sections to see how they will be divided into - program segments. The sections must be arranged in order by - sh_addr for this to work correctly. */ - phdr->p_type = PT_NULL; - last_type = SHT_PROGBITS; - for (i = 1, hdrpp = sorted_hdrs; - i < elf_elfheader (abfd)->e_shnum; - i++, hdrpp++) + if (alloc == 0) + alloc = count; + + phdrs = ((Elf_Internal_Phdr *) + bfd_alloc (abfd, alloc * sizeof (Elf_Internal_Phdr))); + if (phdrs == NULL) { - Elf_Internal_Shdr *hdr; + bfd_set_error (bfd_error_no_memory); + return false; + } - hdr = *hdrpp; + off = bed->s->sizeof_ehdr; + off += alloc * bed->s->sizeof_phdr; - /* Ignore any section which will not be part of the process - image. */ - if ((hdr->sh_flags & SHF_ALLOC) == 0) - continue; + found_load = false; + for (m = elf_tdata (abfd)->segment_map, p = phdrs; + m != NULL; + m = m->next, p++) + { + unsigned int i; + asection **secpp; + boolean adjusted; + + p->p_type = m->p_type; + + if (m->p_flags_valid) + p->p_flags = m->p_flags; + + if (m->count == 0) + p->p_vaddr = 0; + else + p->p_vaddr = m->sections[0]->vma; - /* If this section fits in the segment we are constructing, add - it in. */ - if (phdr->p_type != PT_NULL - && (hdr->sh_offset - (phdr->p_offset + phdr->p_memsz) - == hdr->sh_addr - (phdr->p_vaddr + phdr->p_memsz)) - && (last_type != SHT_NOBITS || hdr->sh_type == SHT_NOBITS)) + if (m->p_paddr_valid) + p->p_paddr = m->p_paddr; + else if (m->count == 0) + p->p_paddr = 0; + else + p->p_paddr = m->sections[0]->lma; + + if (p->p_type == PT_LOAD) + p->p_align = bed->maxpagesize; + else if (m->count == 0) + p->p_align = bed->s->file_align; + else + p->p_align = 0; + + p->p_filesz = 0; + p->p_memsz = 0; + + adjusted = false; + if (p->p_type == PT_LOAD) { - bfd_size_type adjust; - - adjust = hdr->sh_addr - (phdr->p_vaddr + phdr->p_memsz); - phdr->p_memsz += hdr->sh_size + adjust; - if (hdr->sh_type != SHT_NOBITS) - phdr->p_filesz += hdr->sh_size + adjust; - if ((hdr->sh_flags & SHF_WRITE) != 0) - phdr->p_flags |= PF_W; - if ((hdr->sh_flags & SHF_EXECINSTR) != 0) - phdr->p_flags |= PF_X; - last_type = hdr->sh_type; - continue; + p->p_offset = off; + + if (! found_load) + { + struct elf_segment_map *mi; + Elf_Internal_Phdr *pi; + Elf_Internal_Phdr *pi_phdr; + + /* This is the first PT_LOAD segment. If there is a + PT_INTERP segment, adjust the offset of this segment + to include the program headers and the file header. */ + pi_phdr = NULL; + for (mi = elf_tdata (abfd)->segment_map, pi = phdrs; + mi != NULL; + mi = mi->next, pi++) + { + if (mi->p_type == PT_INTERP) + { + p->p_offset = 0; + p->p_filesz = off; + p->p_memsz = off; + p->p_vaddr -= off; + p->p_paddr -= off; + adjusted = true; + } + if (mi->p_type == PT_PHDR) + pi_phdr = pi; + } + + /* Set up the PT_PHDR addresses. */ + if (pi_phdr != NULL) + { + pi_phdr->p_vaddr = p->p_vaddr + bed->s->sizeof_ehdr; + pi_phdr->p_paddr = p->p_paddr + bed->s->sizeof_ehdr; + } + + found_load = true; + } } - /* The section won't fit, start a new segment. If we're already in one, - move to the next one. */ - if (phdr->p_type != PT_NULL) + if (! m->p_flags_valid) + p->p_flags = PF_R; + for (i = 0, secpp = m->sections; i < m->count; i++, secpp++) { - ++phdr; - ++phdr_count; + asection *sec; + flagword flags; + bfd_size_type align; + + sec = *secpp; + flags = sec->flags; + + if (p->p_type == PT_LOAD) + { + bfd_vma adjust; + + /* The section VMA must equal the file position modulo + the page size. */ + adjust = (sec->vma - off) % bed->maxpagesize; + if (adjust != 0) + { + if (i == 0 && ! adjusted) + p->p_offset += adjust; + else + { + p->p_memsz += adjust; + if ((flags & SEC_LOAD) != 0) + p->p_filesz += adjust; + } + off += adjust; + } + + sec->filepos = off; + + if ((flags & SEC_LOAD) != 0) + off += sec->_raw_size; + } + + p->p_memsz += sec->_raw_size; + + if ((flags & SEC_LOAD) != 0) + p->p_filesz += sec->_raw_size; + + align = 1 << bfd_get_section_alignment (abfd, sec); + if (align > p->p_align) + p->p_align = align; + + if (! m->p_flags_valid) + { + if ((flags & SEC_CODE) != 0) + p->p_flags |= PF_X; + if ((flags & SEC_READONLY) == 0) + p->p_flags |= PF_W; + } } + } - /* Initialize the segment. */ - phdr->p_type = PT_LOAD; - phdr->p_offset = hdr->sh_offset; - phdr->p_vaddr = hdr->sh_addr; - phdr->p_paddr = 0; - if (hdr->sh_type == SHT_NOBITS) - phdr->p_filesz = 0; - else - phdr->p_filesz = hdr->sh_size; - phdr->p_memsz = hdr->sh_size; - phdr->p_flags = PF_R; - if ((hdr->sh_flags & SHF_WRITE) != 0) - phdr->p_flags |= PF_W; - if ((hdr->sh_flags & SHF_EXECINSTR) != 0) - phdr->p_flags |= PF_X; - phdr->p_align = bed->maxpagesize; - - if (hdr == first - && (bed->want_hdr_in_seg - || (sinterp != NULL - && (sinterp->flags & SEC_LOAD) != 0))) + /* Now that we have set the section file positions, we can set up + the file positions for the non PT_LOAD segments. */ + for (m = elf_tdata (abfd)->segment_map, p = phdrs; + m != NULL; + m = m->next, p++) + { + if (p->p_type != PT_LOAD && m->count > 0) + p->p_offset = m->sections[0]->filepos; + if (p->p_type == PT_PHDR) { - phdr->p_offset -= phdr_size + phdr_size_adjust; - phdr->p_vaddr -= phdr_size + phdr_size_adjust; - phdr->p_filesz += phdr_size + phdr_size_adjust; - phdr->p_memsz += phdr_size + phdr_size_adjust; + p->p_offset = bed->s->sizeof_ehdr; + p->p_filesz = count * bed->s->sizeof_phdr; + p->p_memsz = p->p_filesz; } - - last_type = hdr->sh_type; } - if (phdr->p_type != PT_NULL) + /* Let the backend set up any program headers it might need. */ + if (bed->elf_backend_create_program_headers) + count = ((*bed->elf_backend_create_program_headers) + (abfd, phdrs, count)); + + /* Clear out any program headers we allocated but did not use. */ + for (; count < alloc; count++, p++) { - ++phdr; - ++phdr_count; + memset (p, 0, sizeof *p); + p->p_type = PT_NULL; } - /* If we have a .dynamic section, create a PT_DYNAMIC segment. */ - sdyn = bfd_get_section_by_name (abfd, ".dynamic"); - if (sdyn != NULL && (sdyn->flags & SEC_LOAD) != 0) - { - phdr->p_type = PT_DYNAMIC; - phdr->p_offset = sdyn->filepos; - phdr->p_vaddr = sdyn->vma; - phdr->p_paddr = 0; - phdr->p_filesz = sdyn->_raw_size; - phdr->p_memsz = sdyn->_raw_size; - phdr->p_flags = PF_R; - if ((sdyn->flags & SEC_READONLY) == 0) - phdr->p_flags |= PF_W; - if ((sdyn->flags & SEC_CODE) != 0) - phdr->p_flags |= PF_X; - phdr->p_align = 1 << bfd_get_section_alignment (abfd, sdyn); + elf_tdata (abfd)->phdr = phdrs; - ++phdr; - ++phdr_count; - } + elf_tdata (abfd)->next_file_pos = off; - /* Let the backend create additional program headers. */ - if (bed->elf_backend_create_program_headers) - phdr_count = (*bed->elf_backend_create_program_headers) (abfd, - phdrs, - phdr_count); + /* Write out the program headers. */ + if (bfd_seek (abfd, bed->s->sizeof_ehdr, SEEK_SET) != 0 + || bed->s->write_out_phdrs (abfd, phdrs, alloc) != 0) + return false; + + return true; +} + +/* Get the size of the program header. + + If this is called by the linker before any of the section VMA's are set, it + can't calculate the correct value for a strange memory layout. This only + happens when SIZEOF_HEADERS is used in a linker script. In this case, + SORTED_HDRS is NULL and we assume the normal scenario of one text and one + data segment (exclusive of .interp and .dynamic). + + ??? User written scripts must either not use SIZEOF_HEADERS, or assume there + will be two segments. */ + +static bfd_size_type +get_program_header_size (abfd) + bfd *abfd; +{ + size_t segs; + asection *s; + struct elf_backend_data *bed = get_elf_backend_data (abfd); + + /* We can't return a different result each time we're called. */ + if (elf_tdata (abfd)->program_header_size != 0) + return elf_tdata (abfd)->program_header_size; - /* Make sure the return value from get_program_header_size matches - what we computed here. Actually, it's OK if we allocated too - much space in the program header. */ - if (phdr_count > phdr_size / bed->s->sizeof_phdr) + /* Assume we will need exactly two PT_LOAD segments: one for text + and one for data. */ + segs = 2; + + s = bfd_get_section_by_name (abfd, ".interp"); + if (s != NULL && (s->flags & SEC_LOAD) != 0) { - ((*_bfd_error_handler) - ("%s: Not enough room for program headers (allocated %lu, need %u)", - bfd_get_filename (abfd), - (unsigned long) (phdr_size / bed->s->sizeof_phdr), - phdr_count)); - bfd_set_error (bfd_error_bad_value); - return (file_ptr) -1; + /* If we have a loadable interpreter section, we need a + PT_INTERP segment. In this case, assume we also need a + PT_PHDR segment, although that may not be true for all + targets. */ + segs += 2; } - /* Set up program header information. */ - i_ehdrp = elf_elfheader (abfd); - i_ehdrp->e_phentsize = bed->s->sizeof_phdr; - i_ehdrp->e_phoff = off; - i_ehdrp->e_phnum = phdr_count; - - /* Save the program headers away. I don't think anybody uses this - information right now. */ - elf_tdata (abfd)->phdr = ((Elf_Internal_Phdr *) - bfd_alloc (abfd, - (phdr_count - * sizeof (Elf_Internal_Phdr)))); - if (elf_tdata (abfd)->phdr == NULL && phdr_count != 0) + if (bfd_get_section_by_name (abfd, ".dynamic") != NULL) { - bfd_set_error (bfd_error_no_memory); - return (file_ptr) -1; + /* We need a PT_DYNAMIC segment. */ + ++segs; } - memcpy (elf_tdata (abfd)->phdr, phdrs, - phdr_count * sizeof (Elf_Internal_Phdr)); - /* Write out the program headers. */ - if (bfd_seek (abfd, off, SEEK_SET) != 0) - return (file_ptr) -1; - - if (bed->s->write_out_phdrs (abfd, phdrs, phdr_count) != 0) - return (file_ptr) -1; + /* Let the backend count up any program headers it might need. */ + if (bed->elf_backend_create_program_headers) + segs = ((*bed->elf_backend_create_program_headers) + (abfd, (Elf_Internal_Phdr *) NULL, segs)); - return off + phdr_count * bed->s->sizeof_phdr; + elf_tdata (abfd)->program_header_size = segs * bed->s->sizeof_phdr; + return elf_tdata (abfd)->program_header_size; } /* Work out the file positions of all the sections. This is called by @@ -1837,15 +2009,11 @@ map_program_segments (abfd, off, first, sorted_hdrs, phdr_size) positions in assign_file_positions_for_relocs, which is called by write_object_contents and final_link. - If DOSYMS is false, we do not assign file positions for the symbol - table or the string table. */ - -static int elf_sort_hdrs PARAMS ((const PTR, const PTR)); + We also don't set the positions of the .symtab and .strtab here. */ static boolean -assign_file_positions_except_relocs (abfd, dosyms) +assign_file_positions_except_relocs (abfd) bfd *abfd; - boolean dosyms; { struct elf_obj_tdata * const tdata = elf_tdata (abfd); Elf_Internal_Ehdr * const i_ehdrp = elf_elfheader (abfd); @@ -1853,14 +2021,14 @@ assign_file_positions_except_relocs (abfd, dosyms) file_ptr off; struct elf_backend_data *bed = get_elf_backend_data (abfd); - /* Start after the ELF header. */ - off = i_ehdrp->e_ehsize; - if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0) { Elf_Internal_Shdr **hdrpp; unsigned int i; + /* Start after the ELF header. */ + off = i_ehdrp->e_ehsize; + /* We are not creating an executable, which means that we are not creating a program header, and that the actual order of the sections in the file is unimportant. */ @@ -1874,9 +2042,8 @@ assign_file_positions_except_relocs (abfd, dosyms) hdr->sh_offset = -1; continue; } - if (! dosyms - && (i == tdata->symtab_section - || i == tdata->strtab_section)) + if (i == tdata->symtab_section + || i == tdata->strtab_section) { hdr->sh_offset = -1; continue; @@ -1887,97 +2054,45 @@ assign_file_positions_except_relocs (abfd, dosyms) } else { - file_ptr phdr_off; - bfd_size_type phdr_size; - bfd_vma maxpagesize; - size_t hdrppsize; - Elf_Internal_Shdr **sorted_hdrs; - Elf_Internal_Shdr **hdrpp; unsigned int i; - Elf_Internal_Shdr *first; - file_ptr phdr_map; - - /* We are creating an executable. */ - - maxpagesize = get_elf_backend_data (abfd)->maxpagesize; - if (maxpagesize == 0) - maxpagesize = 1; - - /* We must sort the sections. The GNU linker will always create - the sections in an appropriate order, but the Irix 5 linker - will not. We don't include the dummy first section in the - sort. We sort sections which are not SHF_ALLOC to the end. */ - hdrppsize = (i_ehdrp->e_shnum - 1) * sizeof (Elf_Internal_Shdr *); - sorted_hdrs = (Elf_Internal_Shdr **) malloc (hdrppsize); - if (sorted_hdrs == NULL) - { - bfd_set_error (bfd_error_no_memory); - return false; - } + Elf_Internal_Shdr **hdrpp; - memcpy (sorted_hdrs, i_shdrpp + 1, hdrppsize); - qsort (sorted_hdrs, (size_t) i_ehdrp->e_shnum - 1, - sizeof (Elf_Internal_Shdr *), elf_sort_hdrs); - - /* We can't actually create the program header until we have set the - file positions for the sections, and we can't do that until we know - how big the header is going to be. */ - off = align_file_position (off, bed->s->file_align); - phdr_size = get_program_header_size (abfd, - sorted_hdrs, i_ehdrp->e_shnum - 1, - maxpagesize); - if (phdr_size == (bfd_size_type) -1) + /* Assign file positions for the loaded sections based on the + assignment of sections to segments. */ + if (! assign_file_positions_for_segments (abfd)) return false; - /* Compute the file offsets of each section. */ - phdr_off = off; - off += phdr_size; - first = NULL; - for (i = 1, hdrpp = sorted_hdrs; i < i_ehdrp->e_shnum; i++, hdrpp++) + /* Assign file positions for the other sections. */ + + off = elf_tdata (abfd)->next_file_pos; + for (i = 1, hdrpp = i_shdrpp + 1; i < i_ehdrp->e_shnum; i++, hdrpp++) { Elf_Internal_Shdr *hdr; hdr = *hdrpp; - if ((hdr->sh_flags & SHF_ALLOC) == 0) - { - if (hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA) - { - hdr->sh_offset = -1; - continue; - } - if (! dosyms - && (hdr == i_shdrpp[tdata->symtab_section] - || hdr == i_shdrpp[tdata->strtab_section])) - { - hdr->sh_offset = -1; - continue; - } - off = _bfd_elf_assign_file_position_for_section (hdr, off, - true); - } - else + if (hdr->bfd_section != NULL + && hdr->bfd_section->filepos != 0) + hdr->sh_offset = hdr->bfd_section->filepos; + else if ((hdr->sh_flags & SHF_ALLOC) != 0) { - if (first == NULL) - first = hdr; - - /* The section VMA must equal the file position modulo - the page size. This is required by the program - header. */ - off += (hdr->sh_addr - off) % maxpagesize; + ((*_bfd_error_handler) + ("%s: warning: allocated section `%s' not in segment", + bfd_get_filename (abfd), + (hdr->bfd_section == NULL + ? "*unknown*" + : hdr->bfd_section->name))); + off += (hdr->sh_addr - off) % bed->maxpagesize; off = _bfd_elf_assign_file_position_for_section (hdr, off, false); } - } - - /* Create the program header. */ - phdr_map = map_program_segments (abfd, phdr_off, first, sorted_hdrs, - phdr_size); - if (phdr_map == (file_ptr) -1) - return false; - BFD_ASSERT ((bfd_size_type) phdr_map - <= (bfd_size_type) phdr_off + phdr_size); - - free (sorted_hdrs); + else if (hdr->sh_type == SHT_REL + || hdr->sh_type == SHT_RELA + || hdr == i_shdrpp[tdata->symtab_section] + || hdr == i_shdrpp[tdata->strtab_section]) + hdr->sh_offset = -1; + else + off = _bfd_elf_assign_file_position_for_section (hdr, off, true); + } } /* Place the section headers. */ @@ -1990,47 +2105,6 @@ assign_file_positions_except_relocs (abfd, dosyms) return true; } -/* Sort the ELF headers by VMA. We sort headers which are not - SHF_ALLOC to the end. */ -static int -elf_sort_hdrs (arg1, arg2) - const PTR arg1; - const PTR arg2; -{ - int ret; - const Elf_Internal_Shdr *hdr1 = *(const Elf_Internal_Shdr **) arg1; - const Elf_Internal_Shdr *hdr2 = *(const Elf_Internal_Shdr **) arg2; - -#define TOEND(x) (((x)->sh_flags & SHF_ALLOC)==0) - - if (TOEND (hdr1)) - if (TOEND (hdr2)) - return 0; - else - return 1; - - if (TOEND (hdr2)) - return -1; - - if (hdr1->sh_addr < hdr2->sh_addr) - return -1; - else if (hdr1->sh_addr > hdr2->sh_addr) - return 1; - - /* Put !SHT_NOBITS sections before SHT_NOBITS ones. - The main loop in map_program_segments requires this. */ - - ret = (hdr1->sh_type == SHT_NOBITS) - (hdr2->sh_type == SHT_NOBITS); - - if (ret != 0) - return ret; - if (hdr1->sh_size < hdr2->sh_size) - return -1; - if (hdr1->sh_size > hdr2->sh_size) - return 1; - return 0; -} - static boolean prep_headers (abfd) bfd *abfd; @@ -2325,6 +2399,80 @@ _bfd_elf_symbol_from_bfd_symbol (abfd, asym_ptr_ptr) return idx; } +/* Copy private section information. This copies over the entsize + field, and sometimes the info field. */ + +boolean +_bfd_elf_copy_private_section_data (ibfd, isec, obfd, osec) + bfd *ibfd; + asection *isec; + bfd *obfd; + asection *osec; +{ + Elf_Internal_Shdr *ihdr, *ohdr; + + if (ibfd->xvec->flavour != bfd_target_elf_flavour + || obfd->xvec->flavour != bfd_target_elf_flavour) + return true; + + ihdr = &elf_section_data (isec)->this_hdr; + ohdr = &elf_section_data (osec)->this_hdr; + + ohdr->sh_entsize = ihdr->sh_entsize; + + if (ihdr->sh_type == SHT_SYMTAB + || ihdr->sh_type == SHT_DYNSYM) + ohdr->sh_info = ihdr->sh_info; + + return true; +} + +/* Copy private symbol information. If this symbol is in a section + which we did not map into a BFD section, try to map the section + index correctly. We use special macro definitions for the mapped + section indices; these definitions are interpreted by the + swap_out_syms function. */ + +#define MAP_ONESYMTAB (SHN_LORESERVE - 1) +#define MAP_DYNSYMTAB (SHN_LORESERVE - 2) +#define MAP_STRTAB (SHN_LORESERVE - 3) +#define MAP_SHSTRTAB (SHN_LORESERVE - 4) + +boolean +_bfd_elf_copy_private_symbol_data (ibfd, isymarg, obfd, osymarg) + bfd *ibfd; + asymbol *isymarg; + bfd *obfd; + asymbol *osymarg; +{ + elf_symbol_type *isym, *osym; + + isym = elf_symbol_from (ibfd, isymarg); + osym = elf_symbol_from (obfd, osymarg); + + if (isym != NULL + && osym != NULL + && bfd_is_abs_section (isym->symbol.section)) + { + unsigned int shndx; + + shndx = isym->internal_elf_sym.st_shndx; + if (shndx == elf_onesymtab (ibfd)) + shndx = MAP_ONESYMTAB; + else if (shndx == elf_dynsymtab (ibfd)) + shndx = MAP_DYNSYMTAB; + else if (shndx == elf_tdata (ibfd)->strtab_section) + shndx = MAP_STRTAB; + else if (shndx == elf_tdata (ibfd)->shstrtab_section) + shndx = MAP_SHSTRTAB; + osym->internal_elf_sym.st_shndx = shndx; + } + + return true; +} + +/* Swap out the symbols. */ + static boolean swap_out_syms (abfd, sttp) bfd *abfd; @@ -2429,21 +2577,56 @@ swap_out_syms (abfd, sttp) value += sec->vma; sym.st_value = value; sym.st_size = type_ptr ? type_ptr->internal_elf_sym.st_size : 0; - sym.st_shndx = shndx = _bfd_elf_section_from_bfd_section (abfd, sec); - if (shndx == -1) + + if (bfd_is_abs_section (sec) + && type_ptr != NULL + && type_ptr->internal_elf_sym.st_shndx != 0) { - asection *sec2; - /* Writing this would be a hell of a lot easier if we had - some decent documentation on bfd, and knew what to expect - of the library, and what to demand of applications. For - example, it appears that `objcopy' might not set the - section of a symbol to be a section that is actually in - the output file. */ - sec2 = bfd_get_section_by_name (abfd, sec->name); - BFD_ASSERT (sec2 != 0); - sym.st_shndx = shndx = _bfd_elf_section_from_bfd_section (abfd, sec2); - BFD_ASSERT (shndx != -1); + /* This symbol is in a real ELF section which we did + not create as a BFD section. Undo the mapping done + by copy_private_symbol_data. */ + shndx = type_ptr->internal_elf_sym.st_shndx; + switch (shndx) + { + case MAP_ONESYMTAB: + shndx = elf_onesymtab (abfd); + break; + case MAP_DYNSYMTAB: + shndx = elf_dynsymtab (abfd); + break; + case MAP_STRTAB: + shndx = elf_tdata (abfd)->strtab_section; + break; + case MAP_SHSTRTAB: + shndx = elf_tdata (abfd)->shstrtab_section; + break; + default: + break; + } + } + else + { + shndx = _bfd_elf_section_from_bfd_section (abfd, sec); + + if (shndx == -1) + { + asection *sec2; + + /* Writing this would be a hell of a lot easier if + we had some decent documentation on bfd, and + knew what to expect of the library, and what to + demand of applications. For example, it + appears that `objcopy' might not set the + section of a symbol to be a section that is + actually in the output file. */ + sec2 = bfd_get_section_by_name (abfd, sec->name); + BFD_ASSERT (sec2 != 0); + shndx = _bfd_elf_section_from_bfd_section (abfd, sec2); + BFD_ASSERT (shndx != -1); + } } + + sym.st_shndx = shndx; } if (bfd_is_com_section (syms[idx]->section)) @@ -2713,8 +2896,7 @@ _bfd_elf_sizeof_headers (abfd, reloc) ret = get_elf_backend_data (abfd)->s->sizeof_ehdr; if (! reloc) - ret += get_program_header_size (abfd, (Elf_Internal_Shdr **) NULL, 0, - (bfd_vma) 0); + ret += get_program_header_size (abfd); return ret; } |