mbox series

[0/6] objtool: Add support for Arm64

Message ID 20190409135243.12424-1-raphael.gault@arm.com (mailing list archive)
Headers show
Series objtool: Add support for Arm64 | expand

Message

Raphael Gault April 9, 2019, 1:52 p.m. UTC
Hi,

As of now, objtool only supports the x86_64 architecture but the
groundwork has already been done in order to add support for other
architecture without too much effort.

This series of patches adds support for the arm64 architecture
based on the Armv8.5 Architecture Reference Manual.

* Patch 1 adapts the existing code to be able to add support for other
  architecture.
* Patch 2 provide implementation of the required function for the arm64
  architecture.
* Patch 3 adapts the checking of the stack state for the arm64
  architecture.
* Patch 4 & 5 fix some warning objtool raised in some particular
  functions of ~/arch/arm64/kernel/sleep.S. Patch 4 add a macro to
  signal that some function should be ignored by objtool. 
* Patch 6 enables stack validation for arm64.

Theses patches should provide support for the main cases and behaviour.
However a few corner cases are not yet handled by objtool:

* In the `~/arch/arm64/crypto/` directory, I noticed that some plain
  data are sometimes stored in the `.text` section causing objtool to mistake
  this for instructions and trying (and failing) to interprete them.  If someone
  could explain to me why we store data directly in the .text section I would
  appreciate it.

* In the support for arm32 architecture such as in `~/arch/arm64/kernel/kuser32.S`
  some A32 instructions are used but such instructions are not understood by
  objtool causing a warning.

I also have a few unclear points I would like to bring to your
attention:

* For x86_64, when looking for a symbol relocation with explicit
  addend, objtool systematically adds a +4 offset to the addend.
  I don't understand why even if I have a feeling it is related
  to the type of relacation.

* I currently don't have a clear understanding about how switch-tables
  are generated on arm64 and how to retrieve them (based on relocations).

Please provide me with any feedback and comments as well on the content
than the style of these patches.

Thanks,

Raphael

->

Raphael Gault (6):
  objtool: Refactor code to make it more suitable for multiple
    architecture support
  objtool: arm64: Add required implementation for supporting the aarch64
    architecture in objtool.
  objtool: arm64: Adapt the stack frame checks and the section analysis
    for the arm architecture
  arm64: assembler: Add macro to annotate asm function having non
    standard stack-frame.
  arm64: sleep: Add stack frame setup for __cpu_supsend_enter
  objtool: arm64: Enable stack validation for arm64

 arch/arm64/Kconfig                            |    1 +
 arch/arm64/include/asm/assembler.h            |   18 +
 arch/arm64/kernel/sleep.S                     |    4 +
 tools/objtool/Build                           |    1 -
 tools/objtool/arch.h                          |   11 +
 tools/objtool/arch/arm64/Build                |    6 +
 tools/objtool/arch/arm64/bit_operations.c     |   65 +
 tools/objtool/arch/arm64/decode.c             | 2870 +++++++++++++++++
 .../objtool/arch/arm64/include/arch_special.h |   44 +
 .../arch/arm64/include/asm/orc_types.h        |  109 +
 .../arch/arm64/include/bit_operations.h       |   22 +
 tools/objtool/arch/arm64/include/cfi.h        |   76 +
 .../objtool/arch/arm64/include/insn_decode.h  |  219 ++
 tools/objtool/arch/arm64/orc_gen.c            |   40 +
 tools/objtool/arch/x86/Build                  |    1 +
 tools/objtool/arch/x86/decode.c               |  111 +
 tools/objtool/arch/x86/include/arch_special.h |   35 +
 tools/objtool/{ => arch/x86/include}/cfi.h    |    0
 tools/objtool/{ => arch/x86}/orc_gen.c        |   10 +-
 tools/objtool/check.c                         |  209 +-
 tools/objtool/check.h                         |    1 +
 tools/objtool/elf.c                           |    3 +-
 tools/objtool/orc.h                           |    4 +-
 tools/objtool/special.c                       |   18 +-
 24 files changed, 3740 insertions(+), 138 deletions(-)
 create mode 100644 tools/objtool/arch/arm64/Build
 create mode 100644 tools/objtool/arch/arm64/bit_operations.c
 create mode 100644 tools/objtool/arch/arm64/decode.c
 create mode 100644 tools/objtool/arch/arm64/include/arch_special.h
 create mode 100644 tools/objtool/arch/arm64/include/asm/orc_types.h
 create mode 100644 tools/objtool/arch/arm64/include/bit_operations.h
 create mode 100644 tools/objtool/arch/arm64/include/cfi.h
 create mode 100644 tools/objtool/arch/arm64/include/insn_decode.h
 create mode 100644 tools/objtool/arch/arm64/orc_gen.c
 create mode 100644 tools/objtool/arch/x86/include/arch_special.h
 rename tools/objtool/{ => arch/x86/include}/cfi.h (100%)
 rename tools/objtool/{ => arch/x86}/orc_gen.c (96%)

Comments

Josh Poimboeuf April 9, 2019, 2:57 p.m. UTC | #1
On Tue, Apr 09, 2019 at 02:52:37PM +0100, Raphael Gault wrote:
> Hi,
> 
> As of now, objtool only supports the x86_64 architecture but the
> groundwork has already been done in order to add support for other
> architecture without too much effort.

Hi Raphael,

This was a pleasant surprise in my inbox.  From a quick glance I'm
actually surprised at how "easy" it looks, though I can tell it was
quite a big effort.  Doing the first arch port is always the hardest.
Kudos!  I will give it a proper review soon.
Ard Biesheuvel April 9, 2019, 5:43 p.m. UTC | #2
On Tue, 9 Apr 2019 at 06:53, Raphael Gault <raphael.gault@arm.com> wrote:
>
> Hi,
>
> As of now, objtool only supports the x86_64 architecture but the
> groundwork has already been done in order to add support for other
> architecture without too much effort.
>
> This series of patches adds support for the arm64 architecture
> based on the Armv8.5 Architecture Reference Manual.
>

I think it makes sense to clarify *why* we want this on arm64. Also,
we should identify things that objtool does today that maybe we don't
want on arm64, rather than buy into all of it by default.

> * Patch 1 adapts the existing code to be able to add support for other
>   architecture.
> * Patch 2 provide implementation of the required function for the arm64
>   architecture.
> * Patch 3 adapts the checking of the stack state for the arm64
>   architecture.
> * Patch 4 & 5 fix some warning objtool raised in some particular
>   functions of ~/arch/arm64/kernel/sleep.S. Patch 4 add a macro to
>   signal that some function should be ignored by objtool.
> * Patch 6 enables stack validation for arm64.
>
> Theses patches should provide support for the main cases and behaviour.
> However a few corner cases are not yet handled by objtool:
>
> * In the `~/arch/arm64/crypto/` directory, I noticed that some plain
>   data are sometimes stored in the `.text` section causing objtool to mistake
>   this for instructions and trying (and failing) to interprete them.  If someone
>   could explain to me why we store data directly in the .text section I would
>   appreciate it.
>

Just for convenience, basically. Not specifying a section at all when
emitting a literal amounts to putting it into .text, and a a bonus, it
is guaranteed to be in range for a ADR instructions (which is not the
case when the code is built into the kernel rather than enabled as a
module)

Due to Spectre I have already updated some of the code so larger
tables are moved into .rodata (since literal data might contain binary
sequences that are usable as spectre gadgets), but some work remains
to be done.

> * In the support for arm32 architecture such as in `~/arch/arm64/kernel/kuser32.S`
>   some A32 instructions are used but such instructions are not understood by
>   objtool causing a warning.
>
> I also have a few unclear points I would like to bring to your
> attention:
>
> * For x86_64, when looking for a symbol relocation with explicit
>   addend, objtool systematically adds a +4 offset to the addend.
>   I don't understand why even if I have a feeling it is related
>   to the type of relacation.
>
> * I currently don't have a clear understanding about how switch-tables
>   are generated on arm64 and how to retrieve them (based on relocations).
>
> Please provide me with any feedback and comments as well on the content
> than the style of these patches.
>
> Thanks,
>
> Raphael
>
> ->
>
> Raphael Gault (6):
>   objtool: Refactor code to make it more suitable for multiple
>     architecture support
>   objtool: arm64: Add required implementation for supporting the aarch64
>     architecture in objtool.
>   objtool: arm64: Adapt the stack frame checks and the section analysis
>     for the arm architecture
>   arm64: assembler: Add macro to annotate asm function having non
>     standard stack-frame.
>   arm64: sleep: Add stack frame setup for __cpu_supsend_enter
>   objtool: arm64: Enable stack validation for arm64
>
>  arch/arm64/Kconfig                            |    1 +
>  arch/arm64/include/asm/assembler.h            |   18 +
>  arch/arm64/kernel/sleep.S                     |    4 +
>  tools/objtool/Build                           |    1 -
>  tools/objtool/arch.h                          |   11 +
>  tools/objtool/arch/arm64/Build                |    6 +
>  tools/objtool/arch/arm64/bit_operations.c     |   65 +
>  tools/objtool/arch/arm64/decode.c             | 2870 +++++++++++++++++
>  .../objtool/arch/arm64/include/arch_special.h |   44 +
>  .../arch/arm64/include/asm/orc_types.h        |  109 +
>  .../arch/arm64/include/bit_operations.h       |   22 +
>  tools/objtool/arch/arm64/include/cfi.h        |   76 +
>  .../objtool/arch/arm64/include/insn_decode.h  |  219 ++
>  tools/objtool/arch/arm64/orc_gen.c            |   40 +
>  tools/objtool/arch/x86/Build                  |    1 +
>  tools/objtool/arch/x86/decode.c               |  111 +
>  tools/objtool/arch/x86/include/arch_special.h |   35 +
>  tools/objtool/{ => arch/x86/include}/cfi.h    |    0
>  tools/objtool/{ => arch/x86}/orc_gen.c        |   10 +-
>  tools/objtool/check.c                         |  209 +-
>  tools/objtool/check.h                         |    1 +
>  tools/objtool/elf.c                           |    3 +-
>  tools/objtool/orc.h                           |    4 +-
>  tools/objtool/special.c                       |   18 +-
>  24 files changed, 3740 insertions(+), 138 deletions(-)
>  create mode 100644 tools/objtool/arch/arm64/Build
>  create mode 100644 tools/objtool/arch/arm64/bit_operations.c
>  create mode 100644 tools/objtool/arch/arm64/decode.c
>  create mode 100644 tools/objtool/arch/arm64/include/arch_special.h
>  create mode 100644 tools/objtool/arch/arm64/include/asm/orc_types.h
>  create mode 100644 tools/objtool/arch/arm64/include/bit_operations.h
>  create mode 100644 tools/objtool/arch/arm64/include/cfi.h
>  create mode 100644 tools/objtool/arch/arm64/include/insn_decode.h
>  create mode 100644 tools/objtool/arch/arm64/orc_gen.c
>  create mode 100644 tools/objtool/arch/x86/include/arch_special.h
>  rename tools/objtool/{ => arch/x86/include}/cfi.h (100%)
>  rename tools/objtool/{ => arch/x86}/orc_gen.c (96%)
>
> --
> 2.17.1
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Josh Poimboeuf April 10, 2019, 3:37 a.m. UTC | #3
On Tue, Apr 09, 2019 at 10:43:18AM -0700, Ard Biesheuvel wrote:
> On Tue, 9 Apr 2019 at 06:53, Raphael Gault <raphael.gault@arm.com> wrote:
> >
> > Hi,
> >
> > As of now, objtool only supports the x86_64 architecture but the
> > groundwork has already been done in order to add support for other
> > architecture without too much effort.
> >
> > This series of patches adds support for the arm64 architecture
> > based on the Armv8.5 Architecture Reference Manual.
> >
> 
> I think it makes sense to clarify *why* we want this on arm64. Also,
> we should identify things that objtool does today that maybe we don't
> want on arm64, rather than buy into all of it by default.

Agreed, the "why" should at least be in the cover letter.  From my
perspective, the "why" includes:

- Live patching - objtool stack validation is the foundation for a
  reliable unwinder

- ORC unwinder - benefits include presumed improved overall performance
  from disabling frame pointers, and the ability to unwind across
  interrupts and exceptions

- PeterZ's new uaccess validation?
Julien Thierry April 10, 2019, 7:20 a.m. UTC | #4
On 10/04/2019 04:37, Josh Poimboeuf wrote:
> On Tue, Apr 09, 2019 at 10:43:18AM -0700, Ard Biesheuvel wrote:
>> On Tue, 9 Apr 2019 at 06:53, Raphael Gault <raphael.gault@arm.com> wrote:
>>>
>>> Hi,
>>>
>>> As of now, objtool only supports the x86_64 architecture but the
>>> groundwork has already been done in order to add support for other
>>> architecture without too much effort.
>>>
>>> This series of patches adds support for the arm64 architecture
>>> based on the Armv8.5 Architecture Reference Manual.
>>>
>>
>> I think it makes sense to clarify *why* we want this on arm64. Also,
>> we should identify things that objtool does today that maybe we don't
>> want on arm64, rather than buy into all of it by default.
> 
> Agreed, the "why" should at least be in the cover letter.  From my
> perspective, the "why" includes:
> 
> - Live patching - objtool stack validation is the foundation for a
>   reliable unwinder
> 

Yes, as I understand Live patching is a work in progress for arm64.
Having objtool to provide more guarantees would be nice.

> - ORC unwinder - benefits include presumed improved overall performance
>   from disabling frame pointers, and the ability to unwind across
>   interrupts and exceptions
> 

I'm unsure this will be part of the plan. I believe so far arm64 code
heavily relies on the presence of frame pointers. It's also part of the
Aarch64 Procedure Call Standard.

But who knows.

> - PeterZ's new uaccess validation?
> 

Yes, we've reverted twice our implementation of user_access_begin/end()
on arm64 because of the issue of potentially calling sleeping functions.

Once we have the base of objtool work, this would be one of the next
work items.

Thanks,
Josh Poimboeuf April 23, 2019, 9:09 p.m. UTC | #5
On Tue, Apr 09, 2019 at 02:52:37PM +0100, Raphael Gault wrote:
> Hi,
> 
> As of now, objtool only supports the x86_64 architecture but the
> groundwork has already been done in order to add support for other
> architecture without too much effort.
> 
> This series of patches adds support for the arm64 architecture
> based on the Armv8.5 Architecture Reference Manual.
> 
> * Patch 1 adapts the existing code to be able to add support for other
>   architecture.
> * Patch 2 provide implementation of the required function for the arm64
>   architecture.
> * Patch 3 adapts the checking of the stack state for the arm64
>   architecture.
> * Patch 4 & 5 fix some warning objtool raised in some particular
>   functions of ~/arch/arm64/kernel/sleep.S. Patch 4 add a macro to
>   signal that some function should be ignored by objtool. 
> * Patch 6 enables stack validation for arm64.
> 
> Theses patches should provide support for the main cases and behaviour.
> However a few corner cases are not yet handled by objtool:
> 
> * In the `~/arch/arm64/crypto/` directory, I noticed that some plain
>   data are sometimes stored in the `.text` section causing objtool to mistake
>   this for instructions and trying (and failing) to interprete them.  If someone
>   could explain to me why we store data directly in the .text section I would
>   appreciate it.

I haven't looked, but it should probably be moved to .rodata.  We had
cases like that for x86.

> * In the support for arm32 architecture such as in `~/arch/arm64/kernel/kuser32.S`
>   some A32 instructions are used but such instructions are not understood by
>   objtool causing a warning.
> 
> I also have a few unclear points I would like to bring to your
> attention:
> 
> * For x86_64, when looking for a symbol relocation with explicit
>   addend, objtool systematically adds a +4 offset to the addend.
>   I don't understand why even if I have a feeling it is related
>   to the type of relacation.

This is because of how relative call/jump addresses are implemented on
x86.  It calculates the call/jump destination by adding the encoded offset
to the *ending* address of the instruction, rather than to the address
of the encoded offset itself.

For example:

  119ca0:       e8 00 00 00 00          callq  119ca5 <__ia32_sys_sched_rr_get_interval+0x5>
                        119ca1: R_X86_64_PC32   __fentry__-0x4

This instruction is a call to the __fentry__ function.  The rela addend
is the address of the destination function (__fentry__) minus 4.  After
applying the relocation, it resolves to:

ffffffff81002010:       e8 eb f7 9f 00          callq  ffffffff81a01800 <__fentry__>

The destination address is "0x9ff7eb", which is indeed __fentry__ - 4.

x86 expects it to be that way, because the x86 CPU adds the offset to
the *end* of the instruction: ffffffff81002015 (last digit is 5, not 0).

0xffffffff81002015 + 0x9ff7eb = 0xfffffff81a01800, which is indeed the
address of __fentry__.

And there's always a 4-byte gap between the relocation target and the
end of the instruction, so the rela addend always has the -4.  So when
reading the relocation we have to add the 4 bytes back to get the actual
destination address.

> * I currently don't have a clear understanding about how switch-tables
>   are generated on arm64 and how to retrieve them (based on relocations).

This is indeed a bit tricky on x86.

> Please provide me with any feedback and comments as well on the content
> than the style of these patches.

Overall it looks like a great start.  I added some per-patch comments.

Has the cross-compile path been tested?  Specifically, compiling for a
arm64 target on an x86 host?  In other words, objtool would be an x86
binary which reads arm64 objects.  I imagine that will be a semi-common
use case.  Objtool already supports cross-compiling for an x86-64 target
on an x86-32 host (and also a powerpc host IIRC), so it should be
do-able in theory, and it might "just work".

For the next version, please base it on the -tip tree, as that's where
all the latest objtool changes are.  Peter refactored some code which
has some minor conflicts with yours.
Raphael Gault April 24, 2019, 4:08 p.m. UTC | #6
Hi Josh,

On 4/23/19 10:09 PM, Josh Poimboeuf wrote:
> On Tue, Apr 09, 2019 at 02:52:37PM +0100, Raphael Gault wrote:
>> Hi,
>>
>> As of now, objtool only supports the x86_64 architecture but the
>> groundwork has already been done in order to add support for other
>> architecture without too much effort.
>>
>> This series of patches adds support for the arm64 architecture
>> based on the Armv8.5 Architecture Reference Manual.
>>
>> * Patch 1 adapts the existing code to be able to add support for other
>>    architecture.
>> * Patch 2 provide implementation of the required function for the arm64
>>    architecture.
>> * Patch 3 adapts the checking of the stack state for the arm64
>>    architecture.
>> * Patch 4 & 5 fix some warning objtool raised in some particular
>>    functions of ~/arch/arm64/kernel/sleep.S. Patch 4 add a macro to
>>    signal that some function should be ignored by objtool.
>> * Patch 6 enables stack validation for arm64.
>>
>> Theses patches should provide support for the main cases and behaviour.
>> However a few corner cases are not yet handled by objtool:
>>
>> * In the `~/arch/arm64/crypto/` directory, I noticed that some plain
>>    data are sometimes stored in the `.text` section causing objtool to mistake
>>    this for instructions and trying (and failing) to interprete them.  If someone
>>    could explain to me why we store data directly in the .text section I would
>>    appreciate it.
>
> I haven't looked, but it should probably be moved to .rodata.  We had
> cases like that for x86.
>
>> * In the support for arm32 architecture such as in `~/arch/arm64/kernel/kuser32.S`
>>    some A32 instructions are used but such instructions are not understood by
>>    objtool causing a warning.
>>
>> I also have a few unclear points I would like to bring to your
>> attention:
>>
>> * For x86_64, when looking for a symbol relocation with explicit
>>    addend, objtool systematically adds a +4 offset to the addend.
>>    I don't understand why even if I have a feeling it is related
>>    to the type of relacation.
>
> This is because of how relative call/jump addresses are implemented on
> x86.  It calculates the call/jump destination by adding the encoded offset
> to the *ending* address of the instruction, rather than to the address
> of the encoded offset itself.
>
> For example:
>
>    119ca0:       e8 00 00 00 00          callq  119ca5 <__ia32_sys_sched_rr_get_interval+0x5>
>                          119ca1: R_X86_64_PC32   __fentry__-0x4
>
> This instruction is a call to the __fentry__ function.  The rela addend
> is the address of the destination function (__fentry__) minus 4.  After
> applying the relocation, it resolves to:
>
> ffffffff81002010:       e8 eb f7 9f 00          callq  ffffffff81a01800 <__fentry__>
>
> The destination address is "0x9ff7eb", which is indeed __fentry__ - 4.
>
> x86 expects it to be that way, because the x86 CPU adds the offset to
> the *end* of the instruction: ffffffff81002015 (last digit is 5, not 0).
>
> 0xffffffff81002015 + 0x9ff7eb = 0xfffffff81a01800, which is indeed the
> address of __fentry__.
>
> And there's always a 4-byte gap between the relocation target and the
> end of the instruction, so the rela addend always has the -4.  So when
> reading the relocation we have to add the 4 bytes back to get the actual
> destination address.
>

Thank you for the explanation!

>> * I currently don't have a clear understanding about how switch-tables
>>    are generated on arm64 and how to retrieve them (based on relocations).
>
> This is indeed a bit tricky on x86.
>
>> Please provide me with any feedback and comments as well on the content
>> than the style of these patches.
>
> Overall it looks like a great start.  I added some per-patch comments.
>

Thank you, I will address them.

> Has the cross-compile path been tested?  Specifically, compiling for a
> arm64 target on an x86 host?  In other words, objtool would be an x86
> binary which reads arm64 objects.  I imagine that will be a semi-common
> use case.  Objtool already supports cross-compiling for an x86-64 target
> on an x86-32 host (and also a powerpc host IIRC), so it should be
> do-able in theory, and it might "just work".
>

It has indeed been tested to build for arm64 target on a x86 host and it
works fine.

> For the next version, please base it on the -tip tree, as that's where
> all the latest objtool changes are.  Peter refactored some code which
> has some minor conflicts with yours.
>

Thanks for letting me know about this. Just a quick precision, when you
talk about the -tip tree, are you talking about this tree ?
https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git/

Thanks,

--
Raphael Gault
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.
Josh Poimboeuf April 24, 2019, 4:14 p.m. UTC | #7
On Wed, Apr 24, 2019 at 04:08:15PM +0000, Raphael Gault wrote:
> > For the next version, please base it on the -tip tree, as that's where
> > all the latest objtool changes are.  Peter refactored some code which
> > has some minor conflicts with yours.
> >
> 
> Thanks for letting me know about this. Just a quick precision, when you
> talk about the -tip tree, are you talking about this tree ?
> https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git/

Indeed.  The git link I use is:

  git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git

And generally the master branch of that tree seems to be a good one to
use.