* How to define a symbol with absolute address for AArch64?
@ 2023-09-12 10:02 Sebastian Huber
2023-09-12 11:21 ` Richard Earnshaw
0 siblings, 1 reply; 9+ messages in thread
From: Sebastian Huber @ 2023-09-12 10:02 UTC (permalink / raw)
To: binutils
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
aarch64-rtems6-objdump -d a.out
a.out: file format elf64-littleaarch64
Disassembly of section .text:
0000000000400000 <f_abs_symbol>:
400000: 90000000 adrp x0, 400000 <f_abs_symbol>
400004: 91048c00 add x0, x0, #0x123
400008: d65f03c0 ret
000000000040000c <f_abs_symbol_2>:
40000c: 90ffe000 adrp x0, 0 <abs_symbol-0x123>
400010: 91048c00 add x0, x0, #0x123
400014: d65f03c0 ret
0000000000400018 <_start>:
400018: a9be7bfd stp x29, x30, [sp, #-32]!
40001c: 910003fd mov x29, sp
400020: f9000bf3 str x19, [sp, #16]
400024: 97fffff7 bl 400000 <f_abs_symbol>
400028: aa0003f3 mov x19, x0
40002c: 97fffff8 bl 40000c <f_abs_symbol_2>
400030: 8b000260 add x0, x19, x0
400034: f9400bf3 ldr x19, [sp, #16]
400038: a8c27bfd ldp x29, x30, [sp], #32
40003c: d65f03c0 ret
On riscv it works for example:
riscv-rtems6-gcc abs.c -Wl,--gc-sections -Wl,--defsym=abs_symbol_2=291
-O2 -march=rv64imafd -mabi=lp64d -mcmodel=medany
riscv-rtems6-objdump -d a.out
a.out: file format elf64-littleriscv
Disassembly of section .text:
00000000000100b0 <f_abs_symbol>:
100b0: 1230051b addiw a0,zero,291
100b4: 00008067 ret
00000000000100b8 <f_abs_symbol_2>:
100b8: 12300513 li a0,291
100bc: 00008067 ret
00000000000100c0 <_start>:
100c0: 12300793 li a5,291
100c4: 1230051b addiw a0,zero,291
100c8: 00f50533 add a0,a0,a5
100cc: 00008067 ret
--
embedded brains GmbH
Herr Sebastian HUBER
Dornierstr. 4
82178 Puchheim
Germany
email: sebastian.huber@embedded-brains.de
phone: +49-89-18 94 741 - 16
fax: +49-89-18 94 741 - 08
Registergericht: Amtsgericht München
Registernummer: HRB 157899
Vertretungsberechtigte Geschäftsführer: Peter Rasmussen, Thomas Dörfler
Unsere Datenschutzerklärung finden Sie hier:
https://embedded-brains.de/datenschutzerklaerung/
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: How to define a symbol with absolute address for AArch64?
2023-09-12 10:02 How to define a symbol with absolute address for AArch64? Sebastian Huber
@ 2023-09-12 11:21 ` Richard Earnshaw
2023-09-12 12:58 ` Sebastian Huber
0 siblings, 1 reply; 9+ messages in thread
From: Richard Earnshaw @ 2023-09-12 11:21 UTC (permalink / raw)
To: Sebastian Huber, binutils
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:
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
0000000000400018 <f_abs_symbol_2>:
400018: 90000000 adrp x0, 400000 <f_abs_symbol>
40001c: 9100a000 add x0, x0, #0x28
400020: f9400000 ldr x0, [x0]
400024: d65f03c0 ret
400028: 00000123 .word 0x00000123
40002c: 00000000 .word 0x00000000
0000000000400030 <_start>:
400030: a9be7bfd stp x29, x30, [sp, #-32]!
400034: 910003fd mov x29, sp
400038: f9000bf3 str x19, [sp, #16]
40003c: 97fffff1 bl 400000 <f_abs_symbol>
400040: aa0003f3 mov x19, x0
400044: 97fffff5 bl 400018 <f_abs_symbol_2>
400048: 8b000260 add x0, x19, x0
40004c: f9400bf3 ldr x19, [sp, #16]
400050: a8c27bfd ldp x29, x30, [sp], #32
400054: d65f03c0 ret
R.
>
> aarch64-rtems6-objdump -d a.out
>
> a.out: file format elf64-littleaarch64
>
>
> Disassembly of section .text:
>
> 0000000000400000 <f_abs_symbol>:
> 400000: 90000000 adrp x0, 400000 <f_abs_symbol>
> 400004: 91048c00 add x0, x0, #0x123
> 400008: d65f03c0 ret
>
> 000000000040000c <f_abs_symbol_2>:
> 40000c: 90ffe000 adrp x0, 0 <abs_symbol-0x123>
> 400010: 91048c00 add x0, x0, #0x123
> 400014: d65f03c0 ret
>
> 0000000000400018 <_start>:
> 400018: a9be7bfd stp x29, x30, [sp, #-32]!
> 40001c: 910003fd mov x29, sp
> 400020: f9000bf3 str x19, [sp, #16]
> 400024: 97fffff7 bl 400000 <f_abs_symbol>
> 400028: aa0003f3 mov x19, x0
> 40002c: 97fffff8 bl 40000c <f_abs_symbol_2>
> 400030: 8b000260 add x0, x19, x0
> 400034: f9400bf3 ldr x19, [sp, #16]
> 400038: a8c27bfd ldp x29, x30, [sp], #32
> 40003c: d65f03c0 ret
>
> On riscv it works for example:
>
> riscv-rtems6-gcc abs.c -Wl,--gc-sections -Wl,--defsym=abs_symbol_2=291
> -O2 -march=rv64imafd -mabi=lp64d -mcmodel=medany
>
> riscv-rtems6-objdump -d a.out
>
> a.out: file format elf64-littleriscv
>
>
> Disassembly of section .text:
>
> 00000000000100b0 <f_abs_symbol>:
> 100b0: 1230051b addiw a0,zero,291
> 100b4: 00008067 ret
>
> 00000000000100b8 <f_abs_symbol_2>:
> 100b8: 12300513 li a0,291
> 100bc: 00008067 ret
>
> 00000000000100c0 <_start>:
> 100c0: 12300793 li a5,291
> 100c4: 1230051b addiw a0,zero,291
> 100c8: 00f50533 add a0,a0,a5
> 100cc: 00008067 ret
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: How to define a symbol with absolute address for AArch64?
2023-09-12 11:21 ` Richard Earnshaw
@ 2023-09-12 12:58 ` Sebastian Huber
2023-09-12 13:46 ` Xi Ruoyao
0 siblings, 1 reply; 9+ messages in thread
From: Sebastian Huber @ 2023-09-12 12:58 UTC (permalink / raw)
To: Richard Earnshaw, binutils
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?
Is there some way to make this working with -mcmodel=small?
--
embedded brains GmbH
Herr Sebastian HUBER
Dornierstr. 4
82178 Puchheim
Germany
email: sebastian.huber@embedded-brains.de
phone: +49-89-18 94 741 - 16
fax: +49-89-18 94 741 - 08
Registergericht: Amtsgericht München
Registernummer: HRB 157899
Vertretungsberechtigte Geschäftsführer: Peter Rasmussen, Thomas Dörfler
Unsere Datenschutzerklärung finden Sie hier:
https://embedded-brains.de/datenschutzerklaerung/
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: How to define a symbol with absolute address for AArch64?
2023-09-12 12:58 ` Sebastian Huber
@ 2023-09-12 13:46 ` Xi Ruoyao
2023-09-12 14:23 ` Sebastian Huber
0 siblings, 1 reply; 9+ messages in thread
From: Xi Ruoyao @ 2023-09-12 13:46 UTC (permalink / raw)
To: Sebastian Huber, Richard Earnshaw, binutils
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.
> 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.
--
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: How to define a symbol with absolute address for AArch64?
2023-09-12 13:46 ` Xi Ruoyao
@ 2023-09-12 14:23 ` Sebastian Huber
2023-09-12 16:18 ` Richard Earnshaw
0 siblings, 1 reply; 9+ messages in thread
From: Sebastian Huber @ 2023-09-12 14:23 UTC (permalink / raw)
To: Xi Ruoyao, Richard Earnshaw, binutils
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.
--
embedded brains GmbH
Herr Sebastian HUBER
Dornierstr. 4
82178 Puchheim
Germany
email: sebastian.huber@embedded-brains.de
phone: +49-89-18 94 741 - 16
fax: +49-89-18 94 741 - 08
Registergericht: Amtsgericht München
Registernummer: HRB 157899
Vertretungsberechtigte Geschäftsführer: Peter Rasmussen, Thomas Dörfler
Unsere Datenschutzerklärung finden Sie hier:
https://embedded-brains.de/datenschutzerklaerung/
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: How to define a symbol with absolute address for AArch64?
2023-09-12 14:23 ` Sebastian Huber
@ 2023-09-12 16:18 ` Richard Earnshaw
2023-09-13 6:04 ` Sebastian Huber
0 siblings, 1 reply; 9+ messages in thread
From: Richard Earnshaw @ 2023-09-12 16:18 UTC (permalink / raw)
To: Sebastian Huber, Xi Ruoyao, binutils
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.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: How to define a symbol with absolute address for AArch64?
2023-09-12 16:18 ` Richard Earnshaw
@ 2023-09-13 6:04 ` Sebastian Huber
2023-09-13 10:02 ` Richard Earnshaw (lists)
0 siblings, 1 reply; 9+ messages in thread
From: Sebastian Huber @ 2023-09-13 6:04 UTC (permalink / raw)
To: binutils
On 12.09.23 18:18, Richard Earnshaw wrote:
>
>
> 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.
For my use case, I can't use things in the data or read-only data
section. The RTEMS real-time operating system is deployed as a start.o
start file and a set of static libraries. Applications are statically
linked with the operating system. The operating system is configured by
the application through a set of objects and some symbols those
addresses are configuration values. One of these symbols is the size of
the interrupt and system initialization stack. Setting up the system
initialization stack is usually one of the first things done by the
startup code in start.o. This is done before the data sections are
copied from the load memory area to the virtual (runtime) memory area.
For example on AArch64 it uses this code currently:
/* Calculate interrupt stack area end for current processor */
#ifdef AARCH64_MULTILIB_ARCH_V8_ILP32
ldr w1, =_ISR_Stack_size
#else
ldr x1, =_ISR_Stack_size
#endif
#ifdef RTEMS_SMP
add x3, x7, #1
mul x1, x1, x3
#endif
#ifdef AARCH64_MULTILIB_ARCH_V8_ILP32
ldr w2, =_ISR_Stack_area_begin
#else
ldr x2, =_ISR_Stack_area_begin
#endif
add x3, x1, x2
I adjusted our test cases so that they work now also for AArch64:
https://git.rtems.org/rtems/commit/?id=d7a6e803984e5508c30aa9e3625c76460beb807b
--
embedded brains GmbH
Herr Sebastian HUBER
Dornierstr. 4
82178 Puchheim
Germany
email: sebastian.huber@embedded-brains.de
phone: +49-89-18 94 741 - 16
fax: +49-89-18 94 741 - 08
Registergericht: Amtsgericht München
Registernummer: HRB 157899
Vertretungsberechtigte Geschäftsführer: Peter Rasmussen, Thomas Dörfler
Unsere Datenschutzerklärung finden Sie hier:
https://embedded-brains.de/datenschutzerklaerung/
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: How to define a symbol with absolute address for AArch64?
2023-09-13 6:04 ` Sebastian Huber
@ 2023-09-13 10:02 ` Richard Earnshaw (lists)
2023-09-14 7:30 ` Sebastian Huber
0 siblings, 1 reply; 9+ messages in thread
From: Richard Earnshaw (lists) @ 2023-09-13 10:02 UTC (permalink / raw)
To: Sebastian Huber, binutils
On 13/09/2023 07:04, Sebastian Huber wrote:
> On 12.09.23 18:18, Richard Earnshaw wrote:
>>
>>
>> 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.
>
> For my use case, I can't use things in the data or read-only data section. The RTEMS real-time operating system is deployed as a start.o start file and a set of static libraries. Applications are statically linked with the operating system. The operating system is configured by the application through a set of objects and some symbols those addresses are configuration values. One of these symbols is the size of the interrupt and system initialization stack. Setting up the system initialization stack is usually one of the first things done by the startup code in start.o. This is done before the data sections are copied from the load memory area to the virtual (runtime) memory area. For example on AArch64 it uses this code currently:
>
> /* Calculate interrupt stack area end for current processor */
> #ifdef AARCH64_MULTILIB_ARCH_V8_ILP32
> ldr w1, =_ISR_Stack_size
> #else
> ldr x1, =_ISR_Stack_size
> #endif
> #ifdef RTEMS_SMP
> add x3, x7, #1
> mul x1, x1, x3
> #endif
> #ifdef AARCH64_MULTILIB_ARCH_V8_ILP32
> ldr w2, =_ISR_Stack_area_begin
> #else
> ldr x2, =_ISR_Stack_area_begin
> #endif
> add x3, x1, x2
>
> I adjusted our test cases so that they work now also for AArch64:
>
> https://git.rtems.org/rtems/commit/?id=d7a6e803984e5508c30aa9e3625c76460beb807b
>
So force the symbol into the text section. It's a bit naughty, but it should work, assuming the text section has read permission:
extern char abs_symbol[];
char * const volatile __attribute__((section (".text.constdata")))
abs_sym_ptr = abs_symbol;
unsigned long f_abs_symbol(void)
{
return (unsigned long)abs_sym_ptr;
}
unsigned long _start(void)
{
return f_abs_symbol();
}
$ aarch64-none-elf-gcc -O -nostartfiles -nostdlib start.c -Wl,--gc-sections -Wl,--defsym=abs_symbol=291
$ aarch64-linux-gnu-objdump -d a.out
a.out: file format elf64-littleaarch64
Disassembly of section .text:
0000000000400000 <f_abs_symbol>:
400000: 90000000 adrp x0, 400000 <f_abs_symbol>
400004: f9400c00 ldr x0, [x0, #24]
400008: d65f03c0 ret
000000000040000c <_start>:
40000c: 90000000 adrp x0, 400000 <f_abs_symbol>
400010: f9400c00 ldr x0, [x0, #24]
400014: d65f03c0 ret
0000000000400018 <abs_sym_ptr>:
400018: 00000123 00000000 #.......
R.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: How to define a symbol with absolute address for AArch64?
2023-09-13 10:02 ` Richard Earnshaw (lists)
@ 2023-09-14 7:30 ` Sebastian Huber
0 siblings, 0 replies; 9+ messages in thread
From: Sebastian Huber @ 2023-09-14 7:30 UTC (permalink / raw)
To: binutils
On 13.09.23 12:02, Richard Earnshaw (lists) wrote:
> On 13/09/2023 07:04, Sebastian Huber wrote:
>> On 12.09.23 18:18, Richard Earnshaw wrote:
>>>
>>> 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.
>> For my use case, I can't use things in the data or read-only data section. The RTEMS real-time operating system is deployed as a start.o start file and a set of static libraries. Applications are statically linked with the operating system. The operating system is configured by the application through a set of objects and some symbols those addresses are configuration values. One of these symbols is the size of the interrupt and system initialization stack. Setting up the system initialization stack is usually one of the first things done by the startup code in start.o. This is done before the data sections are copied from the load memory area to the virtual (runtime) memory area. For example on AArch64 it uses this code currently:
>>
>> /* Calculate interrupt stack area end for current processor */
>> #ifdef AARCH64_MULTILIB_ARCH_V8_ILP32
>> ldr w1, =_ISR_Stack_size
>> #else
>> ldr x1, =_ISR_Stack_size
>> #endif
>> #ifdef RTEMS_SMP
>> add x3, x7, #1
>> mul x1, x1, x3
>> #endif
>> #ifdef AARCH64_MULTILIB_ARCH_V8_ILP32
>> ldr w2, =_ISR_Stack_area_begin
>> #else
>> ldr x2, =_ISR_Stack_area_begin
>> #endif
>> add x3, x1, x2
>>
>> I adjusted our test cases so that they work now also for AArch64:
>>
>> https://git.rtems.org/rtems/commit/?id=d7a6e803984e5508c30aa9e3625c76460beb807b
>>
> So force the symbol into the text section. It's a bit naughty, but it should work, assuming the text section has read permission:
>
> extern char abs_symbol[];
>
> char * const volatile __attribute__((section (".text.constdata")))
> abs_sym_ptr = abs_symbol;
>
> unsigned long f_abs_symbol(void)
> {
> return (unsigned long)abs_sym_ptr;
> }
>
> unsigned long _start(void)
> {
> return f_abs_symbol();
> }
>
> $ aarch64-none-elf-gcc -O -nostartfiles -nostdlib start.c -Wl,--gc-sections -Wl,--defsym=abs_symbol=291
> $ aarch64-linux-gnu-objdump -d a.out
>
> a.out: file format elf64-littleaarch64
>
>
> Disassembly of section .text:
>
> 0000000000400000 <f_abs_symbol>:
> 400000: 90000000 adrp x0, 400000 <f_abs_symbol>
> 400004: f9400c00 ldr x0, [x0, #24]
> 400008: d65f03c0 ret
>
> 000000000040000c <_start>:
> 40000c: 90000000 adrp x0, 400000 <f_abs_symbol>
> 400010: f9400c00 ldr x0, [x0, #24]
> 400014: d65f03c0 ret
>
> 0000000000400018 <abs_sym_ptr>:
> 400018: 00000123 00000000 #.......
Thanks for the trick with the const volatile object. We had some other
places which used symbols with an arbitrary address directly. Using the
const volatile objects worked fine.
Independent of this, I think in the -mcmodel=small case some tool should
issue an error instead of getting an invalid value at runtime. Just like
in the -mcmodel=tiny case, where you get a relocation truncated error.
--
embedded brains GmbH
Herr Sebastian HUBER
Dornierstr. 4
82178 Puchheim
Germany
email: sebastian.huber@embedded-brains.de
phone: +49-89-18 94 741 - 16
fax: +49-89-18 94 741 - 08
Registergericht: Amtsgericht München
Registernummer: HRB 157899
Vertretungsberechtigte Geschäftsführer: Peter Rasmussen, Thomas Dörfler
Unsere Datenschutzerklärung finden Sie hier:
https://embedded-brains.de/datenschutzerklaerung/
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2023-09-14 7:30 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-09-12 10:02 How to define a symbol with absolute address for AArch64? Sebastian Huber
2023-09-12 11:21 ` Richard Earnshaw
2023-09-12 12:58 ` Sebastian Huber
2023-09-12 13:46 ` Xi Ruoyao
2023-09-12 14:23 ` Sebastian Huber
2023-09-12 16:18 ` Richard Earnshaw
2023-09-13 6:04 ` Sebastian Huber
2023-09-13 10:02 ` Richard Earnshaw (lists)
2023-09-14 7:30 ` Sebastian Huber
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).