Using makefile, LD_PRELOAD to executable file - c

I have two files, "abc.c" and "run"
and I want to make a executable binary file which perform below two intstructions
gcc -m32 -O2 -Wall -DRUNTIME -shared -fPIC -o a.so abc.c -ldl
LD_PRELOAD="a.so" ./run
I tried to use makefile in linux, but failed.
Can I use makefile to make executable binary file ?

Ideally, makefile should be used for compilation. For automating the shell commands, you can use a shell script.
Maybe, in your case, you can write a shell script, which will call the make -f <SomeMakeFile> command first to compile and generate the library (.so) and then run the target binary with alogwith the LD_PRELOAD instruction.

I'd do it like this:
all: a.so
test: a.so
LD_PRELOAD="a.so" ./run
a.so: abc.c
gcc -m32 -O2 -Wall -DRUNTIME -shared -fPIC -o a.so abc.c -ldl
clean:
rm -f a.so
Save this in a file called Makefile. Note that the indentations MUST be a single tab - stackoverflow ruined that in their output above.
There are now 4 targets, calling just make will generate the shared library, explicitly calling make test will run your test. If needed, make test will build the library first.
I was tempted to throw in some more flexibility, but that was not what you asked for...

Related

CMake compile NASM and C and link everything together

I'm trying to compile assembly files with NASM and C files with GCC and link all object files together. Moreover, I'd like the C preprocessor to process the assembly files as well. This is normally no problem from the command line or a simple makefile, but I've had some trouble in replicating this functionality in CMake.
The exact process, assuming three files (boot.S, kernel.c, link.ld) would look something like this:
gcc -E -P boot.S -D <...> -o boot.s
nasm -f elf32 boot.s -o boot.o
gcc -c kernel.c -o kernel.o -ffreestanding -O2 -Wall -Wextra
Now its time to link. I want to do this like this (maybe with a few extra flags):
gcc -T link.ld -o out.bin -ffreestanding -O2 -nostdlib boot.o kernel.o -lgcc
The problems with CMake are the following:
Cmake support for NASM is weird at best. When adding .S files as sources to targets they don't get recognized as assembly files and I get hit with 'cannot determine linker language for target'. I have tried adding 's S' to CMAKE_ASM_NASM_SOURCE_FILE_EXTENSIONS but it still doesn't work unless I manually set the languages with set_source_files_properties(). Moreover, as is pointed out here, CMAKE_ASM_NASM_LINK_EXECUTABLE is broken.
As far as I understand, after compiling source files to objects, CMake attempts to link them automatically. Which linker will it use to link all .o files? Will it use the linker for C? Will it use the linker for NASM? The answer is relevant, because I need to configure it with the flags I mentioned above.
What would an example CMakeLists.txt would look like that replicates the previously mentioned process? Also do I need a create_custom_command() in order to invoke just the preprocessor? Thank you.

Use of -g and -o options in gcc command in c programming

Suppose there are 2 c program named abc.c and xyz.c . Now we want to work with the 2 executables at a time. So we change the name of the ./a.out using
gcc -g abc.c -o abc
gcc -g xyz.c -o xyz
Even gcc -o abc abc.c works.
What does the -g and -o in the above commands specify or describe?
What is the significance of -g and -o in the command for renaming ./a.out file.
Thanks in advance.
-g means to leave debugging information in the output file, it's unrelated to renaming.
-o means to put the result in the specified file instead of the default filename (abc.o for object files, a.out for linked executable files).
From https://gcc.gnu.org/onlinedocs/gcc/Option-Summary.html:
-g
Produce debugging information in the operating system's native format (stabs, COFF, XCOFF, or DWARF). GDB can work with this debugging information.
-o file
Place output in file file. This applies to whatever sort of output is being produced, whether it be an executable file, an object file, an assembler file or preprocessed C code.
-g starts becoming useful once you use debuggers such as gdb and lldb. When you attach to a running program and advancing one line at a time printing/altering the state as it changes.
if we specify -g option while compiling, debugging symbols will be available in the output file which will be useful when you try to debug using GDB.
If we won't specify -o option, the output will be placed in default a.out file. So if we run
gcc a.c - output will be in a.out
gcc b.c - output is a.out which is replacing old a.out file
If you want the output not to be a.out file, you can give -o option while compiling
gcc abc.c -o a
-o and -g options are not related.

How to compile an executable using clang and safe-stack flag

I am trying to compile a simple hello-world executable using clang-3.7 (also tried 3.8 (dev)) with -fsanitize=safe-stack flag. As explained here (http://clang.llvm.org/docs/SafeStack.html), I need to pass this flag to compiler and linker.
"To enable SafeStack, just pass -fsanitize=safe-stack flag to both compile and link command lines."
I tried the following command to compile an executable:
clang-3.7 -fsanitize=safe-stack -o a.out -Wl,-fsanitize=safe-stack test.c
But the linker tells me, that i need to compile it as a shared library (-shared), if I pass the -f flag to the linker.
/usr/bin/ld: -f may not be used without -shared
How can I compile an executable using the -fsanitize=safe-stack flag?
By "pass it to both the compile and link command lines" the documentation means to pass it both when you're compiling, and when you're linking. It does not mean to use -Wl, which passes it straight through to the linker - -f means something entirely unrelated to the linker.
In this case,
clang-3.7 -fsanitize=safe-stack -o a.out test.c
is sufficient. If you were using separate command executions to compile and link, you would need to pass it on both:
clang-3.7 -fsanitize=safe-stack -c -o test.o test.c
clang-3.7 -fsanitize=safe-stack -o a.out test.o

Fatal error: modbus.h: No such file or directory

I'm expecting a lot of difficulties to make my program working with the library libmodbus on Linux.
I've installed libmodbus with the command sudo make install and after make but the problem is when I want to link the library in my C program.
My Makefile for now is like:
all: test
test: main.o com.o
gcc main.o com.o -o test
main.o: main.c
gcc -c main.c -o main.o
com.o: com.c
gcc -c com.c -Wl,-rpath=/usr/local/lib -Wl,LIBDIR -o com.o
clean:
rm -rf *o test
In my file com.c I include the file modbus.h like this:
#include <modbus.h>
And I always get the error:
fatal error: modbus.h: No such file or directory.
If it can help when I did make install, the code return me this:
If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the '-LLIBDIR'
flag during linking and do at least one of the following:
add LIBDIR to the `LD_LIBRARY_PATH' environment variable during execution
add LIBDIR to the `LD_RUN_PATH' environment variable during linking
use the `-Wl,-rpath -Wl,LIBDIR' linker flag
have your system administrator add LIBDIR to `/etc/ld.so.conf'
It seems like the modbus.h is not in the standard include directory.
You should to add the -I/<includes_path> flag to gcc options.
I suppose here:
gcc -I/<include_dir_path> -c com.c -Wl,-rpath=/usr/local/lib -Wl,LIBDIR -o com.o

Can't load dll in linux gcc

I'm trying to compile my code with a DLL i made and I get the error below when i write ./prog
./prog: error while loading shared libraries: libctest.so.1: cannot open shared object file: No such file or directory
I followed the tutorial here and my mono app has no problem loading the dll and calling the functions. The key parts of the tutorial were
gcc -Wall -fPIC -c *.c
gcc -shared -Wl,-soname,libctest.so.1 -o libctest.so.1.0 *.o
mv libctest.so.1.0 /opt/lib
ln -sf /opt/lib/libctest.so.1.0 /opt/lib/libctest.so.1
ln -sf /opt/lib/libctest.so.1.0 /opt/lib/libctest.so
My C# code does
[DllImport("path/to/CDLL", CallingConvention = CallingConvention.Cdecl)]
public static extern void test();
I built with
gcc -Wall -L/opt/lib main.c -lctest -o prog
This is the first thing i changed. prog.c to main.c. From there I simply run with ./prog to get the error at the top of this question. I do this as root so there shouldn't be permission issues. I also chmod 755 the so's. What am I doing wrong? This is opensuse. I had to create the /opt/lib so I am thinking this path isn't registered where it should be
The dynamic linker ld.so will not look in /opt/lib by default when attempting to resolve library dependencies. You have to tell the linker about the non-standard library directories or add the /opt/lib path to your prog binary.
eg
LD_LIBRARY_PATH=/opt/lib ./prog
or, link prog with the -rpath linker option. This provides an additional path for the linker to search when resolving locations of shared objects.
gcc -Wall -L/opt/lib -Wl,-rpath,/opt/lib main.c -lctest -o prog
You can use the ldd command on a binary to show the locations of shared libraries.
ldd prog
This will currently show that libctest.so cannot be found. With an additional search path, the following command should show that all libraries are resolved:
LD_LIBRARY_PATH=/opt/lib ldd prog

Resources