Usage and Definition Tables in the Linker

Here are two files to be linked to create a single executable.

file1.c

/* file1.c */
#include <stdio.h>
int g; /* a global variable */
extern double dg; /* another global var, defined
                    in some other file */
void fctnOne();   /* a function prototype */

int main()
{
  int x;  /* a variable local to main
             (an automatic variable) */
  x = 3;
  dg = 3.14;
  g = 17;
  fctnOne();
  printf("x is %d, g is %d, dg is %f\n",
	 x, g, dg);
  return 0;
}

void fctnTwo()
{
  int x;
  x = 5;
  g = 11;
  dg = dg * 2;
}

file2.c

/* file2.c */
extern int g;
double dg;

void fctnTwo(); /* function prototype */
void fctnOne()
{
  int x = 44;
  g = x;
  dg = dg + 2;
  fctnTwo();
}

The compiler command
gcc file1.c file2.c
would produce two object files, named file1.o and file2.o. Each of these would have unresolved references, that is, references to data and functions whose addresses are not known, because they are in the other file.

Each object file would have two tables attached, a definition table which contains the address of all objects which are global, that is, could be referenced by a function in another file, and the usage table, which contains a list of all unresolved references. Here are the contents of the four tables.

file1.o deffile1.usefile2.deffile2.use
gdg line 13 dg g line 10
mainfctnOne line 15fctnOnefctnTwo line 12
fctnTwoprintf line 16
gd line 16
gd line 17
gd line 26
gd line 26