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

Postagens mais visitadas