So in software development, developers write code in high level languages like C, C, plus, plus,
or Java.
But this code cannot be directly executed on the CPU because CPU cannot understand C, C plus, plus,
or Java.
It only knows machine instructions, it only knows ones and zeros.
So we have to convert this high level code into machine instructions.
So we use a lot of tools toolchain uh, connection I mean toolchain, chain of tools.
Right.
To convert this high level language into a machine instruction.
So we start with a compiler which converts this high level language, which is human readable, into
another human readable format, which is assembly code.
And then we use assembler which converts the assembly code into object code.
Finally, the linker comes into picture, which combines object code from different uh programs or different
C files, or different C plus plus files and then it will give us a binary file.
Now this binary file has instructions which CPU can execute and understand.
And as we can have any number of formats.
But the format which Linux uses for binaries or executables is Elf.
So normally you have this stages uh preprocessing compiling and assembler and linking.
So preprocessing is where your all your macros are resolved.
Header files are included.
Compiling is where it creates uh assembly output assembler is it creates an object file output and linker
is where it links and all the dependencies.
And finally all the object files and creates an executable.
So what I will show you is all this in this video video.
So I'll delete this one.
So you have this c file uh which is very simple C file which has a macro.
And then it just do some printf.
So normally what you do is like you either you say make userspace uh which will create the by executable
and the file format is Elf.
This is what we were discussing.
The Elf is the file format for this executable.
Or normally how you do it is you say gcc userspace dot c, hyphen o and user space, and then you say
file user space.
This is the what you do.
But internally there are a lot of compilation stage stages which are going on before it finally creates
this executable.
What we will be doing is we will try to, uh, execute each by one step by step and understand what
is happening.
So we say gcc hyphen E uh, then it will, uh, stop.
GCC will not perform all the stages of pre-processing, compiling, assembling and linking.
It will stop at the pre-processing stage.
So we'll do that first.
So we will say gcc hyphen e user space dot c and store the output in user space AI.
So now let's look in the output of user space AI.
Now you can see all the header files which we have included hash include studio dot H was uh if I will
just open you the C file.
So hash include a studio dot h is included, and the macro which we were uh, using the counter is also
gone.
And the place it was is now be be equals to ten is uh I mean the be equals to counter is replaced with
be equals to ten.
So the pre-processing stage everything starts with hash.
Uh, it will be resolved.
Now this comes the next stage which is the compilation stage of uh compiling uh creating the assembly
file.
So it uses, uh.
So there are two.
I mean, here I have not specified you, uh, this option.
Uh, okay.
This is option, right?
So we have completed this one.
Now we want to generate an assembly output.
So for that we will be using this command CC one.
Internally this command if you run CC one it because this is not part of the path environmental variable.
This this is internally uses this when you run.
This is user space dot c f and user space right.
So that's the reason it is not a part of it.
So we need to give full absolute path starting from slash.
So I'll give that uh copy this one.
And userspace dot I and it prints out something.
And then it should generate you a userspace dot s file.
So if I say file on userspace I just a Ascii file and on s it is an assembly source code.
So I'll just get this one.
So whatever we have written has been converted into assembly.
So if you see the move instructions and call instructions which we are calling printf and all the return
instruction, add instruction or present subtract all, all those.
This is an assembly file.
So we had a user space dot c which was a C file high level language.
Now we have another language which is human readable.
But this is not a high level.
This is an assembly level assembly language.
Now we need to convert this assembly language into an object code.
For that we will be using uh assembler.
Assembler converts assembly language which takes assembly as an input and converts it into object code,
which is an object file.
So now let's do a cat.
So this is not an, uh, human readable file, so it will not be understandable to cat.
So we can use tools like Hexdump to see what is the content of this one.
So it is just ones and zeros I mean in the hex file.
So this is an hex file because we use hexdump if I do a file.
So it is an Elf file.
So in this as I said, as we said in the first lecture, Elf files uh format is used by many files.
One of the file is the object file or relocatable file also uses Elf as an format.
So Elf as a format is used by many files.
And object file also uses Elf as a format.
So now I will run this one.
Let's see whether this works.
Uh user space dot.
Oh, the permission denied.
It says permission denied.
So it does not have the executable permission.
So now let's try out uh giving this user space executable permission.
So let this works.
So it says it cannot execute binary file exec format error.
So we cannot execute uh files which are in object format, uh, or we cannot execute a object file or
relocatable files.
Okay.
So now let's move ahead.
So we generated an object file but it is not an executable.
To generate an executable we need to use something known as linker.
So linker uh is LD command stands for linker.
It actually it stands uh for link editor.
LD stands for link editor.
And then we need to pass some arguments.
So if I say like this LD user space dot o it will not work.
It says undefined reference to printf.
So LD is not able to find out printf definition.
So we need to give the definition of printf and the printf is present lipsy dot so.
So linker we know right?
It combines all the object files.
So that is what we are trying to do.
We are combining all the object files.
Now when we are trying to compile uh this one like this.
So instead of saying gcc hyphen o user space and user space dot o it was we are saying like this.
Now it is not uh, user space code is using printf and printf definition we need to pass to linker.
Linker is trying to resolve the printf.
Uh, it is trying to find out who is providing printf.
And the printf is being provided by C library.
So let's try to add this one and see what happens.
Now when we add the C library uh the error related to printf is gone.
But now it is not able to find out uh underscore start.
So who is providing underscore underscore start.
So there is something in CRT.
One CRT stands for C runtime.
So let's add this CRT.
Now it is giving me an error saying.
Underscore start.
There is a function uh c underscore CSV Fenian in it.
And this definition it is not able to find.
So let's add uh this CRT now it is still not able to find the CRT.
And now I will add CRT n.
Well, let's just say in Korean here.
No.
Still, we need to add both CRT and CRT n.
Leave this one.
And we have not added the loader.
So let's add the loader.
So maybe this format is it is expecting the loader to be and we have not specified this as dynamic linker.
So let's add this as a dynamic linker.
And it should be expecting it in a particular format.
So let's gue ld dynamic linker.
Maybe it is expecting an order.
Uh, so let's give in this order.
And check.
And it is able to generate the binary.
So now we have an binary and automatically it got executable permissions.
If you remember user space was not having executable permissions.
Right now this is having executable permissions.
Now if I say file on user space it is a Elf 64 bit executable and the executable are having Elf file
format right and file on uh user space dot o.
It is not an executable, it is a relocatable file.
Now we can now run this user space and it prints the actual whatever the desired behavior which we want.
So yeah, as we said, uh, my uh, CPU cannot understand, uh, high level code.
It only understands the machine code.
I can use a command known as Objdump, which will print me the actual machine instructions.
Uh objdump.
Hyphen m Intel and I say disassemble.
Give me zero space.
So this we have, uh, what we have done is we have taken the executable file and we have disassembled.
We have, uh, reverse engineered, perform reverse engineering, and instead of, uh, compiling C
and to assembly, we took the executable and we have converted it into assembly.
So this is the machine instruction and the corresponding assembly output of this.
And so this is what uh and we can do this for user space and user space auto.
This is just uh trying to explain you like machine only understands I mean, CPU only understands machine
instructions.
And here we can use Objdump object dump dumping the object code object is nothing but the machine code.
So in this video, we have gone through the various stages of compilation, starting from pre-processing
to compiling to assembly, and then generating an object file and then using linker to link various
object files along with our our own object file and generate a final binary.