I'm on MacOS (Apple Silicon M4 processor, so, ARM64), and when trying to use puts
from the standard C library:
.global main // 1
main: // 2
stp x21, x30, [sp, -16]! // push onto stack // 3
mov x21, x1 // argc -> x0, argv -> x1 // 4
// 5
top: // 6
ldr x0, [x21], 8 // argv++, old value in x0 // 7
cbz x0, bottom // if *argv == NULL goto bottom // 8
bl puts // puts(*argv) // 9
b top // goto top // 10
// 11
bottom: // 12
ldp x21, x30, [sp], 16 // pop from stack // 13
mov x0, xzr // return 0 // 14
ret // 15
// 16
.end
It fails, and returns:
~/ clang -lc -arch arm64 test2.s -e main
Undefined symbols for architecture arm64:
"puts", referenced from:
main in test2-8965bb.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I have tried with the addition of the -lSystem
flag, doesn't work, instead just returns a ld: warning: ignoring duplicate libraries: '-lSystem'
warning.
Not sure what I did wrong, making it that I can't use libc
(just in case, I have tried this:
#include <stdio.h>
int main(){
puts("Hello, World!");
return 0;
}
Whos assembly equivalent is:
.section __TEXT,__text,regular,pure_instructions
.build_version macos, 15, 0 sdk_version 15, 2
.globl _main ; -- Begin function main
.p2align 2
_main: ; @main
.cfi_startproc
; %bb.0:
sub sp, sp, #32
stp x29, x30, [sp, #16] ; 16-byte Folded Spill
add x29, sp, #16
.cfi_def_cfa w29, 16
.cfi_offset w30, -8
.cfi_offset w29, -16
mov w8, #0 ; =0x0
str w8, [sp, #8] ; 4-byte Folded Spill
stur wzr, [x29, #-4]
adrp x0, l_.str@PAGE
add x0, x0, l_.str@PAGEOFF
bl _puts
ldr w0, [sp, #8] ; 4-byte Folded Reload
ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
add sp, sp, #32
ret
.cfi_endproc
; -- End function
.section __TEXT,__cstring,cstring_literals
l_.str: ; @.str
.asciz "Hello, World!"
.subsections_via_symbols
Which works just fine!)
Some help would be appreciated!
As @Shawn and @fuz mentioned, adding a prefixing _
is required for all C code built for the macOS ABI.
Therefore, the corrected code would become:
.global main // 1
main: // 2
stp x21, x30, [sp, -16]! // push onto stack // 3
mov x21, x1 // argc -> x0, argv -> x1 // 4
// 5
top: // 6
ldr x0, [x21], 8 // argv++, old value in x0 // 7
cbz x0, bottom // if *argv == NULL goto bottom // 8
bl _puts // note that there is a `_` // 9
b top // goto top // 10
// 11
bottom: // 12
ldp x21, x30, [sp], 16 // pop from stack // 13
mov x0, xzr // return 0 // 14
ret // 15
// 16
.end
Fixed part:
bl _puts // with the addition of the leading `_`