How to link multiple mach-o files with terminal on MacOS - macos

I created two files: a.c and b.c, they are both *.c file;
Then I use terminal to compile both with command:
gcc -c a.c
gcc -c b.c
I got two mach-o files: a.o and b.o;
So what can I do to link them and generate a linked object file like ab.o ?
I tried the following:
ld a.o b.o -e main -o ab
But it turned me down with the following:
ld: warning: No version-min specified on command line
ld: dynamic main executables must link with libSystem.dylib for inferred architecture x86_64
So what should be done next ?

Just feed them back to gcc:
gcc -o ab a.o b.o
Side note: you might wanna call the resulting file ab.out or ab without suffix, but probably not ab.o, since that usually implies an unlinked object file.

enter image description here
why link a.o and b.o to ab ,but a.o and b.o text size is not ab.o text size
0000005c != 0000002e + 0000002c

Related

Making relocatable object with gcc causes "cannot find -lgcc_s" error

I'm trying to make a relocatable object file with gcc. I use solution from this post. The solution works fine with ld:
$ ld -r a.o b.o -o c.o
However when I try to use it with gcc, the following error happens:
$ gcc -r a.o b.o -o c.o
/usr/bin/ld: cannot find -lgcc_s
/usr/bin/ld: cannot find -lgcc_s
collect2: ld returned 1 exit status
Using the -Wl,-r and -Wl,--relocatable options gives the same result.
Is there any way to link relocatable object file with gcc or I'm forced to use ld for doing this?
To solve this problem, the -nostdlib option must also be passed to gcc:
$ gcc -r -nostdlib a.o b.o -o c.o
I don't know it for sure, but it seems without this option gcc tries to link standard libraries into output relocatable object.

linker option to ignore unused dependencies

I would like to remove all unused symbols from my compiled C++ binary. I saw this, which gives an overview using gcc, which is the toolchain I'm using: How to remove unused C/C++ symbols with GCC and ld?
However, on my system, the linking option (-Wl,--gc-sections) is rejected:
$ gcc -fdata-sections -ffunction-sections a.c -o a.o -Wl,--gc-sections
ld: fatal: unrecognized option '--'
ld: fatal: use the -z help option for usage information
collect2: error: ld returned 1 exit status
I'm running on illumos, which is a (relatively) recent fork of Solaris, with GCC 4.7. Anybody know what the correct linker option to use here is?
Edit: searching the man pages more closely turned up "-zignore":
-z ignore | record
Ignores, or records, dynamic dependencies that are not
referenced as part of the link-edit. Ignores, or
records, unreferenced ELF sections from the relocatable
objects that are read as part of the link-edit. By
default, -z record is in effect.
If an ELF section is ignored, the section is eliminated
from the output file being generated. A section is
ignored when three conditions are true. The eliminated
section must contribute to an allocatable segment. The
eliminated section must provide no global symbols. No
other section from any object that contributes to the
link-edit, must reference an eliminated section.
However the following sequence still puts FUNCTION_SHOULD_BE_REMOVED in the ELF section .text.FUNCTION:
$ cat a.c
int main() {
return 0;
}
$ cat b.c
int FUNCTION_SHOULD_BE_REMOVED() {
return 0;
}
$ gcc -fdata-sections -ffunction-sections -c a.c -Wl,-zignore
$ gcc -fdata-sections -ffunction-sections -c b.c -Wl,-zignore
$ gcc -fdata-sections -ffunction-sections a.o b.o -Wl,-zignore
$ elfdump -s a.out # I removed a lot of output for brevity
Symbol Table Section: .dynsym
[2] 0x08050e72 0x0000000a FUNC GLOB D 1 .text.FUNCTION FUNCTION_SHOULD_BE_REMOVED
Symbol Table Section: .symtab
[71] 0x08050e72 0x0000000a FUNC GLOB D 0 .text.FUNCTION FUNCTION_SHOULD_BE_REMOVED
Because the man pages say "no global symbols", I tried making the function "static" and that had the same end result.
The ld '-z ignore' option is positional, it applies to those input objects which occur after it on the command line. The example you gave:
gcc a.o b.o -Wl,-zignore
Applies the option to no objects -- so nothing is done.
gcc -Wl,-zignore a.o b.o
Should work

Creating shared object from static library whose object files were linked with -fPIC

For a project we are trying to create a shared object file that exports a set of functions specified in libname.exports. Of course we know that the object files from which the .so file gets linked have to be created using -fPIC, so that has been taken care of. We then combined the object files into an archive named libname.a. This should now be the basis for the .so file to be created - or so was the idea.
We're passing libname.exports to --retain-symbols-file, so the expected behavior was that the linker would pull in any of the .a members relevant to those symbols.
However, the output of nm libname.so is empty. On the other hand grepping in nm libname.a shows that the relevant symbols named in libname.exports exist in the .a members.
Now I stumbled over --whole-archive and thus adjusted the command line from:
gcc -o libname.so -shared -Wl,-z,defs,--retain-symbols-file,libname.exports,-L. libname.a -lc
to:
gcc -o libname.so -shared -Wl,-z,defs,--retain-symbols-file,libname.exports,-L.,--whole-archive,libname.a,--no-whole-archive -lc
which appears to have the intended effect of including all the object files from the .a (although the size difference is strange). However, nm libname.so still gives me no output.
How can I use the archive file to create a shared object with only the symbols named in libname.exports visible?
Unfortunately How to create a shared object file from static library doesn't quite answer my question.
Note: before you ask. The idea behind using the .a file as input is because it makes it easy to use a pattern rule in GNUmakefile and because the .a file with -fPIC is needed regardless. There shouldn't be any difference between linking the individual object files versus the archive file.
You could use the -u SYMBOL option to force objects to be read in from an archive.
% cc -c -fPIC a.c
% nm a.o
00000000 T a
% ar rv liba.a a.o
ar: creating liba.a
a - a.o
% gcc -o liba.so -shared -u a liba.a
% nm liba.so | awk '$3 == "a" { print }'
0000042c T a
One thing to check would be the spellings of the symbols being specified with --retain-symbols-file. For example, symbol names in objects compiled from C++ code are likely to be mangled:
% g++ -c -fPIC a.c
% nm a.o | awk '$2 == "T" { print }'
00000000 T _Z1av

combine two GCC compiled .o object files into a third .o file

How does one combine two GCC compiled .o object files into a third .o file?
$ gcc -c a.c -o a.o
$ gcc -c b.c -o b.o
$ ??? a.o b.o -o c.o
$ gcc c.o other.o -o executable
If you have access to the source files the -combine GCC flag will merge the source files before compilation:
$ gcc -c -combine a.c b.c -o c.o
However this only works for source files, and GCC does not accept .o files as input for this command.
Normally, linking .o files does not work properly, as you cannot use the output of the linker as input for it. The result is a shared library and is not linked statically into the resulting executable.
$ gcc -shared a.o b.o -o c.o
$ gcc c.o other.o -o executable
$ ./executable
./executable: error while loading shared libraries: c.o: cannot open shared object file: No such file or directory
$ file c.o
c.o: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, not stripped
$ file a.o
a.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
Passing -relocatable or -r to ld will create an object that is suitable as input of ld.
$ ld -relocatable a.o b.o -o c.o
$ gcc c.o other.o -o executable
$ ./executable
The generated file is of the same type as the original .o files.
$ file a.o
a.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
$ file c.o
c.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
For an in-depth explanation see MaskRay's Relocatable linking article.
If you want to create an archive of two or more .o files (i.e.. a static library) use the ar command:
ar rvs mylib.a file1.o file2.o

is it possible to create an object file from other object files in gcc?

I was trying to do something like this in a makefile:
program.exe: ui.o main.o
gcc ......etc
ui.o: window1.o window2.o
gcc -c window1.o window2.o -o ui.o #this doesn't want to work
window1.o: window1.c window1.h window1_events.c window1_controls.c ...
gcc -c window1.c window1_events.c window1_controls.c... -o window1.o
window2.o: ...
gcc ...
main.o: ...
gcc ...
but when I compile like this, it gives the error "input file unused because linking not done," and then I get a bunch of unresolved externs, etc--problems which are resolved by changing
program.exe: ui.o main.o
gcc ...
to
program.exe: window1.o window2.o main.o
gcc ...
so is it possible to just link object files together, to avoid having mile-long lines in a makefile and break down the build process a little more?
Yes: to merge several object files into one, use ld -r or ld -Ur:
From "man ld" on Linux:
-r
--relocatable
Generate relocatable output---i.e., generate an output file that can
in turn serve as input to ld. This is often called partial linking.
As a side effect, in environments that support standard Unix magic
numbers, this option also sets the output file’s magic number to
"OMAGIC".
If this option is not specified, an absolute file is produced.
When linking C++ programs, this option will not resolve references to
constructors; to do that, use -Ur.
You could also do this with gcc:
gcc -Wl,-r foo.o bar.o -o foobar.o -nostdlib
Merging object files like this has some advantages over using an archive library: if merged files change very infrequently (compared to say main.c), your final executable links will be faster.
OTOH, with archived library, the linker will only use what it needs, so your executable may end up being smaller if e.g. window2.c ends up not being necessary.
I bunch of object files is a library. You can create a library with the ar
utility. The following example creates a library called mylib.a containing the files foo.o and bar.o
ar rvs mylib.a foo.o bar.o
You can then link with it by using it on the compiler command line:
gcc -o myexe main.c mylib.a
To create a library:
ar rvs somelib.a file1.o file2.o file3.o
To link it:
gcc -o program.exe file4.o somelib.a

Resources