How to define a symbol with absolute address for AArch64?
Richard Earnshaw
Richard.Earnshaw@foss.arm.com
Tue Sep 12 16:18:24 GMT 2023
On 12/09/2023 15:23, Sebastian Huber wrote:
> On 12.09.23 15:46, Xi Ruoyao wrote:
>> On Tue, 2023-09-12 at 14:58 +0200, Sebastian Huber wrote:
>>> On 12.09.23 13:21, Richard Earnshaw wrote:
>>>>
>>>> On 12/09/2023 11:02, Sebastian Huber wrote:
>>>>> Hello,
>>>>>
>>>>> I would like to define a global symbol with an absolute address in an
>>>>> assembly/C source file for the AArch64 target. This works for all
>>>>> other architectures I tried so far, but not for AArch64:
>>>>>
>>>>> extern char abs_symbol[];
>>>>> extern char abs_symbol_2[];
>>>>>
>>>>> __asm__(
>>>>> "\t.globl abs_symbol\n"
>>>>> "\t.set abs_symbol, 0x123\n"
>>>>> );
>>>>>
>>>>> unsigned long f_abs_symbol(void)
>>>>> {
>>>>> return (unsigned long)abs_symbol;
>>>>> }
>>>>>
>>>>> unsigned long f_abs_symbol_2(void)
>>>>> {
>>>>> return (unsigned long)abs_symbol_2;
>>>>> }
>>>>>
>>>>> unsigned long _start(void)
>>>>> {
>>>>> return f_abs_symbol() + f_abs_symbol_2();
>>>>> }
>>>>>
>>>>> aarch64-rtems6-gcc abs.c -Wl,--gc-sections
>>>>> -Wl,--defsym=abs_symbol_2=291
>>>> Have you tried -mcmodel=large? With that I get:
>>> I get the same result with -mcmodel=large. With -mcmodel=tiny I get:
>>>
>>> aarch64-rtems6-gcc abs.c -Wl,--gc-sections -Wl,--defsym=abs_symbol_2=291
>>> -mcmodel=tiny
>>> /tmp/ccKUnvyq.o: in function `f_abs_symbol_2':
>>> abs.c:(.text+0x8): relocation truncated to fit: R_AARCH64_ADR_PREL_LO21
>>> against symbol `abs_symbol_2' defined in*ABS* section in a.out
>>> collect2: error: ld returned 1 exit status
>>>
>>> Is this a tool bug?
>> No, it's how code models are defined. GCC documentation says clearly:
>>
>> -mcmodel=tiny
>> Generate code for the tiny code model. The program
>> and its
>> statically defined symbols must be within 1MB of
>> each other.
>> Programs can be statically or dynamically linked.
>>
>> Here the text is located at 0x400000 but abs_symbol_2 is at 0x123, thus
>> violating the definition of -mcmodel=tiny.
>
> Yes, this makes sense.
>
>>
>>> Is there some way to make this working with -mcmodel=small?
>> No because -mcmodel=small only assumes the program and the symbols are
>> within*a* 4GB range - for example it's allowed to be [47GB, 51GB).
>> This is different from the default code model of RISC-V (-
>> mcmodel=medlow) where the symbols must be in [-2GB, 2GB).
>>
>> If you really think GCC should support this you can ask GCC for adding a
>> new code model. Anyway this is not a linker issue because the adrp-add
>> pairs are generated by GCC.
>
> Thanks for the explanation.
>
> I guess what reliably works across code models is using the address of
> an existing symbol and then add a constant which fits into the code
> model. To retrieve the constant, we just have to subtract the address of
> the other symbol.
>
There are various ways you can code this:
1) An alternative when using the large code model is to just write
extern char abs_symbol[];
char * const abs_sym_ptr = abs_symbol;
unsigned long f_abs_symbol(void)
{
return (unsigned long)abs_sym_ptr;
}
Which assembles to:
0000000000400000 <f_abs_symbol>:
400000: 90000000 adrp x0, 400000 <f_abs_symbol>
400004: 91004000 add x0, x0, #0x10
400008: f9400000 ldr x0, [x0]
40000c: d65f03c0 ret
400010: 00000123 .word 0x00000123
400014: 00000000 .word 0x00000000
2) If you really want to use other code models, you can try things like:
extern char abs_symbol[];
char * const volatile abs_sym_ptr = abs_symbol;
unsigned long f_abs_symbol(void)
{
return (unsigned long)abs_sym_ptr;
}
The "const volatile" forces the compiler not to try to inline the
pointer value dereference, so you end up with:
0000000000400000 <f_abs_symbol>:
400000: 90000000 adrp x0, 400000 <f_abs_symbol>
400004: f9400c00 ldr x0, [x0, #24]
400008: d65f03c0 ret
...
Disassembly of section .rodata:
0000000000400018 <abs_sym_ptr>:
400018: 00000123 00000000 #.......
In other respects, though, the pointer is const, so attempts to modify
it via normal C code will be inhibited by the compiler.
This should work with both the small and tiny models as well as the
large model.
R.
More information about the Binutils
mailing list