Re: ArmVirt and Self-Updating Code


Andrew Fish
 

On Aug 1, 2021, at 2:40 PM, Marvin Häuser <mhaeuser@...> wrote:

01.08.2021 18:33:47 Ard Biesheuvel <ardb@...>:

On Sat, 31 Jul 2021 at 21:08, Marvin Häuser <mhaeuser@...> wrote:
On 23.07.21 16:34, Ard Biesheuvel wrote:
On Fri, 23 Jul 2021 at 16:27, Marvin Häuser <mhaeuser@...> wrote:
On 23.07.21 16:09, Ard Biesheuvel wrote:
On Fri, 23 Jul 2021 at 12:47, Marvin Häuser <mhaeuser@...> wrote:
...
Do you maybe have one final comment regarding that second question,
please? :)
The RELA section is not converted into PE/COFF relocations. This would
not achieve a lot, given that no prior PE/COFF loader exists to
process them. There is a snippet of asm code in the startup code that
processes the R_AARCH64_RELATIVE relocation entries before calling
into C code.
I searched for said ASM code till my fingers fell asleep and at last
found this:
https://github.com/tianocore/edk2/commit/b16fd231f6d8124fa05a0f086840934b8709faf9#diff-3d563cc4775c7720900f4895bf619eed06291044aaa277fcc57eddc7618351a1L12-R148
If I understand the commit message correctly, it is basically "pray the
C code does not use globals at all", which is fair enough, so maybe I
should document this in my proposed new library? I trust that this is
enough of a constraint for both ARM and AArch64, because I do not know
them at all.
The C code can use globals, but not global pointer variables. But you
are right, this is not very robust at all.
Right... Will document for my PE library.

What worries me is that StandaloneMmCore has no such ASM entry point at
all and instead it's just executing C directly. Also, it is not passed
the "-fno-jump-tables" flag that is commented to be important in the
commit linked above.
This is because the StandaloneMmCore is built with -fpie, which
already implies -fno-jump-tables, although I suppose this may not
offer complete coverage for BASE libraries that are pulled into the
link.
Ah okay, thanks. Out of curiosity of how ARM implements PIE, and how StMmCore self-relocation can work *after* the PE/COFF section permissions have been applied with .got merged into .text (i.e. read-only), I checked the GCC5 "DLL" with readelf and found many relocations into the .text section. I have no idea how any of this works, and no idea where to find out, but as it apparently does, I might just update the PE calls and call it a day. I cannot test anything either because there is no QEMU code for StMmCore I can find. :(
Marvin,

It is useful to remember that there are object file (resolved by the linker), dynamic loading (resolved when the DLL is bound at runtime), and image relocations. In the EFI PE/COFF we only end up with the image relocations that need to be processed when an image is loaded into memory. I seem to remember seeing the other classes of relocations still being present in the ELF files, but they end up being a no-opt for EFI. You can look at the EFI PE/COFF relocations to see the things EFI cares about.

Side note… The Xcode/clang toolchain requires the TEXT section to not contain relocations for X64, and the linker will fail if there is code that requires a relocation in the text section. This generally is not a problem, but hand coded assembler can trigger a link failure that is specific to Xcode.

Thanks,

Andrew Fish

Thanks for your tireless replies!

Best regards,
Marvin

Best regards,
Marvin
This also gives us the guarantee that no GOT indirections are
dereferenced, given that our asm code simply does not do that.
Let's drop "GOT" and make it "any instruction that requires prior
relocation to function correctly".
The thing to keep in mind here is that R_AARCH64_RELATIVE relocations
never target instructions, but only memory locations that carry
absolute addresses. This could be locations in .rodata or .data
(global vars carrying pointer values), or GOT entries.
Correct. And this works really well for shared libraries, where all
text and data sections can be shared between processes, as they will
not be modified by the loader. All locations targeted by relocations
will be nicely lumped together in the GOT.
However, for bare metal style programs, there is no sharing, and there
is no advantage to lumping anything together. It is much better to use
relative references where possible, and simply apply relocations
wherever needed across the text and data sections,
The GOT is a special data structure used for implicit variable
accesses, i.e., global vars used in the code. Statically initialized
pointer variables are the other category, which are not code, and for
which the same considerations do not apply, given that the right value
simply needs to be stored in the variable before the program starts.
The selection of 'code model' as it is called is controlled by GCC's
-mcmodel= argument, which defaults to 'small' on AArch64, regardless
of whether you use PIC/PIE or not.
Aha, makes sense, thanks!
Best regards,
Marvin




Join devel@edk2.groups.io to automatically receive all group messages.