Bug 77882 - [Aarch64] Add 'naked' function attribute
Summary: [Aarch64] Add 'naked' function attribute
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 6.1.1
: P3 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: inline-asm
Depends on:
Blocks:
 
Reported: 2016-10-06 13:58 UTC by Christophe Monat
Modified: 2024-04-25 16:41 UTC (History)
5 users (show)

See Also:
Host:
Target: aarch64*-*-*
Build:
Known to work:
Known to fail:
Last reconfirmed: 2016-10-06 00:00:00


Attachments
Proposed implementation of naked functions for aarch64 (957 bytes, patch)
2019-10-28 11:17 UTC, Elad Lahav
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Christophe Monat 2016-10-06 13:58:37 UTC
With the following code fragment aarch64-attribute-naked.c :

void
__attribute__((naked))
dealwithit()
{
  // Stuff removed above, below we assume that the 'naked' attribute
  // does the job and does not generate the usual 'ret' instruction
  asm("eret"::);
}

$ aarch64-linux-gnu-gcc -S aarch64-attribute-naked.c
aarch64-attribute-naked.c:4:1: warning: 'naked' attribute directive ignored [-Wattributes]

I have tried with a gcc-6.1.1, but simply as an example, this feature has never been ported to Aarch64, I think.

As this attribute is supported for the legacy ARM target, it would be nice it the Aarch64 compiler could support it.
Comment 1 Ramana Radhakrishnan 2016-10-06 14:24:51 UTC
Confirmed.

> 
> As this attribute is supported for the legacy ARM target, it would be nice
> it the Aarch64 compiler could support it.

s/legacy//

patches welcome for further discussion ;) 

regards
Ramana
Comment 2 Andrew Pinski 2016-10-06 14:27:04 UTC
I really think the naked attribute as not useful at all. I think it was a bad idea. Why not write a .s file which does what you want?
Comment 3 Christophe Monat 2016-10-06 14:47:02 UTC
Andrew,

(In reply to Andrew Pinski from comment #2)
> I really think the naked attribute as not useful at all. I think it was a
> bad idea. Why not write a .s file which does what you want?

Well, from the discussions I read (for instance in bug #25967) before posting this, I was more or less expecting this remark. I agree that some arguments there are not valid.

In a nutshell, I wrote quite a lot of tricky testing code (dealing manually with functions prologues/epilogues, etc..) for the ARM target (Ramana : please pardon the misused 'legacy' adjective) using this feature, and I would like to have a similar installment for ARM64.

I am also generally simply bothered at the idea of putting decoration at the beginning of an assembly file, and starting from .c enables me to have the appropriate tags automatically emitted when I switch from target to target.
--C
Comment 4 Elad Lahav 2019-10-28 11:17:36 UTC
Created attachment 47119 [details]
Proposed implementation of naked functions for aarch64

The change is quite simple (see the proposed patch). I hope it can be made, as I find naked functions quite useful, especially by allowing the use of certain C features in otherwise pure assembly code (e.g., offsetof, _Static_assert). Aesthetically, naked functions provide proper prototypes that are easier to follow, document and test.
Comment 5 Richard Earnshaw 2019-10-28 13:44:44 UTC
(In reply to Elad Lahav from comment #4)
> Created attachment 47119 [details]
> Proposed implementation of naked functions for aarch64
> 
> The change is quite simple (see the proposed patch). I hope it can be made,
> as I find naked functions quite useful, especially by allowing the use of
> certain C features in otherwise pure assembly code (e.g., offsetof,
> _Static_assert). Aesthetically, naked functions provide proper prototypes
> that are easier to follow, document and test.

Patches need to be sent to gcc-patches@gcc.gnu.org.  Note, if you've not contributed to gcc before you'll also need to sort out a copyright assignment for the change (this is a non-trivial change).
Comment 6 Elad Lahav 2019-10-28 14:36:57 UTC
(In reply to Richard Earnshaw from comment #5)
> Patches need to be sent to gcc-patches@gcc.gnu.org.  Note, if you've not
> contributed to gcc before you'll also need to sort out a copyright
> assignment for the change (this is a non-trivial change).

Yes, I figured there is more process to submitting a change. At this point I just wanted to point out that it is a simple enough fix.
Comment 7 Andrew Pinski 2019-10-28 14:43:01 UTC
The problem with the naked attribute is usually it is not well defined.  For things like interrupts functions and interrupt returns, there is always plain .s files. Interrupts usually save/restore all registers including the floating point ones.  So they are large.  The float point ones can get complex now with SVE too.
Comment 8 Elad Lahav 2019-10-28 14:51:09 UTC
(In reply to Andrew Pinski from comment #7)
> The problem with the naked attribute is usually it is not well defined.  For
> things like interrupts functions and interrupt returns, there is always
> plain .s files. Interrupts usually save/restore all registers including the
> floating point ones.  So they are large.  The float point ones can get
> complex now with SVE too.

I am actually using this facility to write kernel entry and exit routines. As I said, the advantage over pure assembly files is that you can use offsetof() and _Static_assert() when storing and loading registers to and from kernel data structures. You can also break up large chunks (such as storing and loading FPU registers) into inline functions.

So far it looks like the compiler is doing the right thing with a combination of naked functions and inline functions: the code I get is exactly the inline assembly in these functions without any modifications or additions. If that is not guaranteed then it is indeed a problem.
Comment 9 Elad Lahav 2019-11-05 12:41:24 UTC
While trying to write a simple test to demonstrate that the suggested patch works I ran into a couple of issues. First, here is the test code:

#include <stdio.h>
#include <stdlib.h>

#if defined(__aarch64__)
static long __attribute__((naked))
add_one(long a)
{
    __asm__ __volatile__("add x0, x0, #1; ret");
}
#elif defined(__arm__)
static long __attribute__((naked))
add_one(long a)
{
    __asm__ __volatile__("add r0, r0, #1; bx lr");
}
#endif

int
main(int argc, char **argv)
{
    long a = 0;
    if (argc > 1) {
        a = strtol(argv[1], NULL, 0);
    }

    a = add_one(a);
    printf("a=%ld\n", a);
    return 0;
}

1. GCC emits a warning:
   /home/elahav/src/projects/aarch64_naked/aarch64_naked.c:15:1: warning: no return statement in function returning non-void [-Wreturn-type]
 }
 This is true for ARMv7 as well. I would not expect such a warning in a naked function.
2. With -O0 GCC puts an instruction before 'add':
   0000000000000000 <add_one>:
     0:   f90007e0        str     x0, [sp, #8]
     4:   91000400        add     x0, x0, #0x1
     8:   d65f03c0        ret
     c:   d503201f        nop

 The ARMv7 version is better, though still has extra baggage:
   00000000 <add_one>:
     0:   f100 0001       add.w   r0, r0, #1
     4:   4770            bx      lr
     6:   bf00            nop
     8:   4618            mov     r0, r3

 With -O2 I get the expected results:
  0000000000000000 <add_one>:
     0:   91000400        add     x0, x0, #0x1
     4:   d65f03c0        ret
Comment 10 Christophe Monat 2019-11-06 16:18:59 UTC
(In reply to Elad Lahav from comment #9)

Thanks for your patch proposal!
 
> 1. GCC emits a warning:
>    /home/elahav/src/projects/aarch64_naked/aarch64_naked.c:15:1: warning: no
> return statement in function returning non-void [-Wreturn-type]
>  }
>  This is true for ARMv7 as well. I would not expect such a warning in a
> naked function.

You may be interested in reading this : bug https://bugs.launchpad.net/gcc-arm-embedded/+bug/1836547
Comment 11 Fangrui Song 2022-05-25 06:39:40 UTC
The number of targets supporting this attribute is large but the popular aarch64 somehow doesn't support it... I just run into a case where supporting this would be nice (https://reviews.llvm.org/D126343#3536318).

% grep 'naked.*function attribute,' gcc/doc/extend.texi
@cindex @code{naked} function attribute, ARC
@cindex @code{naked} function attribute, ARM
@cindex @code{naked} function attribute, AVR
@cindex @code{naked} function attribute, C-SKY
@cindex @code{naked} function attribute, MCORE
@cindex @code{naked} function attribute, MSP430
@cindex @code{naked} function attribute, NDS32
@cindex @code{naked} function attribute, RISC-V
@cindex @code{naked} function attribute, RL78
@cindex @code{naked} function attribute, RX
@cindex @code{naked} function attribute, x86
Comment 12 Andrew Pinski 2022-05-25 06:45:29 UTC
(In reply to Fangrui Song from comment #11)
> The number of targets supporting this attribute is large but the popular
> aarch64 somehow doesn't support it... I just run into a case where
> supporting this would be nice (https://reviews.llvm.org/D126343#3536318).

That is not really a good use case really. a testcase is general purpose use case.
Comment 13 stefan.tauner 2023-01-17 15:28:49 UTC
Please reconsider this. I ran into this when debugging pointer authentication not working correctly where I have to replace the prologue of a specific existing non-trivial C function. This would be way easier with this attribute and some inline assembly than replacing the whole function.
Comment 14 Nick Desaulniers 2024-04-08 18:39:04 UTC
Adding a data point from https://discourse.llvm.org/t/hand-written-in-assembly-in-libc-setjmp-longjmp/73249/9.

It's becoming a code portability issue when clang supports this function attribute on functions for aarch64 targets but GCC does not.
Comment 15 Andrew Pinski 2024-04-08 19:25:49 UTC
(In reply to Nick Desaulniers from comment #14)
> Adding a data point from
> https://discourse.llvm.org/t/hand-written-in-assembly-in-libc-setjmp-longjmp/
> 73249/9.
> 
> It's becoming a code portability issue when clang supports this function
> attribute on functions for aarch64 targets but GCC does not.

Not really since you still can use a .s (or .S) file there .... That is how all other libc implement their setjmp/longjump and even correctly. Some will even use a generator to get the offsets and/or use static_asserts to make sure offsets stay correct.