summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mld/link.c48
-rw-r--r--mld/link.h5
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;
};