-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
mmap
each ELF segment if CONFIG_LIBPOSIXMMAP
is enabled
#28
Conversation
f9e69fd
to
450411f
Compare
The `e_rawfile` of `elf_prog` already contains the entire read or mmap'd ELF so use that instead for computing the interpretor path. Signed-off-by: Sergiu Moga <sergiu@unikraft.io>
450411f
to
336528a
Compare
A quick question: Looks like we didn't use [1] https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-83432/index.html |
I mmap according to the address that the linker already generated the PHDR with 🤔. Is it unsafe to assume that the linker already setup the address layout of the PHDRs according to the alignment the linker itself also used to describe the PHDR? 🤔 I just assume that the alignment is already taken care of implicitly by the address fields of the PHDR. |
Tested with a few applications, all working well, and looks good to me. |
9f4d14e
to
82b5578
Compare
I am going to try to modularize the code some more. |
Ok, it should be easier to read the code now. Separated the logic between the first PT_LOAD and the other PT_LOAD's. |
@i-Pear Thank you for the very thorough review! Here's another update. I hope I integrated all of the comments we reached consensus on. Let me know if you have any other comments! |
The alignment of the first segment should be |
I still don't understand why it's safe. If the va_base is aligned to But if we assume the va_base is |
fc178c4
to
87471cf
Compare
I decided to use the highest alignment after all. Since this is what glibc also does. You're right, let's keep it safe 💯. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, this will be the final round of review.
3673311
to
78b2a70
Compare
Thanks for the very attentive review @i-Pear. If all is fine with you now, feel free to approve and give you |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me, thanks.
Reviewed-by: Tianyi Liu i.pear@outlook.com
78b2a70
to
46bc6c9
Compare
Turns out that |
@i-Pear This is the difference basically. Let me know if this change is still fine with you. You also mentioned it sometime ago IIRC. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks better on my side, everything looks well except the following comments:
46bc6c9
to
d5ab1d2
Compare
We must ensure that the image base address is aligned according to the alignment of the highest PT_LOAD alignment. Thus, do two things: - define `align` field in `struct elf_prog` that we will use to hold this highest alignment - make `elf_load_parse` also compute this, since it makes sense judging by the function name and, besides, it does an initial iteration over PT_LOADs anyway. Signed-off-by: Sergiu Moga <sergiu@unikraft.io>
135d9f2
to
04b559a
Compare
I also realised I could set |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for the update! Looks good to me.
Approved-by: Simon Kuenzer simon@unikraft.io
Add an additional way of loading an ELF depending on whether CONFIG_LIBPOSIX_MMAP is used or not. If it is enabled, then the ELF loader will `mmap` the file instead of `pread` it. Otherwise, the previous method of `pread`ing file contents is used. The first address of the executable will be the first result of the first time call to `mmap` on the first `PT_LOAD` and everything else will be contiguously mapped by using the `MAP_FIXED` flag. Some special things to be noted when it comes to misaligned end addresses of ELF segments. Suppose we have `vastart` and `vaend`, corresponding to the start address of the ELF segment and the end address respectively and consider memsz as the runtime memory size occupied by the loaded segment: if vaend > vastart + memsz if vaend == PAGE_ALIGN_UP(vastart + memsz) the remaining bytes from (vastart + memsz) to vaend have already been mapped, so simply memset with 0 else /* vaend > PAGE_ALIGN_UP(vastart + memsz) */ this segment contains a section with NOBITS, such as .bss, which can be fairly large. Therefore: /* memset what is already mapped */ memset(vastart + memsz, 0, PAGE_ALIGN_UP(vastart + memsz) - vastart); /* anonymously map what is left, as memsetting large * sections such as .bss is very costly. */ mmap(PAGE_ALIGN_UP(vastart + memsz), vaend - PAGE_ALIGN_UP(vastart + memsz), ..., MAP_ANONYMOUS, ...); NOTE: The first segment must be mmap'd with the length of the entire file in memory and then the surplus is to be `munmapped`. This way we ensure we will always have a contiguous mapping big enough ready. Although future `mmap`'s with `MAP_FIXED` should normally overwrite this surplus, ridding us of the need to explicitly `munmap` it, in this current state of Unikraft (0.14.1) there is a bug in `ukvmem` that may not handle overlapping VMA's correctly. Signed-off-by: Sergiu Moga <sergiu@unikraft.io>
04b559a
to
92e0c08
Compare
Realised I forgot to add the |
The `e_rawfile` of `elf_prog` already contains the entire read or mmap'd ELF so use that instead for computing the interpretor path. Signed-off-by: Sergiu Moga <sergiu@unikraft.io> Reviewed-by: Tianyi Liu <i.pear@outlook.com> Approved-by: Simon Kuenzer <simon@unikraft.io> GitHub-Closes: #28
We must ensure that the image base address is aligned according to the alignment of the highest PT_LOAD alignment. Thus, do two things: - define `align` field in `struct elf_prog` that we will use to hold this highest alignment - make `elf_load_parse` also compute this, since it makes sense judging by the function name and, besides, it does an initial iteration over PT_LOADs anyway. Signed-off-by: Sergiu Moga <sergiu@unikraft.io> Reviewed-by: Tianyi Liu <i.pear@outlook.com> Approved-by: Simon Kuenzer <simon@unikraft.io> GitHub-Closes: #28
Add an additional way of loading an ELF depending on whether CONFIG_LIBPOSIX_MMAP is used or not. If it is enabled, then the ELF loader will `mmap` the file instead of `pread` it. Otherwise, the previous method of `pread`ing file contents is used. The first address of the executable will be the first result of the first time call to `mmap` on the first `PT_LOAD` and everything else will be contiguously mapped by using the `MAP_FIXED` flag. Some special things to be noted when it comes to misaligned end addresses of ELF segments. Suppose we have `vastart` and `vaend`, corresponding to the start address of the ELF segment and the end address respectively and consider memsz as the runtime memory size occupied by the loaded segment: if vaend > vastart + memsz if vaend == PAGE_ALIGN_UP(vastart + memsz) the remaining bytes from (vastart + memsz) to vaend have already been mapped, so simply memset with 0 else /* vaend > PAGE_ALIGN_UP(vastart + memsz) */ this segment contains a section with NOBITS, such as .bss, which can be fairly large. Therefore: /* memset what is already mapped */ memset(vastart + memsz, 0, PAGE_ALIGN_UP(vastart + memsz) - vastart); /* anonymously map what is left, as memsetting large * sections such as .bss is very costly. */ mmap(PAGE_ALIGN_UP(vastart + memsz), vaend - PAGE_ALIGN_UP(vastart + memsz), ..., MAP_ANONYMOUS, ...); NOTE: The first segment must be mmap'd with the length of the entire file in memory and then the surplus is to be `munmapped`. This way we ensure we will always have a contiguous mapping big enough ready. Although future `mmap`'s with `MAP_FIXED` should normally overwrite this surplus, ridding us of the need to explicitly `munmap` it, in this current state of Unikraft (0.14.1) there is a bug in `ukvmem` that may not handle overlapping VMA's correctly. Signed-off-by: Sergiu Moga <sergiu@unikraft.io> Reviewed-by: Tianyi Liu <i.pear@outlook.com> Approved-by: Simon Kuenzer <simon@unikraft.io> GitHub-Closes: #28
Deprecate use of
elf_load_do_fdread
anduk_memalign
in favor ofmmap
ing each ELF segment individually. This allows for massiveperformance improvements in conjunction with on-demand paging.
The first address of the executable will be the first result of the
first time call to
mmap
on the firstPT_LOAD
and everything elsewill be contiguously mapped by using the
MAP_FIXED
flag.Depends on
lib-libelf #3
.