Search code examples
assemblyarmarm64

How to declare a variable (in data section) and load the address of the variable in arm64 assembly?


I think I knew this but I forgot how to do it.
In an assembly program (in arch/arm64/kernel/head.S of linux) I declare a variable like this

__INITDATA
mydata1 : .long 0x22222222

and then in the __primary_switch function in __INIT section, which is .init.text, I want to overwrite 0x1406 at mydata1,

mov x27, #0x1406
adrp x25, mydata1
add x25, x25, :lo12:mydata1
str x27, [x25]
dc cvac, x25

But I get this error message when I compile it.

/tmp/ccy8ayvt.s: Error: .size expression for __primary_switch does not evaluate to a constant

What am I doing wrong?

ADD :
I found what my mistake was : I put

__INITDATTA
mydata1: .long 0x22222222

inside a function definition! (right before SYM_FUNC_END(__primary_switch) statement..) That's causing the weird error message.


Solution

  • Just try it?

    unsigned long x=0x22222222;
    void fun ( void )
    {
        x=0x1406;
    }
    
    aarch64-none-elf-gcc -fno-section-anchors -O2 -c -save-temps so.c -o so.o
    
        .arch armv8-a
        .file   "so.c"
        .text
        .align  2
        .p2align 4,,11
        .global fun
        .type   fun, %function
    fun:
        adrp    x0, x
        mov x1, 5126
        str x1, [x0, #:lo12:x]
        ret
        .size   fun, .-fun
        .global x
        .data
        .align  3
        .type   x, %object
        .size   x, 8
    x:
        .xword  572662306
        .ident  "GCC: (GNU) 11.1.0"
    

    so

        .global fun
    fun:
        adrp    x0, x
        mov x1, 0x1406
        str x1, [x0, #:lo12:x]
        ret
    
        .data
        .global x
    x:
        .xword  0x22222222
    

    minimal linking to see it in action

    Disassembly of section .text:
    
    0000000000400000 <fun>:
      400000:   90000080    adrp    x0, 410000 <fun+0x10000>
      400004:   d28280c1    mov x1, #0x1406                 // #5126
      400008:   f9000801    str x1, [x0, #16]
      40000c:   d65f03c0    ret
    
    Disassembly of section .data:
    
    0000000000410010 <__data_start>:
      410010:   22222222    .inst   0x22222222 ; undefined
      410014:   00000000    udf #0
    

    Can do this too

        .global fun
    fun:
        adrp    x0, x
        add    x0,x0,#:lo12:x
        mov x1, #0x1406
        str x1, [x0]
        ret
    
        .data
        .global x
    x:
        .xword  0x22222222
    

    but even if I

    .data
    mydata1 : .long 0x22222222
    
    .text
    mov x27, #0x1406
    adrp x25, mydata1
    add x25, x25, :lo12:mydata1
    str x27, [x25]
    dc cvac, x25
    
    aarch64-none-elf-as so.s -o so.o
    aarch64-none-elf-objdump -D so.o
    
    so.o:     file format elf64-littleaarch64
    
    
    Disassembly of section .text:
    
    0000000000000000 <.text>:
       0:   d28280db    mov x27, #0x1406                    // #5126
       4:   90000019    adrp    x25, 0 <.text>
       8:   91000339    add x25, x25, #0x0
       c:   f900033b    str x27, [x25]
      10:   d50b7a39    dc  cvac, x25
    
    Disassembly of section .data:
    
    0000000000000000 <mydata1>:
       0:   22222222    .inst   0x22222222 ; undefined
    

    What tool (and version) are you using and can you provide a complete minimal example. I do not see the error. Since it talks about size then what does the .size show in your code and why does it not resolve? That is where you need to start