AArch64 ASM / Custom Sections and Common Variables

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

AArch64 ASM / Custom Sections and Common Variables

Tom Stellard via cfe-dev
What is the proper way to have a variable common between two custom-defined sections?

Example:

  .global foo1
  .section .text.foo1, "ax"
foo1:
  ldr w0, FooValue
  ret

  .global foo2
  .section .text.foo2, "ax"
foo2:
  ldr w0, FooValue
  ret

FooValue: .word 0x00

This generates "unsupported relocation type: fixup_aarch64_ldr_pcrel_imm19".  If I comment out the first ldr line, it builds, as FooValue is part of .text.foo2.

If I define FooValue twice, once for each section it complains it's already defined.


Joel


_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: AArch64 ASM / Custom Sections and Common Variables

Tom Stellard via cfe-dev
This is with lld-lnk -target aarch64-unknown-windows.

On Sat, Nov 9, 2019 at 10:25 AM Joel Winarske <[hidden email]> wrote:
What is the proper way to have a variable common between two custom-defined sections?

Example:

  .global foo1
  .section .text.foo1, "ax"
foo1:
  ldr w0, FooValue
  ret

  .global foo2
  .section .text.foo2, "ax"
foo2:
  ldr w0, FooValue
  ret

FooValue: .word 0x00

This generates "unsupported relocation type: fixup_aarch64_ldr_pcrel_imm19".  If I comment out the first ldr line, it builds, as FooValue is part of .text.foo2.

If I define FooValue twice, once for each section it complains it's already defined.


Joel


_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: AArch64 ASM / Custom Sections and Common Variables

Tom Stellard via cfe-dev
In reply to this post by Tom Stellard via cfe-dev
What target (in particular OS, object file format) are you trying to assemble for? Your example assembles without error for me with this command line:
  clang --target=aarch64-none-eabi -c test.s -o test.o

That is generating ELF output, it's possible that other formats don't have the necessary relocations to represent the first LDR instruction, or LLVM doesn't know how to emit them.

It's also worth noting that a single LDR instruction only has a range of +-1MiB, which might not be what you want. I often find the easiest way to find reasonable assembly sequences is to compile a C file which does what you want and look at the assembly output. For example, with this C file:
  long FooValue = 0x0;

  __attribute((section(".text.foo1")))
  long foo1() {
    return FooValue;
  }

  __attribute((section(".text.foo2")))
  long foo2() {
    return FooValue;
  }

clang emits this assembly:
          .text
          .file   "test2.c"
          .section        .text.foo1,"ax",@progbits
          .globl  foo1                    // -- Begin function foo1
          .p2align        2
          .type   foo1,@function
  foo1:                                   // @foo1
  // %bb.0:                               // %entry
          adrp    x8, FooValue
          ldr     x0, [x8, :lo12:FooValue]
          ret
  .Lfunc_end0:
          .size   foo1, .Lfunc_end0-foo1
                                          // -- End function
          .section        .text.foo2,"ax",@progbits
          .globl  foo2                    // -- Begin function foo2
          .p2align        2
          .type   foo2,@function
  foo2:                                   // @foo2
  // %bb.0:                               // %entry
          adrp    x8, FooValue
          ldr     x0, [x8, :lo12:FooValue]
          ret
  .Lfunc_end1:
          .size   foo2, .Lfunc_end1-foo2
                                          // -- End function
          .type   FooValue,@object        // @FooValue
          .bss
          .globl  FooValue
          .p2align        3
  FooValue:
          .xword  0                       // 0x0
          .size   FooValue, 8

          .ident  "clang version 10.0.0 ([hidden email]:llvm/llvm-project.git 36937ec7fb8e20b81adbac40bd48c6ed7ac6df61)"
          .section        ".note.GNU-stack","",@progbits
          .addrsig

Note the use of the ADRP/LDR pair of instructions, which has a range of +-4GiB.

Oliver

On Sat, 9 Nov 2019 at 18:26, Joel Winarske via cfe-dev <[hidden email]> wrote:
What is the proper way to have a variable common between two custom-defined sections?

Example:

  .global foo1
  .section .text.foo1, "ax"
foo1:
  ldr w0, FooValue
  ret

  .global foo2
  .section .text.foo2, "ax"
foo2:
  ldr w0, FooValue
  ret

FooValue: .word 0x00

This generates "unsupported relocation type: fixup_aarch64_ldr_pcrel_imm19".  If I comment out the first ldr line, it builds, as FooValue is part of .text.foo2.

If I define FooValue twice, once for each section it complains it's already defined.


Joel

_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: AArch64 ASM / Custom Sections and Common Variables

Tom Stellard via cfe-dev
In reply to this post by Tom Stellard via cfe-dev
Hi Joel,

On Sat, 9 Nov 2019 at 18:26, Joel Winarske via cfe-dev
<[hidden email]> wrote:
> This generates "unsupported relocation type: fixup_aarch64_ldr_pcrel_imm19".  If I comment out the first ldr line, it builds, as FooValue is part of .text.foo2.

To reference a symbol across sections like this, you'd need to add a
relocation to the object file, but some formats (MachO I know) have a
ridiculously small number of permitted relocations and don't have room
for for pc-relative load relocations. I think you're probably hitting
that issue.

You've got two options:

1. Reference FooValue in a way that does have relocations. For example
(on MachO, I'm afraid I don't know the syntax for COFF, and it should
just be working anyway for ELF):

    adrp x0, FooValue@PAGE
    ldr w0, [x0, FooValue@PAGEOFFSET]

2. Use a local symbol with a different name each time (starting with L
on MachO), and defined within the section that references it
(actually, probably before the next global symbol if you're using
.subsections_via_symbols, which you should be):

    .section .text.foo1
foo1:
   ldr w0, LFooValue.foo1
   ret
LFooValue.foo1:
  .word 0

    .section .text.foo2
foo2:
   ldr w0, LFooValue.foo2
   ret
LFooValue.foo2:
  .word 0

Cheers.

Tim.
_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: AArch64 ASM / Custom Sections and Common Variables

Tom Stellard via cfe-dev
In reply to this post by Tom Stellard via cfe-dev
Hi Oliver,

Great idea.  I'll take this approach.

Thanks,
Joel

On Mon, Nov 11, 2019, 5:36 AM Oliver Stannard <[hidden email]> wrote:
What target (in particular OS, object file format) are you trying to assemble for? Your example assembles without error for me with this command line:
  clang --target=aarch64-none-eabi -c test.s -o test.o

That is generating ELF output, it's possible that other formats don't have the necessary relocations to represent the first LDR instruction, or LLVM doesn't know how to emit them.

It's also worth noting that a single LDR instruction only has a range of +-1MiB, which might not be what you want. I often find the easiest way to find reasonable assembly sequences is to compile a C file which does what you want and look at the assembly output. For example, with this C file:
  long FooValue = 0x0;

  __attribute((section(".text.foo1")))
  long foo1() {
    return FooValue;
  }

  __attribute((section(".text.foo2")))
  long foo2() {
    return FooValue;
  }

clang emits this assembly:
          .text
          .file   "test2.c"
          .section        .text.foo1,"ax",@progbits
          .globl  foo1                    // -- Begin function foo1
          .p2align        2
          .type   foo1,@function
  foo1:                                   // @foo1
  // %bb.0:                               // %entry
          adrp    x8, FooValue
          ldr     x0, [x8, :lo12:FooValue]
          ret
  .Lfunc_end0:
          .size   foo1, .Lfunc_end0-foo1
                                          // -- End function
          .section        .text.foo2,"ax",@progbits
          .globl  foo2                    // -- Begin function foo2
          .p2align        2
          .type   foo2,@function
  foo2:                                   // @foo2
  // %bb.0:                               // %entry
          adrp    x8, FooValue
          ldr     x0, [x8, :lo12:FooValue]
          ret
  .Lfunc_end1:
          .size   foo2, .Lfunc_end1-foo2
                                          // -- End function
          .type   FooValue,@object        // @FooValue
          .bss
          .globl  FooValue
          .p2align        3
  FooValue:
          .xword  0                       // 0x0
          .size   FooValue, 8

          .ident  "clang version 10.0.0 ([hidden email]:llvm/llvm-project.git 36937ec7fb8e20b81adbac40bd48c6ed7ac6df61)"
          .section        ".note.GNU-stack","",@progbits
          .addrsig

Note the use of the ADRP/LDR pair of instructions, which has a range of +-4GiB.

Oliver

On Sat, 9 Nov 2019 at 18:26, Joel Winarske via cfe-dev <[hidden email]> wrote:
What is the proper way to have a variable common between two custom-defined sections?

Example:

  .global foo1
  .section .text.foo1, "ax"
foo1:
  ldr w0, FooValue
  ret

  .global foo2
  .section .text.foo2, "ax"
foo2:
  ldr w0, FooValue
  ret

FooValue: .word 0x00

This generates "unsupported relocation type: fixup_aarch64_ldr_pcrel_imm19".  If I comment out the first ldr line, it builds, as FooValue is part of .text.foo2.

If I define FooValue twice, once for each section it complains it's already defined.


Joel

_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: AArch64 ASM / Custom Sections and Common Variables

Tom Stellard via cfe-dev
In reply to this post by Tom Stellard via cfe-dev
Thanks Tim!

On Mon, Nov 11, 2019, 6:37 AM Tim Northover <[hidden email]> wrote:
Hi Joel,

On Sat, 9 Nov 2019 at 18:26, Joel Winarske via cfe-dev
<[hidden email]> wrote:
> This generates "unsupported relocation type: fixup_aarch64_ldr_pcrel_imm19".  If I comment out the first ldr line, it builds, as FooValue is part of .text.foo2.

To reference a symbol across sections like this, you'd need to add a
relocation to the object file, but some formats (MachO I know) have a
ridiculously small number of permitted relocations and don't have room
for for pc-relative load relocations. I think you're probably hitting
that issue.

You've got two options:

1. Reference FooValue in a way that does have relocations. For example
(on MachO, I'm afraid I don't know the syntax for COFF, and it should
just be working anyway for ELF):

    adrp x0, FooValue@PAGE
    ldr w0, [x0, FooValue@PAGEOFFSET]

2. Use a local symbol with a different name each time (starting with L
on MachO), and defined within the section that references it
(actually, probably before the next global symbol if you're using
.subsections_via_symbols, which you should be):

    .section .text.foo1
foo1:
   ldr w0, LFooValue.foo1
   ret
LFooValue.foo1:
  .word 0

    .section .text.foo2
foo2:
   ldr w0, LFooValue.foo2
   ret
LFooValue.foo2:
  .word 0

Cheers.

Tim.

_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev