1

I am currently learning C with the book "Learn C The Hard Way" and looked into reverse engineering as well. What I want to do is read through the compiler generated assembly for the C programs I have written. I know the option for gcc here is gcc -S -masm=intel file.c.

My question now is: can I automatically have gcc create the .s file and the .out file using the Makefile?

My previous Makefiles always looked like this:

CC=gcc
CLFAGS=-Wall -g

all: file

clean:
    rm -f file

How can I extend my Makefile to make it work?

xbufu
  • 132
  • 8

1 Answers1

2

You could do something like the following:

CC=gcc
CFLAGS=-Wall -Werror -Wextra -O2 -g
SOURCE=file.c

all: binary assembly

binary: $(SOURCE)
    $(CC) $(CFLAGS) $(SOURCE)

assembly: $(SOURCE)
    $(CC) $(CFLAGS) -fverbose-asm -S -masm=intel $(SOURCE)

clean:
    rm -f file.s a.out

And use it like this:

$ make  # same as `make all`
$ make all  # makes both executable (binary) and assembly
$ make binary  # makes binary file only
$ make assembly  # makes assembly only

It seems that you can execute other labels from other labels. However how do they differ from just writing the desired filename like I did?

Remember that Makefiles consist of "rules" with the format:

target: dependencies
    system command(s)

See more here.

The make program decides on what should be done based on how you invoke it and how you define your rules. For example, the first rule with target all depends on binary and assembly, so make checks those rules, and carries out the relevant steps (in this case executing gcc).

How does gcc differentiate between them?

The gcc program is a compiler, which is a completely separate program. It is merely invoked by make, just like rm is for the clean rule. It has no involvement in processing the Makefile itself, so it doesn't need to "differentiate" anything -- make does all the processing of the Makefile.

Also, the $() variables you use, do they only exist for gcc or could you also define them globally in your operating system?

The variables have nothing to do with gcc. The make program parses the Makefile and performs the necessary substitutions before invoking the commands (e.g. gcc).

The variables could be used elsewhere in the Makefile too, for example with the rm command. They are not specific to any command in particular.

You can also make use of environment variables in a Makefile, as explained in this post.

costaparas
  • 5,047
  • 11
  • 16
  • 26
  • 2
    And `CFLAGS` could have *both* `-O2` and `-g` – Basile Starynkevitch Jan 28 '21 at 12:57
  • @basile yep I agree, I originally used the OP's choice of CLFAGS flags, but I've updated it now with some important extras – costaparas Jan 28 '21 at 12:59
  • Thanks! From your answer it seems that you can execute other labels from other labels. However how do they differ from just writing the desired filename like I did? How does gcc differentiate between them? Also, the $() variables you use, do they only exist for gcc or could you also define them globally in your operating system? – xbufu Jan 28 '21 at 14:11
  • Also, how do I set the -o flag in the binary label? When I just insert -o test it create both a.out and test – xbufu Jan 28 '21 at 14:33
  • @bartman1912 glad it helped, see the updated answer in response to your comments – costaparas Jan 28 '21 at 14:33
  • @bartman1912 adding `-o test` should be enough. Maybe `a.out` is leftover from the previous invocation of `make`? Make sure you `make clean` and then try `make` again. Also don't forget to update the `clean` rule with the correct output file name. – costaparas Jan 28 '21 at 14:37
  • 1
    @costaparas Really thanks a lot! Yes, the a.out was indeed leftover I think and now everything is working perfectly! – xbufu Jan 28 '21 at 15:14