Skip to content

Commit 5020a92

Browse files
committed
Refine ELF segments
This commit refines the program headers to generate a better ELF executable file, with the following changes: - Always create two load segments, regardless of static or dynamic linking. - The first load segment is readable and executable, and includes the read-only sections such as .text, .rodata, etc. - The second load segment is readable and writable, and contains the remaining sections, including .data and .bss. - In dynamic linking mode, the .rel.plt and .plt sections reside in the first segment, while the other dynamic sections are placed in the second segment. - Set the alignment value of both load segments to 0x1000 (the default page size) to meet the alignment requirement when the ELF interpreter loads the executable. - Adjust the offset and virtual address of the first load segment to ensure that dynamically linked executable can be correctly loaded by the kernel program loader. - Now, the ELF header and program headers are also loaded into the first segment but they are never used. - Update other segments as necessary to reflect the above changes.
1 parent e69e679 commit 5020a92

File tree

1 file changed

+137
-113
lines changed

1 file changed

+137
-113
lines changed

src/elf.c

Lines changed: 137 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,12 @@ void elf_generate_header(void)
6868
}
6969

7070
elf32_hdr_t hdr;
71-
int phnum = 1, shnum = 8, shstrndx = 7;
71+
int phnum = 2, shnum = 8, shstrndx = 7;
7272
int shoff = elf_header_len + elf_code->size + elf_data->size +
7373
elf_rodata->size + elf_symtab->size + elf_strtab->size +
7474
elf_shstr->size;
7575
if (dynlink) {
76-
phnum += 3;
76+
phnum += 2;
7777
shnum += 7;
7878
shstrndx += 7;
7979
shoff += elf_interp->size + elf_relplt->size + elf_plt->size +
@@ -198,60 +198,74 @@ void elf_generate_program_headers(void)
198198
* ---+----------------+-------------------------------------------------+
199199
* 54 | | |
200200
*/
201-
/* program header - code and data combined */
201+
/* program header - read only segment */
202202
elf32_phdr_t phdr;
203-
phdr.p_type = 1; /* PT_LOAD */
204-
phdr.p_offset = elf_header_len; /* offset of segment */
205-
phdr.p_vaddr = ELF_START + phdr.p_offset; /* virtual address */
206-
phdr.p_paddr = ELF_START + phdr.p_offset; /* physical address */
203+
phdr.p_type = 1; /* PT_LOAD */
204+
phdr.p_offset = 0; /* offset of segment */
205+
phdr.p_vaddr = ELF_START; /* virtual address */
206+
phdr.p_paddr = ELF_START; /* physical address */
207207
phdr.p_filesz =
208-
elf_code->size + elf_data->size + elf_rodata->size; /* size in file */
209-
phdr.p_memsz = elf_code->size + elf_data->size + elf_rodata->size +
210-
elf_bss_size; /* size in memory */
211-
phdr.p_flags = 7; /* flags */
212-
phdr.p_align = 4; /* alignment */
208+
elf_header_len + elf_code->size + elf_rodata->size; /* size in file */
209+
phdr.p_memsz =
210+
elf_header_len + elf_code->size + elf_rodata->size; /* size in memory */
211+
phdr.p_flags = 5; /* flags */
212+
phdr.p_align = 0x1000; /* alignment */
213+
if (dynlink) {
214+
phdr.p_filesz += elf_relplt->size + elf_plt->size;
215+
phdr.p_memsz += elf_relplt->size + elf_plt->size;
216+
}
213217
elf_write_blk(elf_program_header, &phdr, sizeof(elf32_phdr_t));
218+
219+
/* program header - readable and writable segment */
220+
phdr.p_type = 1; /* PT_LOAD */
221+
phdr.p_offset = elf_header_len + elf_code->size +
222+
elf_rodata->size; /* offset of segment */
223+
phdr.p_vaddr = elf_data_start; /* virtual address */
224+
phdr.p_paddr = elf_data_start; /* physical address */
225+
phdr.p_filesz = elf_data->size; /* size in file */
226+
phdr.p_memsz = elf_data->size + elf_bss_size; /* size in memory */
227+
phdr.p_flags = 6; /* flags */
228+
phdr.p_align = 0x1000; /* alignment */
214229
if (dynlink) {
215-
/* program header - all dynamic sections combined */
216-
phdr.p_type = 1; /* PT_LOAD */
217-
phdr.p_offset = elf_header_len + elf_code->size + elf_data->size +
218-
elf_rodata->size; /* offset of segment */
219-
phdr.p_vaddr = ELF_START + phdr.p_offset; /* virtual address */
220-
phdr.p_paddr = ELF_START + phdr.p_offset; /* physical address */
221-
phdr.p_filesz = elf_interp->size + elf_relplt->size + elf_plt->size +
222-
elf_got->size + elf_dynstr->size + elf_dynsym->size +
223-
elf_dynamic->size; /* size in file */
224-
phdr.p_memsz = elf_interp->size + elf_relplt->size + elf_plt->size +
225-
elf_got->size + elf_dynstr->size + elf_dynsym->size +
226-
elf_dynamic->size; /* size in memory */
227-
phdr.p_flags = 7; /* flags */
228-
phdr.p_align = 4; /* alignment */
229-
elf_write_blk(elf_program_header, &phdr, sizeof(elf32_phdr_t));
230+
phdr.p_offset += elf_relplt->size + elf_plt->size;
231+
phdr.p_vaddr = elf_interp_start;
232+
phdr.p_paddr = elf_interp_start;
233+
phdr.p_filesz += elf_interp->size + elf_got->size + elf_dynstr->size +
234+
elf_dynsym->size + elf_dynamic->size;
235+
phdr.p_memsz += elf_interp->size + elf_got->size + elf_dynstr->size +
236+
elf_dynsym->size + elf_dynamic->size;
237+
}
238+
elf_write_blk(elf_program_header, &phdr, sizeof(elf32_phdr_t));
230239

240+
241+
if (dynlink) {
231242
/* program header - program interpreter (.interp section) */
232243
phdr.p_type = 3; /* PT_INTERP */
233-
phdr.p_offset = elf_header_len + elf_code->size + elf_data->size +
234-
elf_rodata->size; /* offset of segment */
235-
phdr.p_vaddr = ELF_START + phdr.p_offset; /* virtual address */
236-
phdr.p_paddr = ELF_START + phdr.p_offset; /* physical address */
237-
phdr.p_filesz = strlen(DYN_LINKER) + 1; /* size in file */
238-
phdr.p_memsz = strlen(DYN_LINKER) + 1; /* size in memory */
239-
phdr.p_flags = 4; /* flags */
240-
phdr.p_align = 1; /* alignment */
244+
phdr.p_offset = elf_header_len + elf_code->size + elf_rodata->size +
245+
elf_relplt->size +
246+
elf_plt->size; /* offset of segment */
247+
phdr.p_vaddr = elf_interp_start; /* virtual address */
248+
phdr.p_paddr = elf_interp_start; /* physical address */
249+
phdr.p_filesz = strlen(DYN_LINKER) + 1; /* size in file */
250+
phdr.p_memsz = strlen(DYN_LINKER) + 1; /* size in memory */
251+
phdr.p_flags = 4; /* flags */
252+
phdr.p_align = 1; /* alignment */
241253
elf_write_blk(elf_program_header, &phdr, sizeof(elf32_phdr_t));
242254

243255
/* program header - .dynamic section */
244256
phdr.p_type = 2; /* PT_DYNAMIC */
245-
phdr.p_offset = elf_header_len + elf_code->size + elf_data->size +
246-
elf_rodata->size + elf_interp->size + elf_relplt->size +
247-
elf_plt->size + elf_got->size + elf_dynstr->size +
248-
elf_dynsym->size; /* offset of segment */
249-
phdr.p_vaddr = ELF_START + phdr.p_offset; /* virtual address */
250-
phdr.p_paddr = ELF_START + phdr.p_offset; /* physical address */
251-
phdr.p_filesz = elf_dynamic->size; /* size in file */
252-
phdr.p_memsz = elf_dynamic->size; /* size in memory */
253-
phdr.p_flags = 6; /* flags */
254-
phdr.p_align = 4; /* alignment */
257+
phdr.p_offset = elf_header_len + elf_code->size + elf_rodata->size +
258+
elf_relplt->size + elf_plt->size + elf_interp->size +
259+
elf_got->size + elf_dynstr->size +
260+
elf_dynsym->size; /* offset of segment */
261+
phdr.p_vaddr = elf_got_start + elf_got->size + elf_dynstr->size +
262+
elf_dynsym->size; /* virtual address */
263+
phdr.p_paddr = elf_got_start + elf_got->size + elf_dynstr->size +
264+
elf_dynsym->size; /* physical address */
265+
phdr.p_filesz = elf_dynamic->size; /* size in file */
266+
phdr.p_memsz = elf_dynamic->size; /* size in memory */
267+
phdr.p_flags = 6; /* flags */
268+
phdr.p_align = 4; /* alignment */
255269
elf_write_blk(elf_program_header, &phdr, sizeof(elf32_phdr_t));
256270
}
257271
}
@@ -327,21 +341,6 @@ void elf_generate_section_headers(void)
327341
ofs += elf_code->size;
328342
sh_name += strlen(".text") + 1;
329343

330-
/* .data */
331-
shdr.sh_name = sh_name;
332-
shdr.sh_type = 1;
333-
shdr.sh_flags = 3;
334-
shdr.sh_addr = elf_data_start;
335-
shdr.sh_offset = ofs;
336-
shdr.sh_size = elf_data->size;
337-
shdr.sh_link = 0;
338-
shdr.sh_info = 0;
339-
shdr.sh_addralign = 4;
340-
shdr.sh_entsize = 0;
341-
elf_write_blk(elf_section_header, &shdr, sizeof(elf32_shdr_t));
342-
ofs += elf_data->size;
343-
sh_name += strlen(".data") + 1;
344-
345344
/* .rodata */
346345
shdr.sh_name = sh_name; /* Offset in shstrtab for ".rodata" */
347346
shdr.sh_type = 1; /* SHT_PROGBITS */
@@ -357,46 +356,16 @@ void elf_generate_section_headers(void)
357356
ofs += elf_rodata->size;
358357
sh_name += strlen(".rodata") + 1;
359358

360-
/* .bss */
361-
shdr.sh_name = sh_name; /* Offset in shstrtab for ".bss" */
362-
shdr.sh_type = 8; /* SHT_NOBITS */
363-
shdr.sh_flags = 3; /* SHF_ALLOC | SHF_WRITE */
364-
shdr.sh_addr = elf_bss_start;
365-
shdr.sh_offset = ofs; /* File offset (not actually used for NOBITS) */
366-
shdr.sh_size = elf_bss_size;
367-
shdr.sh_link = 0;
368-
shdr.sh_info = 0;
369-
shdr.sh_addralign = 4;
370-
shdr.sh_entsize = 0;
371-
elf_write_blk(elf_section_header, &shdr, sizeof(elf32_shdr_t));
372-
sh_name += strlen(".bss") + 1;
373-
/* Note: .bss is not written to file (SHT_NOBITS) */
374-
375359
if (dynlink) {
376-
/* .interp */
377-
shdr.sh_name = sh_name;
378-
shdr.sh_type = 1;
379-
shdr.sh_flags = 0x2;
380-
shdr.sh_addr = elf_interp_start;
381-
shdr.sh_offset = ofs;
382-
shdr.sh_size = strlen(DYN_LINKER) + 1;
383-
shdr.sh_link = 0;
384-
shdr.sh_info = 0;
385-
shdr.sh_addralign = 1;
386-
shdr.sh_entsize = 0;
387-
elf_write_blk(elf_section_header, &shdr, sizeof(elf32_shdr_t));
388-
ofs += elf_interp->size;
389-
sh_name += strlen(".interp") + 1;
390-
391360
/* .rel.plt */
392361
shdr.sh_name = sh_name;
393362
shdr.sh_type = 9; /* SHT_REL */
394363
shdr.sh_flags = 0x42; /* 0x40 | SHF_ALLOC */
395364
shdr.sh_addr = elf_relplt_start;
396365
shdr.sh_offset = ofs;
397366
shdr.sh_size = elf_relplt->size;
398-
shdr.sh_link = 10; /* The section header index of .dynsym. */
399-
shdr.sh_info = 8; /* The section header index of .got. */
367+
shdr.sh_link = 8; /* The section header index of .dynsym. */
368+
shdr.sh_info = 6; /* The section header index of .got. */
400369
shdr.sh_addralign = 4;
401370
shdr.sh_entsize = sizeof(elf32_rel_t);
402371
elf_write_blk(elf_section_header, &shdr, sizeof(elf32_shdr_t));
@@ -418,6 +387,21 @@ void elf_generate_section_headers(void)
418387
ofs += elf_plt->size;
419388
sh_name += strlen(".plt") + 1;
420389

390+
/* .interp */
391+
shdr.sh_name = sh_name;
392+
shdr.sh_type = 1;
393+
shdr.sh_flags = 0x2;
394+
shdr.sh_addr = elf_interp_start;
395+
shdr.sh_offset = ofs;
396+
shdr.sh_size = strlen(DYN_LINKER) + 1;
397+
shdr.sh_link = 0;
398+
shdr.sh_info = 0;
399+
shdr.sh_addralign = 1;
400+
shdr.sh_entsize = 0;
401+
elf_write_blk(elf_section_header, &shdr, sizeof(elf32_shdr_t));
402+
ofs += elf_interp->size;
403+
sh_name += strlen(".interp") + 1;
404+
421405
/* .got */
422406
shdr.sh_name = sh_name;
423407
shdr.sh_type = 1;
@@ -455,7 +439,7 @@ void elf_generate_section_headers(void)
455439
shdr.sh_addr = elf_got_start + elf_got->size + elf_dynstr->size;
456440
shdr.sh_offset = ofs;
457441
shdr.sh_size = elf_dynsym->size;
458-
shdr.sh_link = 9;
442+
shdr.sh_link = 7;
459443
shdr.sh_info = 1;
460444
shdr.sh_addralign = 4;
461445
shdr.sh_entsize = sizeof(elf32_sym_t);
@@ -471,7 +455,7 @@ void elf_generate_section_headers(void)
471455
elf_got_start + elf_got->size + elf_dynstr->size + elf_dynsym->size;
472456
shdr.sh_offset = ofs;
473457
shdr.sh_size = elf_dynamic->size;
474-
shdr.sh_link = 9; /* The section header index of .dynstr. */
458+
shdr.sh_link = 7; /* The section header index of .dynstr. */
475459
shdr.sh_info = 0;
476460
shdr.sh_addralign = 4;
477461
shdr.sh_entsize = 0;
@@ -480,6 +464,36 @@ void elf_generate_section_headers(void)
480464
sh_name += strlen(".dynamic") + 1;
481465
}
482466

467+
/* .data */
468+
shdr.sh_name = sh_name;
469+
shdr.sh_type = 1;
470+
shdr.sh_flags = 3;
471+
shdr.sh_addr = elf_data_start;
472+
shdr.sh_offset = ofs;
473+
shdr.sh_size = elf_data->size;
474+
shdr.sh_link = 0;
475+
shdr.sh_info = 0;
476+
shdr.sh_addralign = 4;
477+
shdr.sh_entsize = 0;
478+
elf_write_blk(elf_section_header, &shdr, sizeof(elf32_shdr_t));
479+
ofs += elf_data->size;
480+
sh_name += strlen(".data") + 1;
481+
482+
/* .bss */
483+
shdr.sh_name = sh_name; /* Offset in shstrtab for ".bss" */
484+
shdr.sh_type = 8; /* SHT_NOBITS */
485+
shdr.sh_flags = 3; /* SHF_ALLOC | SHF_WRITE */
486+
shdr.sh_addr = elf_bss_start;
487+
shdr.sh_offset = ofs; /* File offset (not actually used for NOBITS) */
488+
shdr.sh_size = elf_bss_size;
489+
shdr.sh_link = 0;
490+
shdr.sh_info = 0;
491+
shdr.sh_addralign = 4;
492+
shdr.sh_entsize = 0;
493+
elf_write_blk(elf_section_header, &shdr, sizeof(elf32_shdr_t));
494+
sh_name += strlen(".bss") + 1;
495+
/* Note: .bss is not written to file (SHT_NOBITS) */
496+
483497
/* .symtab */
484498
shdr.sh_name = sh_name;
485499
shdr.sh_type = 2;
@@ -587,10 +601,10 @@ void elf_generate_sections(void)
587601
got_size += PTR_SIZE;
588602

589603
/* Get the starting points of the sections. */
590-
elf_interp_start = elf_bss_start + elf_bss_size;
591-
elf_relplt_start = elf_interp_start + elf_interp->size;
604+
elf_relplt_start = elf_rodata_start + elf_rodata->size;
592605
elf_plt_start = elf_relplt_start + relplt_size;
593-
elf_got_start = elf_plt_start + plt_size;
606+
elf_interp_start = elf_plt_start + plt_size + 0x1000;
607+
elf_got_start = elf_interp_start + elf_interp->size;
594608

595609
/* dynstr, dynsym and relplt sections */
596610
elf_write_byte(elf_dynstr, 0);
@@ -708,19 +722,15 @@ void elf_generate_sections(void)
708722
elf_write_byte(elf_shstr, 0);
709723
elf_write_str(elf_shstr, ".text");
710724
elf_write_byte(elf_shstr, 0);
711-
elf_write_str(elf_shstr, ".data");
712-
elf_write_byte(elf_shstr, 0);
713725
elf_write_str(elf_shstr, ".rodata");
714726
elf_write_byte(elf_shstr, 0);
715-
elf_write_str(elf_shstr, ".bss");
716-
elf_write_byte(elf_shstr, 0);
717727
if (dynlink) {
718-
elf_write_str(elf_shstr, ".interp");
719-
elf_write_byte(elf_shstr, 0);
720728
elf_write_str(elf_shstr, ".rel.plt");
721729
elf_write_byte(elf_shstr, 0);
722730
elf_write_str(elf_shstr, ".plt");
723731
elf_write_byte(elf_shstr, 0);
732+
elf_write_str(elf_shstr, ".interp");
733+
elf_write_byte(elf_shstr, 0);
724734
elf_write_str(elf_shstr, ".got");
725735
elf_write_byte(elf_shstr, 0);
726736
elf_write_str(elf_shstr, ".dynstr");
@@ -730,6 +740,10 @@ void elf_generate_sections(void)
730740
elf_write_str(elf_shstr, ".dynamic");
731741
elf_write_byte(elf_shstr, 0);
732742
}
743+
elf_write_str(elf_shstr, ".data");
744+
elf_write_byte(elf_shstr, 0);
745+
elf_write_str(elf_shstr, ".bss");
746+
elf_write_byte(elf_shstr, 0);
733747
elf_write_str(elf_shstr, ".symtab");
734748
elf_write_byte(elf_shstr, 0);
735749
elf_write_str(elf_shstr, ".strtab");
@@ -758,16 +772,21 @@ void elf_add_symbol(const char *symbol, int pc)
758772

759773
void elf_preprocess(void)
760774
{
761-
elf_header_len = sizeof(elf32_hdr_t) + sizeof(elf32_phdr_t);
775+
elf_header_len = sizeof(elf32_hdr_t) + (sizeof(elf32_phdr_t) << 1);
762776
if (dynlink)
763-
elf_header_len += (sizeof(elf32_phdr_t) * 3);
777+
elf_header_len += (sizeof(elf32_phdr_t) << 1);
764778
elf_align(elf_data);
765779
elf_align(elf_rodata);
766780
elf_code_start = ELF_START + elf_header_len;
767-
elf_data_start = elf_code_start + elf_offset;
768-
elf_rodata_start = elf_data_start + elf_data->size;
769-
elf_bss_start = elf_rodata_start + elf_rodata->size;
781+
elf_rodata_start = elf_code_start + elf_offset;
770782
elf_generate_sections();
783+
if (dynlink) {
784+
elf_data_start = elf_got_start + elf_got->size + elf_dynstr->size +
785+
elf_dynsym->size + elf_dynamic->size;
786+
} else {
787+
elf_data_start = elf_rodata_start + elf_rodata->size + 0x1000;
788+
}
789+
elf_bss_start = elf_data_start + elf_data->size;
771790
elf_align(elf_symtab);
772791
elf_align(elf_strtab);
773792
}
@@ -794,20 +813,20 @@ void elf_generate(const char *outfile)
794813
fputc(elf_header->elements[i], fp);
795814
for (int i = 0; i < elf_program_header->size; i++)
796815
fputc(elf_program_header->elements[i], fp);
816+
/* Read only sections */
797817
for (int i = 0; i < elf_code->size; i++)
798818
fputc(elf_code->elements[i], fp);
799-
for (int i = 0; i < elf_data->size; i++)
800-
fputc(elf_data->elements[i], fp);
801819
for (int i = 0; i < elf_rodata->size; i++)
802820
fputc(elf_rodata->elements[i], fp);
803-
/* Note: .bss is not written to file (SHT_NOBITS) */
821+
822+
/* Readable and writable sections */
804823
if (dynlink) {
805-
for (int i = 0; i < elf_interp->size; i++)
806-
fputc(elf_interp->elements[i], fp);
807824
for (int i = 0; i < elf_relplt->size; i++)
808825
fputc(elf_relplt->elements[i], fp);
809826
for (int i = 0; i < elf_plt->size; i++)
810827
fputc(elf_plt->elements[i], fp);
828+
for (int i = 0; i < elf_interp->size; i++)
829+
fputc(elf_interp->elements[i], fp);
811830
for (int i = 0; i < elf_got->size; i++)
812831
fputc(elf_got->elements[i], fp);
813832
for (int i = 0; i < elf_dynstr->size; i++)
@@ -817,6 +836,11 @@ void elf_generate(const char *outfile)
817836
for (int i = 0; i < elf_dynamic->size; i++)
818837
fputc(elf_dynamic->elements[i], fp);
819838
}
839+
for (int i = 0; i < elf_data->size; i++)
840+
fputc(elf_data->elements[i], fp);
841+
/* Note: .bss is not written to file (SHT_NOBITS) */
842+
843+
/* Other sections and section headers */
820844
for (int i = 0; i < elf_symtab->size; i++)
821845
fputc(elf_symtab->elements[i], fp);
822846
for (int i = 0; i < elf_strtab->size; i++)

0 commit comments

Comments
 (0)