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

Eli Friedman via cfe-dev cfe-dev at lists.llvm.org
Fri Jul 2 19:01:52 PDT 2021


Easy as in "easy to change the source code of the linker".  See https://github.com/llvm/llvm-project/blob/af331e82845523751d39193ae657ca4f20ba1576/lld/COFF/Writer.cpp#L1355 . Just add a check "if (config->subsystem == COFF::IMAGE_SUBSYSTEM_EFI_APPLICATION && config->machine == ARMNT)" or something like that.

-Eli

> -----Original Message-----
> From: valerij zaporogeci <vlrzprgts at gmail.com>
> Sent: Friday, July 2, 2021 6:17 PM
> To: Eli Friedman <efriedma at quicinc.com>
> Cc: David Spickett <david.spickett at linaro.org>; cfe-dev at lists.llvm.org
> Subject: [EXT] Re: [cfe-dev] Q: ARM, why -marm is ignored
> 
> 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