* [PATCH 1/2] Fix several mix up between octets and bytes in ELF program headers [not found] <20200215193050.22717-1-ceggers@gmx.de> @ 2020-02-15 19:31 ` Christian Eggers 2020-03-02 14:17 ` Nick Clifton 2020-02-15 19:31 ` [PATCH 2/2] " Christian Eggers 1 sibling, 1 reply; 8+ messages in thread From: Christian Eggers @ 2020-02-15 19:31 UTC (permalink / raw) To: binutils; +Cc: amodra, Christian Eggers When converting between addresses in ELF headers [octets] and bfd LMA/VMA [bytes], the number of octets per byte needs to be incorperated. In ld, the SIZEOF_HEADERS linker script statement must be resolved to bytes instead of octets. Patch changelog: v2: - Keep ELF header entries as octets. v3: - Revert changes to elf32-rx.c and elf64-ia64-vmx.c - Revert change of "break" statement in the patch for elf.c, elf_link_add_object_symbols() - Fix change of IS_CONTAINED_BY_LMA() include/ * elf/internal.h (struct elf_internal_phdr): Add unit (octets) to several member field comments. (Elf_Internal_Shdr): likewise. bfd/ * elf.c (_bfd_elf_make_section_from_shdr): Introduce new temp opb. Divide Elf_Internal_Shdr::sh_addr by opb when setting section LMA/VMA. (_bfd_elf_make_section_from_phdr): Similarly. (elf_fake_sections): Fix calculation of Elf_Internal_shdr::sh_addr from section VMA. (_bfd_elf_map_sections_to_segments): Fix mixup between octets and bytes. (assign_file_positions_for_load_sections): Fix calculations of Elf_Internal_shdr::p_vaddr and p_paddr from section LMA/VMA. Fix comparison between program header address and section LMA. (assign_file_positions_for_non_load_sections): Likewise. (rewrite_elf_program_header): Likewise. Introduce new temp opb. (IS_CONTAINED_BY_VMA): Add parameter opb. (IS_CONTAINED_BY_LMA,IS_SECTION_IN_INPUT_SEGMENT, INCLUDE_SECTION_IN_SEGMENT): Likewise. (copy_elf_program_header): Update call to ELF_SECTION_IN_SEGMENT(). Fix calculations of p_addr_valid and p_vaddr_offset. * elflink.c (elf_link_add_object_symbols): Multiply section VMA with octets per byte when comparing against p_vaddr. ld/ * ldexp.c (fold_name): Return SIZEOF_HEADERS in bytes. Signed-off-by: Christian Eggers <ceggers@gmx.de> --- bfd/elf.c | 131 ++++++++++++++++++++++++++++--------------------- bfd/elflink.c | 12 +++-- include/elf/internal.h | 19 +++---- ld/ldexp.c | 3 +- 4 files changed, 95 insertions(+), 70 deletions(-) diff --git a/bfd/elf.c b/bfd/elf.c index c85face6309..d941b33b15c 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -1028,6 +1028,7 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, asection *newsect; flagword flags; const struct elf_backend_data *bed; + unsigned int opb = bfd_octets_per_byte (abfd, NULL); if (hdr->bfd_section != NULL) return TRUE; @@ -1046,11 +1047,6 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, newsect->filepos = hdr->sh_offset; - if (!bfd_set_section_vma (newsect, hdr->sh_addr) - || !bfd_set_section_size (newsect, hdr->sh_size) - || !bfd_set_section_alignment (newsect, bfd_log2 (hdr->sh_addralign))) - return FALSE; - flags = SEC_NO_FLAGS; if (hdr->sh_type != SHT_NOBITS) flags |= SEC_HAS_CONTENTS; @@ -1108,7 +1104,10 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, 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; + { + flags |= SEC_ELF_OCTETS; + opb = 1; + } else if (strncmp (name, ".line", 5) == 0 || strncmp (name, ".stab", 5) == 0 || strcmp (name, ".gdb_index") == 0) @@ -1116,6 +1115,11 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, } } + if (!bfd_set_section_vma (newsect, hdr->sh_addr / opb) + || !bfd_set_section_size (newsect, hdr->sh_size) + || !bfd_set_section_alignment (newsect, bfd_log2 (hdr->sh_addralign))) + return FALSE; + /* As a GNU extension, if the name begins with .gnu.linkonce, we only link a single copy of the section. This is used to support g++. g++ will emit each template expansion in its own section. @@ -1177,7 +1181,7 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, { if ((flags & SEC_LOAD) == 0) newsect->lma = (phdr->p_paddr - + hdr->sh_addr - phdr->p_vaddr); + + hdr->sh_addr - phdr->p_vaddr) / opb; else /* We used to use the same adjustment for SEC_LOAD sections, but that doesn't work if the segment @@ -1187,7 +1191,7 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, segment will contain sections with contiguous LMAs, even if the VMAs are not. */ newsect->lma = (phdr->p_paddr - + hdr->sh_offset - phdr->p_offset); + + hdr->sh_offset - phdr->p_offset) / opb; /* With contiguous segments, we can't tell from file offsets whether a section with zero size should @@ -2970,6 +2974,7 @@ _bfd_elf_make_section_from_phdr (bfd *abfd, char namebuf[64]; size_t len; int split; + unsigned int opb = bfd_octets_per_byte (abfd, NULL); split = ((hdr->p_memsz > 0) && (hdr->p_filesz > 0) @@ -2986,8 +2991,8 @@ _bfd_elf_make_section_from_phdr (bfd *abfd, newsect = bfd_make_section (abfd, name); if (newsect == NULL) return FALSE; - newsect->vma = hdr->p_vaddr; - newsect->lma = hdr->p_paddr; + newsect->vma = hdr->p_vaddr / opb; + newsect->lma = hdr->p_paddr / opb; newsect->size = hdr->p_filesz; newsect->filepos = hdr->p_offset; newsect->flags |= SEC_HAS_CONTENTS; @@ -3022,8 +3027,8 @@ _bfd_elf_make_section_from_phdr (bfd *abfd, newsect = bfd_make_section (abfd, name); if (newsect == NULL) return FALSE; - newsect->vma = hdr->p_vaddr + hdr->p_filesz; - newsect->lma = hdr->p_paddr + hdr->p_filesz; + newsect->vma = (hdr->p_vaddr + hdr->p_filesz) / opb; + newsect->lma = (hdr->p_paddr + hdr->p_filesz) / opb; newsect->size = hdr->p_memsz - hdr->p_filesz; newsect->filepos = hdr->p_offset + hdr->p_filesz; align = newsect->vma & -newsect->vma; @@ -3299,7 +3304,7 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg) if ((asect->flags & SEC_ALLOC) != 0 || asect->user_set_vma) - this_hdr->sh_addr = asect->vma; + this_hdr->sh_addr = asect->vma * bfd_octets_per_byte (abfd, asect); else this_hdr->sh_addr = 0; @@ -4685,6 +4690,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) bfd_size_type amt; bfd_vma addr_mask, wrap_to = 0; bfd_size_type phdr_size; + unsigned int opb = bfd_octets_per_byte (abfd, NULL); /* Select the allocated sections, and sort them. */ @@ -4724,6 +4730,8 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) if (phdr_size == (bfd_size_type) -1) phdr_size = get_program_header_size (abfd, info); phdr_size += bed->s->sizeof_ehdr; + /* phdr_size is compared to LMA values which are in bytes */ + phdr_size /= opb; maxpagesize = bed->maxpagesize; if (maxpagesize == 0) maxpagesize = 1; @@ -4948,7 +4956,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) executable = TRUE; last_hdr = hdr; /* .tbss sections effectively have zero size. */ - last_size = !IS_TBSS (hdr) ? hdr->size : 0; + last_size = (!IS_TBSS (hdr) ? hdr->size : 0) / opb; continue; } @@ -4974,7 +4982,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) last_hdr = hdr; /* .tbss sections effectively have zero size. */ - last_size = !IS_TBSS (hdr) ? hdr->size : 0; + last_size = (!IS_TBSS (hdr) ? hdr->size : 0) / opb; hdr_index = i; phdr_in_segment = FALSE; } @@ -5428,11 +5436,12 @@ assign_file_positions_for_load_sections (bfd *abfd, struct elf_segment_map *phdr_load_seg; Elf_Internal_Phdr *phdrs; Elf_Internal_Phdr *p; - file_ptr off; + file_ptr off; /* octets */ bfd_size_type maxpagesize; unsigned int alloc, actual; unsigned int i, j; struct elf_segment_map **sorted_seg_map; + unsigned int opb = bfd_octets_per_byte (abfd, NULL); if (link_info == NULL && !_bfd_elf_map_sections_to_segments (abfd, link_info)) @@ -5540,7 +5549,7 @@ assign_file_positions_for_load_sections (bfd *abfd, for (j = 0; j < alloc; j++) { asection **secpp; - bfd_vma off_adjust; + bfd_vma off_adjust; /* octets */ bfd_boolean no_contents; /* An ELF segment (described by Elf_Internal_Phdr) may contain a @@ -5554,16 +5563,16 @@ assign_file_positions_for_load_sections (bfd *abfd, p->p_flags = m->p_flags; if (m->count == 0) - p->p_vaddr = m->p_vaddr_offset; + p->p_vaddr = m->p_vaddr_offset * opb; else - p->p_vaddr = m->sections[0]->vma + m->p_vaddr_offset; + p->p_vaddr = (m->sections[0]->vma + m->p_vaddr_offset) * opb; 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 + m->p_vaddr_offset; + p->p_paddr = (m->sections[0]->lma + m->p_vaddr_offset) * opb; if (p->p_type == PT_LOAD && (abfd->flags & D_PAGED) != 0) @@ -5644,7 +5653,8 @@ assign_file_positions_for_load_sections (bfd *abfd, && (abfd->flags & D_PAGED) != 0 && bed->no_page_alias && (off & (maxpagesize - 1)) != 0 - && (off & -maxpagesize) == ((off + off_adjust) & -maxpagesize)) + && ((off & -maxpagesize) + == ((off + off_adjust) & -maxpagesize))) off_adjust += maxpagesize; off += off_adjust; if (no_contents) @@ -5735,7 +5745,7 @@ assign_file_positions_for_load_sections (bfd *abfd, else if (phdr_load_seg != NULL) { Elf_Internal_Phdr *phdr = phdrs + phdr_load_seg->idx; - bfd_vma phdr_off = 0; + bfd_vma phdr_off = 0; /* octets */ if (phdr_load_seg->includes_filehdr) phdr_off = bed->s->sizeof_ehdr; p->p_vaddr = phdr->p_vaddr + phdr_off; @@ -5769,7 +5779,7 @@ assign_file_positions_for_load_sections (bfd *abfd, } else { - file_ptr adjust; + file_ptr adjust; /* octets */ adjust = off - (p->p_offset + p->p_filesz); if (!no_contents) @@ -5800,10 +5810,10 @@ assign_file_positions_for_load_sections (bfd *abfd, && ((this_hdr->sh_flags & SHF_TLS) == 0 || p->p_type == PT_TLS)))) { - bfd_vma p_start = p->p_paddr; - bfd_vma p_end = p_start + p->p_memsz; - bfd_vma s_start = sec->lma; - bfd_vma adjust = s_start - p_end; + bfd_vma p_start = p->p_paddr; /* octets */ + bfd_vma p_end = p_start + p->p_memsz; /* octets */ + bfd_vma s_start = sec->lma * opb; /* octets */ + bfd_vma adjust = s_start - p_end; /* octets */ if (adjust != 0 && (s_start < p_end @@ -5812,9 +5822,10 @@ assign_file_positions_for_load_sections (bfd *abfd, _bfd_error_handler /* xgettext:c-format */ (_("%pB: section %pA lma %#" PRIx64 " adjusted to %#" PRIx64), - abfd, sec, (uint64_t) s_start, (uint64_t) p_end); + abfd, sec, (uint64_t) s_start / opb, + (uint64_t) p_end / opb); adjust = 0; - sec->lma = p_end; + sec->lma = p_end / opb; } p->p_memsz += adjust; @@ -6200,8 +6211,11 @@ assign_file_positions_for_non_load_sections (bfd *abfd, if (i < lm->count) { - p->p_vaddr = lm->sections[i]->vma; - p->p_paddr = lm->sections[i]->lma; + unsigned int opb = bfd_octets_per_byte (abfd, + lm->sections[i]); + + p->p_vaddr = lm->sections[i]->vma * opb; + p->p_paddr = lm->sections[i]->lma * opb; p->p_offset = lm->sections[i]->filepos; p->p_memsz = end - p->p_vaddr; p->p_filesz = p->p_memsz; @@ -6800,6 +6814,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) struct elf_segment_map *phdr_adjust_seg = NULL; unsigned int phdr_adjust_num = 0; const struct elf_backend_data *bed; + unsigned int opb = bfd_octets_per_byte (ibfd, NULL); bed = get_elf_backend_data (ibfd); iehdr = elf_elfheader (ibfd); @@ -6822,17 +6837,17 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) /* Returns TRUE if the given section is contained within the given segment. VMA addresses are compared. */ -#define IS_CONTAINED_BY_VMA(section, segment) \ - (section->vma >= segment->p_vaddr \ - && (section->vma + SECTION_SIZE (section, segment) \ +#define IS_CONTAINED_BY_VMA(section, segment, opb) \ + (section->vma * (opb) >= segment->p_vaddr \ + && (section->vma * (opb) + SECTION_SIZE (section, segment) \ <= (SEGMENT_END (segment, segment->p_vaddr)))) /* Returns TRUE if the given section is contained within the given segment. LMA addresses are compared. */ -#define IS_CONTAINED_BY_LMA(section, segment, base) \ - (section->lma >= base \ - && (section->lma + SECTION_SIZE (section, segment) >= section->lma) \ - && (section->lma + SECTION_SIZE (section, segment) \ +#define IS_CONTAINED_BY_LMA(section, segment, base, opb) \ + (section->lma * (opb) >= base \ + && (section->lma + SECTION_SIZE (section, segment) / (opb) >= section->lma) \ + && (section->lma * (opb) + SECTION_SIZE (section, segment) \ <= SEGMENT_END (segment, base))) /* Handle PT_NOTE segment. */ @@ -6878,10 +6893,10 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) 7. SHF_TLS sections are only in PT_TLS or PT_LOAD segments. 8. PT_DYNAMIC should not contain empty sections at the beginning (with the possible exception of .dynamic). */ -#define IS_SECTION_IN_INPUT_SEGMENT(section, segment, bed) \ +#define IS_SECTION_IN_INPUT_SEGMENT(section, segment, bed, opb) \ ((((segment->p_paddr \ - ? IS_CONTAINED_BY_LMA (section, segment, segment->p_paddr) \ - : IS_CONTAINED_BY_VMA (section, segment)) \ + ? IS_CONTAINED_BY_LMA (section, segment, segment->p_paddr, opb) \ + : IS_CONTAINED_BY_VMA (section, segment, opb)) \ && (section->flags & SEC_ALLOC) != 0) \ || IS_NOTE (segment, section)) \ && segment->p_type != PT_GNU_STACK \ @@ -6893,15 +6908,15 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) && (segment->p_type != PT_DYNAMIC \ || SECTION_SIZE (section, segment) > 0 \ || (segment->p_paddr \ - ? segment->p_paddr != section->lma \ - : segment->p_vaddr != section->vma) \ + ? segment->p_paddr != section->lma * (opb) \ + : segment->p_vaddr != section->vma * (opb)) \ || (strcmp (bfd_section_name (section), ".dynamic") == 0)) \ && (segment->p_type != PT_LOAD || !section->segment_mark)) /* If the output section of a section in the input segment is NULL, it is removed from the corresponding output segment. */ -#define INCLUDE_SECTION_IN_SEGMENT(section, segment, bed) \ - (IS_SECTION_IN_INPUT_SEGMENT (section, segment, bed) \ +#define INCLUDE_SECTION_IN_SEGMENT(section, segment, bed, opb) \ + (IS_SECTION_IN_INPUT_SEGMENT (section, segment, bed, opb) \ && section->output_section != NULL) /* Returns TRUE iff seg1 starts after the end of seg2. */ @@ -6955,7 +6970,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) { /* Mininal change so that the normal section to segment assignment code will work. */ - segment->p_vaddr = section->vma; + segment->p_vaddr = section->vma * opb; break; } @@ -7041,7 +7056,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) { /* Find the first section in the input segment, which may be removed from the corresponding output segment. */ - if (IS_SECTION_IN_INPUT_SEGMENT (section, segment, bed)) + if (IS_SECTION_IN_INPUT_SEGMENT (section, segment, bed, opb)) { if (first_section == NULL) first_section = section; @@ -7109,7 +7124,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) " at vaddr=%#" PRIx64 ", is this intentional?"), ibfd, (uint64_t) segment->p_vaddr); - map->p_vaddr_offset = segment->p_vaddr; + map->p_vaddr_offset = segment->p_vaddr / opb; map->count = 0; *pointer_to_map = map; pointer_to_map = &map->next; @@ -7163,7 +7178,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) section != NULL; section = section->next) { - if (INCLUDE_SECTION_IN_SEGMENT (section, segment, bed)) + if (INCLUDE_SECTION_IN_SEGMENT (section, segment, bed, opb)) { output_section = section->output_section; @@ -7190,10 +7205,11 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) /* Match up the physical address of the segment with the LMA address of the output section. */ - if (IS_CONTAINED_BY_LMA (output_section, segment, map->p_paddr) + if (IS_CONTAINED_BY_LMA (output_section, segment, map->p_paddr, + opb) || IS_COREFILE_NOTE (segment, section) || (bed->want_p_paddr_set_to_zero - && IS_CONTAINED_BY_VMA (output_section, segment))) + && IS_CONTAINED_BY_VMA (output_section, segment, opb))) { if (matching_lma == NULL || output_section->lma < matching_lma->lma) @@ -7237,7 +7253,8 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) /* Account for padding before the first section in the segment. */ - map->p_vaddr_offset = map->p_paddr + hdr_size - matching_lma->lma; + map->p_vaddr_offset = ((map->p_paddr + hdr_size) / opb + - matching_lma->lma); } free (sections); @@ -7308,7 +7325,8 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) BFD_ASSERT (output_section != NULL); - if (IS_CONTAINED_BY_LMA (output_section, segment, map->p_paddr) + if (IS_CONTAINED_BY_LMA (output_section, segment, map->p_paddr, + opb) || IS_COREFILE_NOTE (segment, section)) { if (map->count == 0) @@ -7460,6 +7478,7 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd) unsigned int num_segments; bfd_boolean phdr_included = FALSE; bfd_boolean p_paddr_valid; + unsigned int opb = bfd_octets_per_byte (ibfd, NULL); iehdr = elf_elfheader (ibfd); @@ -7585,7 +7604,7 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd) seg_off = this_hdr->sh_offset - segment->p_offset; else seg_off = this_hdr->sh_addr - segment->p_vaddr; - if (section->lma - segment->p_paddr != seg_off) + if (section->lma * opb - segment->p_paddr != seg_off) map->p_paddr_valid = FALSE; } if (isec == section_count) @@ -7595,7 +7614,7 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd) } if (section_count == 0) - map->p_vaddr_offset = segment->p_vaddr; + map->p_vaddr_offset = segment->p_vaddr / opb; else if (map->p_paddr_valid) { /* Account for padding before the first section in the segment. */ @@ -7605,7 +7624,7 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd) if (map->includes_phdrs) hdr_size += iehdr->e_phnum * iehdr->e_phentsize; - map->p_vaddr_offset = (map->p_paddr + hdr_size + map->p_vaddr_offset = ((map->p_paddr + hdr_size) / opb - (lowest_section ? lowest_section->lma : 0)); } diff --git a/bfd/elflink.c b/bfd/elflink.c index 3add9f18bd7..43fbbf0dd1b 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -4227,10 +4227,14 @@ error_free_dyn: if (phdr->p_type == PT_GNU_RELRO) { for (s = abfd->sections; s != NULL; s = s->next) - if ((s->flags & SEC_ALLOC) != 0 - && s->vma >= phdr->p_vaddr - && s->vma + s->size <= phdr->p_vaddr + phdr->p_memsz) - s->flags |= SEC_READONLY; + { + unsigned int opb = bfd_octets_per_byte (abfd, s); + + if ((s->flags & SEC_ALLOC) != 0 + && s->vma * opb >= phdr->p_vaddr + && s->vma * opb + s->size <= phdr->p_vaddr + phdr->p_memsz) + s->flags |= SEC_READONLY; + } break; } diff --git a/include/elf/internal.h b/include/elf/internal.h index 844675c30f3..c436e64fe56 100644 --- a/include/elf/internal.h +++ b/include/elf/internal.h @@ -86,11 +86,11 @@ typedef struct elf_internal_ehdr { struct elf_internal_phdr { unsigned long p_type; /* Identifies program segment type */ unsigned long p_flags; /* Segment flags */ - bfd_vma p_offset; /* Segment file offset */ - bfd_vma p_vaddr; /* Segment virtual address */ - bfd_vma p_paddr; /* Segment physical address */ - bfd_vma p_filesz; /* Segment size in file */ - bfd_vma p_memsz; /* Segment size in memory */ + bfd_vma p_offset; /* Segment file offset in octets */ + bfd_vma p_vaddr; /* Segment virtual address in octets */ + bfd_vma p_paddr; /* Segment physical address in octets */ + bfd_vma p_filesz; /* Segment size in file in octets */ + bfd_vma p_memsz; /* Segment size in memory in octets */ bfd_vma p_align; /* Segment alignment, file & memory */ }; @@ -102,9 +102,10 @@ typedef struct elf_internal_shdr { unsigned int sh_name; /* Section name, index in string tbl */ unsigned int sh_type; /* Type of section */ bfd_vma sh_flags; /* Miscellaneous section attributes */ - bfd_vma sh_addr; /* Section virtual addr at execution */ - file_ptr sh_offset; /* Section file offset */ - bfd_size_type sh_size; /* Size of section in bytes */ + bfd_vma sh_addr; /* Section virtual addr at execution in + octets */ + file_ptr sh_offset; /* Section file offset in octets */ + bfd_size_type sh_size; /* Size of section in octets */ unsigned int sh_link; /* Index of another section */ unsigned int sh_info; /* Additional section information */ bfd_vma sh_addralign; /* Section alignment */ @@ -267,7 +268,7 @@ struct elf_segment_map unsigned long p_flags; /* Program segment physical address. */ bfd_vma p_paddr; - /* Program segment virtual address offset from section vma. */ + /* Program segment virtual address offset from section vma in bytes. */ bfd_vma p_vaddr_offset; /* Program segment alignment. */ bfd_vma p_align; diff --git a/ld/ldexp.c b/ld/ldexp.c index 6d1457b929a..3ffabb8c1da 100644 --- a/ld/ldexp.c +++ b/ld/ldexp.c @@ -700,7 +700,8 @@ fold_name (etree_type *tree) /* Don't find the real header size if only marking sections; The bfd function may cache incorrect data. */ if (expld.phase != lang_mark_phase_enum) - hdr_size = bfd_sizeof_headers (link_info.output_bfd, &link_info); + hdr_size = (bfd_sizeof_headers (link_info.output_bfd, &link_info) + / bfd_octets_per_byte (link_info.output_bfd, NULL)); new_number (hdr_size); } break; -- 2.16.4 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] Fix several mix up between octets and bytes in ELF program headers 2020-02-15 19:31 ` [PATCH 1/2] Fix several mix up between octets and bytes in ELF program headers Christian Eggers @ 2020-03-02 14:17 ` Nick Clifton 2020-03-02 20:11 ` [PATCH v4] " Christian Eggers 0 siblings, 1 reply; 8+ messages in thread From: Nick Clifton @ 2020-03-02 14:17 UTC (permalink / raw) To: Christian Eggers, binutils; +Cc: amodra Hi Christian, > include/ > * elf/internal.h (struct elf_internal_phdr): Add unit (octets) > to several member field comments. > (Elf_Internal_Shdr): likewise. > > bfd/ > * elf.c (_bfd_elf_make_section_from_shdr): Introduce new temp > opb. Divide Elf_Internal_Shdr::sh_addr by opb when setting > section LMA/VMA. > (_bfd_elf_make_section_from_phdr): Similarly. > (elf_fake_sections): Fix calculation of > Elf_Internal_shdr::sh_addr from section VMA. > (_bfd_elf_map_sections_to_segments): Fix mixup between octets > and bytes. > (assign_file_positions_for_load_sections): Fix calculations of > Elf_Internal_shdr::p_vaddr and p_paddr from section LMA/VMA. Fix > comparison between program header address and section LMA. > (assign_file_positions_for_non_load_sections): Likewise. > (rewrite_elf_program_header): Likewise. Introduce new temp opb. > (IS_CONTAINED_BY_VMA): Add parameter opb. > (IS_CONTAINED_BY_LMA,IS_SECTION_IN_INPUT_SEGMENT, > INCLUDE_SECTION_IN_SEGMENT): Likewise. > (copy_elf_program_header): Update call to > ELF_SECTION_IN_SEGMENT(). Fix calculations of p_addr_valid and > p_vaddr_offset. > * elflink.c (elf_link_add_object_symbols): Multiply section VMA > with octets per byte when comparing against p_vaddr. > > ld/ > * ldexp.c (fold_name): Return SIZEOF_HEADERS in bytes. Approved - please apply - but with one change: > + bfd_vma p_start = p->p_paddr; /* octets */ Please could yoy change the format of these comments so that they follow the GNU Coding Standard guidelines ? Ie, please start with a capital letter and end with a period: /* Octets. */ And similarly for you /* bytes */ comments - they should be /* Bytes. */ Thanks. ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v4] Fix several mix up between octets and bytes in ELF program headers 2020-03-02 14:17 ` Nick Clifton @ 2020-03-02 20:11 ` Christian Eggers 0 siblings, 0 replies; 8+ messages in thread From: Christian Eggers @ 2020-03-02 20:11 UTC (permalink / raw) To: binutils, Nick Clifton; +Cc: amodra, Christian Eggers On Monday, March 2nd 2020, Nick Clifton wrote: > Approved - please apply - but with one change: > > + bfd_vma p_start = p->p_paddr; /* octets */ > > Please could yoy change the format of these comments so that they follow > the GNU Coding Standard guidelines ? Ie, please start with a capital > letter and end with a period: > > /* Octets. */ > > And similarly for you /* bytes */ comments - they should be /* Bytes. */ Changed all occurrences in the patch. Thanks Christian --- When converting between addresses in ELF headers [octets] and bfd LMA/VMA [bytes], the number of octets per byte needs to be incorperated. In ld, the SIZEOF_HEADERS linker script statement must be resolved to bytes instead of octets. Patch changelog: v2: - Keep ELF header entries as octets. v3: - Revert changes to elf32-rx.c and elf64-ia64-vmx.c - Revert change of "break" statement in the patch for elf.c, elf_link_add_object_symbols() - Fix change of IS_CONTAINED_BY_LMA() v4: - GNU coding style for comments. include/ * elf/internal.h (struct elf_internal_phdr): Add unit (octets) to several member field comments. (Elf_Internal_Shdr): likewise. bfd/ * elf.c (_bfd_elf_make_section_from_shdr): Introduce new temp opb. Divide Elf_Internal_Shdr::sh_addr by opb when setting section LMA/VMA. (_bfd_elf_make_section_from_phdr): Similarly. (elf_fake_sections): Fix calculation of Elf_Internal_shdr::sh_addr from section VMA. (_bfd_elf_map_sections_to_segments): Fix mixup between octets and bytes. (assign_file_positions_for_load_sections): Fix calculations of Elf_Internal_shdr::p_vaddr and p_paddr from section LMA/VMA. Fix comparison between program header address and section LMA. (assign_file_positions_for_non_load_sections): Likewise. (rewrite_elf_program_header): Likewise. Introduce new temp opb. (IS_CONTAINED_BY_VMA): Add parameter opb. (IS_CONTAINED_BY_LMA,IS_SECTION_IN_INPUT_SEGMENT, INCLUDE_SECTION_IN_SEGMENT): Likewise. (copy_elf_program_header): Update call to ELF_SECTION_IN_SEGMENT(). Fix calculations of p_addr_valid and p_vaddr_offset. * elflink.c (elf_link_add_object_symbols): Multiply section VMA with octets per byte when comparing against p_vaddr. ld/ * ldexp.c (fold_name): Return SIZEOF_HEADERS in bytes. Signed-off-by: Christian Eggers <ceggers@gmx.de> --- bfd/elf.c | 131 ++++++++++++++++++++++++++++--------------------- bfd/elflink.c | 12 +++-- include/elf/internal.h | 25 +++++----- ld/ldexp.c | 3 +- 4 files changed, 98 insertions(+), 73 deletions(-) diff --git a/bfd/elf.c b/bfd/elf.c index fcd84d2d17b..a329e239828 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -1016,6 +1016,7 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, asection *newsect; flagword flags; const struct elf_backend_data *bed; + unsigned int opb = bfd_octets_per_byte (abfd, NULL); if (hdr->bfd_section != NULL) return TRUE; @@ -1034,11 +1035,6 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, newsect->filepos = hdr->sh_offset; - if (!bfd_set_section_vma (newsect, hdr->sh_addr) - || !bfd_set_section_size (newsect, hdr->sh_size) - || !bfd_set_section_alignment (newsect, bfd_log2 (hdr->sh_addralign))) - return FALSE; - flags = SEC_NO_FLAGS; if (hdr->sh_type != SHT_NOBITS) flags |= SEC_HAS_CONTENTS; @@ -1096,7 +1092,10 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, 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; + { + flags |= SEC_ELF_OCTETS; + opb = 1; + } else if (strncmp (name, ".line", 5) == 0 || strncmp (name, ".stab", 5) == 0 || strcmp (name, ".gdb_index") == 0) @@ -1104,6 +1103,11 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, } } + if (!bfd_set_section_vma (newsect, hdr->sh_addr / opb) + || !bfd_set_section_size (newsect, hdr->sh_size) + || !bfd_set_section_alignment (newsect, bfd_log2 (hdr->sh_addralign))) + return FALSE; + /* As a GNU extension, if the name begins with .gnu.linkonce, we only link a single copy of the section. This is used to support g++. g++ will emit each template expansion in its own section. @@ -1165,7 +1169,7 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, { if ((newsect->flags & SEC_LOAD) == 0) newsect->lma = (phdr->p_paddr - + hdr->sh_addr - phdr->p_vaddr); + + hdr->sh_addr - phdr->p_vaddr) / opb; else /* We used to use the same adjustment for SEC_LOAD sections, but that doesn't work if the segment @@ -1175,7 +1179,7 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, segment will contain sections with contiguous LMAs, even if the VMAs are not. */ newsect->lma = (phdr->p_paddr - + hdr->sh_offset - phdr->p_offset); + + hdr->sh_offset - phdr->p_offset) / opb; /* With contiguous segments, we can't tell from file offsets whether a section with zero size should @@ -2945,6 +2949,7 @@ _bfd_elf_make_section_from_phdr (bfd *abfd, char namebuf[64]; size_t len; int split; + unsigned int opb = bfd_octets_per_byte (abfd, NULL); split = ((hdr->p_memsz > 0) && (hdr->p_filesz > 0) @@ -2961,8 +2966,8 @@ _bfd_elf_make_section_from_phdr (bfd *abfd, newsect = bfd_make_section (abfd, name); if (newsect == NULL) return FALSE; - newsect->vma = hdr->p_vaddr; - newsect->lma = hdr->p_paddr; + newsect->vma = hdr->p_vaddr / opb; + newsect->lma = hdr->p_paddr / opb; newsect->size = hdr->p_filesz; newsect->filepos = hdr->p_offset; newsect->flags |= SEC_HAS_CONTENTS; @@ -2997,8 +3002,8 @@ _bfd_elf_make_section_from_phdr (bfd *abfd, newsect = bfd_make_section (abfd, name); if (newsect == NULL) return FALSE; - newsect->vma = hdr->p_vaddr + hdr->p_filesz; - newsect->lma = hdr->p_paddr + hdr->p_filesz; + newsect->vma = (hdr->p_vaddr + hdr->p_filesz) / opb; + newsect->lma = (hdr->p_paddr + hdr->p_filesz) / opb; newsect->size = hdr->p_memsz - hdr->p_filesz; newsect->filepos = hdr->p_offset + hdr->p_filesz; align = newsect->vma & -newsect->vma; @@ -3274,7 +3279,7 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg) if ((asect->flags & SEC_ALLOC) != 0 || asect->user_set_vma) - this_hdr->sh_addr = asect->vma; + this_hdr->sh_addr = asect->vma * bfd_octets_per_byte (abfd, asect); else this_hdr->sh_addr = 0; @@ -4662,6 +4667,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) size_t amt; bfd_vma addr_mask, wrap_to = 0; bfd_size_type phdr_size; + unsigned int opb = bfd_octets_per_byte (abfd, NULL); /* Select the allocated sections, and sort them. */ @@ -4701,6 +4707,8 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) if (phdr_size == (bfd_size_type) -1) phdr_size = get_program_header_size (abfd, info); phdr_size += bed->s->sizeof_ehdr; + /* phdr_size is compared to LMA values which are in bytes. */ + phdr_size /= opb; maxpagesize = bed->maxpagesize; if (maxpagesize == 0) maxpagesize = 1; @@ -4925,7 +4933,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) executable = TRUE; last_hdr = hdr; /* .tbss sections effectively have zero size. */ - last_size = !IS_TBSS (hdr) ? hdr->size : 0; + last_size = (!IS_TBSS (hdr) ? hdr->size : 0) / opb; continue; } @@ -4951,7 +4959,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) last_hdr = hdr; /* .tbss sections effectively have zero size. */ - last_size = !IS_TBSS (hdr) ? hdr->size : 0; + last_size = (!IS_TBSS (hdr) ? hdr->size : 0) / opb; hdr_index = i; phdr_in_segment = FALSE; } @@ -5405,11 +5413,12 @@ assign_file_positions_for_load_sections (bfd *abfd, struct elf_segment_map *phdr_load_seg; Elf_Internal_Phdr *phdrs; Elf_Internal_Phdr *p; - file_ptr off; + file_ptr off; /* Octets. */ bfd_size_type maxpagesize; unsigned int alloc, actual; unsigned int i, j; struct elf_segment_map **sorted_seg_map; + unsigned int opb = bfd_octets_per_byte (abfd, NULL); if (link_info == NULL && !_bfd_elf_map_sections_to_segments (abfd, link_info)) @@ -5517,7 +5526,7 @@ assign_file_positions_for_load_sections (bfd *abfd, for (j = 0; j < alloc; j++) { asection **secpp; - bfd_vma off_adjust; + bfd_vma off_adjust; /* Octets. */ bfd_boolean no_contents; /* An ELF segment (described by Elf_Internal_Phdr) may contain a @@ -5531,16 +5540,16 @@ assign_file_positions_for_load_sections (bfd *abfd, p->p_flags = m->p_flags; if (m->count == 0) - p->p_vaddr = m->p_vaddr_offset; + p->p_vaddr = m->p_vaddr_offset * opb; else - p->p_vaddr = m->sections[0]->vma + m->p_vaddr_offset; + p->p_vaddr = (m->sections[0]->vma + m->p_vaddr_offset) * opb; 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 + m->p_vaddr_offset; + p->p_paddr = (m->sections[0]->lma + m->p_vaddr_offset) * opb; if (p->p_type == PT_LOAD && (abfd->flags & D_PAGED) != 0) @@ -5621,7 +5630,8 @@ assign_file_positions_for_load_sections (bfd *abfd, && (abfd->flags & D_PAGED) != 0 && bed->no_page_alias && (off & (maxpagesize - 1)) != 0 - && (off & -maxpagesize) == ((off + off_adjust) & -maxpagesize)) + && ((off & -maxpagesize) + == ((off + off_adjust) & -maxpagesize))) off_adjust += maxpagesize; off += off_adjust; if (no_contents) @@ -5712,7 +5722,7 @@ assign_file_positions_for_load_sections (bfd *abfd, else if (phdr_load_seg != NULL) { Elf_Internal_Phdr *phdr = phdrs + phdr_load_seg->idx; - bfd_vma phdr_off = 0; + bfd_vma phdr_off = 0; /* Octets. */ if (phdr_load_seg->includes_filehdr) phdr_off = bed->s->sizeof_ehdr; p->p_vaddr = phdr->p_vaddr + phdr_off; @@ -5746,7 +5756,7 @@ assign_file_positions_for_load_sections (bfd *abfd, } else { - file_ptr adjust; + file_ptr adjust; /* Octets. */ adjust = off - (p->p_offset + p->p_filesz); if (!no_contents) @@ -5777,10 +5787,10 @@ assign_file_positions_for_load_sections (bfd *abfd, && ((this_hdr->sh_flags & SHF_TLS) == 0 || p->p_type == PT_TLS)))) { - bfd_vma p_start = p->p_paddr; - bfd_vma p_end = p_start + p->p_memsz; - bfd_vma s_start = sec->lma; - bfd_vma adjust = s_start - p_end; + bfd_vma p_start = p->p_paddr; /* Octets. */ + bfd_vma p_end = p_start + p->p_memsz; /* Octets. */ + bfd_vma s_start = sec->lma * opb; /* Octets. */ + bfd_vma adjust = s_start - p_end; /* Octets. */ if (adjust != 0 && (s_start < p_end @@ -5789,9 +5799,10 @@ assign_file_positions_for_load_sections (bfd *abfd, _bfd_error_handler /* xgettext:c-format */ (_("%pB: section %pA lma %#" PRIx64 " adjusted to %#" PRIx64), - abfd, sec, (uint64_t) s_start, (uint64_t) p_end); + abfd, sec, (uint64_t) s_start / opb, + (uint64_t) p_end / opb); adjust = 0; - sec->lma = p_end; + sec->lma = p_end / opb; } p->p_memsz += adjust; @@ -6181,8 +6192,11 @@ assign_file_positions_for_non_load_sections (bfd *abfd, if (i < lm->count) { - p->p_vaddr = lm->sections[i]->vma; - p->p_paddr = lm->sections[i]->lma; + unsigned int opb = bfd_octets_per_byte (abfd, + lm->sections[i]); + + p->p_vaddr = lm->sections[i]->vma * opb; + p->p_paddr = lm->sections[i]->lma * opb; p->p_offset = lm->sections[i]->filepos; p->p_memsz = end - p->p_vaddr; p->p_filesz = p->p_memsz; @@ -6781,6 +6795,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) struct elf_segment_map *phdr_adjust_seg = NULL; unsigned int phdr_adjust_num = 0; const struct elf_backend_data *bed; + unsigned int opb = bfd_octets_per_byte (ibfd, NULL); bed = get_elf_backend_data (ibfd); iehdr = elf_elfheader (ibfd); @@ -6803,17 +6818,17 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) /* Returns TRUE if the given section is contained within the given segment. VMA addresses are compared. */ -#define IS_CONTAINED_BY_VMA(section, segment) \ - (section->vma >= segment->p_vaddr \ - && (section->vma + SECTION_SIZE (section, segment) \ +#define IS_CONTAINED_BY_VMA(section, segment, opb) \ + (section->vma * (opb) >= segment->p_vaddr \ + && (section->vma * (opb) + SECTION_SIZE (section, segment) \ <= (SEGMENT_END (segment, segment->p_vaddr)))) /* Returns TRUE if the given section is contained within the given segment. LMA addresses are compared. */ -#define IS_CONTAINED_BY_LMA(section, segment, base) \ - (section->lma >= base \ - && (section->lma + SECTION_SIZE (section, segment) >= section->lma) \ - && (section->lma + SECTION_SIZE (section, segment) \ +#define IS_CONTAINED_BY_LMA(section, segment, base, opb) \ + (section->lma * (opb) >= base \ + && (section->lma + SECTION_SIZE (section, segment) / (opb) >= section->lma) \ + && (section->lma * (opb) + SECTION_SIZE (section, segment) \ <= SEGMENT_END (segment, base))) /* Handle PT_NOTE segment. */ @@ -6859,10 +6874,10 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) 7. SHF_TLS sections are only in PT_TLS or PT_LOAD segments. 8. PT_DYNAMIC should not contain empty sections at the beginning (with the possible exception of .dynamic). */ -#define IS_SECTION_IN_INPUT_SEGMENT(section, segment, bed) \ +#define IS_SECTION_IN_INPUT_SEGMENT(section, segment, bed, opb) \ ((((segment->p_paddr \ - ? IS_CONTAINED_BY_LMA (section, segment, segment->p_paddr) \ - : IS_CONTAINED_BY_VMA (section, segment)) \ + ? IS_CONTAINED_BY_LMA (section, segment, segment->p_paddr, opb) \ + : IS_CONTAINED_BY_VMA (section, segment, opb)) \ && (section->flags & SEC_ALLOC) != 0) \ || IS_NOTE (segment, section)) \ && segment->p_type != PT_GNU_STACK \ @@ -6874,15 +6889,15 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) && (segment->p_type != PT_DYNAMIC \ || SECTION_SIZE (section, segment) > 0 \ || (segment->p_paddr \ - ? segment->p_paddr != section->lma \ - : segment->p_vaddr != section->vma) \ + ? segment->p_paddr != section->lma * (opb) \ + : segment->p_vaddr != section->vma * (opb)) \ || (strcmp (bfd_section_name (section), ".dynamic") == 0)) \ && (segment->p_type != PT_LOAD || !section->segment_mark)) /* If the output section of a section in the input segment is NULL, it is removed from the corresponding output segment. */ -#define INCLUDE_SECTION_IN_SEGMENT(section, segment, bed) \ - (IS_SECTION_IN_INPUT_SEGMENT (section, segment, bed) \ +#define INCLUDE_SECTION_IN_SEGMENT(section, segment, bed, opb) \ + (IS_SECTION_IN_INPUT_SEGMENT (section, segment, bed, opb) \ && section->output_section != NULL) /* Returns TRUE iff seg1 starts after the end of seg2. */ @@ -6936,7 +6951,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) { /* Mininal change so that the normal section to segment assignment code will work. */ - segment->p_vaddr = section->vma; + segment->p_vaddr = section->vma * opb; break; } @@ -7022,7 +7037,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) { /* Find the first section in the input segment, which may be removed from the corresponding output segment. */ - if (IS_SECTION_IN_INPUT_SEGMENT (section, segment, bed)) + if (IS_SECTION_IN_INPUT_SEGMENT (section, segment, bed, opb)) { if (first_section == NULL) first_section = section; @@ -7090,7 +7105,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) " at vaddr=%#" PRIx64 ", is this intentional?"), ibfd, (uint64_t) segment->p_vaddr); - map->p_vaddr_offset = segment->p_vaddr; + map->p_vaddr_offset = segment->p_vaddr / opb; map->count = 0; *pointer_to_map = map; pointer_to_map = &map->next; @@ -7145,7 +7160,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) section != NULL; section = section->next) { - if (INCLUDE_SECTION_IN_SEGMENT (section, segment, bed)) + if (INCLUDE_SECTION_IN_SEGMENT (section, segment, bed, opb)) { output_section = section->output_section; @@ -7172,10 +7187,11 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) /* Match up the physical address of the segment with the LMA address of the output section. */ - if (IS_CONTAINED_BY_LMA (output_section, segment, map->p_paddr) + if (IS_CONTAINED_BY_LMA (output_section, segment, map->p_paddr, + opb) || IS_COREFILE_NOTE (segment, section) || (bed->want_p_paddr_set_to_zero - && IS_CONTAINED_BY_VMA (output_section, segment))) + && IS_CONTAINED_BY_VMA (output_section, segment, opb))) { if (matching_lma == NULL || output_section->lma < matching_lma->lma) @@ -7219,7 +7235,8 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) /* Account for padding before the first section in the segment. */ - map->p_vaddr_offset = map->p_paddr + hdr_size - matching_lma->lma; + map->p_vaddr_offset = ((map->p_paddr + hdr_size) / opb + - matching_lma->lma); } free (sections); @@ -7290,7 +7307,8 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) BFD_ASSERT (output_section != NULL); - if (IS_CONTAINED_BY_LMA (output_section, segment, map->p_paddr) + if (IS_CONTAINED_BY_LMA (output_section, segment, map->p_paddr, + opb) || IS_COREFILE_NOTE (segment, section)) { if (map->count == 0) @@ -7442,6 +7460,7 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd) unsigned int num_segments; bfd_boolean phdr_included = FALSE; bfd_boolean p_paddr_valid; + unsigned int opb = bfd_octets_per_byte (ibfd, NULL); iehdr = elf_elfheader (ibfd); @@ -7567,7 +7586,7 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd) seg_off = this_hdr->sh_offset - segment->p_offset; else seg_off = this_hdr->sh_addr - segment->p_vaddr; - if (section->lma - segment->p_paddr != seg_off) + if (section->lma * opb - segment->p_paddr != seg_off) map->p_paddr_valid = FALSE; } if (isec == section_count) @@ -7577,7 +7596,7 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd) } if (section_count == 0) - map->p_vaddr_offset = segment->p_vaddr; + map->p_vaddr_offset = segment->p_vaddr / opb; else if (map->p_paddr_valid) { /* Account for padding before the first section in the segment. */ @@ -7587,7 +7606,7 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd) if (map->includes_phdrs) hdr_size += iehdr->e_phnum * iehdr->e_phentsize; - map->p_vaddr_offset = (map->p_paddr + hdr_size + map->p_vaddr_offset = ((map->p_paddr + hdr_size) / opb - (lowest_section ? lowest_section->lma : 0)); } diff --git a/bfd/elflink.c b/bfd/elflink.c index c04712a10f6..369f3cb3e7b 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -4218,10 +4218,14 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) if (phdr->p_type == PT_GNU_RELRO) { for (s = abfd->sections; s != NULL; s = s->next) - if ((s->flags & SEC_ALLOC) != 0 - && s->vma >= phdr->p_vaddr - && s->vma + s->size <= phdr->p_vaddr + phdr->p_memsz) - s->flags |= SEC_READONLY; + { + unsigned int opb = bfd_octets_per_byte (abfd, s); + + if ((s->flags & SEC_ALLOC) != 0 + && s->vma * opb >= phdr->p_vaddr + && s->vma * opb + s->size <= phdr->p_vaddr + phdr->p_memsz) + s->flags |= SEC_READONLY; + } break; } diff --git a/include/elf/internal.h b/include/elf/internal.h index 844675c30f3..d626adece5b 100644 --- a/include/elf/internal.h +++ b/include/elf/internal.h @@ -84,14 +84,14 @@ typedef struct elf_internal_ehdr { /* Program header */ struct elf_internal_phdr { - unsigned long p_type; /* Identifies program segment type */ - unsigned long p_flags; /* Segment flags */ - bfd_vma p_offset; /* Segment file offset */ - bfd_vma p_vaddr; /* Segment virtual address */ - bfd_vma p_paddr; /* Segment physical address */ - bfd_vma p_filesz; /* Segment size in file */ - bfd_vma p_memsz; /* Segment size in memory */ - bfd_vma p_align; /* Segment alignment, file & memory */ + unsigned long p_type; /* Identifies program segment type. */ + unsigned long p_flags; /* Segment flags. */ + bfd_vma p_offset; /* Segment file offset in octets. */ + bfd_vma p_vaddr; /* Segment virtual address in octets. */ + bfd_vma p_paddr; /* Segment physical address in octets. */ + bfd_vma p_filesz; /* Segment size in file in octets. */ + bfd_vma p_memsz; /* Segment size in memory in octets. */ + bfd_vma p_align; /* Segment alignment, file & memory. */ }; typedef struct elf_internal_phdr Elf_Internal_Phdr; @@ -102,9 +102,10 @@ typedef struct elf_internal_shdr { unsigned int sh_name; /* Section name, index in string tbl */ unsigned int sh_type; /* Type of section */ bfd_vma sh_flags; /* Miscellaneous section attributes */ - bfd_vma sh_addr; /* Section virtual addr at execution */ - file_ptr sh_offset; /* Section file offset */ - bfd_size_type sh_size; /* Size of section in bytes */ + bfd_vma sh_addr; /* Section virtual addr at execution in + octets. */ + file_ptr sh_offset; /* Section file offset in octets. */ + bfd_size_type sh_size; /* Size of section in octets. */ unsigned int sh_link; /* Index of another section */ unsigned int sh_info; /* Additional section information */ bfd_vma sh_addralign; /* Section alignment */ @@ -267,7 +268,7 @@ struct elf_segment_map unsigned long p_flags; /* Program segment physical address. */ bfd_vma p_paddr; - /* Program segment virtual address offset from section vma. */ + /* Program segment virtual address offset from section vma in bytes. */ bfd_vma p_vaddr_offset; /* Program segment alignment. */ bfd_vma p_align; diff --git a/ld/ldexp.c b/ld/ldexp.c index 6d1457b929a..3ffabb8c1da 100644 --- a/ld/ldexp.c +++ b/ld/ldexp.c @@ -700,7 +700,8 @@ fold_name (etree_type *tree) /* Don't find the real header size if only marking sections; The bfd function may cache incorrect data. */ if (expld.phase != lang_mark_phase_enum) - hdr_size = bfd_sizeof_headers (link_info.output_bfd, &link_info); + hdr_size = (bfd_sizeof_headers (link_info.output_bfd, &link_info) + / bfd_octets_per_byte (link_info.output_bfd, NULL)); new_number (hdr_size); } break; -- 2.16.4 ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 2/2] Fix several mix up between octets and bytes in ELF program headers [not found] <20200215193050.22717-1-ceggers@gmx.de> 2020-02-15 19:31 ` [PATCH 1/2] Fix several mix up between octets and bytes in ELF program headers Christian Eggers @ 2020-02-15 19:31 ` Christian Eggers 2020-03-02 14:18 ` Nick Clifton 1 sibling, 1 reply; 8+ messages in thread From: Christian Eggers @ 2020-02-15 19:31 UTC (permalink / raw) To: binutils; +Cc: amodra, Christian Eggers This is a follow-up patch for my patch from december 09 with the same subject. It fixes additional locations not handled in the first patch. When converting between addresses in ELF headers [octets] and bfd LMA/VMA [bytes], the number of octets per byte needs to be incorperated. include/ * bfdlink.h (struct bfd_link_order): Add unit (bytes/octets) to offset and size members. * elf/internal.h (struct elf_internal_phdr): likewise for p_align member. (struct elf_segment_map): likewise for p_paddr and p_size members bfd/ * bfd.c (bfd_record_phdr): New local "opb". Fix assignment of "p_paddr" from "at". * elfcode.h (bfd_from_remote_memory): Add units to several parameters. New local "opb". Fix usage of p_align. Fix calculation of "localbase" from "ehdr_vma" and "p_vaddr". Fix call of target_read_memory(). * elflink.c (elf_fixup_link_order): Fix scope of "s" local. Fix calculation of "offset" and "output_offset". (bfd_elf_final_link): New local "opb". Fix calculation of "size" from "offset" and fix calculation of "end" from "vma+size". Fix comparison between "sh_addr" and "vma"/"output_offset". (bfd_elf_discard_info): Fix calculation of "eh_alignment". * elf-bfd.h (struct elf_link_hash_table): Add unit to tls_size member. * elf.c (_bfd_elf_map_sections_to_segments): Add unit (bytes/ octets) to "wrap_to2 and "phdr_size" locals. Fix calculation of "wrap_to" value. Add unit (bytes) to phdr_lma variable. Fix assignment of p_paddr from phdr_lma. Fix comparison between "lma +size" and "next->lma". (elf_sort_segments): Fix assignment from p_paddr to lma. (assign_file_positions_for_load_sections): Add unit (bytes) to local "align". Fix calculation of local "off_adjust". Fix calculation of local "filehdr_vaddr". (assign_file_positions_for_non_load_sections): New local "opb". Fix calculation of "end" from "p_size". Fix comparison between "vma+SECTION_SIZE()" and "start". Fix calculation of "p_memsz" from "end" and "p_vaddr". (rewrite_elf_program_header): Fix comparison between p_vaddr and vma. Fix assignment to p_paddr from lma. Fix comparison between p_paddr and lma. Fix assignment to p_paddr from lma. * merge.c (sec_merge_emit): New local "opb". Convert "alignment_power" to octets. (_bfd_add_merge_section): New locals "alignment_power" and "opb". Fix comparison between "alignment_power" and "sizeof(align)". (_bfd_merge_sections): New local "opb". Divide size by opb before checking align mask. Signed-off-by: Christian Eggers <ceggers@gmx.de> --- bfd/bfd.c | 5 +++-- bfd/elf-bfd.h | 2 +- bfd/elf.c | 54 +++++++++++++++++++++++++------------------------- bfd/elfcode.h | 28 ++++++++++++++------------ bfd/elflink.c | 31 +++++++++++++++++------------ bfd/merge.c | 22 ++++++++++++-------- include/bfdlink.h | 4 ++-- include/elf/internal.h | 7 ++++--- 8 files changed, 84 insertions(+), 69 deletions(-) diff --git a/bfd/bfd.c b/bfd/bfd.c index b1050626b68..5802985099a 100644 --- a/bfd/bfd.c +++ b/bfd/bfd.c @@ -2162,7 +2162,7 @@ bfd_record_phdr (bfd *abfd, bfd_boolean flags_valid, flagword flags, bfd_boolean at_valid, - bfd_vma at, + bfd_vma at, /* bytes */ bfd_boolean includes_filehdr, bfd_boolean includes_phdrs, unsigned int count, @@ -2170,6 +2170,7 @@ bfd_record_phdr (bfd *abfd, { struct elf_segment_map *m, **pm; bfd_size_type amt; + unsigned int opb = bfd_octets_per_byte (abfd, NULL); if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) return TRUE; @@ -2182,7 +2183,7 @@ bfd_record_phdr (bfd *abfd, m->p_type = type; m->p_flags = flags; - m->p_paddr = at; + m->p_paddr = at * opb; m->p_flags_valid = flags_valid; m->p_paddr_valid = at_valid; m->includes_filehdr = includes_filehdr; diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index cbbba153f49..f74afacc976 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -635,7 +635,7 @@ struct elf_link_hash_table /* Cached first output tls section and size of PT_TLS segment. */ asection *tls_sec; - bfd_size_type tls_size; + bfd_size_type tls_size; /* bytes */ /* A linked list of BFD's loaded in the link. */ struct elf_link_loaded_list *loaded; diff --git a/bfd/elf.c b/bfd/elf.c index d941b33b15c..fbc45f6d30f 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -4688,8 +4688,8 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) asection *first_mbind = NULL; asection *dynsec, *eh_frame_hdr; bfd_size_type amt; - bfd_vma addr_mask, wrap_to = 0; - bfd_size_type phdr_size; + bfd_vma addr_mask, wrap_to = 0; /* bytes */ + bfd_size_type phdr_size; /* octets/bytes */ unsigned int opb = bfd_octets_per_byte (abfd, NULL); /* Select the allocated sections, and sort them. */ @@ -4717,8 +4717,8 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) sections[i] = s; ++i; /* A wrapping section potentially clashes with header. */ - if (((s->lma + s->size) & addr_mask) < (s->lma & addr_mask)) - wrap_to = (s->lma + s->size) & addr_mask; + if (((s->lma + s->size / opb) & addr_mask) < (s->lma & addr_mask)) + wrap_to = (s->lma + s->size / opb) & addr_mask; } } BFD_ASSERT (i <= bfd_count_sections (abfd)); @@ -4802,7 +4802,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) program headers we will need. */ if (phdr_in_segment && count > 0) { - bfd_vma phdr_lma; + bfd_vma phdr_lma; /* bytes */ bfd_boolean separate_phdr = FALSE; phdr_lma = (sections[0]->lma - phdr_size) & addr_mask & -maxpagesize; @@ -4842,7 +4842,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) m = make_mapping (abfd, sections, 0, 0, phdr_in_segment); if (m == NULL) goto error_return; - m->p_paddr = phdr_lma; + m->p_paddr = phdr_lma * opb; m->p_vaddr_offset = (sections[0]->vma - phdr_size) & addr_mask & -maxpagesize; m->p_paddr_valid = 1; @@ -5030,7 +5030,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) if (s2->next->alignment_power == alignment_power && (s2->next->flags & SEC_LOAD) != 0 && elf_section_type (s2->next) == SHT_NOTE - && align_power (s2->lma + s2->size, + && align_power (s2->lma + s2->size / opb, alignment_power) == s2->next->lma) count++; @@ -5328,15 +5328,17 @@ elf_sort_segments (const void *arg1, const void *arg2) return m1->no_sort_lma ? -1 : 1; if (m1->p_type == PT_LOAD && !m1->no_sort_lma) { - bfd_vma lma1, lma2; + unsigned int opb = bfd_octets_per_byte (m1->sections[0]->owner, + m1->sections[0]); + bfd_vma lma1, lma2; /* bytes */ lma1 = 0; if (m1->p_paddr_valid) - lma1 = m1->p_paddr; + lma1 = m1->p_paddr / opb; 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; + lma2 = m2->p_paddr / opb; else if (m2->count != 0) lma2 = m2->sections[0]->lma + m2->p_vaddr_offset; if (lma1 != lma2) @@ -5607,7 +5609,7 @@ assign_file_positions_for_load_sections (bfd *abfd, if (p->p_type == PT_LOAD && m->count > 0) { - bfd_size_type align; + bfd_size_type align; /* bytes */ unsigned int align_power = 0; if (m->p_align_valid) @@ -5644,7 +5646,7 @@ assign_file_positions_for_load_sections (bfd *abfd, break; } - off_adjust = vma_page_aligned_bias (p->p_vaddr, off, align); + off_adjust = vma_page_aligned_bias (p->p_vaddr, off, align * opb); /* Broken hardware and/or kernel require that files do not map the same page with different permissions on some hppa @@ -6007,7 +6009,7 @@ assign_file_positions_for_load_sections (bfd *abfd, || hash->root.type == bfd_link_hash_common)) { asection *s = NULL; - bfd_vma filehdr_vaddr = phdrs[phdr_load_seg->idx].p_vaddr; + bfd_vma filehdr_vaddr = phdrs[phdr_load_seg->idx].p_vaddr / opb; if (phdr_load_seg->count != 0) /* The segment contains sections, so use the first one. */ @@ -6084,6 +6086,7 @@ assign_file_positions_for_non_load_sections (bfd *abfd, Elf_Internal_Phdr *p; struct elf_segment_map *m; file_ptr off; + unsigned int opb = bfd_octets_per_byte (abfd, NULL); i_shdrpp = elf_elfsections (abfd); end_hdrpp = i_shdrpp + elf_numsections (abfd); @@ -6150,7 +6153,7 @@ assign_file_positions_for_non_load_sections (bfd *abfd, { if (p->p_type == PT_GNU_RELRO) { - bfd_vma start, end; + bfd_vma start, end; /* bytes */ bfd_boolean ok; if (link_info != NULL) @@ -6166,7 +6169,7 @@ assign_file_positions_for_non_load_sections (bfd *abfd, if (!m->p_size_valid) abort (); start = m->sections[0]->vma; - end = start + m->p_size; + end = start + m->p_size / opb; } else { @@ -6191,7 +6194,7 @@ assign_file_positions_for_non_load_sections (bfd *abfd, && lm->count != 0 && (lm->sections[lm->count - 1]->vma + (!IS_TBSS (lm->sections[lm->count - 1]) - ? lm->sections[lm->count - 1]->size + ? lm->sections[lm->count - 1]->size / opb : 0)) > start && lm->sections[0]->vma < end) break; @@ -6211,13 +6214,10 @@ assign_file_positions_for_non_load_sections (bfd *abfd, if (i < lm->count) { - unsigned int opb = bfd_octets_per_byte (abfd, - lm->sections[i]); - p->p_vaddr = lm->sections[i]->vma * opb; p->p_paddr = lm->sections[i]->lma * opb; p->p_offset = lm->sections[i]->filepos; - p->p_memsz = end - p->p_vaddr; + p->p_memsz = end * opb - p->p_vaddr; p->p_filesz = p->p_memsz; /* The RELRO segment typically ends a few bytes @@ -7199,8 +7199,8 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) + (map->includes_phdrs ? iehdr->e_phnum * iehdr->e_phentsize : 0), - output_section->alignment_power) - == output_section->vma)) + output_section->alignment_power * opb) + == (output_section->vma * opb))) map->p_paddr = segment->p_vaddr; /* Match up the physical address of the segment with the @@ -7268,7 +7268,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) if (matching_lma == NULL) matching_lma = suggested_lma; - map->p_paddr = matching_lma->lma; + map->p_paddr = matching_lma->lma * opb; /* Offset the segment physical address from the lma to allow for space taken up by elf headers. */ @@ -7296,7 +7296,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) the same alignment. */ if (segment->p_align != 0 && segment->p_align < align) align = segment->p_align; - map->p_paddr &= -align; + map->p_paddr &= -(align * opb); } } @@ -7340,8 +7340,8 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) + (map->includes_phdrs ? iehdr->e_phnum * iehdr->e_phentsize : 0), - output_section->alignment_power) - != output_section->lma) + output_section->alignment_power * opb) + != output_section->lma * opb) goto sorry; } else @@ -7407,7 +7407,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) map->p_type = segment->p_type; map->p_flags = segment->p_flags; map->p_flags_valid = 1; - map->p_paddr = suggested_lma->lma; + map->p_paddr = suggested_lma->lma * opb; map->p_paddr_valid = p_paddr_valid; map->includes_filehdr = 0; map->includes_phdrs = 0; diff --git a/bfd/elfcode.h b/bfd/elfcode.h index e1e89cf78f2..9ffdba56b66 100644 --- a/bfd/elfcode.h +++ b/bfd/elfcode.h @@ -1635,10 +1635,11 @@ elf_debug_file (Elf_Internal_Ehdr *ehdrp) bfd * NAME(_bfd_elf,bfd_from_remote_memory) (bfd *templ, - bfd_vma ehdr_vma, - bfd_size_type size, - bfd_vma *loadbasep, + bfd_vma ehdr_vma /* bytes */, + bfd_size_type size /* octets */, + bfd_vma *loadbasep /* bytes */, int (*target_read_memory) (bfd_vma, bfd_byte *, bfd_size_type)) + /* (bytes , , octets )*/ { Elf_External_Ehdr x_ehdr; /* Elf file header, external form */ Elf_Internal_Ehdr i_ehdr; /* Elf file header, internal form */ @@ -1651,8 +1652,9 @@ NAME(_bfd_elf,bfd_from_remote_memory) unsigned int i; bfd_vma high_offset; bfd_vma shdr_end; - bfd_vma loadbase; + bfd_vma loadbase; /* bytes */ char *filename; + unsigned int opb = bfd_octets_per_byte (templ, NULL); /* Read in the ELF header in external format. */ err = target_read_memory (ehdr_vma, (bfd_byte *) &x_ehdr, sizeof x_ehdr); @@ -1746,17 +1748,17 @@ NAME(_bfd_elf,bfd_from_remote_memory) header sits, then we can figure out the loadbase. */ if (first_phdr == NULL) { - bfd_vma p_offset = i_phdrs[i].p_offset; - bfd_vma p_vaddr = i_phdrs[i].p_vaddr; + bfd_vma p_offset = i_phdrs[i].p_offset; /* octets */ + bfd_vma p_vaddr = i_phdrs[i].p_vaddr; /* octets */ if (i_phdrs[i].p_align > 1) { - p_offset &= -i_phdrs[i].p_align; - p_vaddr &= -i_phdrs[i].p_align; + p_offset &= -(i_phdrs[i].p_align * opb); + p_vaddr &= -(i_phdrs[i].p_align * opb); } if (p_offset == 0) { - loadbase = ehdr_vma - p_vaddr; + loadbase = ehdr_vma - p_vaddr / opb; first_phdr = &i_phdrs[i]; } } @@ -1812,9 +1814,9 @@ NAME(_bfd_elf,bfd_from_remote_memory) for (i = 0; i < i_ehdr.e_phnum; ++i) if (i_phdrs[i].p_type == PT_LOAD) { - bfd_vma start = i_phdrs[i].p_offset; - bfd_vma end = start + i_phdrs[i].p_filesz; - bfd_vma vaddr = i_phdrs[i].p_vaddr; + bfd_vma start = i_phdrs[i].p_offset; /* octets */ + bfd_vma end = start + i_phdrs[i].p_filesz; /* octets */ + bfd_vma vaddr = i_phdrs[i].p_vaddr; /* octets */ /* Extend the beginning of the first pt_load to cover file header and program headers, if we proved earlier that its @@ -1827,7 +1829,7 @@ NAME(_bfd_elf,bfd_from_remote_memory) /* Extend the end of the last pt_load to cover section headers. */ if (last_phdr == &i_phdrs[i]) end = high_offset; - err = target_read_memory (loadbase + vaddr, + err = target_read_memory (loadbase + vaddr / opb, contents + start, end - start); if (err) { diff --git a/bfd/elflink.c b/bfd/elflink.c index 43fbbf0dd1b..788fd803f35 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -11570,8 +11570,8 @@ elf_fixup_link_order (bfd *abfd, asection *o) struct bfd_link_order *p; bfd *sub; struct bfd_link_order **sections; - asection *s, *other_sec, *linkorder_sec; - bfd_vma offset; + asection *other_sec, *linkorder_sec; + bfd_vma offset; /* octets */ other_sec = NULL; linkorder_sec = NULL; @@ -11581,7 +11581,7 @@ elf_fixup_link_order (bfd *abfd, asection *o) { if (p->type == bfd_indirect_link_order) { - s = p->u.indirect.section; + asection *s = p->u.indirect.section; sub = s->owner; if ((s->flags & SEC_LINKER_CREATED) == 0 && bfd_get_flavour (sub) == bfd_target_elf_flavour @@ -11636,11 +11636,12 @@ elf_fixup_link_order (bfd *abfd, asection *o) for (n = 0; n < seen_linkorder; n++) { bfd_vma mask; - s = sections[n]->u.indirect.section; - mask = ~(bfd_vma) 0 << s->alignment_power; + asection *s = sections[n]->u.indirect.section; + unsigned int opb = bfd_octets_per_byte (abfd, s); + + mask = ~(bfd_vma) 0 << s->alignment_power * opb; offset = (offset + ~mask) & mask; - s->output_offset = offset / bfd_octets_per_byte (abfd, s); - sections[n]->offset = offset; + sections[n]->offset = s->output_offset = offset / opb; offset += sections[n]->size; } @@ -12250,7 +12251,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) if (htab->tls_sec) { - bfd_vma base, end = 0; + bfd_vma base, end = 0; /* both bytes */ asection *sec; for (sec = htab->tls_sec; @@ -12258,6 +12259,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) sec = sec->next) { bfd_size_type size = sec->size; + unsigned int opb = bfd_octets_per_byte (abfd, sec); if (size == 0 && (sec->flags & SEC_HAS_CONTENTS) == 0) @@ -12265,9 +12267,9 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) struct bfd_link_order *ord = sec->map_tail.link_order; if (ord != NULL) - size = ord->offset + ord->size; + size = ord->offset * opb + ord->size; } - end = sec->vma + size; + end = sec->vma + size / opb; } base = htab->tls_sec->vma; /* Only align end of TLS section if static TLS doesn't have special @@ -12780,6 +12782,8 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) if (bed->dtrel_excludes_plt && htab->srelplt != NULL) { + unsigned int opb = bfd_octets_per_byte (abfd, o); + /* Don't count procedure linkage table relocs in the overall reloc count. */ sh_size -= htab->srelplt->size; @@ -12799,7 +12803,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) /* If .rela.plt is the first .rela section, exclude it from DT_RELA. */ else if (sh_addr == (htab->srelplt->output_section->vma - + htab->srelplt->output_offset)) + + htab->srelplt->output_offset) * opb) sh_addr += htab->srelplt->size; } @@ -14254,7 +14258,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) { asection *i; int eh_changed = 0; - unsigned int eh_alignment; + unsigned int eh_alignment; /* octets */ for (i = o->map_head.s; i != NULL; i = i->map_head.s) { @@ -14281,7 +14285,8 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) fini_reloc_cookie_for_section (&cookie, i); } - eh_alignment = 1 << o->alignment_power; + eh_alignment = ((1 << o->alignment_power) + * bfd_octets_per_byte (output_bfd, o)); /* Skip over zero terminator, and prevent empty sections from adding alignment padding at the end. */ for (i = o->map_tail.s; i != NULL; i = i->map_tail.s) diff --git a/bfd/merge.c b/bfd/merge.c index 2ed1ef595c4..59805325273 100644 --- a/bfd/merge.c +++ b/bfd/merge.c @@ -292,8 +292,9 @@ sec_merge_emit (bfd *abfd, struct sec_merge_hash_entry *entry, asection *sec = secinfo->sec; char *pad = NULL; bfd_size_type off = 0; - int alignment_power = sec->output_section->alignment_power; - bfd_size_type pad_len; + unsigned int opb = bfd_octets_per_byte (abfd, sec); + int alignment_power = sec->output_section->alignment_power * opb; + bfd_size_type pad_len; /* octets */ /* FIXME: If alignment_power is 0 then really we should scan the entry list for the largest required alignment and use that. */ @@ -364,9 +365,11 @@ _bfd_add_merge_section (bfd *abfd, void **psinfo, asection *sec, { struct sec_merge_info *sinfo; struct sec_merge_sec_info *secinfo; - unsigned int align; + unsigned int alignment_power; /* octets */ + unsigned int align; /* octets */ bfd_size_type amt; bfd_byte *contents; + unsigned int opb = bfd_octets_per_byte (abfd, sec); if ((abfd->flags & DYNAMIC) != 0 || (sec->flags & SEC_MERGE) == 0) @@ -389,10 +392,11 @@ _bfd_add_merge_section (bfd *abfd, void **psinfo, asection *sec, #ifndef CHAR_BIT #define CHAR_BIT 8 #endif - if (sec->alignment_power >= sizeof (align) * CHAR_BIT) + alignment_power = sec->alignment_power * opb; + if (alignment_power >= sizeof (align) * CHAR_BIT) return TRUE; - align = 1u << sec->alignment_power; + align = 1u << alignment_power; if ((sec->entsize < align && ((sec->entsize & (sec->entsize - 1)) || !(sec->flags & SEC_STRINGS))) @@ -739,7 +743,7 @@ _bfd_merge_sections (bfd *abfd, for (sinfo = (struct sec_merge_info *) xsinfo; sinfo; sinfo = sinfo->next) { struct sec_merge_sec_info *secinfo; - bfd_size_type align; + bfd_size_type align; /* bytes */ if (! sinfo->chain) continue; @@ -764,8 +768,10 @@ _bfd_merge_sections (bfd *abfd, return FALSE; if (align) { + unsigned int opb = bfd_octets_per_byte (abfd, secinfo->sec); + align = (bfd_size_type) 1 << secinfo->sec->alignment_power; - if ((secinfo->sec->size & (align - 1)) != 0) + if (((secinfo->sec->size / opb) & (align - 1)) != 0) align = 0; } } @@ -782,7 +788,7 @@ _bfd_merge_sections (bfd *abfd, else { struct sec_merge_hash_entry *e; - bfd_size_type size = 0; + bfd_size_type size = 0; /* octets */ /* Things are much simpler for non-strings. Just assign them slots in the section. */ diff --git a/include/bfdlink.h b/include/bfdlink.h index 8d85530e390..40a6d4d40a6 100644 --- a/include/bfdlink.h +++ b/include/bfdlink.h @@ -801,9 +801,9 @@ struct bfd_link_order struct bfd_link_order *next; /* Type of link_order. */ enum bfd_link_order_type type; - /* Offset within output section. */ + /* Offset within output section in bytes. */ bfd_vma offset; - /* Size within output section. */ + /* Size within output section in octets. */ bfd_size_type size; /* Type specific information. */ union diff --git a/include/elf/internal.h b/include/elf/internal.h index c436e64fe56..c9be57fa1f7 100644 --- a/include/elf/internal.h +++ b/include/elf/internal.h @@ -91,7 +91,8 @@ struct elf_internal_phdr { bfd_vma p_paddr; /* Segment physical address in octets */ bfd_vma p_filesz; /* Segment size in file in octets */ bfd_vma p_memsz; /* Segment size in memory in octets */ - bfd_vma p_align; /* Segment alignment, file & memory */ + bfd_vma p_align; /* Segment alignment in bytes, file + & memory */ }; typedef struct elf_internal_phdr Elf_Internal_Phdr; @@ -266,13 +267,13 @@ struct elf_segment_map unsigned long p_type; /* Program segment flags. */ unsigned long p_flags; - /* Program segment physical address. */ + /* Program segment physical address in octets. */ bfd_vma p_paddr; /* Program segment virtual address offset from section vma in bytes. */ bfd_vma p_vaddr_offset; /* Program segment alignment. */ bfd_vma p_align; - /* Segment size in file and memory */ + /* Segment size in file and memory in octets. */ bfd_vma p_size; /* Whether the p_flags field is valid; if not, the flags are based on the section flags. */ -- 2.16.4 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/2] Fix several mix up between octets and bytes in ELF program headers 2020-02-15 19:31 ` [PATCH 2/2] " Christian Eggers @ 2020-03-02 14:18 ` Nick Clifton 2020-03-02 20:17 ` [PATCH v2 " Christian Eggers 0 siblings, 1 reply; 8+ messages in thread From: Nick Clifton @ 2020-03-02 14:18 UTC (permalink / raw) To: Christian Eggers, binutils; +Cc: amodra Hi Christian, > include/ > * bfdlink.h (struct bfd_link_order): Add unit (bytes/octets) to > offset and size members. > * elf/internal.h (struct elf_internal_phdr): likewise for > p_align member. > (struct elf_segment_map): likewise for p_paddr and p_size > members > > bfd/ > * bfd.c (bfd_record_phdr): New local "opb". Fix assignment of > "p_paddr" from "at". > * elfcode.h (bfd_from_remote_memory): Add units to several > parameters. New local "opb". Fix usage of p_align. Fix > calculation of "localbase" from "ehdr_vma" and "p_vaddr". Fix > call of target_read_memory(). > * elflink.c (elf_fixup_link_order): Fix scope of "s" local. Fix > calculation of "offset" and "output_offset". > (bfd_elf_final_link): New local "opb". Fix calculation of "size" > from "offset" and fix calculation of "end" from "vma+size". Fix > comparison between "sh_addr" and "vma"/"output_offset". > (bfd_elf_discard_info): Fix calculation of "eh_alignment". > * elf-bfd.h (struct elf_link_hash_table): Add unit to tls_size > member. > * elf.c (_bfd_elf_map_sections_to_segments): Add unit (bytes/ > octets) to "wrap_to2 and "phdr_size" locals. Fix calculation of > "wrap_to" value. Add unit (bytes) to phdr_lma variable. Fix > assignment of p_paddr from phdr_lma. Fix comparison between "lma > +size" and "next->lma". > (elf_sort_segments): Fix assignment from p_paddr to lma. > (assign_file_positions_for_load_sections): Add unit (bytes) to > local "align". Fix calculation of local "off_adjust". Fix > calculation of local "filehdr_vaddr". > (assign_file_positions_for_non_load_sections): New local "opb". > Fix calculation of "end" from "p_size". Fix comparison between > "vma+SECTION_SIZE()" and "start". Fix calculation of "p_memsz" > from "end" and "p_vaddr". > (rewrite_elf_program_header): Fix comparison between p_vaddr and > vma. Fix assignment to p_paddr from lma. Fix comparison between > p_paddr and lma. Fix assignment to p_paddr from lma. > * merge.c (sec_merge_emit): New local "opb". Convert > "alignment_power" to octets. > (_bfd_add_merge_section): New locals "alignment_power" and > "opb". Fix comparison between "alignment_power" and > "sizeof(align)". > (_bfd_merge_sections): New local "opb". Divide size by opb > before checking align mask. Approved - please apply - but please fixup the comments first. Cheers Nick ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2 2/2] Fix several mix up between octets and bytes in ELF program headers 2020-03-02 14:18 ` Nick Clifton @ 2020-03-02 20:17 ` Christian Eggers 2020-03-12 18:24 ` Christian Eggers 0 siblings, 1 reply; 8+ messages in thread From: Christian Eggers @ 2020-03-02 20:17 UTC (permalink / raw) To: binutils, Nick Clifton; +Cc: amodra, Christian Eggers Hi Nick, On Monday, March 2nd 2020, Nick Clifton wrote: > Approved - please apply - but please fixup the comments first. Comments changed, thanks. Christian --- This is a follow-up patch for my patch from december 09 with the same subject. It fixes additional locations not handled in the first patch. When converting between addresses in ELF headers [octets] and bfd LMA/VMA [bytes], the number of octets per byte needs to be incorperated. Patch changelog: v2: - GNU coding style for comments. include/ * bfdlink.h (struct bfd_link_order): Add unit (bytes/octets) to offset and size members. * elf/internal.h (struct elf_internal_phdr): likewise for p_align member. (struct elf_segment_map): likewise for p_paddr and p_size members bfd/ * bfd.c (bfd_record_phdr): New local "opb". Fix assignment of "p_paddr" from "at". * elfcode.h (bfd_from_remote_memory): Add units to several parameters. New local "opb". Fix usage of p_align. Fix calculation of "localbase" from "ehdr_vma" and "p_vaddr". Fix call of target_read_memory(). * elflink.c (elf_fixup_link_order): Fix scope of "s" local. Fix calculation of "offset" and "output_offset". (bfd_elf_final_link): New local "opb". Fix calculation of "size" from "offset" and fix calculation of "end" from "vma+size". Fix comparison between "sh_addr" and "vma"/"output_offset". (bfd_elf_discard_info): Fix calculation of "eh_alignment". * elf-bfd.h (struct elf_link_hash_table): Add unit to tls_size member. * elf.c (_bfd_elf_map_sections_to_segments): Add unit (bytes/ octets) to "wrap_to2 and "phdr_size" locals. Fix calculation of "wrap_to" value. Add unit (bytes) to phdr_lma variable. Fix assignment of p_paddr from phdr_lma. Fix comparison between "lma +size" and "next->lma". (elf_sort_segments): Fix assignment from p_paddr to lma. (assign_file_positions_for_load_sections): Add unit (bytes) to local "align". Fix calculation of local "off_adjust". Fix calculation of local "filehdr_vaddr". (assign_file_positions_for_non_load_sections): New local "opb". Fix calculation of "end" from "p_size". Fix comparison between "vma+SECTION_SIZE()" and "start". Fix calculation of "p_memsz" from "end" and "p_vaddr". (rewrite_elf_program_header): Fix comparison between p_vaddr and vma. Fix assignment to p_paddr from lma. Fix comparison between p_paddr and lma. Fix assignment to p_paddr from lma. * merge.c (sec_merge_emit): New local "opb". Convert "alignment_power" to octets. (_bfd_add_merge_section): New locals "alignment_power" and "opb". Fix comparison between "alignment_power" and "sizeof(align)". (_bfd_merge_sections): New local "opb". Divide size by opb before checking align mask. Signed-off-by: Christian Eggers <ceggers@gmx.de> --- bfd/bfd.c | 5 +++-- bfd/elf-bfd.h | 2 +- bfd/elf.c | 54 +++++++++++++++++++++++++------------------------- bfd/elfcode.h | 28 ++++++++++++++------------ bfd/elflink.c | 31 +++++++++++++++++------------ bfd/merge.c | 22 ++++++++++++-------- include/bfdlink.h | 4 ++-- include/elf/internal.h | 7 ++++--- 8 files changed, 84 insertions(+), 69 deletions(-) diff --git a/bfd/bfd.c b/bfd/bfd.c index 1c1238c036a..100359ccfe6 100644 --- a/bfd/bfd.c +++ b/bfd/bfd.c @@ -2168,7 +2168,7 @@ bfd_record_phdr (bfd *abfd, bfd_boolean flags_valid, flagword flags, bfd_boolean at_valid, - bfd_vma at, + bfd_vma at, /* Bytes. */ bfd_boolean includes_filehdr, bfd_boolean includes_phdrs, unsigned int count, @@ -2176,6 +2176,7 @@ bfd_record_phdr (bfd *abfd, { struct elf_segment_map *m, **pm; size_t amt; + unsigned int opb = bfd_octets_per_byte (abfd, NULL); if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) return TRUE; @@ -2188,7 +2189,7 @@ bfd_record_phdr (bfd *abfd, m->p_type = type; m->p_flags = flags; - m->p_paddr = at; + m->p_paddr = at * opb; m->p_flags_valid = flags_valid; m->p_paddr_valid = at_valid; m->includes_filehdr = includes_filehdr; diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 38a9aa06019..54c27a1b76c 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -635,7 +635,7 @@ struct elf_link_hash_table /* Cached first output tls section and size of PT_TLS segment. */ asection *tls_sec; - bfd_size_type tls_size; + bfd_size_type tls_size; /* Bytes. */ /* A linked list of dynamic BFD's loaded in the link. */ struct elf_link_loaded_list *dyn_loaded; diff --git a/bfd/elf.c b/bfd/elf.c index a329e239828..bc75b96adcb 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -4665,8 +4665,8 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) asection *first_mbind = NULL; asection *dynsec, *eh_frame_hdr; size_t amt; - bfd_vma addr_mask, wrap_to = 0; - bfd_size_type phdr_size; + bfd_vma addr_mask, wrap_to = 0; /* Bytes. */ + bfd_size_type phdr_size; /* Octets/bytes. */ unsigned int opb = bfd_octets_per_byte (abfd, NULL); /* Select the allocated sections, and sort them. */ @@ -4694,8 +4694,8 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) sections[i] = s; ++i; /* A wrapping section potentially clashes with header. */ - if (((s->lma + s->size) & addr_mask) < (s->lma & addr_mask)) - wrap_to = (s->lma + s->size) & addr_mask; + if (((s->lma + s->size / opb) & addr_mask) < (s->lma & addr_mask)) + wrap_to = (s->lma + s->size / opb) & addr_mask; } } BFD_ASSERT (i <= bfd_count_sections (abfd)); @@ -4779,7 +4779,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) program headers we will need. */ if (phdr_in_segment && count > 0) { - bfd_vma phdr_lma; + bfd_vma phdr_lma; /* Bytes. */ bfd_boolean separate_phdr = FALSE; phdr_lma = (sections[0]->lma - phdr_size) & addr_mask & -maxpagesize; @@ -4819,7 +4819,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) m = make_mapping (abfd, sections, 0, 0, phdr_in_segment); if (m == NULL) goto error_return; - m->p_paddr = phdr_lma; + m->p_paddr = phdr_lma * opb; m->p_vaddr_offset = (sections[0]->vma - phdr_size) & addr_mask & -maxpagesize; m->p_paddr_valid = 1; @@ -5007,7 +5007,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) if (s2->next->alignment_power == alignment_power && (s2->next->flags & SEC_LOAD) != 0 && elf_section_type (s2->next) == SHT_NOTE - && align_power (s2->lma + s2->size, + && align_power (s2->lma + s2->size / opb, alignment_power) == s2->next->lma) count++; @@ -5305,15 +5305,17 @@ elf_sort_segments (const void *arg1, const void *arg2) return m1->no_sort_lma ? -1 : 1; if (m1->p_type == PT_LOAD && !m1->no_sort_lma) { - bfd_vma lma1, lma2; + unsigned int opb = bfd_octets_per_byte (m1->sections[0]->owner, + m1->sections[0]); + bfd_vma lma1, lma2; /* Bytes. */ lma1 = 0; if (m1->p_paddr_valid) - lma1 = m1->p_paddr; + lma1 = m1->p_paddr / opb; 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; + lma2 = m2->p_paddr / opb; else if (m2->count != 0) lma2 = m2->sections[0]->lma + m2->p_vaddr_offset; if (lma1 != lma2) @@ -5584,7 +5586,7 @@ assign_file_positions_for_load_sections (bfd *abfd, if (p->p_type == PT_LOAD && m->count > 0) { - bfd_size_type align; + bfd_size_type align; /* Bytes. */ unsigned int align_power = 0; if (m->p_align_valid) @@ -5621,7 +5623,7 @@ assign_file_positions_for_load_sections (bfd *abfd, break; } - off_adjust = vma_page_aligned_bias (p->p_vaddr, off, align); + off_adjust = vma_page_aligned_bias (p->p_vaddr, off, align * opb); /* Broken hardware and/or kernel require that files do not map the same page with different permissions on some hppa @@ -5988,7 +5990,7 @@ assign_file_positions_for_load_sections (bfd *abfd, || hash->root.type == bfd_link_hash_common)) { asection *s = NULL; - bfd_vma filehdr_vaddr = phdrs[phdr_load_seg->idx].p_vaddr; + bfd_vma filehdr_vaddr = phdrs[phdr_load_seg->idx].p_vaddr / opb; if (phdr_load_seg->count != 0) /* The segment contains sections, so use the first one. */ @@ -6065,6 +6067,7 @@ assign_file_positions_for_non_load_sections (bfd *abfd, Elf_Internal_Phdr *p; struct elf_segment_map *m; file_ptr off; + unsigned int opb = bfd_octets_per_byte (abfd, NULL); i_shdrpp = elf_elfsections (abfd); end_hdrpp = i_shdrpp + elf_numsections (abfd); @@ -6131,7 +6134,7 @@ assign_file_positions_for_non_load_sections (bfd *abfd, { if (p->p_type == PT_GNU_RELRO) { - bfd_vma start, end; + bfd_vma start, end; /* Bytes. */ bfd_boolean ok; if (link_info != NULL) @@ -6147,7 +6150,7 @@ assign_file_positions_for_non_load_sections (bfd *abfd, if (!m->p_size_valid) abort (); start = m->sections[0]->vma; - end = start + m->p_size; + end = start + m->p_size / opb; } else { @@ -6172,7 +6175,7 @@ assign_file_positions_for_non_load_sections (bfd *abfd, && lm->count != 0 && (lm->sections[lm->count - 1]->vma + (!IS_TBSS (lm->sections[lm->count - 1]) - ? lm->sections[lm->count - 1]->size + ? lm->sections[lm->count - 1]->size / opb : 0)) > start && lm->sections[0]->vma < end) break; @@ -6192,13 +6195,10 @@ assign_file_positions_for_non_load_sections (bfd *abfd, if (i < lm->count) { - unsigned int opb = bfd_octets_per_byte (abfd, - lm->sections[i]); - p->p_vaddr = lm->sections[i]->vma * opb; p->p_paddr = lm->sections[i]->lma * opb; p->p_offset = lm->sections[i]->filepos; - p->p_memsz = end - p->p_vaddr; + p->p_memsz = end * opb - p->p_vaddr; p->p_filesz = p->p_memsz; /* The RELRO segment typically ends a few bytes @@ -7181,8 +7181,8 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) + (map->includes_phdrs ? iehdr->e_phnum * iehdr->e_phentsize : 0), - output_section->alignment_power) - == output_section->vma)) + output_section->alignment_power * opb) + == (output_section->vma * opb))) map->p_paddr = segment->p_vaddr; /* Match up the physical address of the segment with the @@ -7250,7 +7250,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) if (matching_lma == NULL) matching_lma = suggested_lma; - map->p_paddr = matching_lma->lma; + map->p_paddr = matching_lma->lma * opb; /* Offset the segment physical address from the lma to allow for space taken up by elf headers. */ @@ -7278,7 +7278,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) the same alignment. */ if (segment->p_align != 0 && segment->p_align < align) align = segment->p_align; - map->p_paddr &= -align; + map->p_paddr &= -(align * opb); } } @@ -7322,8 +7322,8 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) + (map->includes_phdrs ? iehdr->e_phnum * iehdr->e_phentsize : 0), - output_section->alignment_power) - != output_section->lma) + output_section->alignment_power * opb) + != output_section->lma * opb) goto sorry; } else @@ -7389,7 +7389,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) map->p_type = segment->p_type; map->p_flags = segment->p_flags; map->p_flags_valid = 1; - map->p_paddr = suggested_lma->lma; + map->p_paddr = suggested_lma->lma * opb; map->p_paddr_valid = p_paddr_valid; map->includes_filehdr = 0; map->includes_phdrs = 0; diff --git a/bfd/elfcode.h b/bfd/elfcode.h index 600abfe836e..ec5156a433d 100644 --- a/bfd/elfcode.h +++ b/bfd/elfcode.h @@ -1648,10 +1648,11 @@ elf_debug_file (Elf_Internal_Ehdr *ehdrp) bfd * NAME(_bfd_elf,bfd_from_remote_memory) (bfd *templ, - bfd_vma ehdr_vma, - bfd_size_type size, - bfd_vma *loadbasep, + bfd_vma ehdr_vma /* Bytes. */, + bfd_size_type size /* Octets. */, + bfd_vma *loadbasep /* Bytes. */, int (*target_read_memory) (bfd_vma, bfd_byte *, bfd_size_type)) + /* (Bytes , , octets ). */ { Elf_External_Ehdr x_ehdr; /* Elf file header, external form */ Elf_Internal_Ehdr i_ehdr; /* Elf file header, internal form */ @@ -1664,9 +1665,10 @@ NAME(_bfd_elf,bfd_from_remote_memory) unsigned int i; bfd_vma high_offset; bfd_vma shdr_end; - bfd_vma loadbase; + bfd_vma loadbase; /* Bytes. */ char *filename; size_t amt; + unsigned int opb = bfd_octets_per_byte (templ, NULL); /* Read in the ELF header in external format. */ err = target_read_memory (ehdr_vma, (bfd_byte *) &x_ehdr, sizeof x_ehdr); @@ -1764,17 +1766,17 @@ NAME(_bfd_elf,bfd_from_remote_memory) header sits, then we can figure out the loadbase. */ if (first_phdr == NULL) { - bfd_vma p_offset = i_phdrs[i].p_offset; - bfd_vma p_vaddr = i_phdrs[i].p_vaddr; + bfd_vma p_offset = i_phdrs[i].p_offset; /* Octets. */ + bfd_vma p_vaddr = i_phdrs[i].p_vaddr; /* Octets. */ if (i_phdrs[i].p_align > 1) { - p_offset &= -i_phdrs[i].p_align; - p_vaddr &= -i_phdrs[i].p_align; + p_offset &= -(i_phdrs[i].p_align * opb); + p_vaddr &= -(i_phdrs[i].p_align * opb); } if (p_offset == 0) { - loadbase = ehdr_vma - p_vaddr; + loadbase = ehdr_vma - p_vaddr / opb; first_phdr = &i_phdrs[i]; } } @@ -1830,9 +1832,9 @@ NAME(_bfd_elf,bfd_from_remote_memory) for (i = 0; i < i_ehdr.e_phnum; ++i) if (i_phdrs[i].p_type == PT_LOAD) { - bfd_vma start = i_phdrs[i].p_offset; - bfd_vma end = start + i_phdrs[i].p_filesz; - bfd_vma vaddr = i_phdrs[i].p_vaddr; + bfd_vma start = i_phdrs[i].p_offset; /* Octets. */ + bfd_vma end = start + i_phdrs[i].p_filesz; /* Octets. */ + bfd_vma vaddr = i_phdrs[i].p_vaddr; /* Octets. */ /* Extend the beginning of the first pt_load to cover file header and program headers, if we proved earlier that its @@ -1845,7 +1847,7 @@ NAME(_bfd_elf,bfd_from_remote_memory) /* Extend the end of the last pt_load to cover section headers. */ if (last_phdr == &i_phdrs[i]) end = high_offset; - err = target_read_memory (loadbase + vaddr, + err = target_read_memory (loadbase + vaddr / opb, contents + start, end - start); if (err) { diff --git a/bfd/elflink.c b/bfd/elflink.c index 369f3cb3e7b..5852844498a 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -11566,8 +11566,8 @@ elf_fixup_link_order (bfd *abfd, asection *o) struct bfd_link_order *p; bfd *sub; struct bfd_link_order **sections; - asection *s, *other_sec, *linkorder_sec; - bfd_vma offset; + asection *other_sec, *linkorder_sec; + bfd_vma offset; /* Octets. */ other_sec = NULL; linkorder_sec = NULL; @@ -11577,7 +11577,7 @@ elf_fixup_link_order (bfd *abfd, asection *o) { if (p->type == bfd_indirect_link_order) { - s = p->u.indirect.section; + asection *s = p->u.indirect.section; sub = s->owner; if ((s->flags & SEC_LINKER_CREATED) == 0 && bfd_get_flavour (sub) == bfd_target_elf_flavour @@ -11632,11 +11632,12 @@ elf_fixup_link_order (bfd *abfd, asection *o) for (n = 0; n < seen_linkorder; n++) { bfd_vma mask; - s = sections[n]->u.indirect.section; - mask = ~(bfd_vma) 0 << s->alignment_power; + asection *s = sections[n]->u.indirect.section; + unsigned int opb = bfd_octets_per_byte (abfd, s); + + mask = ~(bfd_vma) 0 << s->alignment_power * opb; offset = (offset + ~mask) & mask; - s->output_offset = offset / bfd_octets_per_byte (abfd, s); - sections[n]->offset = offset; + sections[n]->offset = s->output_offset = offset / opb; offset += sections[n]->size; } @@ -12247,7 +12248,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) if (htab->tls_sec) { - bfd_vma base, end = 0; + bfd_vma base, end = 0; /* Both bytes. */ asection *sec; for (sec = htab->tls_sec; @@ -12255,6 +12256,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) sec = sec->next) { bfd_size_type size = sec->size; + unsigned int opb = bfd_octets_per_byte (abfd, sec); if (size == 0 && (sec->flags & SEC_HAS_CONTENTS) == 0) @@ -12262,9 +12264,9 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) struct bfd_link_order *ord = sec->map_tail.link_order; if (ord != NULL) - size = ord->offset + ord->size; + size = ord->offset * opb + ord->size; } - end = sec->vma + size; + end = sec->vma + size / opb; } base = htab->tls_sec->vma; /* Only align end of TLS section if static TLS doesn't have special @@ -12777,6 +12779,8 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) if (bed->dtrel_excludes_plt && htab->srelplt != NULL) { + unsigned int opb = bfd_octets_per_byte (abfd, o); + /* Don't count procedure linkage table relocs in the overall reloc count. */ sh_size -= htab->srelplt->size; @@ -12796,7 +12800,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) /* If .rela.plt is the first .rela section, exclude it from DT_RELA. */ else if (sh_addr == (htab->srelplt->output_section->vma - + htab->srelplt->output_offset)) + + htab->srelplt->output_offset) * opb) sh_addr += htab->srelplt->size; } @@ -14251,7 +14255,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) { asection *i; int eh_changed = 0; - unsigned int eh_alignment; + unsigned int eh_alignment; /* Octets. */ for (i = o->map_head.s; i != NULL; i = i->map_head.s) { @@ -14278,7 +14282,8 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) fini_reloc_cookie_for_section (&cookie, i); } - eh_alignment = 1 << o->alignment_power; + eh_alignment = ((1 << o->alignment_power) + * bfd_octets_per_byte (output_bfd, o)); /* Skip over zero terminator, and prevent empty sections from adding alignment padding at the end. */ for (i = o->map_tail.s; i != NULL; i = i->map_tail.s) diff --git a/bfd/merge.c b/bfd/merge.c index 5a4e709ef38..0c6f7a10d3d 100644 --- a/bfd/merge.c +++ b/bfd/merge.c @@ -292,8 +292,9 @@ sec_merge_emit (bfd *abfd, struct sec_merge_hash_entry *entry, asection *sec = secinfo->sec; char *pad = NULL; bfd_size_type off = 0; - int alignment_power = sec->output_section->alignment_power; - bfd_size_type pad_len; + unsigned int opb = bfd_octets_per_byte (abfd, sec); + int alignment_power = sec->output_section->alignment_power * opb; + bfd_size_type pad_len; /* Octets. */ /* FIXME: If alignment_power is 0 then really we should scan the entry list for the largest required alignment and use that. */ @@ -364,9 +365,11 @@ _bfd_add_merge_section (bfd *abfd, void **psinfo, asection *sec, { struct sec_merge_info *sinfo; struct sec_merge_sec_info *secinfo; - unsigned int align; + unsigned int alignment_power; /* Octets. */ + unsigned int align; /* Octets. */ bfd_size_type amt; bfd_byte *contents; + unsigned int opb = bfd_octets_per_byte (abfd, sec); if ((abfd->flags & DYNAMIC) != 0 || (sec->flags & SEC_MERGE) == 0) @@ -389,10 +392,11 @@ _bfd_add_merge_section (bfd *abfd, void **psinfo, asection *sec, #ifndef CHAR_BIT #define CHAR_BIT 8 #endif - if (sec->alignment_power >= sizeof (align) * CHAR_BIT) + alignment_power = sec->alignment_power * opb; + if (alignment_power >= sizeof (align) * CHAR_BIT) return TRUE; - align = 1u << sec->alignment_power; + align = 1u << alignment_power; if ((sec->entsize < align && ((sec->entsize & (sec->entsize - 1)) || !(sec->flags & SEC_STRINGS))) @@ -739,7 +743,7 @@ _bfd_merge_sections (bfd *abfd, for (sinfo = (struct sec_merge_info *) xsinfo; sinfo; sinfo = sinfo->next) { struct sec_merge_sec_info *secinfo; - bfd_size_type align; + bfd_size_type align; /* Bytes. */ if (! sinfo->chain) continue; @@ -764,8 +768,10 @@ _bfd_merge_sections (bfd *abfd, return FALSE; if (align) { + unsigned int opb = bfd_octets_per_byte (abfd, secinfo->sec); + align = (bfd_size_type) 1 << secinfo->sec->alignment_power; - if ((secinfo->sec->size & (align - 1)) != 0) + if (((secinfo->sec->size / opb) & (align - 1)) != 0) align = 0; } } @@ -782,7 +788,7 @@ _bfd_merge_sections (bfd *abfd, else { struct sec_merge_hash_entry *e; - bfd_size_type size = 0; + bfd_size_type size = 0; /* Octets. */ /* Things are much simpler for non-strings. Just assign them slots in the section. */ diff --git a/include/bfdlink.h b/include/bfdlink.h index 8d85530e390..40a6d4d40a6 100644 --- a/include/bfdlink.h +++ b/include/bfdlink.h @@ -801,9 +801,9 @@ struct bfd_link_order struct bfd_link_order *next; /* Type of link_order. */ enum bfd_link_order_type type; - /* Offset within output section. */ + /* Offset within output section in bytes. */ bfd_vma offset; - /* Size within output section. */ + /* Size within output section in octets. */ bfd_size_type size; /* Type specific information. */ union diff --git a/include/elf/internal.h b/include/elf/internal.h index d626adece5b..9692028eed3 100644 --- a/include/elf/internal.h +++ b/include/elf/internal.h @@ -91,7 +91,8 @@ struct elf_internal_phdr { bfd_vma p_paddr; /* Segment physical address in octets. */ bfd_vma p_filesz; /* Segment size in file in octets. */ bfd_vma p_memsz; /* Segment size in memory in octets. */ - bfd_vma p_align; /* Segment alignment, file & memory. */ + bfd_vma p_align; /* Segment alignment in bytes, file + & memory */ }; typedef struct elf_internal_phdr Elf_Internal_Phdr; @@ -266,13 +267,13 @@ struct elf_segment_map unsigned long p_type; /* Program segment flags. */ unsigned long p_flags; - /* Program segment physical address. */ + /* Program segment physical address in octets. */ bfd_vma p_paddr; /* Program segment virtual address offset from section vma in bytes. */ bfd_vma p_vaddr_offset; /* Program segment alignment. */ bfd_vma p_align; - /* Segment size in file and memory */ + /* Segment size in file and memory in octets. */ bfd_vma p_size; /* Whether the p_flags field is valid; if not, the flags are based on the section flags. */ -- 2.16.4 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v2 2/2] Fix several mix up between octets and bytes in ELF program headers 2020-03-02 20:17 ` [PATCH v2 " Christian Eggers @ 2020-03-12 18:24 ` Christian Eggers 2020-03-13 5:31 ` Alan Modra 0 siblings, 1 reply; 8+ messages in thread From: Christian Eggers @ 2020-03-12 18:24 UTC (permalink / raw) To: binutils Ping? Who can apply these two patches? I have not write access for GIT. Link to the first patch of this series: https://sourceware.org/pipermail/binutils/2020-March/109971.html Regards Christian Am Montag, 2. März 2020, 21:15:24 CET schrieb Christian Eggers: > Hi Nick, > > On Monday, March 2nd 2020, Nick Clifton wrote: > > Approved - please apply - but please fixup the comments first. > > Comments changed, thanks. > > Christian > > --- > This is a follow-up patch for my patch from december 09 with the same > subject. It fixes additional locations not handled in the first patch. > > When converting between addresses in ELF headers [octets] and bfd > LMA/VMA [bytes], the number of octets per byte needs to be incorperated. > > Patch changelog: > v2: > - GNU coding style for comments. > > include/ > * bfdlink.h (struct bfd_link_order): Add unit (bytes/octets) to > offset and size members. > * elf/internal.h (struct elf_internal_phdr): likewise for > p_align member. > (struct elf_segment_map): likewise for p_paddr and p_size > members > > bfd/ > * bfd.c (bfd_record_phdr): New local "opb". Fix assignment of > "p_paddr" from "at". > * elfcode.h (bfd_from_remote_memory): Add units to several > parameters. New local "opb". Fix usage of p_align. Fix > calculation of "localbase" from "ehdr_vma" and "p_vaddr". Fix > call of target_read_memory(). > * elflink.c (elf_fixup_link_order): Fix scope of "s" local. Fix > calculation of "offset" and "output_offset". > (bfd_elf_final_link): New local "opb". Fix calculation of "size" > from "offset" and fix calculation of "end" from "vma+size". Fix > comparison between "sh_addr" and "vma"/"output_offset". > (bfd_elf_discard_info): Fix calculation of "eh_alignment". > * elf-bfd.h (struct elf_link_hash_table): Add unit to tls_size > member. > * elf.c (_bfd_elf_map_sections_to_segments): Add unit (bytes/ > octets) to "wrap_to2 and "phdr_size" locals. Fix calculation of > "wrap_to" value. Add unit (bytes) to phdr_lma variable. Fix > assignment of p_paddr from phdr_lma. Fix comparison between "lma > +size" and "next->lma". > (elf_sort_segments): Fix assignment from p_paddr to lma. > (assign_file_positions_for_load_sections): Add unit (bytes) to > local "align". Fix calculation of local "off_adjust". Fix > calculation of local "filehdr_vaddr". > (assign_file_positions_for_non_load_sections): New local "opb". > Fix calculation of "end" from "p_size". Fix comparison between > "vma+SECTION_SIZE()" and "start". Fix calculation of "p_memsz" > from "end" and "p_vaddr". > (rewrite_elf_program_header): Fix comparison between p_vaddr and > vma. Fix assignment to p_paddr from lma. Fix comparison between > p_paddr and lma. Fix assignment to p_paddr from lma. > * merge.c (sec_merge_emit): New local "opb". Convert > "alignment_power" to octets. > (_bfd_add_merge_section): New locals "alignment_power" and > "opb". Fix comparison between "alignment_power" and > "sizeof(align)". > (_bfd_merge_sections): New local "opb". Divide size by opb > before checking align mask. > > Signed-off-by: Christian Eggers <ceggers@gmx.de> > --- > bfd/bfd.c | 5 +++-- > bfd/elf-bfd.h | 2 +- > bfd/elf.c | 54 > +++++++++++++++++++++++++------------------------- bfd/elfcode.h | > 28 ++++++++++++++------------ > bfd/elflink.c | 31 +++++++++++++++++------------ > bfd/merge.c | 22 ++++++++++++-------- > include/bfdlink.h | 4 ++-- > include/elf/internal.h | 7 ++++--- > 8 files changed, 84 insertions(+), 69 deletions(-) > > diff --git a/bfd/bfd.c b/bfd/bfd.c > index 1c1238c036a..100359ccfe6 100644 > --- a/bfd/bfd.c > +++ b/bfd/bfd.c > @@ -2168,7 +2168,7 @@ bfd_record_phdr (bfd *abfd, > bfd_boolean flags_valid, > flagword flags, > bfd_boolean at_valid, > - bfd_vma at, > + bfd_vma at, /* Bytes. */ > bfd_boolean includes_filehdr, > bfd_boolean includes_phdrs, > unsigned int count, > @@ -2176,6 +2176,7 @@ bfd_record_phdr (bfd *abfd, > { > struct elf_segment_map *m, **pm; > size_t amt; > + unsigned int opb = bfd_octets_per_byte (abfd, NULL); > > if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) > return TRUE; > @@ -2188,7 +2189,7 @@ bfd_record_phdr (bfd *abfd, > > m->p_type = type; > m->p_flags = flags; > - m->p_paddr = at; > + m->p_paddr = at * opb; > m->p_flags_valid = flags_valid; > m->p_paddr_valid = at_valid; > m->includes_filehdr = includes_filehdr; > diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h > index 38a9aa06019..54c27a1b76c 100644 > --- a/bfd/elf-bfd.h > +++ b/bfd/elf-bfd.h > @@ -635,7 +635,7 @@ struct elf_link_hash_table > > /* Cached first output tls section and size of PT_TLS segment. */ > asection *tls_sec; > - bfd_size_type tls_size; > + bfd_size_type tls_size; /* Bytes. */ > > /* A linked list of dynamic BFD's loaded in the link. */ > struct elf_link_loaded_list *dyn_loaded; > diff --git a/bfd/elf.c b/bfd/elf.c > index a329e239828..bc75b96adcb 100644 > --- a/bfd/elf.c > +++ b/bfd/elf.c > @@ -4665,8 +4665,8 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct > bfd_link_info *info) asection *first_mbind = NULL; > asection *dynsec, *eh_frame_hdr; > size_t amt; > - bfd_vma addr_mask, wrap_to = 0; > - bfd_size_type phdr_size; > + bfd_vma addr_mask, wrap_to = 0; /* Bytes. */ > + bfd_size_type phdr_size; /* Octets/bytes. */ > unsigned int opb = bfd_octets_per_byte (abfd, NULL); > > /* Select the allocated sections, and sort them. */ > @@ -4694,8 +4694,8 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct > bfd_link_info *info) sections[i] = s; > ++i; > /* A wrapping section potentially clashes with header. */ > - if (((s->lma + s->size) & addr_mask) < (s->lma & addr_mask)) > - wrap_to = (s->lma + s->size) & addr_mask; > + if (((s->lma + s->size / opb) & addr_mask) < (s->lma & addr_mask)) > + wrap_to = (s->lma + s->size / opb) & addr_mask; > } > } > BFD_ASSERT (i <= bfd_count_sections (abfd)); > @@ -4779,7 +4779,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct > bfd_link_info *info) program headers we will need. */ > if (phdr_in_segment && count > 0) > { > - bfd_vma phdr_lma; > + bfd_vma phdr_lma; /* Bytes. */ > bfd_boolean separate_phdr = FALSE; > > phdr_lma = (sections[0]->lma - phdr_size) & addr_mask & -maxpagesize; > @@ -4819,7 +4819,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct > bfd_link_info *info) m = make_mapping (abfd, sections, 0, 0, > phdr_in_segment); > if (m == NULL) > goto error_return; > - m->p_paddr = phdr_lma; > + m->p_paddr = phdr_lma * opb; > m->p_vaddr_offset > = (sections[0]->vma - phdr_size) & addr_mask & -maxpagesize; > m->p_paddr_valid = 1; > @@ -5007,7 +5007,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct > bfd_link_info *info) if (s2->next->alignment_power == alignment_power > && (s2->next->flags & SEC_LOAD) != 0 > && elf_section_type (s2->next) == SHT_NOTE > - && align_power (s2->lma + s2->size, > + && align_power (s2->lma + s2->size / opb, > alignment_power) > == s2->next->lma) > count++; > @@ -5305,15 +5305,17 @@ elf_sort_segments (const void *arg1, const void > *arg2) return m1->no_sort_lma ? -1 : 1; > if (m1->p_type == PT_LOAD && !m1->no_sort_lma) > { > - bfd_vma lma1, lma2; > + unsigned int opb = bfd_octets_per_byte (m1->sections[0]->owner, > + m1->sections[0]); > + bfd_vma lma1, lma2; /* Bytes. */ > lma1 = 0; > if (m1->p_paddr_valid) > - lma1 = m1->p_paddr; > + lma1 = m1->p_paddr / opb; > 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; > + lma2 = m2->p_paddr / opb; > else if (m2->count != 0) > lma2 = m2->sections[0]->lma + m2->p_vaddr_offset; > if (lma1 != lma2) > @@ -5584,7 +5586,7 @@ assign_file_positions_for_load_sections (bfd *abfd, > if (p->p_type == PT_LOAD > && m->count > 0) > { > - bfd_size_type align; > + bfd_size_type align; /* Bytes. */ > unsigned int align_power = 0; > > if (m->p_align_valid) > @@ -5621,7 +5623,7 @@ assign_file_positions_for_load_sections (bfd *abfd, > break; > } > > - off_adjust = vma_page_aligned_bias (p->p_vaddr, off, align); > + off_adjust = vma_page_aligned_bias (p->p_vaddr, off, align * opb); > > /* Broken hardware and/or kernel require that files do not > map the same page with different permissions on some hppa > @@ -5988,7 +5990,7 @@ assign_file_positions_for_load_sections (bfd *abfd, > > || hash->root.type == bfd_link_hash_common)) > > { > asection *s = NULL; > - bfd_vma filehdr_vaddr = phdrs[phdr_load_seg->idx].p_vaddr; > + bfd_vma filehdr_vaddr = phdrs[phdr_load_seg->idx].p_vaddr / opb; > > if (phdr_load_seg->count != 0) > /* The segment contains sections, so use the first one. */ > @@ -6065,6 +6067,7 @@ assign_file_positions_for_non_load_sections (bfd > *abfd, Elf_Internal_Phdr *p; > struct elf_segment_map *m; > file_ptr off; > + unsigned int opb = bfd_octets_per_byte (abfd, NULL); > > i_shdrpp = elf_elfsections (abfd); > end_hdrpp = i_shdrpp + elf_numsections (abfd); > @@ -6131,7 +6134,7 @@ assign_file_positions_for_non_load_sections (bfd > *abfd, { > if (p->p_type == PT_GNU_RELRO) > { > - bfd_vma start, end; > + bfd_vma start, end; /* Bytes. */ > bfd_boolean ok; > > if (link_info != NULL) > @@ -6147,7 +6150,7 @@ assign_file_positions_for_non_load_sections (bfd > *abfd, if (!m->p_size_valid) > abort (); > start = m->sections[0]->vma; > - end = start + m->p_size; > + end = start + m->p_size / opb; > } > else > { > @@ -6172,7 +6175,7 @@ assign_file_positions_for_non_load_sections (bfd > *abfd, && lm->count != 0 > && (lm->sections[lm->count - 1]->vma > + (!IS_TBSS (lm->sections[lm->count - 1]) > - ? lm->sections[lm->count - 1]->size > + ? lm->sections[lm->count - 1]->size / opb > > : 0)) > start > > && lm->sections[0]->vma < end) > break; > @@ -6192,13 +6195,10 @@ assign_file_positions_for_non_load_sections (bfd > *abfd, > > if (i < lm->count) > { > - unsigned int opb = bfd_octets_per_byte (abfd, > - lm->sections[i]); > - > p->p_vaddr = lm->sections[i]->vma * opb; > p->p_paddr = lm->sections[i]->lma * opb; > p->p_offset = lm->sections[i]->filepos; > - p->p_memsz = end - p->p_vaddr; > + p->p_memsz = end * opb - p->p_vaddr; > p->p_filesz = p->p_memsz; > > /* The RELRO segment typically ends a few bytes > @@ -7181,8 +7181,8 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) > + (map->includes_phdrs > ? iehdr->e_phnum * iehdr->e_phentsize > > : 0), > > - output_section->alignment_power) > - == output_section->vma)) > + output_section->alignment_power * opb) > + == (output_section->vma * opb))) > map->p_paddr = segment->p_vaddr; > > /* Match up the physical address of the segment with the > @@ -7250,7 +7250,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) > if (matching_lma == NULL) > matching_lma = suggested_lma; > > - map->p_paddr = matching_lma->lma; > + map->p_paddr = matching_lma->lma * opb; > > /* Offset the segment physical address from the lma > to allow for space taken up by elf headers. */ > @@ -7278,7 +7278,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) > the same alignment. */ > if (segment->p_align != 0 && segment->p_align < align) > align = segment->p_align; > - map->p_paddr &= -align; > + map->p_paddr &= -(align * opb); > } > } > > @@ -7322,8 +7322,8 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) > + (map->includes_phdrs > ? iehdr->e_phnum * iehdr->e_phentsize > > : 0), > > - output_section->alignment_power) > - != output_section->lma) > + output_section->alignment_power * opb) > + != output_section->lma * opb) > goto sorry; > } > else > @@ -7389,7 +7389,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) > map->p_type = segment->p_type; > map->p_flags = segment->p_flags; > map->p_flags_valid = 1; > - map->p_paddr = suggested_lma->lma; > + map->p_paddr = suggested_lma->lma * opb; > map->p_paddr_valid = p_paddr_valid; > map->includes_filehdr = 0; > map->includes_phdrs = 0; > diff --git a/bfd/elfcode.h b/bfd/elfcode.h > index 600abfe836e..ec5156a433d 100644 > --- a/bfd/elfcode.h > +++ b/bfd/elfcode.h > @@ -1648,10 +1648,11 @@ elf_debug_file (Elf_Internal_Ehdr *ehdrp) > bfd * > NAME(_bfd_elf,bfd_from_remote_memory) > (bfd *templ, > - bfd_vma ehdr_vma, > - bfd_size_type size, > - bfd_vma *loadbasep, > + bfd_vma ehdr_vma /* Bytes. */, > + bfd_size_type size /* Octets. */, > + bfd_vma *loadbasep /* Bytes. */, > int (*target_read_memory) (bfd_vma, bfd_byte *, bfd_size_type)) > + /* (Bytes , , octets ). */ > { > Elf_External_Ehdr x_ehdr; /* Elf file header, external form */ > Elf_Internal_Ehdr i_ehdr; /* Elf file header, internal form */ > @@ -1664,9 +1665,10 @@ NAME(_bfd_elf,bfd_from_remote_memory) > unsigned int i; > bfd_vma high_offset; > bfd_vma shdr_end; > - bfd_vma loadbase; > + bfd_vma loadbase; /* Bytes. */ > char *filename; > size_t amt; > + unsigned int opb = bfd_octets_per_byte (templ, NULL); > > /* Read in the ELF header in external format. */ > err = target_read_memory (ehdr_vma, (bfd_byte *) &x_ehdr, sizeof x_ehdr); > @@ -1764,17 +1766,17 @@ NAME(_bfd_elf,bfd_from_remote_memory) > header sits, then we can figure out the loadbase. */ > if (first_phdr == NULL) > { > - bfd_vma p_offset = i_phdrs[i].p_offset; > - bfd_vma p_vaddr = i_phdrs[i].p_vaddr; > + bfd_vma p_offset = i_phdrs[i].p_offset; /* Octets. */ > + bfd_vma p_vaddr = i_phdrs[i].p_vaddr; /* Octets. */ > > if (i_phdrs[i].p_align > 1) > { > - p_offset &= -i_phdrs[i].p_align; > - p_vaddr &= -i_phdrs[i].p_align; > + p_offset &= -(i_phdrs[i].p_align * opb); > + p_vaddr &= -(i_phdrs[i].p_align * opb); > } > if (p_offset == 0) > { > - loadbase = ehdr_vma - p_vaddr; > + loadbase = ehdr_vma - p_vaddr / opb; > first_phdr = &i_phdrs[i]; > } > } > @@ -1830,9 +1832,9 @@ NAME(_bfd_elf,bfd_from_remote_memory) > for (i = 0; i < i_ehdr.e_phnum; ++i) > if (i_phdrs[i].p_type == PT_LOAD) > { > - bfd_vma start = i_phdrs[i].p_offset; > - bfd_vma end = start + i_phdrs[i].p_filesz; > - bfd_vma vaddr = i_phdrs[i].p_vaddr; > + bfd_vma start = i_phdrs[i].p_offset; /* Octets. */ > + bfd_vma end = start + i_phdrs[i].p_filesz; /* Octets. */ > + bfd_vma vaddr = i_phdrs[i].p_vaddr; /* Octets. */ > > /* Extend the beginning of the first pt_load to cover file > header and program headers, if we proved earlier that its > @@ -1845,7 +1847,7 @@ NAME(_bfd_elf,bfd_from_remote_memory) > /* Extend the end of the last pt_load to cover section headers. */ > if (last_phdr == &i_phdrs[i]) > end = high_offset; > - err = target_read_memory (loadbase + vaddr, > + err = target_read_memory (loadbase + vaddr / opb, > contents + start, end - start); > if (err) > { > diff --git a/bfd/elflink.c b/bfd/elflink.c > index 369f3cb3e7b..5852844498a 100644 > --- a/bfd/elflink.c > +++ b/bfd/elflink.c > @@ -11566,8 +11566,8 @@ elf_fixup_link_order (bfd *abfd, asection *o) > struct bfd_link_order *p; > bfd *sub; > struct bfd_link_order **sections; > - asection *s, *other_sec, *linkorder_sec; > - bfd_vma offset; > + asection *other_sec, *linkorder_sec; > + bfd_vma offset; /* Octets. */ > > other_sec = NULL; > linkorder_sec = NULL; > @@ -11577,7 +11577,7 @@ elf_fixup_link_order (bfd *abfd, asection *o) > { > if (p->type == bfd_indirect_link_order) > { > - s = p->u.indirect.section; > + asection *s = p->u.indirect.section; > sub = s->owner; > if ((s->flags & SEC_LINKER_CREATED) == 0 > && bfd_get_flavour (sub) == bfd_target_elf_flavour > @@ -11632,11 +11632,12 @@ elf_fixup_link_order (bfd *abfd, asection *o) > for (n = 0; n < seen_linkorder; n++) > { > bfd_vma mask; > - s = sections[n]->u.indirect.section; > - mask = ~(bfd_vma) 0 << s->alignment_power; > + asection *s = sections[n]->u.indirect.section; > + unsigned int opb = bfd_octets_per_byte (abfd, s); > + > + mask = ~(bfd_vma) 0 << s->alignment_power * opb; > offset = (offset + ~mask) & mask; > - s->output_offset = offset / bfd_octets_per_byte (abfd, s); > - sections[n]->offset = offset; > + sections[n]->offset = s->output_offset = offset / opb; > offset += sections[n]->size; > } > > @@ -12247,7 +12248,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info > *info) > > if (htab->tls_sec) > { > - bfd_vma base, end = 0; > + bfd_vma base, end = 0; /* Both bytes. */ > asection *sec; > > for (sec = htab->tls_sec; > @@ -12255,6 +12256,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info > *info) sec = sec->next) > { > bfd_size_type size = sec->size; > + unsigned int opb = bfd_octets_per_byte (abfd, sec); > > if (size == 0 > && (sec->flags & SEC_HAS_CONTENTS) == 0) > @@ -12262,9 +12264,9 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info > *info) struct bfd_link_order *ord = sec->map_tail.link_order; > > if (ord != NULL) > - size = ord->offset + ord->size; > + size = ord->offset * opb + ord->size; > } > - end = sec->vma + size; > + end = sec->vma + size / opb; > } > base = htab->tls_sec->vma; > /* Only align end of TLS section if static TLS doesn't have special > @@ -12777,6 +12779,8 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info > *info) > > if (bed->dtrel_excludes_plt && htab->srelplt != NULL) > { > + unsigned int opb = bfd_octets_per_byte (abfd, o); > + > /* Don't count procedure linkage table relocs in the > overall reloc count. */ > sh_size -= htab->srelplt->size; > @@ -12796,7 +12800,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info > *info) /* If .rela.plt is the first .rela section, exclude > it from DT_RELA. */ > else if (sh_addr == (htab->srelplt->output_section->vma > - + htab->srelplt->output_offset)) > + + htab->srelplt->output_offset) * opb) > sh_addr += htab->srelplt->size; > } > > @@ -14251,7 +14255,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct > bfd_link_info *info) { > asection *i; > int eh_changed = 0; > - unsigned int eh_alignment; > + unsigned int eh_alignment; /* Octets. */ > > for (i = o->map_head.s; i != NULL; i = i->map_head.s) > { > @@ -14278,7 +14282,8 @@ bfd_elf_discard_info (bfd *output_bfd, struct > bfd_link_info *info) fini_reloc_cookie_for_section (&cookie, i); > } > > - eh_alignment = 1 << o->alignment_power; > + eh_alignment = ((1 << o->alignment_power) > + * bfd_octets_per_byte (output_bfd, o)); > /* Skip over zero terminator, and prevent empty sections from > adding alignment padding at the end. */ > for (i = o->map_tail.s; i != NULL; i = i->map_tail.s) > diff --git a/bfd/merge.c b/bfd/merge.c > index 5a4e709ef38..0c6f7a10d3d 100644 > --- a/bfd/merge.c > +++ b/bfd/merge.c > @@ -292,8 +292,9 @@ sec_merge_emit (bfd *abfd, struct sec_merge_hash_entry > *entry, asection *sec = secinfo->sec; > char *pad = NULL; > bfd_size_type off = 0; > - int alignment_power = sec->output_section->alignment_power; > - bfd_size_type pad_len; > + unsigned int opb = bfd_octets_per_byte (abfd, sec); > + int alignment_power = sec->output_section->alignment_power * opb; > + bfd_size_type pad_len; /* Octets. */ > > /* FIXME: If alignment_power is 0 then really we should scan the > entry list for the largest required alignment and use that. */ > @@ -364,9 +365,11 @@ _bfd_add_merge_section (bfd *abfd, void **psinfo, > asection *sec, { > struct sec_merge_info *sinfo; > struct sec_merge_sec_info *secinfo; > - unsigned int align; > + unsigned int alignment_power; /* Octets. */ > + unsigned int align; /* Octets. */ > bfd_size_type amt; > bfd_byte *contents; > + unsigned int opb = bfd_octets_per_byte (abfd, sec); > > if ((abfd->flags & DYNAMIC) != 0 > > || (sec->flags & SEC_MERGE) == 0) > > @@ -389,10 +392,11 @@ _bfd_add_merge_section (bfd *abfd, void **psinfo, > asection *sec, #ifndef CHAR_BIT > #define CHAR_BIT 8 > #endif > - if (sec->alignment_power >= sizeof (align) * CHAR_BIT) > + alignment_power = sec->alignment_power * opb; > + if (alignment_power >= sizeof (align) * CHAR_BIT) > return TRUE; > > - align = 1u << sec->alignment_power; > + align = 1u << alignment_power; > if ((sec->entsize < align > && ((sec->entsize & (sec->entsize - 1)) > > || !(sec->flags & SEC_STRINGS))) > > @@ -739,7 +743,7 @@ _bfd_merge_sections (bfd *abfd, > for (sinfo = (struct sec_merge_info *) xsinfo; sinfo; sinfo = > sinfo->next) { > struct sec_merge_sec_info *secinfo; > - bfd_size_type align; > + bfd_size_type align; /* Bytes. */ > > if (! sinfo->chain) > continue; > @@ -764,8 +768,10 @@ _bfd_merge_sections (bfd *abfd, > return FALSE; > if (align) > { > + unsigned int opb = bfd_octets_per_byte (abfd, secinfo->sec); > + > align = (bfd_size_type) 1 << secinfo->sec->alignment_power; > - if ((secinfo->sec->size & (align - 1)) != 0) > + if (((secinfo->sec->size / opb) & (align - 1)) != 0) > align = 0; > } > } > @@ -782,7 +788,7 @@ _bfd_merge_sections (bfd *abfd, > else > { > struct sec_merge_hash_entry *e; > - bfd_size_type size = 0; > + bfd_size_type size = 0; /* Octets. */ > > /* Things are much simpler for non-strings. > Just assign them slots in the section. */ > diff --git a/include/bfdlink.h b/include/bfdlink.h > index 8d85530e390..40a6d4d40a6 100644 > --- a/include/bfdlink.h > +++ b/include/bfdlink.h > @@ -801,9 +801,9 @@ struct bfd_link_order > struct bfd_link_order *next; > /* Type of link_order. */ > enum bfd_link_order_type type; > - /* Offset within output section. */ > + /* Offset within output section in bytes. */ > bfd_vma offset; > - /* Size within output section. */ > + /* Size within output section in octets. */ > bfd_size_type size; > /* Type specific information. */ > union > diff --git a/include/elf/internal.h b/include/elf/internal.h > index d626adece5b..9692028eed3 100644 > --- a/include/elf/internal.h > +++ b/include/elf/internal.h > @@ -91,7 +91,8 @@ struct elf_internal_phdr { > bfd_vma p_paddr; /* Segment physical address in octets. */ > bfd_vma p_filesz; /* Segment size in file in octets. */ > bfd_vma p_memsz; /* Segment size in memory in octets. */ > - bfd_vma p_align; /* Segment alignment, file & memory. */ > + bfd_vma p_align; /* Segment alignment in bytes, file > + & memory */ > }; > > typedef struct elf_internal_phdr Elf_Internal_Phdr; > @@ -266,13 +267,13 @@ struct elf_segment_map > unsigned long p_type; > /* Program segment flags. */ > unsigned long p_flags; > - /* Program segment physical address. */ > + /* Program segment physical address in octets. */ > bfd_vma p_paddr; > /* Program segment virtual address offset from section vma in bytes. */ > bfd_vma p_vaddr_offset; > /* Program segment alignment. */ > bfd_vma p_align; > - /* Segment size in file and memory */ > + /* Segment size in file and memory in octets. */ > bfd_vma p_size; > /* Whether the p_flags field is valid; if not, the flags are based > on the section flags. */ > -- > 2.16.4 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v2 2/2] Fix several mix up between octets and bytes in ELF program headers 2020-03-12 18:24 ` Christian Eggers @ 2020-03-13 5:31 ` Alan Modra 0 siblings, 0 replies; 8+ messages in thread From: Alan Modra @ 2020-03-13 5:31 UTC (permalink / raw) To: Christian Eggers; +Cc: binutils, Nick Clifton On Thu, Mar 12, 2020 at 07:24:45PM +0100, Christian Eggers wrote: > Ping? Who can apply these two patches? I have not write access for GIT. Applied. -- Alan Modra Australia Development Lab, IBM ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2020-03-13 5:31 UTC | newest] Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- [not found] <20200215193050.22717-1-ceggers@gmx.de> 2020-02-15 19:31 ` [PATCH 1/2] Fix several mix up between octets and bytes in ELF program headers Christian Eggers 2020-03-02 14:17 ` Nick Clifton 2020-03-02 20:11 ` [PATCH v4] " Christian Eggers 2020-02-15 19:31 ` [PATCH 2/2] " Christian Eggers 2020-03-02 14:18 ` Nick Clifton 2020-03-02 20:17 ` [PATCH v2 " Christian Eggers 2020-03-12 18:24 ` Christian Eggers 2020-03-13 5:31 ` Alan Modra
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).