0

I'm probably way off but this is what I did, I'm also trying to get this to work from linux to cross compile to mac

I did a hello world kind of thing in C with write, malloc and realloc. I notice in the assembly it used adrp but I couldn't figure out how to use that instruction. I kept getting a label must be GOT relative error. I was hoping I could use the section as the label but ended up writing a label which didn't help.

Essentially the write c stub function uses adrp, then ldr [x16, #24]. Since I couldn't figure out adrp I used mov and movk. It seemed to do the same thing but I got a segment fault when I execute it. Stepping through lldb it appears that the code did what I thought however the GOT section wasn't replaced at runtime like I thought it would. Objdump leaves me to believe I named the section right. I don't know if figuring out adrp is all I need to get this to work or if I did everything completely wrong

.global _main
.align 2

_main:
    mov X0, #1
    adr X1, hello
    mov X2, #13
    mov X16, #4
    svc 0

    mov     x16, 16384
    movk    x16, 0x1, lsl 32
    ldr     x16, [x16, #24]

    #adrp   x16, HowGOTLabel
    #ldr        x16, [x16, #24]
    br      x16

    mov X0, #0
    mov X16, #1
    svc 0

hello: .ascii  "Hello\n"

.section __DATA_CONST,__got
.align 3
HowGOTLabel:
    .word 0
    .word 0x80100000
    .word 1
    .word 0x80100000
    .word 2
    .word 0x80100000
    .word 3
    .word 0x80000000
Stan
  • 161
  • 8
  • 1
    Focus at one problem at a time. Default Linux GNU assembler will have different syntax compared to `clang` on Apple ecosystem so this would affect your cross compiling. You probably should go for `clang` for Linux/Apple portability. You are trying to invoke a kernel `syscall` not a function in dynamic library. Start here: https://stackoverflow.com/questions/56985859/ios-arm64-syscalls https://github.com/below/HelloSilicon https://stackoverflow.com/questions/41906688/what-are-the-semantics-of-adrp-and-adrl-instructions-in-arm-assembly Use `svc 0x80` on Apple, instead of `svc 0` from *nix. – Kamil.S Dec 04 '22 at 08:57
  • @Kamil.S that part I figured out days ago – Stan Dec 04 '22 at 14:19

1 Answers1

1

Darwin on arm64 forces all userland binaries to use ASLR, so you cannot use movz/movk for PC-relative addresses.

The reason why your adrp doesn't work is because it can only refer to 0x1000-byte aligned locations. For more granular targeting you'd use adr, but there you have the issue of being limited to ±1MB of the instruction. For Linux targets, the compiler seems to be more lenient here, but for Darwin targets, adr can only really be used for locations within the same section, and you're trying to refer to __DATA_CONST.__got from __TEXT.__text.

So how can you fix this? You use @PAGE and @PAGEOFF:

adrp x16, HowGOTLabel@PAGE
add x16, x16, HowGOTLabel@PAGEOFF

You can even have this be fixed up to adr+nop at link-time if the target is in range, with some asm directives:

Lloh0:
    adrp x16, HowGOTLabel@PAGE
Lloh1:
    add x16, x16, HowGOTLabel@PAGEOFF
.loh AdrpAdd Lloh0, Lloh1

You can also do this with AdrpLdr if the second instruction is ldr rather than add.

But once you fix that, you've got two other issues in your code:

  1. You use br x16. This means you won't return to the callsite. Use blr for function calls.

  2. You don't actually have any imports? It's not clear how you think this would end up calling library functions, but really you can just do it like this:

    bl _printf
    

    And the compiler and linker will take care of imports.

Siguza
  • 21,155
  • 6
  • 52
  • 89
  • Thank you. I posted another question. This is proving to be difficult and I think I should stick to service calls until I can read the mach-o format and figure out why my binary is different https://stackoverflow.com/questions/74678466/call-shared-function-from-assembly-arm-mac – Stan Dec 04 '22 at 16:18