CS641 Building a C Program: Compile, Assemble, Link, look at symbol tables

Put printbinc.c into two files, upper.c and lower.c. Note that code in upper.c calls code in lower.c. These files are available in $cs641/cbuild.

 

sf06.cs.umb.edu$ more upper.c lower.c

::::::::::::::

upper.c

::::::::::::::

 

void printbin(char);

void donibble(int);

void printchar(char);

 

int main() {

    int i=0;

    char chars[]= {'A','B','0'};

    char temp;

 

    for(i=0;i<sizeof(chars); i++){ // here C knows the size of the array

        temp=chars[i];

        printbin(temp);

    }

    return 0;

}

 

void printbin(char achar){

    int a_hi = achar>>4;  /* high nibble */

    int a_lo = achar&0xf; /* low nibble */

 

    donibble(a_hi);

    printchar(' ');

    donibble(a_lo);

    printchar('\n');

}

::::::::::::::

lower.c

::::::::::::::

void printchar(char);

int printf(char *format, ...);

 

void donibble(int val){

    int i;

 

    for (i=3; i>=0; i--){

        if (val & (1<<i))

            printchar('1');

        else

            printchar('0');

    }

}

void printchar(char c){

    printf("%c", c);

}

 

gcc –S *.c    creates upper.s and lower.s, assembly language

gcc –c *.c    creates upper.o and lower.o, “object files”

gcc *.c  creates a.out, the executable

sf06.cs.umb.edu$ a.out       runs the executable,

0100 0001

0100 0010

0011 0000


Symbol Tables: Use nm to see them in object files and executables

nm (short for namelist, an old name for the symbol table) dumps the symbol table.

 

sf06.cs.umb.edu$ nm upper.o

                 U donibble    <---unknown symbol: donibble is in lower.c

0000000000000000 T main        <--known symbol, offset 0 from start of this code

000000000000004d T printbin    <--known symbol, offset of 0x4d from start of code

                 U printchar   <--another unknown symbol

 

sf06.cs.umb.edu$ nm lower.o

0000000000000000 T donibble    <---known offset for this code

0000000000000045 T printchar   <---known offset

                 U putchar      <--from printf in printchar, needs library

 

Use gcc as linker: gcc passes *.o through to the linker (also relevant flags)

 

sf06.cs.umb.edu$ gcc upper.o  lower.o

sf06.cs.umb.edu$ nm -n a.out    <-- ask for symbols in value order

                 w _Jv_RegisterClasses

                 w __gmon_start__

                 U __libc_start_main@@GLIBC_2.2.5

                 U putchar@@GLIBC_2.2.5     <---- putchar is still undefined: using DLL

00000000004003d0 T _init

0000000000400420 T _start

000000000040044c t call_gmon_start

0000000000400470 t __do_global_dtors_aux

00000000004004e0 t frame_dummy

000000000040050c T main

0000000000400559 T printbin      <--- printbin is 0x4d after main

00000000004005a4 T donibble      <--- lower.o code follows upper.o code, no gap

00000000004005e9 T printchar     <--- offset 0x45 from donibble, as promised

0000000000400600 T __libc_csu_fini

0000000000400610 T __libc_csu_init

00000000004006a0 t __do_global_ctors_aux

00000000004006d8 T _fini

00000000004006e8 R _IO_stdin_used

0000000000400818 r __FRAME_END__

0000000000600e14 d __init_array_end

0000000000600e14 d __init_array_start

0000000000600e18 d __CTOR_LIST__

0000000000600e20 d __CTOR_END__

0000000000600e28 d __DTOR_LIST__

0000000000600e30 D __DTOR_END__

0000000000600e38 d __JCR_END__

0000000000600e38 d __JCR_LIST__

0000000000600e40 d _DYNAMIC

0000000000600fe8 d _GLOBAL_OFFSET_TABLE_

0000000000601010 D __data_start    <--external variables would be after here

0000000000601010 W data_start

0000000000601018 D __dso_handle

0000000000601020 A __bss_start

0000000000601020 A _edata

0000000000601020 b completed.6987

0000000000601028 b dtor_idx.6989

0000000000601030 A _end

 

sf06.cs.umb.edu$ gcc -static -o statprog upper.o lower.o   <---static load links in needed parts of C libarary

sf06.cs.umb.edu$ ls -l a.out statprog

-rwxr-xr-x 1 eoneil man  10986 Feb 22 09:58 a.out   <--using DLL

-rwxr-xr-x 1 eoneil man 700602 Feb 22 10:08 statprog   <-- using static library

 

sf06.cs.umb.edu$ nm statprog|grep putchar    <--Check that putchar has known value in statically loaded program

0000000000401010 T putchar    <-- it’s a little after the code shown above