CS61C
Summer 2005
Lab 07 - .o and a.out files

Purpose

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 Common Object File Format (COFF). The purpose of this lab is to familiarize you with the COFF file formats and to practice linking several .o files together to form an a.out file.

Note

On the lab computers, MIPSgcc is aliased to always use the -S option which generates assembly code. For this lab, you'll need to unalias it in order to generate object code. Before you start the lab, type:

% alias MIPSgcc mips-dec-ultrix4.3-gcc

Description

Until now, we have been feeding a single .c file to gcc to get an executable file. For example, we would say:

gcc -o lisp lisp.c

to get an executable for project 1. Today we are going to walk through the compilation process to learn some interesting facts about object files and the link editor. Start by downloading the files stack.c, stack.h, and teststack.c. Look at the code and learn what it does.

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

  1. takes your source files and creates assembly files
  2. takes your assembly files and creates object files
  3. takes your object files and makes an executable file

From lab 04 We already know how to do step 1. (i.e., invoke MIPSgcc with the -S option.) Right now we are going to jump all the way to step 2. To do this, we use the -c option instead of the -S option like this:

MIPSgcc -c -fno-delayed-branch inputfile

Run this command on the files stack.c and teststack.c. This creates the object files stack.o and teststack.o. As we know from lecture, these object files each have a .text section where the code lives, a .data section where some of the data lives, a symbol table that indicates where the symbols are defined, etc. If you were to open these files in a normal text editor, however, you would not see these sections. This is because the file is already binary. To read these files, we use a utility called an object dumper. The one we will be using is MIPSobjdump. Invoke it on the two object files like this:

MIPSobjdump -x -d stack.o > stack.o.dump 

MIPSobjdump -x -d teststack.o > teststack.o.dump 

The -x option tells MIPSobjdump 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 size of the section, virtual memory address of the section (VMA), and some interesting flags (CONTENTS, ALLOC, etc.)

Question 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. What are the relative addresses of the functions isEmpty, Push, and Pop in stack.o?

Question 2: Look at teststack.o.dump. The main function calls several functions that are in the stack.o object file. However, at this stage of creating the executable, the addresses of those functions are unknown. What does the assembler put in place of the actual addresses in the jal instructions that call these funcitons?

Now we are going to use the linker to make an executable. To do this, we simply invoke MIPSgcc with the names of the object files. It knows based on the .o file extension that these are object files and do not require compilation or assembly. Here's how you do it:

MIPSgcc teststack.o stack.o

The output file is called a.out. It too is an object file. However, it does not have any unresolved references so it is executable. Like the other object file, opening it in a text editor is not very revealing. Instead, dump it using MIPSobjdump like we did before 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.

Question 3: What are the actual addresses of the funcitons isEmpty, Push, and Pop in a.out?

Question 4: What is the address of the structure ourStack in the final executable? What section is ourStack in?