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 (git@github.com: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