[cfe-dev] Q: ARM, why -marm is ignored

valerij zaporogeci via cfe-dev cfe-dev at lists.llvm.org
Fri Jul 2 18:17:00 PDT 2021


Indeed! :D I am not that familiar with ARM ISA. but it makes sense and
is not a coincidence, probably, that there is only blx reg. because
having another bl reg, that wouldn't understand mode switch and fail,
whereas instructions, directly modifying pc don't fail and do switch,
would be alogical and redundant. Thank you for your help, now it's
clear. btw, you said, it should be easy to teach lld-link to set
MachineType to 1C2. is it really doable at the option setting level or
it's "easy" as in "easy to change the source code of the linker"? :)

2021-07-03 3:55 GMT+03:00, Eli Friedman <efriedma at quicinc.com>:
> We have to use blx for indirect calls; there's no other version of "bl" that
> takes a register operand.  (Well, technically, you can emulate a call using
> "mov lr, pc; mov pc, ip", but that's slower.)
>
> -Eli
>
>> -----Original Message-----
>> From: cfe-dev <cfe-dev-bounces at lists.llvm.org> On Behalf Of valerij
>> zaporogeci
>> via cfe-dev
>> Sent: Friday, July 2, 2021 4:11 PM
>> To: David Spickett <david.spickett at linaro.org>
>> Cc: cfe-dev at lists.llvm.org Developers <cfe-dev at lists.llvm.org>
>> Subject: [EXT] Re: [cfe-dev] Q: ARM, why -marm is ignored
>>
>> Thank you, David (and Eli). That really looks interesting, because if
>> clang doesn't support mixing modes, it shouldn't use blx. right?
>> However, looking at the image disassembly, reveals, that calling to
>> the UEFI interfaces are being done through blx ip. :)
>>
>> Maybe it's a common rule, to use blx instead of bl if the call is to
>> something, whose exact mode of execution the compiler cannot know
>> about?
>>
>> In both cases, (clang and msvc), even though there are no options to
>> tell the _compiler_ it's interworking, because they both target thumb
>> only, the produced images are interwoking correct. :) I looked into
>> disassembly of .obj files, both for msvc and clang, to see if there
>> might be bl->blx exchange by the linker. there is no such. in the
>> object files of both compilers, calling to UEFI interfaces are done
>> through blx. interesting, that MachineType of msvc .obj files are set
>> to 1C4 (it's link.exe, who changes it to 1C2). finally, a quick check
>> for a msvc produced "hello world" windows console program, linked
>> against msvcrt.dll shows, that the calls to imported functions are
>> done through blx.
>>
>> 2021-07-02 12:37 GMT+03:00, David Spickett <david.spickett at linaro.org>:
>> >> As of the calling convention, it's basically AAPCS:
>> >
>> > I thought a linux but coff triple would work for this but alas:
>> >
>> > $ ../build-llvm-aarch64/bin/clang --target=armv7a-unkonwn-linux-coff
>> > -c /tmp/test.c -o /tmp/test.o
>> > clang-13: warning: unknown platform, assuming -mfloat-abi=soft
>> > clang-13: warning: unknown platform, assuming -mfloat-abi=soft
>> > clang-13: warning: unknown platform, assuming -mfloat-abi=soft
>> > fatal error: error in backend: Cannot initialize MC for non-Windows
>> > COFF object files.
>> >
>> >> • Calls to UEFI defined interfaces must be done assuming that the
>> >> target
>> >> code requires
>> >> the ARM instruction set state. Images are free to use other
>> >> instruction
>> >> set states except
>> >> when invoking UEFI interfaces.
>> >
>> >> I use MSVC, which generates Thumb, but when being told about
>> >> /subsystem:EFI_APPLICATION at least, sets 1C2 MachineType
>> >
>> > My only worry there is that the Windows ABI assumes Thumb only
>> > (https://docs.microsoft.com/en-us/cpp/build/overview-of-arm-abi-
>> conventions?view=msvc-160).
>> > However if they specifically support EFI then there's probably some
>> > special case for that, where you need the interworking.
>> >
>> > Just from the llvm source there's a few places where interworking is
>> > mentioned. For example we don't emit "__THUMB_INTERWORK__" for
>> Windows
>> > triples. That said the comment above is mysterious:
>> > // FIXME: It's more complicated than this and we don't really support
>> > // interworking.
>> >
>> > A very quick test https://godbolt.org/z/18oWPWzsK uses "bl" not "blx"
>> > that you'd want for interworking. If hex editing the machine type
>> > works then great but if you find it failing when you're calling these
>> > interfaces that could be the reason. (perhaps if you link against
>> > functions in another object marked as arm, the linker will convert
>> > this to a blx regardless of the windows triple?)
>> >
>> > On Thu, 1 Jul 2021 at 23:53, valerij zaporogeci <vlrzprgts at gmail.com>
>> > wrote:
>> >>
>> >> > > maybe there is another target, better suitable for a UEFI OSL
>> >> >
>> >> > Can you describe (or link to docs) what this means? What does a UEFI
>> >> > compatible executable involve, what format would it be, does it have
>> >> > to use Windows calling conventions, that sort of thing. (I'm not
>> >> > familiar with this area myself)
>> >>
>> >> The UEFI specification says (section 2.1.1 in 2.4.Errata_B, yes, it's
>> >> old, but I bet, it's the same in the newest one - compatibility), it
>> >> wants MachineType field for ARM32:
>> >> > #define EFI_IMAGE_MACHINE_ARMTHUMB_MIXED 0x01C2
>> >>
>> >> and explains:
>> >>
>> >> > This image type is chosen to enable UEFI images to contain Thumb and
>> >> > Thumb2
>> >> > instructions while defining the EFI interfaces themselves to be in
>> >> > ARM
>> >> > mode.
>> >>
>> >> As of the calling convention, it's basically AAPCS:
>> >> > 2.3.5.3 Detailed Calling Convention
>> >> > The base calling convention for the ARM binding is defined here:
>> >> >   Procedure Call Standard for the ARM Architecture V2.06 (or later)
>> >> > http://infocenter.arm.com/
>> >> > This binding further constrains the calling convention in these
>> >> > ways:
>> >> > • Calls to UEFI defined interfaces must be done assuming that the
>> >> > target
>> >> > code requires
>> >> > the ARM instruction set state. Images are free to use other
>> >> > instruction
>> >> > set states except
>> >> > when invoking UEFI interfaces.
>> >> > • Floating point, SIMD, vector operations and other instruction set
>> >> > extensions must not
>> >> > be used.
>> >> > • Only little endian operation is supported.
>> >> > • The stack will maintain 8 byte alignment as described in the AAPCS
>> >> > for
>> >> > public
>> >> > interfaces.
>> >>
>> >> So, the loader can be compiled to the Thumb instructions, but it has
>> >> to be "interworking" aware, and, as an indication of that, it should
>> >> use 1C2 machine type. And you know, what's funny, I just hexedited the
>> >> clang compiled image, changing MachineType from 1C4 to 1C2 and it
>> >> worked. :) without this, FW rejected to start it. So, if this is going
>> >> to be this optimistic, then this is the only change to be needed to
>> >> make it suitable for UEFI. Of course, pity, there is no way to tell
>> >> clang generate ARM only code.
>> >>
>> >> >> as said in the title, gcc's -marm option (that is not reported as
>> >> >> not
>> >> >> recognized) gets
>> >> >> absolutely ignored.
>> >> >
>> >> > The title I assume refers to clang. Do you mean gcc here, or clang?
>> >> > Would be good to compare the results if gcc is doing something
>> >> > different. (that doesn't make either correct just more data points)
>> >>
>> >> yes, clang, I just hoped, that passing to it this gcc option, would
>> >> make it generate ARM code fpr Windows targets. naivety. :) gcc
>> >> probably does generate ARM code in this case, but gcc can't do PE, so
>> >> I didn't use it. I use MSVC, which generates Thumb, but when being
>> >> told about /subsystem:EFI_APPLICATION at least, sets 1C2 MachineType.
>> >>
>> >> Thank you for your help.
>> >
>> _______________________________________________
>> cfe-dev mailing list
>> cfe-dev at lists.llvm.org
>> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>


More information about the cfe-dev mailing list