X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felf.c;h=fd447fdb281e5de1cd3cbb5917a57ac80ffd1f0e;hb=0bc3450e220a4fb29f931ada84b546ce8993e85e;hp=bb994b5aaa380a23df8745412e970585dbfc2c0a;hpb=6d5944fca682fe97f37e537f78b665ada2400f51;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf.c b/bfd/elf.c index bb994b5aaa..fd447fdb28 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -51,10 +51,7 @@ SECTION static int elf_sort_sections (const void *, const void *); static bfd_boolean assign_file_positions_except_relocs (bfd *, struct bfd_link_info *); -static bfd_boolean prep_headers (bfd *); static bfd_boolean swap_out_syms (bfd *, struct elf_strtab_hash **, int) ; -static bfd_boolean elf_read_notes (bfd *, file_ptr, bfd_size_type, - size_t align) ; static bfd_boolean elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset, size_t align); @@ -1105,23 +1102,16 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, not any sort of flag. Their SEC_ALLOC bits are cleared. */ if (name [0] == '.') { - const char *p; - int n; - if (name[1] == 'd') - p = ".debug", n = 6; - else if (name[1] == 'g' && name[2] == 'n') - p = ".gnu.linkonce.wi.", n = 17; - else if (name[1] == 'g' && name[2] == 'd') - p = ".gdb_index", n = 11; /* yes we really do mean 11. */ - else if (name[1] == 'l') - p = ".line", n = 5; - else if (name[1] == 's') - p = ".stab", n = 5; - else if (name[1] == 'z') - p = ".zdebug", n = 7; - else - p = NULL, n = 0; - if (p != NULL && strncmp (name, p, n) == 0) + if (strncmp (name, ".debug", 6) == 0 + || strncmp (name, ".gnu.linkonce.wi.", 17) == 0 + || strncmp (name, ".zdebug", 7) == 0) + flags |= SEC_DEBUGGING | SEC_ELF_OCTETS; + else if (strncmp (name, GNU_BUILD_ATTRS_SECTION_NAME, 21) == 0 + || strncmp (name, ".note.gnu", 9) == 0) + flags |= SEC_ELF_OCTETS; + else if (strncmp (name, ".line", 5) == 0 + || strncmp (name, ".stab", 5) == 0 + || strcmp (name, ".gdb_index") == 0) flags |= SEC_DEBUGGING; } } @@ -2671,6 +2661,7 @@ static const struct bfd_elf_special_section special_sections_b[] = static const struct bfd_elf_special_section special_sections_c[] = { { STRING_COMMA_LEN (".comment"), 0, SHT_PROGBITS, 0 }, + { STRING_COMMA_LEN (".ctf"), 0, SHT_PROGBITS, 0 }, { NULL, 0, 0, 0, 0 } }; @@ -3060,6 +3051,16 @@ _bfd_elf_make_section_from_phdr (bfd *abfd, return TRUE; } +static bfd_boolean +_bfd_elf_core_find_build_id (bfd *templ, bfd_vma offset) +{ + /* The return value is ignored. Build-ids are considered optional. */ + if (templ->xvec->flavour == bfd_target_elf_flavour) + return (*get_elf_backend_data (templ)->elf_backend_core_find_build_id) + (templ, offset); + return FALSE; +} + bfd_boolean bfd_section_from_phdr (bfd *abfd, Elf_Internal_Phdr *hdr, int hdr_index) { @@ -3071,7 +3072,11 @@ bfd_section_from_phdr (bfd *abfd, Elf_Internal_Phdr *hdr, int hdr_index) return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "null"); case PT_LOAD: - return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "load"); + if (! _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "load")) + return FALSE; + if (bfd_get_format (abfd) == bfd_core && abfd->build_id == NULL) + _bfd_elf_core_find_build_id (abfd, hdr->p_offset); + return TRUE; case PT_DYNAMIC: return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "dynamic"); @@ -4299,12 +4304,9 @@ _bfd_elf_compute_section_file_positions (bfd *abfd, if (bed->elf_backend_begin_write_processing) (*bed->elf_backend_begin_write_processing) (abfd, link_info); - if (! prep_headers (abfd)) + if (!(*bed->elf_backend_init_file_header) (abfd, link_info)) return FALSE; - /* Post process the headers if necessary. */ - (*bed->elf_backend_post_process_headers) (abfd, link_info); - fsargs.failed = FALSE; fsargs.link_info = link_info; bfd_map_over_sections (abfd, elf_fake_sections, &fsargs); @@ -4337,7 +4339,7 @@ _bfd_elf_compute_section_file_positions (bfd *abfd, } shstrtab_hdr = &elf_tdata (abfd)->shstrtab_hdr; - /* sh_name was set in prep_headers. */ + /* sh_name was set in init_file_header. */ shstrtab_hdr->sh_type = SHT_STRTAB; shstrtab_hdr->sh_flags = bed->elf_strtab_flags; shstrtab_hdr->sh_addr = 0; @@ -4702,6 +4704,10 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) { if ((s->flags & SEC_ALLOC) != 0) { + /* target_index is unused until bfd_elf_final_link + starts output of section symbols. Use it to make + qsort stable. */ + s->target_index = i; sections[i] = s; ++i; /* A wrapping section potentially clashes with header. */ @@ -5269,14 +5275,7 @@ elf_sort_sections (const void *arg1, const void *arg2) if (TOEND (sec1)) { - if (TOEND (sec2)) - { - /* If the indices are the same, do not return 0 - here, but continue to try the next comparison. */ - if (sec1->target_index - sec2->target_index != 0) - return sec1->target_index - sec2->target_index; - } - else + if (!TOEND (sec2)) return 1; } else if (TOEND (sec2)) @@ -5298,6 +5297,48 @@ elf_sort_sections (const void *arg1, const void *arg2) return sec1->target_index - sec2->target_index; } +/* This qsort comparison functions sorts PT_LOAD segments first and + by p_paddr, for assign_file_positions_for_load_sections. */ + +static int +elf_sort_segments (const void *arg1, const void *arg2) +{ + const struct elf_segment_map *m1 = *(const struct elf_segment_map **) arg1; + const struct elf_segment_map *m2 = *(const struct elf_segment_map **) arg2; + + if (m1->p_type != m2->p_type) + { + if (m1->p_type == PT_NULL) + return 1; + if (m2->p_type == PT_NULL) + return -1; + return m1->p_type < m2->p_type ? -1 : 1; + } + if (m1->includes_filehdr != m2->includes_filehdr) + return m1->includes_filehdr ? -1 : 1; + if (m1->no_sort_lma != m2->no_sort_lma) + return m1->no_sort_lma ? -1 : 1; + if (m1->p_type == PT_LOAD && !m1->no_sort_lma) + { + bfd_vma lma1, lma2; + lma1 = 0; + if (m1->p_paddr_valid) + lma1 = m1->p_paddr; + else if (m1->count != 0) + lma1 = m1->sections[0]->lma + m1->p_vaddr_offset; + lma2 = 0; + if (m2->p_paddr_valid) + lma2 = m2->p_paddr; + else if (m2->count != 0) + lma2 = m2->sections[0]->lma + m2->p_vaddr_offset; + if (lma1 != lma2) + return lma1 < lma2 ? -1 : 1; + } + if (m1->idx != m2->idx) + return m1->idx < m2->idx ? -1 : 1; + return 0; +} + /* Ian Lance Taylor writes: We shouldn't be using % with a negative signed number. That's just @@ -5384,14 +5425,14 @@ assign_file_positions_for_load_sections (bfd *abfd, { const struct elf_backend_data *bed = get_elf_backend_data (abfd); struct elf_segment_map *m; + struct elf_segment_map *phdr_load_seg; Elf_Internal_Phdr *phdrs; Elf_Internal_Phdr *p; file_ptr off; bfd_size_type maxpagesize; - unsigned int pt_load_count = 0; - unsigned int alloc; + unsigned int alloc, actual; unsigned int i, j; - bfd_vma header_pad = 0; + struct elf_segment_map **sorted_seg_map; if (link_info == NULL && !_bfd_elf_map_sections_to_segments (abfd, link_info)) @@ -5399,11 +5440,7 @@ assign_file_positions_for_load_sections (bfd *abfd, alloc = 0; for (m = elf_seg_map (abfd); m != NULL; m = m->next) - { - ++alloc; - if (m->header_size) - header_pad = m->header_size; - } + m->idx = alloc++; if (alloc) { @@ -5420,10 +5457,17 @@ assign_file_positions_for_load_sections (bfd *abfd, elf_elfheader (abfd)->e_phnum = alloc; if (elf_program_header_size (abfd) == (bfd_size_type) -1) - elf_program_header_size (abfd) = alloc * bed->s->sizeof_phdr; + { + actual = alloc; + elf_program_header_size (abfd) = alloc * bed->s->sizeof_phdr; + } else - BFD_ASSERT (elf_program_header_size (abfd) - >= alloc * bed->s->sizeof_phdr); + { + actual = elf_program_header_size (abfd) / bed->s->sizeof_phdr; + BFD_ASSERT (elf_program_header_size (abfd) + == actual * bed->s->sizeof_phdr); + BFD_ASSERT (actual >= alloc); + } if (alloc == 0) { @@ -5440,52 +5484,72 @@ assign_file_positions_for_load_sections (bfd *abfd, See ld/emultempl/elf-generic.em:gld${EMULATION_NAME}_map_segments where the layout is forced to according to a larger size in the last iterations for the testcase ld-elf/header. */ - BFD_ASSERT (elf_program_header_size (abfd) % bed->s->sizeof_phdr - == 0); - phdrs = (Elf_Internal_Phdr *) - bfd_zalloc2 (abfd, - (elf_program_header_size (abfd) / bed->s->sizeof_phdr), - sizeof (Elf_Internal_Phdr)); + phdrs = bfd_zalloc (abfd, (actual * sizeof (*phdrs) + + alloc * sizeof (*sorted_seg_map))); + sorted_seg_map = (struct elf_segment_map **) (phdrs + actual); elf_tdata (abfd)->phdr = phdrs; if (phdrs == NULL) return FALSE; + for (m = elf_seg_map (abfd), j = 0; m != NULL; m = m->next, j++) + { + sorted_seg_map[j] = m; + /* If elf_segment_map is not from map_sections_to_segments, the + sections may not be correctly ordered. NOTE: sorting should + not be done to the PT_NOTE section of a corefile, which may + contain several pseudo-sections artificially created by bfd. + Sorting these pseudo-sections breaks things badly. */ + if (m->count > 1 + && !(elf_elfheader (abfd)->e_type == ET_CORE + && m->p_type == PT_NOTE)) + { + for (i = 0; i < m->count; i++) + m->sections[i]->target_index = i; + qsort (m->sections, (size_t) m->count, sizeof (asection *), + elf_sort_sections); + } + } + if (alloc > 1) + qsort (sorted_seg_map, alloc, sizeof (*sorted_seg_map), + elf_sort_segments); + maxpagesize = 1; if ((abfd->flags & D_PAGED) != 0) maxpagesize = bed->maxpagesize; + /* Sections must map to file offsets past the ELF file header. */ off = bed->s->sizeof_ehdr; - off += alloc * bed->s->sizeof_phdr; - if (header_pad < (bfd_vma) off) - header_pad = 0; - else - header_pad -= off; - off += header_pad; + /* And if one of the PT_LOAD headers doesn't include the program + headers then we'll be mapping program headers in the usual + position after the ELF file header. */ + phdr_load_seg = NULL; + for (j = 0; j < alloc; j++) + { + m = sorted_seg_map[j]; + if (m->p_type != PT_LOAD) + break; + if (m->includes_phdrs) + { + phdr_load_seg = m; + break; + } + } + if (phdr_load_seg == NULL) + off += actual * bed->s->sizeof_phdr; - for (m = elf_seg_map (abfd), p = phdrs, j = 0; - m != NULL; - m = m->next, p++, j++) + for (j = 0; j < alloc; j++) { asection **secpp; bfd_vma off_adjust; bfd_boolean no_contents; - /* If elf_segment_map is not from map_sections_to_segments, the - sections may not be correctly ordered. NOTE: sorting should - not be done to the PT_NOTE section of a corefile, which may - contain several pseudo-sections artificially created by bfd. - Sorting these pseudo-sections breaks things badly. */ - if (m->count > 1 - && !(elf_elfheader (abfd)->e_type == ET_CORE - && m->p_type == PT_NOTE)) - qsort (m->sections, (size_t) m->count, sizeof (asection *), - elf_sort_sections); - /* An ELF segment (described by Elf_Internal_Phdr) may contain a number of sections with contents contributing to both p_filesz and p_memsz, followed by a number of sections with no contents that just contribute to p_memsz. In this loop, OFF tracks next available file offset for PT_LOAD and PT_NOTE segments. */ + m = sorted_seg_map[j]; + p = phdrs + m->idx; p->p_type = m->p_type; p->p_flags = m->p_flags; @@ -5516,14 +5580,18 @@ assign_file_positions_for_load_sections (bfd *abfd, maxpagesize = m->p_align; p->p_align = maxpagesize; - pt_load_count += 1; } else if (m->p_align_valid) p->p_align = m->p_align; else if (m->count == 0) p->p_align = 1 << bed->s->log_file_align; - else - p->p_align = 0; + + if (m == phdr_load_seg) + { + if (!m->includes_filehdr) + p->p_offset = off; + off += actual * bed->s->sizeof_phdr; + } no_contents = FALSE; off_adjust = 0; @@ -5572,7 +5640,8 @@ assign_file_positions_for_load_sections (bfd *abfd, /* Broken hardware and/or kernel require that files do not map the same page with different permissions on some hppa processors. */ - if (pt_load_count > 1 + if (j != 0 + && (abfd->flags & D_PAGED) != 0 && bed->no_page_alias && (off & (maxpagesize - 1)) != 0 && (off & -maxpagesize) == ((off + off_adjust) & -maxpagesize)) @@ -5610,33 +5679,38 @@ assign_file_positions_for_load_sections (bfd *abfd, for (i = 0; i < m->count; i++) elf_section_type (m->sections[i]) = SHT_NOTE; - p->p_offset = 0; - p->p_filesz = 0; - p->p_memsz = 0; - if (m->includes_filehdr) { if (!m->p_flags_valid) p->p_flags |= PF_R; p->p_filesz = bed->s->sizeof_ehdr; p->p_memsz = bed->s->sizeof_ehdr; - if (m->count > 0) + if (p->p_type == PT_LOAD) { - if (p->p_vaddr < (bfd_vma) off - || (!m->p_paddr_valid - && p->p_paddr < (bfd_vma) off)) + if (m->count > 0) { - _bfd_error_handler - (_("%pB: not enough room for program headers," - " try linking with -N"), - abfd); - bfd_set_error (bfd_error_bad_value); - return FALSE; + if (p->p_vaddr < (bfd_vma) off + || (!m->p_paddr_valid + && p->p_paddr < (bfd_vma) off)) + { + _bfd_error_handler + (_("%pB: not enough room for program headers," + " try linking with -N"), + abfd); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + p->p_vaddr -= off; + if (!m->p_paddr_valid) + p->p_paddr -= off; } - - p->p_vaddr -= off; + } + else if (sorted_seg_map[0]->includes_filehdr) + { + Elf_Internal_Phdr *filehdr = phdrs + sorted_seg_map[0]->idx; + p->p_vaddr = filehdr->p_vaddr; if (!m->p_paddr_valid) - p->p_paddr -= off; + p->p_paddr = filehdr->p_paddr; } } @@ -5644,25 +5718,33 @@ assign_file_positions_for_load_sections (bfd *abfd, { if (!m->p_flags_valid) p->p_flags |= PF_R; - + p->p_filesz += actual * bed->s->sizeof_phdr; + p->p_memsz += actual * bed->s->sizeof_phdr; if (!m->includes_filehdr) { - p->p_offset = bed->s->sizeof_ehdr; - - if (m->count > 0) + if (p->p_type == PT_LOAD) { - p->p_vaddr -= off - p->p_offset; + elf_elfheader (abfd)->e_phoff = p->p_offset; + if (m->count > 0) + { + p->p_vaddr -= off - p->p_offset; + if (!m->p_paddr_valid) + p->p_paddr -= off - p->p_offset; + } + } + else if (phdr_load_seg != NULL) + { + Elf_Internal_Phdr *phdr = phdrs + phdr_load_seg->idx; + bfd_vma phdr_off = 0; + if (phdr_load_seg->includes_filehdr) + phdr_off = bed->s->sizeof_ehdr; + p->p_vaddr = phdr->p_vaddr + phdr_off; if (!m->p_paddr_valid) - p->p_paddr -= off - p->p_offset; + p->p_paddr = phdr->p_paddr + phdr_off; + p->p_offset = phdr->p_offset + phdr_off; } - } - - p->p_filesz += alloc * bed->s->sizeof_phdr; - p->p_memsz += alloc * bed->s->sizeof_phdr; - if (m->count) - { - p->p_filesz += header_pad; - p->p_memsz += header_pad; + else + p->p_offset = bed->s->sizeof_ehdr; } } @@ -5670,7 +5752,15 @@ assign_file_positions_for_load_sections (bfd *abfd, || (p->p_type == PT_NOTE && bfd_get_format (abfd) == bfd_core)) { if (!m->includes_filehdr && !m->includes_phdrs) - p->p_offset = off; + { + p->p_offset = off; + if (no_contents) + /* Put meaningless p_offset for PT_LOAD segments + without file contents somewhere within the first + page, in an attempt to not point past EOF. */ + p->p_offset = off % (p->p_align > maxpagesize + ? p->p_align : maxpagesize); + } else { file_ptr adjust; @@ -5724,16 +5814,19 @@ assign_file_positions_for_load_sections (bfd *abfd, if (this_hdr->sh_type != SHT_NOBITS) { - if (p->p_filesz + adjust < p->p_memsz) + if (p->p_type == PT_LOAD) { - /* We have a PROGBITS section following NOBITS ones. - Allocate file space for the NOBITS section(s) and - zero it. */ - adjust = p->p_memsz - p->p_filesz; - if (!write_zeros (abfd, off, adjust)) - return FALSE; + if (p->p_filesz + adjust < p->p_memsz) + { + /* We have a PROGBITS section following NOBITS ones. + Allocate file space for the NOBITS section(s) and + zero it. */ + adjust = p->p_memsz - p->p_filesz; + if (!write_zeros (abfd, off, adjust)) + return FALSE; + } + off += adjust; } - off += adjust; p->p_filesz += adjust; } } @@ -5822,6 +5915,22 @@ assign_file_positions_for_load_sections (bfd *abfd, off -= off_adjust; + /* PR ld/20815 - Check that the program header segment, if + present, will be loaded into memory. */ + if (p->p_type == PT_PHDR + && phdr_load_seg == NULL + && !(bed->elf_backend_allow_non_load_phdr != NULL + && bed->elf_backend_allow_non_load_phdr (abfd, phdrs, alloc))) + { + /* The fix for this error is usually to edit the linker script being + used and set up the program headers manually. Either that or + leave room for the headers at the start of the SECTIONS. */ + _bfd_error_handler (_("%pB: error: PHDR segment not covered" + " by LOAD segment"), + abfd); + return FALSE; + } + /* Check that all sections are in a PT_LOAD segment. Don't check funky gdb generated core files. */ if (p->p_type == PT_LOAD && bfd_get_format (abfd) != bfd_core) @@ -5861,6 +5970,57 @@ assign_file_positions_for_load_sections (bfd *abfd, } elf_next_file_pos (abfd) = off; + + if (link_info != NULL + && phdr_load_seg != NULL + && phdr_load_seg->includes_filehdr) + { + /* There is a segment that contains both the file headers and the + program headers, so provide a symbol __ehdr_start pointing there. + A program can use this to examine itself robustly. */ + + struct elf_link_hash_entry *hash + = elf_link_hash_lookup (elf_hash_table (link_info), "__ehdr_start", + FALSE, FALSE, TRUE); + /* If the symbol was referenced and not defined, define it. */ + if (hash != NULL + && (hash->root.type == bfd_link_hash_new + || hash->root.type == bfd_link_hash_undefined + || hash->root.type == bfd_link_hash_undefweak + || hash->root.type == bfd_link_hash_common)) + { + asection *s = NULL; + bfd_vma filehdr_vaddr = phdrs[phdr_load_seg->idx].p_vaddr; + + if (phdr_load_seg->count != 0) + /* The segment contains sections, so use the first one. */ + s = phdr_load_seg->sections[0]; + else + /* Use the first (i.e. lowest-addressed) section in any segment. */ + for (m = elf_seg_map (abfd); m != NULL; m = m->next) + if (m->p_type == PT_LOAD && m->count != 0) + { + s = m->sections[0]; + break; + } + + if (s != NULL) + { + hash->root.u.def.value = filehdr_vaddr - s->vma; + hash->root.u.def.section = s; + } + else + { + hash->root.u.def.value = filehdr_vaddr; + hash->root.u.def.section = bfd_abs_section_ptr; + } + + hash->root.type = bfd_link_hash_defined; + hash->def_regular = 1; + hash->non_elf = 0; + } + } + return TRUE; } @@ -5893,7 +6053,8 @@ is_debuginfo_file (bfd *abfd) return TRUE; } -/* Assign file positions for the other sections. */ +/* Assign file positions for the other sections, except for compressed debugging + and other sections assigned in _bfd_elf_assign_file_positions_for_non_load(). */ static bfd_boolean assign_file_positions_for_non_load_sections (bfd *abfd, @@ -5905,11 +6066,7 @@ assign_file_positions_for_non_load_sections (bfd *abfd, Elf_Internal_Phdr *phdrs; Elf_Internal_Phdr *p; struct elf_segment_map *m; - struct elf_segment_map *hdrs_segment; - bfd_vma filehdr_vaddr, filehdr_paddr; - bfd_vma phdrs_vaddr, phdrs_paddr; file_ptr off; - unsigned int count; i_shdrpp = elf_elfsections (abfd); end_hdrpp = i_shdrpp + elf_numsections (abfd); @@ -5952,9 +6109,12 @@ assign_file_positions_for_non_load_sections (bfd *abfd, } else if (((hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA) && hdr->bfd_section == NULL) + /* We don't know the offset of these sections yet: their size has + not been decided. */ || (hdr->bfd_section != NULL - && (hdr->bfd_section->flags & SEC_ELF_COMPRESS)) - /* Compress DWARF debug sections. */ + && (hdr->bfd_section->flags & SEC_ELF_COMPRESS + || (bfd_section_is_ctf (hdr->bfd_section) + && abfd->is_linker_output))) || hdr == i_shdrpp[elf_onesymtab (abfd)] || (elf_symtab_shndx_list (abfd) != NULL && hdr == i_shdrpp[elf_symtab_shndx_list (abfd)->ndx]) @@ -5964,86 +6124,11 @@ assign_file_positions_for_non_load_sections (bfd *abfd, else off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE); } + elf_next_file_pos (abfd) = off; /* Now that we have set the section file positions, we can set up the file positions for the non PT_LOAD segments. */ - count = 0; - filehdr_vaddr = 0; - filehdr_paddr = 0; - phdrs_vaddr = bed->maxpagesize + bed->s->sizeof_ehdr; - phdrs_paddr = 0; - hdrs_segment = NULL; phdrs = elf_tdata (abfd)->phdr; - for (m = elf_seg_map (abfd), p = phdrs; m != NULL; m = m->next, p++) - { - ++count; - if (p->p_type != PT_LOAD) - continue; - - if (m->includes_filehdr) - { - filehdr_vaddr = p->p_vaddr; - filehdr_paddr = p->p_paddr; - } - if (m->includes_phdrs) - { - phdrs_vaddr = p->p_vaddr; - phdrs_paddr = p->p_paddr; - if (m->includes_filehdr) - { - hdrs_segment = m; - phdrs_vaddr += bed->s->sizeof_ehdr; - phdrs_paddr += bed->s->sizeof_ehdr; - } - } - } - - if (hdrs_segment != NULL && link_info != NULL) - { - /* There is a segment that contains both the file headers and the - program headers, so provide a symbol __ehdr_start pointing there. - A program can use this to examine itself robustly. */ - - struct elf_link_hash_entry *hash - = elf_link_hash_lookup (elf_hash_table (link_info), "__ehdr_start", - FALSE, FALSE, TRUE); - /* If the symbol was referenced and not defined, define it. */ - if (hash != NULL - && (hash->root.type == bfd_link_hash_new - || hash->root.type == bfd_link_hash_undefined - || hash->root.type == bfd_link_hash_undefweak - || hash->root.type == bfd_link_hash_common)) - { - asection *s = NULL; - if (hdrs_segment->count != 0) - /* The segment contains sections, so use the first one. */ - s = hdrs_segment->sections[0]; - else - /* Use the first (i.e. lowest-addressed) section in any segment. */ - for (m = elf_seg_map (abfd); m != NULL; m = m->next) - if (m->count != 0) - { - s = m->sections[0]; - break; - } - - if (s != NULL) - { - hash->root.u.def.value = filehdr_vaddr - s->vma; - hash->root.u.def.section = s; - } - else - { - hash->root.u.def.value = filehdr_vaddr; - hash->root.u.def.section = bfd_abs_section_ptr; - } - - hash->root.type = bfd_link_hash_defined; - hash->def_regular = 1; - hash->non_elf = 0; - } - } - for (m = elf_seg_map (abfd), p = phdrs; m != NULL; m = m->next, p++) { if (p->p_type == PT_GNU_RELRO) @@ -6189,22 +6274,8 @@ assign_file_positions_for_non_load_sections (bfd *abfd, } } } - else if (m->includes_filehdr) - { - p->p_vaddr = filehdr_vaddr; - if (! m->p_paddr_valid) - p->p_paddr = filehdr_paddr; - } - else if (m->includes_phdrs) - { - p->p_vaddr = phdrs_vaddr; - if (! m->p_paddr_valid) - p->p_paddr = phdrs_paddr; - } } - elf_next_file_pos (abfd) = off; - return TRUE; } @@ -6222,11 +6293,12 @@ find_section_in_list (unsigned int i, elf_section_list * list) VMAs must be known before this is called. Reloc sections come in two flavours: Those processed specially as - "side-channel" data attached to a section to which they apply, and - those that bfd doesn't process as relocations. The latter sort are - stored in a normal bfd section by bfd_section_from_shdr. We don't - consider the former sort here, unless they form part of the loadable - image. Reloc sections not assigned here will be handled later by + "side-channel" data attached to a section to which they apply, and those that + bfd doesn't process as relocations. The latter sort are stored in a normal + bfd section by bfd_section_from_shdr. We don't consider the former sort + here, unless they form part of the loadable image. Reloc sections not + assigned here (and compressed debugging sections and CTF sections which + nothing else in the file can rely upon) will be handled later by assign_file_positions_for_relocs. We also don't set the positions of the .symtab and .strtab here. */ @@ -6238,6 +6310,7 @@ assign_file_positions_except_relocs (bfd *abfd, struct elf_obj_tdata *tdata = elf_tdata (abfd); Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd); const struct elf_backend_data *bed = get_elf_backend_data (abfd); + unsigned int alloc; if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0 && bfd_get_format (abfd) != bfd_core) @@ -6261,9 +6334,12 @@ assign_file_positions_except_relocs (bfd *abfd, hdr = *hdrpp; if (((hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA) && hdr->bfd_section == NULL) + /* Do not assign offsets for these sections yet: we don't know + their sizes. */ || (hdr->bfd_section != NULL - && (hdr->bfd_section->flags & SEC_ELF_COMPRESS)) - /* Compress DWARF debug sections. */ + && (hdr->bfd_section->flags & SEC_ELF_COMPRESS + || (bfd_section_is_ctf (hdr->bfd_section) + && abfd->is_linker_output))) || i == elf_onesymtab (abfd) || (elf_symtab_shndx_list (abfd) != NULL && hdr == i_shdrpp[elf_symtab_shndx_list (abfd)->ndx]) @@ -6277,11 +6353,10 @@ assign_file_positions_except_relocs (bfd *abfd, } elf_next_file_pos (abfd) = off; + elf_program_header_size (abfd) = 0; } else { - unsigned int alloc; - /* Assign file positions for the loaded sections based on the assignment of sections to segments. */ if (!assign_file_positions_for_load_sections (abfd, link_info)) @@ -6290,68 +6365,16 @@ assign_file_positions_except_relocs (bfd *abfd, /* And for non-load sections. */ if (!assign_file_positions_for_non_load_sections (abfd, link_info)) return FALSE; + } - if (bed->elf_backend_modify_program_headers != NULL) - { - if (!(*bed->elf_backend_modify_program_headers) (abfd, link_info)) - return FALSE; - } - - /* Set e_type in ELF header to ET_EXEC for -pie -Ttext-segment=. */ - if (link_info != NULL && bfd_link_pie (link_info)) - { - unsigned int num_segments = elf_elfheader (abfd)->e_phnum; - Elf_Internal_Phdr *segment = elf_tdata (abfd)->phdr; - Elf_Internal_Phdr *end_segment = &segment[num_segments]; - - /* Find the lowest p_vaddr in PT_LOAD segments. */ - bfd_vma p_vaddr = (bfd_vma) -1; - for (; segment < end_segment; segment++) - if (segment->p_type == PT_LOAD && p_vaddr > segment->p_vaddr) - p_vaddr = segment->p_vaddr; - - /* Set e_type to ET_EXEC if the lowest p_vaddr in PT_LOAD - segments is non-zero. */ - if (p_vaddr) - i_ehdrp->e_type = ET_EXEC; - } - - /* Write out the program headers. */ - alloc = elf_elfheader (abfd)->e_phnum; - if (alloc == 0) - return TRUE; - - /* PR ld/20815 - Check that the program header segment, if present, will - be loaded into memory. FIXME: The check below is not sufficient as - really all PT_LOAD segments should be checked before issuing an error - message. Plus the PHDR segment does not have to be the first segment - in the program header table. But this version of the check should - catch all real world use cases. - - FIXME: We used to have code here to sort the PT_LOAD segments into - ascending order, as per the ELF spec. But this breaks some programs, - including the Linux kernel. But really either the spec should be - changed or the programs updated. */ - if (alloc > 1 - && tdata->phdr[0].p_type == PT_PHDR - && (bed->elf_backend_allow_non_load_phdr == NULL - || !bed->elf_backend_allow_non_load_phdr (abfd, tdata->phdr, - alloc)) - && tdata->phdr[1].p_type == PT_LOAD - && (tdata->phdr[1].p_vaddr > tdata->phdr[0].p_vaddr - || (tdata->phdr[1].p_vaddr + tdata->phdr[1].p_memsz - < tdata->phdr[0].p_vaddr + tdata->phdr[0].p_memsz))) - { - /* The fix for this error is usually to edit the linker script being - used and set up the program headers manually. Either that or - leave room for the headers at the start of the SECTIONS. */ - _bfd_error_handler (_("%pB: error: PHDR segment not covered" - " by LOAD segment"), - abfd); - return FALSE; - } + if (!(*bed->elf_backend_modify_headers) (abfd, link_info)) + return FALSE; - if (bfd_seek (abfd, (bfd_signed_vma) bed->s->sizeof_ehdr, SEEK_SET) != 0 + /* Write out the program headers. */ + alloc = i_ehdrp->e_phnum; + if (alloc != 0) + { + if (bfd_seek (abfd, i_ehdrp->e_phoff, SEEK_SET) != 0 || bed->s->write_out_phdrs (abfd, tdata->phdr, alloc) != 0) return FALSE; } @@ -6359,8 +6382,9 @@ assign_file_positions_except_relocs (bfd *abfd, return TRUE; } -static bfd_boolean -prep_headers (bfd *abfd) +bfd_boolean +_bfd_elf_init_file_header (bfd *abfd, + struct bfd_link_info *info ATTRIBUTE_UNUSED) { Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form. */ struct elf_strtab_hash *shstrtab; @@ -6423,16 +6447,6 @@ prep_headers (bfd *abfd) i_ehdrp->e_entry = bfd_get_start_address (abfd); i_ehdrp->e_shentsize = bed->s->sizeof_shdr; - /* If we're building an executable, we'll need a program header table. */ - if (abfd->flags & EXEC_P) - /* It all happens later. */ - ; - else - { - i_ehdrp->e_phentsize = 0; - i_ehdrp->e_phoff = 0; - } - elf_tdata (abfd)->symtab_hdr.sh_name = (unsigned int) _bfd_elf_strtab_add (shstrtab, ".symtab", FALSE); elf_tdata (abfd)->strtab_hdr.sh_name = @@ -6447,6 +6461,38 @@ prep_headers (bfd *abfd) return TRUE; } +/* Set e_type in ELF header to ET_EXEC for -pie -Ttext-segment=. + + FIXME: We used to have code here to sort the PT_LOAD segments into + ascending order, as per the ELF spec. But this breaks some programs, + including the Linux kernel. But really either the spec should be + changed or the programs updated. */ + +bfd_boolean +_bfd_elf_modify_headers (bfd *obfd, struct bfd_link_info *link_info) +{ + if (link_info != NULL && bfd_link_pie (link_info)) + { + Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (obfd); + unsigned int num_segments = i_ehdrp->e_phnum; + struct elf_obj_tdata *tdata = elf_tdata (obfd); + Elf_Internal_Phdr *segment = tdata->phdr; + Elf_Internal_Phdr *end_segment = &segment[num_segments]; + + /* Find the lowest p_vaddr in PT_LOAD segments. */ + bfd_vma p_vaddr = (bfd_vma) -1; + for (; segment < end_segment; segment++) + if (segment->p_type == PT_LOAD && p_vaddr > segment->p_vaddr) + p_vaddr = segment->p_vaddr; + + /* Set e_type to ET_EXEC if the lowest p_vaddr in PT_LOAD + segments is non-zero. */ + if (p_vaddr) + i_ehdrp->e_type = ET_EXEC; + } + return TRUE; +} + /* Assign file positions for all the reloc sections which are not part of the loadable file image, and the file position of section headers. */ @@ -6471,10 +6517,12 @@ _bfd_elf_assign_file_positions_for_non_load (bfd *abfd) asection *sec = shdrp->bfd_section; bfd_boolean is_rel = (shdrp->sh_type == SHT_REL || shdrp->sh_type == SHT_RELA); + bfd_boolean is_ctf = sec && bfd_section_is_ctf (sec); if (is_rel + || is_ctf || (sec != NULL && (sec->flags & SEC_ELF_COMPRESS))) { - if (!is_rel) + if (!is_rel && !is_ctf) { const char *name = sec->name; struct bfd_elf_section_data *d; @@ -6520,6 +6568,13 @@ _bfd_elf_assign_file_positions_for_non_load (bfd *abfd) shdrp->contents = sec->contents; shdrp->bfd_section->contents = NULL; } + else if (is_ctf) + { + /* Update section size and contents. */ + shdrp->sh_size = sec->size; + shdrp->contents = sec->contents; + } + off = _bfd_elf_assign_file_position_for_section (shdrp, off, TRUE); @@ -7166,14 +7221,18 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) pointer_to_map = &map->next; if (p_paddr_valid - && !bed->want_p_paddr_set_to_zero - && matching_lma->lma != map->p_paddr - && !map->includes_filehdr - && !map->includes_phdrs) - /* There is some padding before the first section in the - segment. So, we must account for that in the output - segment's vma. */ - map->p_vaddr_offset = map->p_paddr - matching_lma->lma; + && !bed->want_p_paddr_set_to_zero) + { + bfd_vma hdr_size = 0; + if (map->includes_filehdr) + hdr_size = iehdr->e_ehsize; + if (map->includes_phdrs) + hdr_size += iehdr->e_phnum * iehdr->e_phentsize; + + /* Account for padding before the first section in the + segment. */ + map->p_vaddr_offset = map->p_paddr + hdr_size - matching_lma->lma; + } free (sections); continue; @@ -7259,7 +7318,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) : 0), output_section->alignment_power) != output_section->lma) - abort (); + goto sorry; } else { @@ -7298,7 +7357,8 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) negative size - or segments that do not contain any sections. */ if (map->count == 0) { - bfd_set_error (bfd_error_bad_value); + sorry: + bfd_set_error (bfd_error_sorry); free (sections); return FALSE; } @@ -7422,7 +7482,6 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd) Elf_Internal_Shdr *this_hdr; asection *first_section = NULL; asection *lowest_section; - bfd_boolean no_contents = TRUE; /* Compute how many sections are in this segment. */ for (section = ibfd->sections, section_count = 0; @@ -7434,8 +7493,6 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd) { if (first_section == NULL) first_section = section; - if (elf_section_type (section) != SHT_NOBITS) - no_contents = FALSE; section_count++; } } @@ -7530,27 +7587,20 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd) } } - if (map->includes_filehdr && lowest_section != NULL) - { - /* Try to keep the space used by the headers plus any - padding fixed. If there are sections with file contents - in this segment then the lowest sh_offset is the best - guess. Otherwise the segment only has file contents for - the headers, and p_filesz is the best guess. */ - if (no_contents) - map->header_size = segment->p_filesz; - else - map->header_size = lowest_section->filepos; - } - if (section_count == 0) map->p_vaddr_offset = segment->p_vaddr; - else if (!map->includes_phdrs - && !map->includes_filehdr - && map->p_paddr_valid) - /* Account for padding before the first section. */ - map->p_vaddr_offset = (segment->p_paddr - - (lowest_section ? lowest_section->lma : 0)); + else if (map->p_paddr_valid) + { + /* Account for padding before the first section in the segment. */ + bfd_vma hdr_size = 0; + if (map->includes_filehdr) + hdr_size = iehdr->e_ehsize; + if (map->includes_phdrs) + hdr_size += iehdr->e_phnum * iehdr->e_phentsize; + + map->p_vaddr_offset = (map->p_paddr + hdr_size + - (lowest_section ? lowest_section->lma : 0)); + } map->count = section_count; *pointer_to_map = map; @@ -8988,10 +9038,11 @@ _bfd_elf_find_nearest_line (bfd *abfd, filename_ptr, functionname_ptr, line_ptr, discriminator_ptr, dwarf_debug_sections, - &elf_tdata (abfd)->dwarf2_find_line_info) - || _bfd_dwarf1_find_nearest_line (abfd, symbols, section, offset, - filename_ptr, functionname_ptr, - line_ptr)) + &elf_tdata (abfd)->dwarf2_find_line_info)) + return TRUE; + + if (_bfd_dwarf1_find_nearest_line (abfd, symbols, section, offset, + filename_ptr, functionname_ptr, line_ptr)) { if (!*functionname_ptr) _bfd_elf_find_function (abfd, symbols, section, offset, @@ -9099,6 +9150,11 @@ _bfd_elf_set_section_contents (bfd *abfd, hdr = &elf_section_data (section)->this_hdr; if (hdr->sh_offset == (file_ptr) -1) { + if (bfd_section_is_ctf (section)) + /* Nothing to do with this section: the contents are generated + later. */ + return TRUE; + /* We must compress this section. Write output to the buffer. */ unsigned char *contents = hdr->contents; if ((offset + count) > hdr->sh_size @@ -9168,7 +9224,7 @@ _bfd_elf_validate_reloc (bfd *abfd, arelent *areloc) howto = bfd_reloc_type_lookup (abfd, code); - if (areloc->howto->pcrel_offset != howto->pcrel_offset) + if (howto && areloc->howto->pcrel_offset != howto->pcrel_offset) { if (howto->pcrel_offset) areloc->addend += areloc->address; @@ -9217,7 +9273,7 @@ _bfd_elf_validate_reloc (bfd *abfd, arelent *areloc) /* xgettext:c-format */ _bfd_error_handler (_("%pB: %s unsupported"), abfd, areloc->howto->name); - bfd_set_error (bfd_error_bad_value); + bfd_set_error (bfd_error_sorry); return FALSE; } @@ -11790,7 +11846,8 @@ elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset, GROKER_ELEMENT ("NetBSD-CORE", elfcore_grok_netbsd_note), GROKER_ELEMENT ( "OpenBSD", elfcore_grok_openbsd_note), GROKER_ELEMENT ("QNX", elfcore_grok_nto_note), - GROKER_ELEMENT ("SPU/", elfcore_grok_spu_note) + GROKER_ELEMENT ("SPU/", elfcore_grok_spu_note), + GROKER_ELEMENT ("GNU", elfobj_grok_gnu_note) }; #undef GROKER_ELEMENT int i; @@ -11830,7 +11887,7 @@ elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset, return TRUE; } -static bfd_boolean +bfd_boolean elf_read_notes (bfd *abfd, file_ptr offset, bfd_size_type size, size_t align) { @@ -11999,7 +12056,8 @@ _bfd_elf_section_offset (bfd *abfd, /* address_size and sec->size are in octets. Convert to bytes before subtracting the original offset. */ - offset = (sec->size - address_size) / bfd_octets_per_byte (abfd) - offset; + offset = ((sec->size - address_size) + / bfd_octets_per_byte (abfd, sec) - offset); } return offset; } @@ -12156,12 +12214,6 @@ asection _bfd_elf_large_com_section = BFD_FAKE_SECTION (_bfd_elf_large_com_section, &lcomm_sym, "LARGE_COMMON", 0, SEC_IS_COMMON); -void -_bfd_elf_post_process_headers (bfd *abfd ATTRIBUTE_UNUSED, - struct bfd_link_info *info ATTRIBUTE_UNUSED) -{ -} - bfd_boolean _bfd_elf_final_write_processing (bfd *abfd) { @@ -12188,7 +12240,7 @@ _bfd_elf_final_write_processing (bfd *abfd) _bfd_error_handler (_("symbol type STT_GNU_IFUNC is unsupported")); if (elf_tdata (abfd)->has_gnu_osabi & elf_gnu_osabi_unique) _bfd_error_handler (_("symbol binding STB_GNU_UNIQUE is unsupported")); - bfd_set_error (bfd_error_bad_value); + bfd_set_error (bfd_error_sorry); return FALSE; } }