From 6991a233adb1437db6ee2883acc2472843a1ddb6 Mon Sep 17 00:00:00 2001 From: Freya Murphy Date: Mon, 30 Sep 2024 15:10:16 -0400 Subject: [PATCH] fix elf section padding --- mld/link.c | 48 +++++++++++++++++++++++++++++++----------------- mld/link.h | 5 ++--- 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/mld/link.c b/mld/link.c index e9a886c..88b295e 100644 --- a/mld/link.c +++ b/mld/link.c @@ -125,7 +125,18 @@ static int relocate_segment_name(struct linker *linker, const char *name) if (segtab_ent_push(ent, seg)) return M_ERROR; } else { - // else create a new segment + // update vaddr to be page aligned + uint32_t m = seg->new_vaddr % SEC_ALIGN; + if (m) { + uint32_t add = SEC_ALIGN - m; + seg->new_vaddr += add; + if (B32(seg->phdr->p_flags) & PF_X) + linker->text_vaddr += add; + else + linker->data_vaddr += add; + } + + // else create a new segment if (segtab_push(&linker->segments, NULL, seg)) return M_ERROR; } @@ -536,19 +547,21 @@ static void update_offsets(struct linker *linker) linker->ehdr.e_phoff = B32(ptr); ptr += linker->phdr_len * sizeof(Elf32_Phdr); - // section padding - { - uint32_t mod = ptr % SEC_ALIGN; - if (mod != 0) - linker->secalign = (SEC_ALIGN - mod); - else - linker->secalign = 0; - ptr += linker->secalign; - } - // sections for (uint32_t i = 0; i < linker->segments.len; i++) { struct segment_table_entry *ent = &linker->segments.entries[i]; + + // section padding + { + uint32_t m = ptr % SEC_ALIGN; + if (m) { + uint32_t add = SEC_ALIGN - m; + ptr += add; + ent->off = ptr; + ent->padding = add; + } + } + uint32_t idx = i + 1; uint32_t size = segtab_ent_size(ent); linker->phdr[i].p_offset = B32(ptr); @@ -604,15 +617,16 @@ static int write_file(struct linker *linker) // phdr res |= fwrite(linker->phdr, sizeof(Elf32_Phdr), linker->phdr_len, out); - // section padding - for (uint32_t i = 0; i < linker->secalign; i++) { - uint8_t zero = 0; - res |= fwrite(&zero, 1, 1, out); - } - // sections for (uint32_t i = 0; i < linker->segments.len; i++) { struct segment_table_entry *ent = &linker->segments.entries[i]; + // section padding + { + for (uint32_t i = 0; i < ent->padding; i++) { + uint8_t zero = 0; + res |= fwrite(&zero, 1, 1, out); + } + } for (uint32_t j = 0; j < ent->len; j++) { struct segment *seg = ent->parts[j]; res |= fwrite(seg->bytes, 1, seg->size, out); diff --git a/mld/link.h b/mld/link.h index 6c3b714..435a8d5 100644 --- a/mld/link.h +++ b/mld/link.h @@ -170,6 +170,8 @@ struct segment_table_entry { uint32_t vaddr; // weak segment pointers. we do not own these!!! struct segment **parts; + // section padding + uint32_t padding; }; int segtab_ent_init(struct segment_table_entry *ent); @@ -273,9 +275,6 @@ struct linker { uint32_t strtab_shidx; uint32_t shstrtab_shidx; - // section alignment after phdr bytes - uint32_t secalign; - // all segments struct segment_table segments; };