gdb and valgrind within a makefile - c

I have a very basic question. I did look around like over here http://www.cs.cmu.edu/~gilpin/tutorial/ but still doubtfull..
Consider the following makefile(had also given it in a previous question)
all: clients.so simulator backup
LD_PRELOAD=/home/Juggler/client/clients.so ./simulator
backup: backup.c libclient.a
gcc backup.c -o backup -L /home/Juggler/client -L. -lclient -ldl
simulator: simulator.c libclient.a
gcc -g simulator.c -o simulator -L /home/Juggler/client -L. -lclient -ldl -pthread
libclient.a: libclient.o client.o
ar rcs libclient.a libclient.o client.o
libclient.o:libclient.c
gcc -c libclient.c -o libclient.o -pthread
clients.so: client.o client_invoke.o
ld -shared -o clients.so client_invoke.o client.o -ldl
client_invoke.o: client_invoke.c
gcc -Wall -fPIC -DPIC -c -g client_invoke.c
client.o: client.c
gcc -Wall -fPIC -DPIC -c -g client.c -ldl -pthread
What do I do/change to debug using either gdb or valgrind. Actually I am getting a segmentation fault while doing make and would like to debug. But I have never used gdb or valgrind from within a makefile
Thanks

I made a small edit to your presentation. You originally wrote
client.o: client.c gcc -Wall -fPIC -DPIC -c -g client.c -ldl -pthread
Can you change it to the new form and see if make segfaults?

normally I would do something to the effect of:
$(DEBUGGER) ./simulator
then
$ make DEBUGGER=gdb --args
$ make DEBUGGER=valgrind
$ make # should still work without the debugger.
(technically the --args isn't needed for the command like it is, but if you add arguments to simulator in the future.)
but using LD_PRELOAD complicates this, because you probably don't want gdb loading libclient
gdb -ex 'set env LD_PRELOAD=/home/Juggler/client/clients.so' -ex 'run' ./simulator
Additionally its normal to link shared libraries through gcc via gcc -shared -o client.so

One inelegant way would be to spawn the process via the makefile, and then attach to it with GDB in another terminal. Using the trick from linux: suspend process at startup, you can launch the process and have it suspend immediately, and then connect with gdb.
have a script called launch.sh:
#!/bin/bash
echo "Pid is $$"
echo -n "Press Enter.."
read
exec $#
have a makefile recipe like this:
whatever_target: whatever_deps
./launch.sh PROGRAM [ARGS]
if for some reason you can't see the output (like if you are redirecting), you can still get the PID via ps -ef or something. then with gdb:
gdb PROGRAM_NAME PID

Related

How to create command in bash to compile multiple C program with multiple flags

So my file structure is basically this -
I have a .zshrc file since I'm on OS X
I have a .my_custom_commands.sh file which contains the shortcuts I want
In my .zshrc I source the commands file
Currently, I'm looking for a solution to compile multiple files with flags using the "gcc" command
For example, if I want to compile a.c and b.c
gcc -Wall -Werror -ansi -pedantic -o output.c a.c b.c
However, I don't want to type this out every time, so I was thinking there would be a way to create a custom command say 'gccf' (gcc flags). The thing is that I don't know zsh programming language so I'm just wondering if there is a way to pass multiple args into the function I created in the commands file.
I have something like this right now
function gccf() {
gcc -Wall -Werror -ansi -pedantic -o output.c $1 $2
}
I understand that the args you pass into the command line are represented by $1, $2..., but is there anyway to check how many args have been passed? Because if $2 isn't passed then this won't work I think.
Set CFLAGS as you want and just use the default rules for make. You don't even need a makefile:
$ rm -f Makefile
$ ls a.c
a.c
$ make a
cc a.c -o a
$ rm -f a.o a
$ export CFLAGS=-pedantic
$ make a
cc -pedantic a.c -o a
If you have multiple source files, you'll need a (trivial) makefile:
$ rm -f a *.o output Makefile
$ unset CFLAGS
$ make a
cc a.c -o a
$ export CFLAGS='-Wall -Werror -ansi -pedantic'
$ rm a; make a
cc -Wall -Werror -ansi -pedantic a.c -o a
$ printf 'output: a.o b.o\n\t$(CC) $(LDFLAGS) $^ -o $# $(LDLIBS)\n' > Makefile
$ make output
cc -Wall -Werror -ansi -pedantic -c -o a.o a.c
cc -Wall -Werror -ansi -pedantic -c -o b.o b.c
cc a.o b.o -o output
$ rm -rf *.o output
$ export CC=gcc LDLIBS=-lm
$ make output
gcc -Wall -Werror -ansi -pedantic -c -o a.o a.c
gcc -Wall -Werror -ansi -pedantic -c -o b.o b.c
gcc a.o b.o -o output -lm
In other words, don't try to reinvent the wheel. Your use case has been encountered by many people, and there are long standing conventions and tools in place to enable the work flow.
Note that you may want to include LOADLIBES along with LDLIBS, but the former name should (probably?) no longer be used.
In Bourne-heritage shells (e.g. sh, zsh, bash, ksh), to specify all arguments passed to a program or function, use "$#" (including the double quotes!), which expands to any number of args passed, including none.
But if you follow the Unix philosophy of using the one tool that does just one thing, you want to look at make as suggested in comments and other answers.
PS: you also want -o output, not -o output.c, since your program is not a C source file, but an executable.

Compiling C code in Linux terminal

I am using Linux mint 16. I had a code that I change it a bit.
I use two following commands in terminal in order to run the code. The problem is that it does not give me any error but the changes are not applied, which means it runs the previous version of code.
gcc -std=c99 -c Code.c -o Code.o
./Code
gcc -std=c99 -c Code.c -o Code.o will put the compiled object file in Code.o, not ./Code as you expect it to be..
Also, -c tells do not run the linker. So effectively you end up with an object file which cannot be run.
gcc -std=c99 Code.c -o Code will produce what you need.
For a complete list of gcc flags either use man gcc or see http://linux.die.net/man/1/gcc
Try
gcc -std=c99 -c Code.c -o Code
./Code

Running gcc's steps manually, compiling, assembling, linking

If you have a simple C program, like
int main(void) {return 0;}
It can be compiled with gcc -o test test.c.
As I understand, gcc performs compiling, assembling then linking. The latter two steps are achieved by it running as and ld.
I can generate the assembly code by using gcc -S test.c.
What would you type into a terminal, to convert the assembly code into an executable?
(the reason for doing so is to learn assembly)
These are the different stages using gcc
gcc -E --> Preprocessor, but don't compile
gcc -S --> Compile but don't assemble
gcc -c --> Preprocess, compile, and assemble, but don't link
gcc with no switch will link your object files and generate the executable
// main.c
#include <stdio.h>
int main(void)
{
printf("Hello World !\n");
return 0;
}
For preprocessing, compiling, assembling and then finally linking the simple aforementioned hello world program, follow the steps below:
Step 1/4) Preprocess main.c to generate main.i:
$: gcc -E main.c -o main.i
NOTE: You could call the C preprocessor directly as well:
$: cpp main.c -o main.i
Step 2/4) Compile main.i to generate main.s:
$: gcc -S main.i -o main.s
Step 3/4) Assemble main.s to generate main.o:
$: as main.s -o main.o
NOTE: You can combine the aforementioned steps 1, 2 and 3 by using the -c (small C) flag of gcc:
$: gcc -c main.s -o main.o // OR $: gcc -c main.c -o main.o
Step 4/4) Link main.o with other necessary object files namely, crti.o & crtn.o (they define function prologs & epilogs, respectively), crt1.o (contains _start symbol for bootstrapping the initial execution of the program), libc.so path or -lc flag for libc and then finally set the name of the dynamic linker, to generate a dynamically linked ELF executable:
On x86_64:
$: ld /usr/lib/x86_64-linux-gnu/crti.o /usr/lib/x86_64-linux-gnu/crtn.o /usr/lib/x86_64-linux-gnu/crt1.o -lc main.o -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o main_ELF_executable
OR (if you'd like to specify path to libc.so)
$: ld /usr/lib/x86_64-linux-gnu/crti.o /usr/lib/x86_64-linux-gnu/crtn.o /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/libc.so main.o -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o main_ELF_executable
On 32-bit ARM:
$: ld /usr/lib/arm-linux-gnueabihf/crti.o /usr/lib/arm-linux-gnueabihf/crtn.o /usr/lib/arm-linux-gnueabihf/crt1.o -lc main.o -dynamic-linker /lib/ld-linux.so.3 -o main_ELF_executable
OR (if you'd like to specify path to libc.so)
$: ld /usr/lib/arm-linux-gnueabihf/crti.o /usr/lib/arm-linux-gnueabihf/crtn.o /usr/lib/arm-linux-gnueabihf/crt1.o /usr/lib/arm-linux-gnueabihf/libc.so main.o -dynamic-linker /lib/ld-linux-armhf.so.3 -o main_ELF_executable
You can then run the ELF executable 'main_ELF_executable':
$: ./main_ELF_executable
Hello World !
Sources:
https://linux.die.net/man/1/gcc
https://linux.die.net/man/1/ld
https://dev.gentoo.org/~vapier/crt.txt
gcc test.s -o test will compile the test from test.s for you.
NASM might also be worth your time -- it might be easier / more friendly than gcc for compiling assembly.
After you do gcc -S -o test.s test.c, type gcc -o test test.s.
As you may or may not know, the four stages of compilation are to preprocess (-E), compile to assembly (-S), assemble to object code (-c), and finally link. The hardest for me to figure out was how to use the preprocessor output. Here's how to do it:
gcc -E hello.c | gcc -S -xc -o hello.s -
gcc -c hello.s -o hello.o
gcc hello.o -o hello
You can have gcc start and stop the compilation process wherever you want. gcc test.s -o test will have it compile test.s from assembly into an executable.
what I did was first I run the preprocessor by
clang++ test.cpp -E > test.i
then compiled it with ...
clang++ -S test.i
it should create a assembly file test.s ... then make the machine insturction file by
as test.s -o test.o
now you need to link it which is kinda confusing for dumb peoples like me ...
so we don't know the arguments for our last process which is linking ... to find out ... run
clang++ -v test.s
it should give you some big text of something ... find this line "-dynamic-linker" ... there's definately a -dynamic-linker in your output text ... now copy the text from -dynamic-linker to rest of the output ... just copy everything afterwards including "-dynamic-linker" ... now what i got is ...
-dynamic-linker /system/bin/linker -o a.out /data/data/com.termux/files/usr/lib/gcc/arm-linux-androideabi/11.1.0/../../../../lib/crtbegin_dynamic.o -L/data/data/com.termux/files/usr/lib/gcc/arm-linux-androideabi/11.1.0 -L/data/data/com.termux/files/usr/lib/gcc/arm-linux-androideabi/11.1.0/../../../../lib -L/data/data/com.termux/files/usr/lib/gcc/arm-linux-androideabi/11.1.0/../../.. -L/data/data/com.termux/files/usr/lib -L/system/lib /data/data/com.termux/files/usr/tmp/test-169b42.o -lc++_shared -lgcc -ldl -lm -lc -lgcc -ldl /data/data/com.termux/files/usr/lib/gcc/arm-linux-androideabi/11.1.0/../../../../lib/crtend_android.o
in this what you have to change is where your object file is ... in my case it is /data/data/com.termux/files/usr/tmp/test-169b42.o ... i need to change it to where my test.o file is ... /data/data/com.termux/files/home/CPP/Cpp_Log/hello_world/test.o ... this is where my test.o file is ...
so the argument we have to pass is ...
-dynamic-linker /system/bin/linker -o a.out /data/data/com.termux/files/usr/lib/gcc/arm-linux-androideabi/11.1.0/../../../../lib/crtbegin_dynamic.o -L/data/data/com.termux/files/usr/lib/gcc/arm-linux-androideabi/11.1.0 -L/data/data/com.termux/files/usr/lib/gcc/arm-linux-androideabi/11.1.0/../../../../lib -L/data/data/com.termux/files/usr/lib/gcc/arm-linux-androideabi/11.1.0/../../.. -L/data/data/com.termux/files/usr/lib -L/system/lib /data/data/com.termux/files/home/CPP/Cpp_Log/hello_world/main.o -lc++_shared -lgcc -ldl -lm -lc -lgcc -ldl /data/data/com.termux/files/usr/lib/gcc/arm-linux-androideabi/11.1.0/../../../../lib/crtend_android.o
now to link ... use the ld ... so the command is ld args -o test or in our case ...
ld -dynamic-linker /system/bin/linker -o a.out /data/data/com.termux/files/usr/lib/gcc/arm-linux-androideabi/11.1.0/../../../../lib/crtbegin_dynamic.o -L/data/data/com.termux/files/usr/lib/gcc/arm-linux-androideabi/11.1.0 -L/data/data/com.termux/files/usr/lib/gcc/arm-linux-androideabi/11.1.0/../../../../lib -L/data/data/com.termux/files/usr/lib/gcc/arm-linux-androideabi/11.1.0/../../.. -L/data/data/com.termux/files/usr/lib -L/system/lib /data/data/com.termux/files/home/CPP/Cpp_Log/hello_world/main.o -lc++_shared -lgcc -ldl -lm -lc -lgcc -ldl /data/data/com.termux/files/usr/lib/gcc/arm-linux-androideabi/11.1.0/../../../../lib/crtend_android.o -pie -o test ...
since andriod 5+ can only run pie elf executables ... i also added the "-pie" (position independent executable) before the -o test ...
now it should give you a executable file test ... just run it by ./test
it should work

linking pthread library issue

Am facing a problem that may be slightly complicated to explain and understand as giving the entire picture would be too big and difficult.
Please excuse me for it.
Consider the following Makefile:
all: clients.so simulator backup
LD_PRELOAD=/home/Juggler/client/clients.so ./simulator
backup: backup.c libclient.a
gcc backup.c -o backup -L /home/Juggler/client -L. -lclient -ldl
simulator: simulator.c libclient.a
gcc -g simulator.c -o simulator -L /home/Juggler/client -L. -lclient -ldl -pthread
libclient.a: libclient.o client.o
ar rcs libclient.a libclient.o client.o
libclient.o:libclient.c
gcc -c libclient.c -o libclient.o -pthread
clients.so: client.o client_invoke.o
ld -shared -o clients.so client_invoke.o client.o -ldl
client_invoke.o: client_invoke.c
gcc -Wall -fPIC -DPIC -c -g client_invoke.c
client.o: client.c
gcc -Wall -fPIC -DPIC -c -g client.c -ldl -pthread
We call function written in client.c from libclient.c and these functions in client.c make call to pthread_key_create(), pthread_setspecific..etc.
Threads are created by simulator.c and theses threads access functions written in he other files.
On doing make...Errors like the following appear.
/home/Juggler/client/libclient.a(client.o):In function 'setup_connection':
/home/Juggler/client/client.c:35: undefined reference to 'pthread_setspecific'
pthread.h has been included in both client.c and libclient.c
Would be grateful for anypointers . I understand information is very less...
Thanks
On linux, pthread functions live in the libpthread library. So you have to link to that.
The proper way, when using pthreads, is to compile and link using the -pthread , which, among other things, will link in the pthread library. You have the -pthread flag for some of your executables, but not for others, and not for your clients.so library, so add the flag where required.
Also, remember, when you are creating a shared library, you should compile the source files with the -fPIC flag.
(And, seems you are calling ld directly to produce the client.so library, you really should use gcc to do the linking.)

GCC compiler error on Windows XP

I'm getting a totally bizzare error trying to compile a C program using GCC. Here is the batch file I am using:
echo Now compiling, assembling, and linking the core:
nasm -f aout -o start.o start.asm
gcc -Wall -O -fstrength-reduce -fomit-frame-pointer -finline-functions -nostdinc -fno-builtin -I./include -c -o consoleio.o consoleio.c
gcc -Wall -O -fstrength-reduce -fomit-frame-pointer -finline-functions -nostdinc -fno-builtin -I./include -c -o core.o core.c
gcc -Wall -O -fstrength-reduce -fomit-frame-pointer -finline-functions -nostdinc -fno-builtin -I./include -c -o system.o system.c
ld -T link.ld -o core.bin start.o core.o system.o consoleio.o
echo Done!
concat.py
pause
Here are the error messages I am receiving when trying to run this code. All files are in the same directory, yes the PATH variable is set up correctly:
C:\Simple\core>build.bat
C:\Simple\core>echo Now compiling, assembling, and linking the core:
Now compiling, assembling, and linking the core:
C:\Simple\core>nasm -f aout -o start.o start.asm
C:\Simple\core>gcc -Wall -O -fstrength-reduce -fomit-frame-pointer -finline-func
tions -nostdinc -fno-builtin -I./include -c -o consoleio.o consoleio.c
The system cannot execute the specified program.
C:\Simple\core>gcc -Wall -O -fstrength-reduce -fomit-frame-pointer -finline-func
tions -nostdinc -fno-builtin -I./include -c -o core.o core.c
C:\Simple\core>gcc -Wall -O -fstrength-reduce -fomit-frame-pointer -finline-func
tions -nostdinc -fno-builtin -I./include -c -o system.o system.c
The system cannot execute the specified program.
C:\Simple\core>ld -T link.ld -o core.bin start.o core.o system.o consoleio.o
c:/djgpp/bin/ld.exe: system.o: No such file: No such file or directory (ENOENT)
C:\Simple\core>echo Done!
Done!
C:\Simple\core>concat.py
Traceback (most recent call last):
File "C:\Simple\core\concat.py", line 12, in <module>
with open("core.bin", "rb") as core:
IOError: [Errno 2] No such file or directory: 'core.bin'
Now, the interesting thing is the gcc command, which is the issue I'm having. (The other issues seem to be cascading from this.) When compiling core.c, the GCC command works just fine and great, and produces a .o file as expected. When attempting to compile system.c or consoleio.c, GCC fails, but in a very unexpected way: it appears as though windows cannot run the program. This makes zero sense to me. I've tried any number of things, including running these commands myself outside the window. Something about core.c is just special, and I can't figure out what the difference is. I literally copied that line and changed the filenames to create the other two lines that are failing.
So, in short, HELP. I'm using DJGPP and GCC on windows XP, along with a python script at the end that should tie everything together. (This all worked when the project was a single source file, but attempting to split the file into separate files has caused this strange error.)
Thanks.
PS: Yes, we are using a batch file, and I know that makes some of you cringe. However, I'd really like to understand this error before moving on to a makefile if possible. ^_^
EDIT: The accepted answer was indeed our problem, although the issue was with DJGPP, not Windows. (Windows doesn't seem to have a command limit.) The solution was to compile with MinGW instead of DJGPP, which fixed the issue right away. Thanks guys!
The line that works is 126 characters long, the others are 130 and 136 characters long. The problem is that there is a 127-character limit. I'm not sure how to get around this, but maybe make would get around it for you?...
Add -v to the gcc command line. gcc is in fact a driver, which runs several other auxiliary programs (tradicionally, the preprocessor, compiler, and assembler); -v makes it show their command lines as they are being executed, and also enables verbose mode. With this, you can see where it is failing.
As mentioned, DJGPP make (or Bash) or even a simple response file would solve this problem, so it's a non-issue. DJGPP is still plenty good as long for what it does. (P.S. Also see the ELF port or Japheth's HX mod.)

Resources