Lab 2
Hello
again,
I forget to explain what SPO600 is! So let’s do it now: SPO600
(Software Portability and Optimization) is a course from Seneca
College. Here I will try to improve codes using open source
softwares. The commands that will follow in lab 2 were executed on a
Ubuntu 16.04 OS, but future commands will be done in machines with
Aarch64 and x86_64 processors through remote access that respectively
have aarchie and xerxes as nicknames.
Now, let’s talk about Lab 2:
1. Lab 2 was a class where we had to modify the compilation options
and some stuff in a Hello World C code and see the differences
between them. First of all, we wrote the code below:
#include <stdio.h>
int main() {
printf("Hello World!\n");
}
2. Then we compile the code (let’s call our code as HelloWorld.c)
with the “gcc HelloWorld.c -g -O0 -fno-builtin” command to get
some optimization. Note that a.out is a binary that we created with
the command, our ELF (Executable and Linkable Format) file (you can
execute it by typing “./a.out” command).
Obs.: To understand the command, you can access the manpage by typing
“man gcc” and then “h” for help. Then, if you want to know
about “-g” option, you can type “/-g” and press enter to find
the explanation (commands are case sensitive, “-g” and “-G”
are different commands). When you’re done, type “:q” to quit
manpage (use twice to quit help and then gcc manpage).
3. After that, we examined the binary using objdump program by typing
“objdump -f -s -d a.out” command.
Obs.2: We can use “objdump -f -s -d a.out | less” command to
access the result as a page like manpage, so we can also use “/”
+ a word or phrase to search them on the result.
Obs.3: objdump has a manpage too.
That’s a lot of information, right? Where is our code then? If you
used “| less” as observation 2 said, you can search “/<main>”
and you’ll find it in “Disassembly of section .text:” on
<main>.
Obs.4: You’ll only find <main> if you haven’t passed by it.
For best results, search for it in the beginning of the page.
(i) Which section contains the code you wrote? In .text section.
You will see in <main> our printf function, but our message,
Hello World!, it’s not stored there. So where is it stored? Look
for “Hello” and you’ll find it in .rodata section.
(ii) Which section contains the string to be printed? In .rodata
section.
4. The “a.out” file had 9,6 kB in my machine.
5. Now, I’ll change my compilation to add some options.
(1)
If we add the compiler option -static (use “gcc
HelloWorld.c -g -O0 -fno-builtin -static”
command, then “objdump -f -s -d a.out”
or “objdump -f -s -d a.out | less” again), we’ll see that
“a.out” file has increased its size (913,8 kb in my machine),
there are new
headers, but we still have the <main>. The function call that
was <printf@plt> is now <_IO_printf>
and there is much more lines of code than the first one.
(2)
Now, if we remove the -fno-builtin from the first command (use “gcc
HelloWorld.c -g -O0”, then “objdump
-f -s -d a.out” or “objdump -f -s -d a.out | less”) we’ll
notice that the file will decrease the size again (9,6 kb in my
machine, the same of the first compilation). And if you see the
<main>, the function call has changed again (and there is one
mov less than the firsts compilations) that is now <puts@plt>.
(3)
If we remove the -g option (use “gcc
HelloWorld.c -O0 -fno-builtin”, then
“objdump -f -s -d a.out” or “objdump
-f -s -d a.out | less”) the size will be
even smaller (8,6 kb in my machine), because won’t have the debug
section, but I have seen no difference
between the first and this disassembly output.
(4)
What happens when we add numbers to the
arguments? If we write 1 to 5 after hello world, as below:
#include
<stdio.h>
int
main() {
printf("Hello World!\n%d%d%d%d%d\n", 1,
2, 3, 4, 5);
}
Then
write the first command (use “gcc
HelloWorld.c -g -O0 -fno-builtin”, then
“objdump -f -s -d a.out” or “objdump
-f -s -d a.out | less”) and we’ll can
see in which register each number will be placed, as below ($0x1
means 1, $0x2 means 2, etc):
mov
$0x5,%r9d
mov
$0x4,%r8d
mov
$0x3,%ecx
mov
$0x2,%edx
mov
$0x1,%esi
Unfortunately,
I haven’t detected a pattern in these registers.
(5)
And if we move the printf function to a
separated function as below?
#include
<stdio.h>
void
output() {
printf("Hello World!\n");
}
int
main() {
output();
}
Compile
and now you’ll see it has a new section with the name of our new
function (output) and the main section will call the <output>
instead of the <printf@plt> function (this one is called inside
<output>).
(6)
And finally, let’s see what happens when
the -O3 command is written instead the -O0 command (use
“gcc
HelloWorld.c -g -O3
-fno-builtin”, then “objdump
-f -s -d a.out” or “objdump -f -s -d a.out | less”).
The file will become bigger (11,4 kb), in
.dynstr section you would see that __printf_chk is used instead
printf, the debug sections have more line of code and
the main section is executed in a different way (including a
different call of function, <__printf_chk@plt> instead
<printf@plt>).
Comentários
Postar um comentário