Difference between revisions of "SPO600 Compiled C Lab"

From CDOT Wiki
Jump to: navigation, search
 
(44 intermediate revisions by the same user not shown)
Line 1: Line 1:
[[Category:SPO600]][[Category:Chris Tyler Drafts]]
+
[[Category:SPO600 Labs - Retired]]{{Admon/lab|Purpose of this Lab|In this lab, you will investigate the relationship between basic C source code and the output of the C compiler.}}
 +
{{Admon/tip|Host System|You can choose to perform this lab on any of the [[SPO600 Servers]]. Alternately, you may use your own system if it has been set up with development tools and libraries, '''plus''' the static version of the glibc library.}}
 +
{{Admon/important|Winter 2020|In Winter 2020, this lab is not a required lab and will instead be used as an in-class Demo.}}
  
{{Admon/note|Purpose of this Lab|In this lab, you will see the relationship between basic C source code and the output of the C compiler.}}
+
== Resources ==
{{Admon/tip|Ireland|If you do not have a Linux machine with you, you can use ireland.proximity.on.ca -- an account has
 
== Lab 2 ==
 
  
1. Write a basic C program which prints a message on the screen, [http://en.wikipedia.org/wiki/Hello_world_program Hello World!]-style -- something like this:
+
* [[Assembly Language]]
 +
* [[ELF]] file format
 +
* [[X86_64 Register and Instruction Quick Start]]
 +
* [[Aarch64 Register and Instruction Quick Start]]
 +
 
 +
== Lab / Demo ==
 +
 
 +
1. Write a basic C program which prints a message on the screen, [http://www.roesler-ac.de/wolfram/hello.htm Hello World!]-style -- something like this:
  
 
  #include <stdio.h>
 
  #include <stdio.h>
Line 13: Line 20:
 
  }
 
  }
  
2. Compile the program using the GCC compiler. Include these compiler options:
+
2. Compile the program using the GCC compiler. Include each of these compiler options (refer to the gcc manpage for details):
  
 
  -g              # enable debugging information
 
  -g              # enable debugging information
 
  -O0              # do not optimize (that's a capital letter and then the digit zero)
 
  -O0              # do not optimize (that's a capital letter and then the digit zero)
  -fno-builtins    # do not use builtin function optimizations
+
  -fno-builtin    # do not use builtin function optimizations
 +
 
 +
3. The resulting binary is an ELF (Executable and Linkable Format) file, which contains multiple sections. These sections may contain [[Machine Language|object code]], link tables, [[Debugger|debugging]] [[Symbol|symbols]], program data (such as constants and the initial values of variables), metadata about the program and ELF sections, and comments.
 +
 
 +
Examine the binary produced by the previous step using the ''objdump'' program. These options may be useful -- see the manpage for ''objdump'' for other options:
 +
 
 +
-f          # display header information for the entire file
 +
-s          # display per-section summary information
 +
-d          # disassemble sections containing code
 +
--source    # (implies -d) show source code, if available, along with disassembly
 +
 
 +
Using objdump, find the answers to these questions:
 +
(i) Which section contains the code you wrote?
 +
(ii) Which section contains the string to be printed?
 +
 
 +
{{Admon/tip|objdump ''vs'' readelf|The way that <code>objdump</code> formats strings is not well suited for some uses. The <code>readelf -p</code> command may be a better tool for viewing some strings.}}
 +
 
 +
4. Try to gain a basic understanding of what the compiled code is doing. '''Focus on the section marked <main> but also take a look at the other sections and the overall file size.'''
 +
 
 +
5. Recompile the code with these changes:
 +
 
 +
(1) Add the compiler option <code>-static</code>. Note and explain the change in size, section headers, and the function call.
 +
 
 +
(2) Remove the compiler option <code>-fno-builtin</code>. Note and explain the change in the function call.
 +
 
 +
(3) Remove the compiler option <code>-g</code>. Note and explain the change in size, section headers, and disassembly output.
 +
 
 +
(4) Add additional arguments to the <code>printf()</code> function in your program. Note which register each argument is placed in. (Tip: Use sequential integer arguments after the first string argument. Go up to 10 arguments and note the pattern).
 +
 
 +
(5) Move the <code>printf()</code> call to a separate function named <code>output()</code>, and call that function from <code>main()</code>. Explain the changes in the object code.
 +
 
 +
(6) Remove <code>-O0</code> and add <code>-O3</code> to the gcc options. Note and explain the difference in the compiled code.
 +
 
 +
6. Blog about your results. Important! -- explain what you're doing so that a reader coming across your blog post understands the context (in other words, don't just jump into a discussion of optimization results -- give your post some context).
 +
 
 +
{{Admon/important|Include Seven Variants|Blog about all seven compilations -- the original and the six variants listed in step (5) -- not the just variant your group examined in class.}}
 +
 
 +
{{Admon/tip|Make|Learn how to use [[Make and Makefiles|make]] -- your life as a programmer will be much easier, and you'll get back years of your life!}}
 +
 
 +
== External Resources ==
 +
 
 +
* Wikipedia article on [http://en.wikipedia.org/wiki/Executable_and_Linkable_Format Executable and Linkable Format]

Latest revision as of 08:43, 1 November 2023

Lab icon.png
Purpose of this Lab
In this lab, you will investigate the relationship between basic C source code and the output of the C compiler.
Idea.png
Host System
You can choose to perform this lab on any of the SPO600 Servers. Alternately, you may use your own system if it has been set up with development tools and libraries, plus the static version of the glibc library.
Important.png
Winter 2020
In Winter 2020, this lab is not a required lab and will instead be used as an in-class Demo.

Resources

Lab / Demo

1. Write a basic C program which prints a message on the screen, Hello World!-style -- something like this:

#include <stdio.h>

int main() {
    printf("Hello World!\n");
}

2. Compile the program using the GCC compiler. Include each of these compiler options (refer to the gcc manpage for details):

-g               # enable debugging information
-O0              # do not optimize (that's a capital letter and then the digit zero)
-fno-builtin     # do not use builtin function optimizations

3. The resulting binary is an ELF (Executable and Linkable Format) file, which contains multiple sections. These sections may contain object code, link tables, debugging symbols, program data (such as constants and the initial values of variables), metadata about the program and ELF sections, and comments.

Examine the binary produced by the previous step using the objdump program. These options may be useful -- see the manpage for objdump for other options:

-f          # display header information for the entire file
-s          # display per-section summary information
-d          # disassemble sections containing code
--source    # (implies -d) show source code, if available, along with disassembly

Using objdump, find the answers to these questions: (i) Which section contains the code you wrote? (ii) Which section contains the string to be printed?

Idea.png
objdump vs readelf
The way that objdump formats strings is not well suited for some uses. The readelf -p command may be a better tool for viewing some strings.

4. Try to gain a basic understanding of what the compiled code is doing. Focus on the section marked <main> but also take a look at the other sections and the overall file size.

5. Recompile the code with these changes:

(1) Add the compiler option -static. Note and explain the change in size, section headers, and the function call.

(2) Remove the compiler option -fno-builtin. Note and explain the change in the function call.

(3) Remove the compiler option -g. Note and explain the change in size, section headers, and disassembly output.

(4) Add additional arguments to the printf() function in your program. Note which register each argument is placed in. (Tip: Use sequential integer arguments after the first string argument. Go up to 10 arguments and note the pattern).

(5) Move the printf() call to a separate function named output(), and call that function from main(). Explain the changes in the object code.

(6) Remove -O0 and add -O3 to the gcc options. Note and explain the difference in the compiled code.

6. Blog about your results. Important! -- explain what you're doing so that a reader coming across your blog post understands the context (in other words, don't just jump into a discussion of optimization results -- give your post some context).

Important.png
Include Seven Variants
Blog about all seven compilations -- the original and the six variants listed in step (5) -- not the just variant your group examined in class.
Idea.png
Make
Learn how to use make -- your life as a programmer will be much easier, and you'll get back years of your life!

External Resources