Compile assembler in nasm on mac os - macos

So, i write some instruction on asm, and compile them.
nasm -f macho test.asm
Now, nasm generate obj file, test.o
gcc test.o
Returned next error:
ld: warning: ignoring file test.o, file was built for unsupported file
format which is not the architecture being linked (x86_64)
Undefined
symbols for architecture x86_64: "_main", referenced from:
start in crt1.10.6.o ld: symbol(s) not found for architecture x86_64 collect2: ld returned 1 exit status
in gcc line, i used -arch i386 (x86_64), returned same error.
Can anybody help? :)

These commands work for me (OS X 10.12 x64):
nasm -f macho test.asm -DDARWIN
ld -o test test.o -arch i386 -lc -no_pie -macosx_version_min 10.12 -lSystem

macho is a 32 bit format.
Try to use macho64 instead of macho. Complete line:
nasm -f macho64 test.asm

Try to update your nasm version and use the following command:
/usr/local/bin/nasm -f macho64 ${file}
ld -o ${file_path}/${file_base_name} -e _main ${file_path}/${file_base_name}.o
${file_path}/${file_base_name}

Related

How to modify makefile for openMP inclusion

HI everybody I am a beginner for both openMP and makefile. Here is my problem.
I usually compile simple openMP code via terminale using:
g++-10 -o file.exe -fopenmp file.cxx
Now I want to modify a code, which consists in many file linked together, adding openMP libraries. Indeed I have to change the already existing makefile and I have no idea how to do it. The openMP libraries are used only in the file "esercizio1.1.cxx".
Here the makefile:
esercizio1.1 : esercizio1.1.o random.o
g++ -o esercizio1.1 esercizio1.1.o random.o
esercizio1.1.o : esercizio1.1.cxx funzioni.h random.h
g++ -c -o esercizio1.1.o esercizio1.1.cxx
random.o : random.cxx random.h
g++ -c -o random.o random.cxx
clean:
rm esercizio1.1
Here an example of how I tried to modify my makefile. I renamed my file and I added
g++-10 -fopenmp
to all the line at the same time, to all the line one per time. but still does not work. Here an example:
esercizio : esercizio.o random.o
g++-10 -fopenmp esercizio.o random.o -o esercizio
esercizio.o : esercizio.cc funzioni.h random.h
g++-10 -fopenmp esercizio.cc -o esercizio.o
random.o : random.cc random.h
g++ random.cc -o random.o
clean:
rm esercizio
Here is the error:
Undefined symbols for architecture x86_64:
"__ZN6Random6RannyuEv", referenced from:
_main._omp_fn.0 in ccA635Wn.o
"__ZN6Random8SaveSeedEv", referenced from:
_main in ccA635Wn.o
"__ZN6Random9SetRandomEPiii", referenced from:
_main in ccA635Wn.o
"__ZN6RandomC1Ev", referenced from:
_main in ccA635Wn.o
"__ZN6RandomD1Ev", referenced from:
_main in ccA635Wn.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
make: *** [esercizio.o] Error 1
Does it exist a guide for makefile beginner?
Anyway I would appreciate if someone helped me. Thanks in advance.
"C++ compilers are picky and may come with different ABIs, thus mixing different C++ compilers in the same project isn't advised. You are compiling random.cc with g++, which on macOS is a symlink to Apple's clang++. Use g++-10 instead. Also, g++ -o random.o random.cc produces an executable file, not an object file. Leave it as g++-10 -c -o random.o random.cc."
credits to Hristo Iliev. Thank you.

How to run manually produce an elf executable using ld?

I'm trying to get my head around how the linking process works when producing an executable. To do that I'm reading Ian Taylor's blog series about it, but a lot of it is beyond me at the moment - so I'd like to see how it works in practice.
At the moment I produce some object files and link them via gcc with:
gcc -m32 -o test.o -c test.c
gcc -m32 -o main.o -c main.c
gcc -m32 -o test main.o test.o
How do I replicate the gcc -m32 -o test main.o test.o stage using ld?
I've tried a very naive: ld -A i386 ./test.o ./main.o
But that returns me these errors:
ld: i386 architecture of input file `./test.o' is incompatible with i386:x86-64 output
ld: i386 architecture of input file `./main.o' is incompatible with i386:x86-64 output
ld: warning: cannot find entry symbol _start; defaulting to 00000000004000b0
./test.o: In function `print_hello':
test.c:(.text+0xd): undefined reference to `_GLOBAL_OFFSET_TABLE_'
test.c:(.text+0x1e): undefined reference to `puts'
./main.o: In function `main':
main.c:(.text+0x15): undefined reference to `_GLOBAL_OFFSET_TABLE_
I'm most confused by _start and _GLOBAL_OFFSET_TABLE_ being missing - what additional info does gcc give to ld to add them?
Here are the files:
main.c
#include "test.h"
void main()
{
print_hello();
}
test.h
void print_hello();
test.c
#include <stdio.h>
void print_hello()
{
puts("Hello, world");
}
#sam : I am not the best people to answer your question because I am a beginner in compilation. I know how to compile programs but I do not really understand all the details (https://en.wikipedia.org/wiki/Compilers:_Principles,_Techniques,_and_Tools)
So, I decided this year to try to understand how compilation works and I tried to do, more or less, the same things as you tried a few days ago. As nobody has answered, I am going to expose what I have done but I hope an expert will supplement my answer.
Short answer : It is recommended to not use ld directly but to use gcc directly instead. Nevertheless, it is, as you write, interesting to know how the linking process works. This command works on my computer :
ld -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -o test test.o main.o /usr/lib/crt1.o /usr/lib/libc.so /usr/lib/crti.o /usr/lib/crtn.o
Very Long answer :
How did I find the command above ?
As n.m suggested, run gcc with -v option.
gcc -v -m32 -o test main.o test.o
... /usr/libexec/gcc/x86_64-redhat-linux/4.8.5/collect2 ... (many
options and parameters)....
If you run ld with these options and parameters (copy and paste), it should work.
Try your command with -m elf_i386 (cf. collect2 parameters)
ld -m elf_i386 test.o main.o
ld: warning: cannot find entry symbol _start; ....
Look for symbol _start in object files used in the full ld command.
readelf -s /usr/lib/crt1.o (or objdump -t)
Symbol table '.symtab' contains 18 entries: Num: Value Size
Type Bind Vis Ndx Name... 11: 00000000 0 FUNC
GLOBAL DEFAULT 2 _start
Add this object to your ld command :ld -m elf_i386 test.o main.o /usr/lib/crt1.o
... undefined reference to `__libc_csu_fini'...
Look for this new reference in object files. It is not so obvious to know which library/object files are used because of -L, -l options and some .so include other libraries. For example, cat /usr/lib/libc.so. But, ld with --trace option helps. Try this commandld --trace ... (collect2 parameters)At the end, you should findld -m elf_i386 -o test test.o main.o /usr/lib/crt1.o /usr/lib/libc_nonshared.a /lib/libc.so.6 /usr/lib/crti.oor shorter (cf. cat /usr/lib/libc.so) ld -m elf_i386 -o test test.o main.o /usr/lib/crt1.o /usr/lib/libc.so /usr/lib/crti.o
It compiles but it does not run (Try to run ./test). It needs the right -dynamic-linker option because it is a dynamically linked ELF executable. (cf collect2 parameters to find it) ld -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -o test test.o main.o /usr/lib/crt1.o /usr/lib/libc.so /usr/lib/crti.o But, it does not run (Segmentation fault (core dumped)) because you need the epilogue of the _init and _fini functions (https://gcc.gnu.org/onlinedocs/gccint/Initialization.html). Add the ctrn.o object. ld -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -o test test.o main.o /usr/lib/crt1.o /usr/lib/libc.so /usr/lib/crti.o /usr/lib/crtn.o./test
Hello, world

How to link a C library to an Assembly library on Mac with clang

I have this in my C library:
myc:
#clang -I . -dynamiclib \
-undefined dynamic_lookup \
-o myc.dylib myc.c
.PHONY: myc
And this in my assembly library:
buildasm:
#nasm -f macho64 myasm.asm
#clang -o myasm myasm.o myc.dylib
# #ld -macosx_version_min 10.13.0 \
# -lSystem -o myasm \
# myasm.o
#./myasm
.PHONY: buildasm
I would like to then have a third either assembly or C project which loads the assembly library. But I can't get this C -> assembly working. I also don't have dyld the "dynamic loader" on Mac installed, so if possible I would prefer not to install any special tools, but if required I would like to know how to do the linking with the tool.
If I make the buildasm into this:
buildasm:
#nasm -f macho64 myasm.asm
#ld -macosx_version_min 10.13.0 \
-lSystem -o myasm \
myasm.o myc.dylib
#./myasm
.PHONY: buildasm
it compiles without any errors, but when it runs with ./myasm it gives:
Undefined symbols for architecture x86_64:
"my_c_function", referenced from:
start in myasm.o
ld: symbol(s) not found for inferred architecture x86_64
If I do this basically in asm:
extern my_c_function
start:
call my_c_function
And something like this in C:
extern void my_c_function() {
}
Wondering what would make this work.

Breaking NASM files into multiple with link errors on OS X

My base assembler file foidlrt.asm started getting a bit too large so I broke it up into two. Here is the entirety of the second file folder_stdio.asm:
; foidl_stdio.asm
%include "foidlstnd.inc"
section .text
DEFAULT REL
global foidl_fclose ; Raw file close
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; foidl_close
; Raw file close
; REGISTERS (1):
; RDI file handle
; CALLS:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
foidl_fclose:
mov rax,SYSCALL_FILE_CLOSE ; 0x2000006
syscall
ret
However, now when I build I am now getting this error from make despite the global declaration in the new file:
nasm src/foidlrt.asm -f macho64 --prefix _ -g -O0 -Iincludes/ -o asmobjs/foildrt.o
nasm src/foidlrt.asm -f macho64 --prefix _ -g -O0 -Iincludes/ -o asmobjs/foidl_stdio.o
libtool -static -s -o libs/libfoidlrt.a asmobjs/foildrt.o asmobjs/foidl_stdio.o
gcc src/testlink.c -L libs -l foidlrt -Wall -g -L. -Wl,-pie -I. -o bin/testlink
Undefined symbols for architecture x86_64:
"_foidl_fclose", referenced from:
_main in testlink-4b5ad3.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Version information:
XCode - 7.2.1 (7C1002)
nasm - NASM version 2.12 compiled on Feb 28 2016
gcc - Apple LLVM version 7.0.2 (clang-700.1.81)
RESOLVED
Error was all mine, makefile rule was bad. Working as expected now.

How to link compiled object file (hello.o) with ld on Mac OS X?

I got a problem with link objective files on a Mac OS X. Tracing back the problem is,
here is my C hello world program
#include <stdio.h>
int main(){
printf("Hello, world!\n");
return 0;
}
//Compile with gcc (clang LLVM compiler on mac)
$ gcc -c hello.c
The output file is hello.o
link with gcc and run the executable is
$ gcc hello.o -o hello
$ ./hello
Now, I have to use the mac linker program ld or Ld to link the the objective files instead of gcc. In this case, what arguments should I pass into the ld program in order to get the program run? A simple pass in the object file name, i.e.
$ ld hello.o
resulting in
ld: warning: -macosx_version_min not specified, assuming 10.6
Undefined symbols for architecture x86_64:
"_printf", referenced from:
_main in hello.o
"start", referenced from:
implicit entry/start for main executable
ld: symbol(s) not found for inferred architecture x86_64
So what other files that i need to include to link or architecture information that I need to specify? Thanks.
For a reference, my complete linker options are
ld -demangle -dynamic -arch x86_64
-macosx_version_min 10.9.0
-o hello
-lSystem /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/5.0/lib/darwin/libclang_rt.osx.a
Okay, I had this question before too. Yes, the reason for the linker errors is because you need to feed it all the magic arguments that gcc does. And the easy way to discover those is to invoke the -v option on gcc to reveal all the commands executed in the compilation stages. In your case, run:
gcc hello.o -o hello -v
...the output of which, on my system, ends with the line:
/usr/libexec/gcc/i686-apple-darwin9/4.2.1/collect2 -dynamic -arch i386 -macosx_version_min 10.5.8 -weak_reference_mismatches non-weak -o test -lcrt1.10.5.o -L/usr/lib/i686-apple-darwin9/4.2.1 -L/usr/lib/gcc/i686-apple-darwin9/4.2.1 -L/usr/lib/gcc/i686-apple-darwin9/4.2.1 -L/usr/lib/gcc/i686-apple-darwin9/4.2.1/../../../i686-apple-darwin9/4.2.1 -L/usr/lib/gcc/i686-apple-darwin9/4.2.1/../../.. test.o -lgcc_s.10.5 -lgcc -lSystem
I don't know what the collect2 program is, but if you feed all those arguments to ld it should work just the same (at least it does on my system).

Resources