-
Notifications
You must be signed in to change notification settings - Fork 159
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
Segments change, when saving a loaded file #135
Comments
Thank you for your analysis. You are right - ELFIO maps sections to segments and calculates alignment of section in accordance to contained sections. I'll try to reproduce and find the reason for the case you provided. |
I am also experiencing this issue, since I am trying to load existing static ELF files, modify them, and write them back. Any help on this would be appreciated. |
Most likely, the issue is related to section size equal to zero and inability to assign a proper segment for such section. I'm sorry, but, I'll not come to this issue soon. Any help will be appreciated. |
Well, as you can see, even Another issue with the executable is that the last segment of type PT_GNU_RELRO contains sections with alignments up to 32 (section |
3 segments of the initial file are located at the same memory location and even worse - at the same file offset. I doubt that such configuration can be supported for modification easily. I'll leave the issue opened for meantime. May be some ideas will come. But, I am very sceptic about this. Another question arises regarding the size of ninth segment GNU_RELRO. If it contains |
I think this is a design problem in elfio. In the elf specification sections and segments are almost completely unrelated. Segments are used, when loading the binary into memory for execution. Here the type of the segment determines how it is used (e.g. PT_LOAD is mapped into the virtual memory space of the process). I don't really know what the other sections are used for, but they may be used by the linker or kernel during loading. So it is no coincidence, that there is no reference from segments to sections (e.g. id or name) in the elf. You simple cannot deduce the sections from segments, but that is what elfio is trying to do. Section to segment mapping is also in readelf just a best effort approach. I only see two segments at the same address (NOTE and GNU_PROPERTY @ 0x400270). Both segments map the same physical data from the file (0x270 - 0x290). From an elf perspective this is totally fine, because the PT_NOE and PT_GNU_PROPERTY may be used to describe the same thing (as I said, I don't really know). The main thing here is: This is not an artificial binary, this is generated by gcc/binutils without any special flags, except Maybe one option would at least be, to just deny saving the file, when it is not possible to save it exactly the way it was read, because right now this produces bugs, that are extremely hard to understand. If I recall correctly it took me a few days to until I understood what was happening, because the resulting program crashed for no obvious reason and this was related to TLS init in libc, which was hard to debug and understand why a pointer was just wrong |
When saving a file loaded with ELFIO, without any modifications, the segment definition can change.
I added a test in MofX@0ac9c67, that shows the behavior and could be added as a regression test, after fixing the bug.
It includes a binary generated with
echo "int main(){}" | gcc -xc -static -o x86_64_static -
, that is loaded with elfio and saved again. In the initial version the segments are compared to the output ofreadelf -l
and for the saved one the same is done, but fails, because elfio changes four fields of the segment Definition:At least the change in segment 6, which is the the TLS segment breaks the binary, because it changes the memory layout of the TLS, so that the libc initialization code uses an invalid pointer and segfaults.
I think the changed sizes are due to how elfio tries to map sections to segments. Instead of just mapping .tdata and .tbss to the TLS segment, it also maps .init_array and .finit_array to the TLS segment. The combined file size of these sections is 0x80.
readelf -l
shows a correct mapping. I imagine, the same is happening for segment 9.I did not look into why the alignment of segment 9 is changed.
The text was updated successfully, but these errors were encountered: