CS61C Lab 7

Linking

Background

Goals

Assemblers output object files. Object files are binary files that contain the machine code and data that corresponds to the assembly code that you (or a compiler) wrote. Several object files can be linked together to form executable files. Object files and executable files can come in several different formats. The most common one is the Executable and Linking Format (ELF). The purpose of this lab is to familiarize you with the ELF file formats and to practice linking several .o files together to form an a.out file.

Reading

  • P&H Sections on compilation, assembly, and linking
  • Mid-Semester Survey -- you need to fill this out in order to get credit for lab (coming soon).

Info

From class, we know that the toolchain executes the following steps to make your executable:

  1. Compile your source files into assembly (compiler)
  2. Assemble the assembly files into object files (assembler)
  3. Combine your object files into an executable (linker)

Compiler

To create the assembly files which result from the first stage (compilation), you can execute the following:

$ mips-gcc -S input.c

Please note the capital S. This will create a file called input.s which contains the assembly for input.c.

Assembler

To create the object files which result from the second stage (assembly), you can execute either of the following:

$ mips-gcc -c input.c

or:

$ mips-gcc -c input.s

Either command will create an object file called input.o.

Linking

To create the final executable from multiple object files, you can just pass the filenames to gcc like this:

$ mips-gcc input1.o input2.o -o finalexe

This creates an executable called 'finalexe' that results from linking the two given object files.

Object Dump

The object files are binary files and not readable in an editor, so we need to make use of another utility to view the contents. To view the contents of an object file, you can use mips-objdump as follows:

$ mips-objdump -x -d input.o > input.o.dump

The -x option tells mips-objdump to print information about all of the sections and the -d option tells it to disassemble the instructions in the .text section. Open the .dump files in your favorite text editor and look them over. There will be many fields that you do not understand but you should recognize certain things. In particular, the part that begins with the label "Sections:" tells you the section name, size of the section, virtual memory address of the section (VMA), and some interesting flags (CONTENTS, ALLOC, etc.)

Additionally, mips-readelf can print out some of the information in the object file in a more human-friendly format. You can do this using:

$ mips-readelf -a input.o > input.o.readelf

The file command

The name of a file usually gives you a good idea about the type of a file. For example, you know, usually, a file named input.c should be a C program, while a file input.s is usually an assembly program. But what about a file input.o? The Unix command file can report the type of a file. For example, the following command tells you the type of input.o:

$ file input.o

Exercises

Setup

Copy the contents of ~cs61c/labs/07 to a suitable location in your home directory.

$ mkdir ~/lab
$ cp -r ~cs61c/labs/07/ ~/lab

The mips-gcc tools do not work on the macs in 200 Sutardja Dai. You will need to ssh into any of the SPARC-Solaris machines (such as nova).

Exercise 0

Please fill out the Mid-Semester Survey. You will not get checked off unless you do this survey. You can verify that you submitted the quiz using the Submission Verifier.

Exercise 1

When the object files are created, the absolute addresses of functions and data are unknown. Instead, relative addresses are specified in the left most column. Create the file stack.o by the command:

$ mips-gcc -c stack.c

Then create an object dump of the resulting stack.o by:

$ mips-objdump -x -d stack.o > stack.o.dump

Inspect the file stack.o.dump in your favorite text editor. What are the addresses of the functions IsEmpty, Push, and Pop in stack.o? Are these addresses relative or absolute addresses? Why?

Exercise 2

Create an object dump of teststack.o following similar steps as above. Look at teststack.o.dump. The main function calls several functions that are in the stack.o object file. What instruction does it use to call the functions found in stack.o? Why does it use this instruction instead of another instruction you are more familiar with?

Exercise 3

Now, link stack.o and teststack.o into an executable as follows.

$ mips-gcc -o lab7_stack stack.o teststack.o

If you do not use -o, the output file will be called a.out. The resulting file is also an object file. However, because it does not have any unresolved references, we call it an executable. Like the other object files, opening it in a text editor is not very revealing. Instead, dump it using mips-objdump and open the resulting file. Note that there are MANY symbols in this file that we did not define. These are all linked in by default. You may ignore these symbols.

When you run the executable, what address will the program start at?

Exercise 4

What are the addresses of the functions isEmpty, Push, and Pop in the executable? Are these addresses relative or absolute addresses? How do you know?

Exercise 5

What is the address of the structure ourStack in the final executable? What section (.data, .text, or another section) did mips-gcc place ourStack global variable in?