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