You are on page 1of 8

Mjellma Berisha

Homework 3.1
#include <stdio.h>
#include <unistd.h>
int main() {
sleep(10);
printf("Hello world!\n");
//sleeping needed in f), the rest is not calculated with sleep included
return 0;
}
/*******************************************************************************
*******************
a) For the dynamically linked binary:
Workflow:
gcc -o helloD hello_world.c
file helloD
helloD: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dyn
amically linked (uses shared libs), for GNU/Linux 2.6.15, not stripped
ls -l helloD
-rwxrwxrwx 1 root root 8383 2012-03-27 13:03 helloD
strip -s helloD
file helloD
helloD: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dyn
amically linked (uses shared libs), for GNU/Linux 2.6.15, stripped
ls -l helloD
-rwxrwxrwx 1 root root 6200 2012-03-27 13:04 helloD
Conclusion:
From this data we can see that the size of the executable helloD
changed from 8383 bytes to 6200 bytes after being striped.
A 26% reduction in size.
a) For the statically linked binary:
Workflow:
gcc -o helloS hello_world.c -static -z muldefs
file helloS
helloS: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux)
, statically linked, for GNU/Linux 2.6.15, not stripped
ls -l helloS
-rwxrwxrwx 1 root root 825685 2012-03-27 13:25 helloS
strip -s helloS

file helloS
helloS: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), sta
tically linked, for GNU/Linux 2.6.15, stripped
ls -l helloS
-rwxrwxrwx 1 root root 747096 2012-03-27 13:29 helloS
Conclusion:
From this data we can see that the size of the statically linked
executable hello changed from 825685 bytes to 747096 bytes after being striped.
A 9.5% reduction in size.
The size for the dynamically linked binary is 8383 byte in comparison to
the 825685 bytes for the statically linked binary.
b)
Dynamically linked executable produces:
nm helloD
0000000000600e50 d _DYNAMIC
0000000000600fe8 d _GLOBAL_OFFSET_TABLE_
00000000004005f8 R _IO_stdin_used
w _Jv_RegisterClasses
0000000000600e30 d __CTOR_END__
0000000000600e28 d __CTOR_LIST__
0000000000600e40 D __DTOR_END__
0000000000600e38 d __DTOR_LIST__
00000000004006d8 r __FRAME_END__
0000000000600e48 d __JCR_END__
0000000000600e48 d __JCR_LIST__
0000000000601020 A __bss_start
0000000000601010 D __data_start
00000000004005b0 t __do_global_ctors_aux
0000000000400460 t __do_global_dtors_aux
0000000000601018 D __dso_handle
w __gmon_start__
0000000000600e24 d __init_array_end
0000000000600e24 d __init_array_start
00000000004005a0 T __libc_csu_fini
0000000000400510 T __libc_csu_init
U __libc_start_main@@GLIBC_2.2.5
0000000000601020 A _edata
0000000000601030 A _end
00000000004005e8 T _fini
00000000004003c8 T _init
0000000000400410 T _start
000000000040043c t call_gmon_start
0000000000601020 b completed.6458
0000000000601010 W data_start
0000000000601028 b dtor_idx.6460
00000000004004d0 t frame_dummy
00000000004004f4 T main
U puts@@GLIBC_2.2.5
The statically linked executable produces:

nm helloS
00000000004a5cc0
00000000004a5ce0
00000000004a5d00
00000000006b5860
00000000006b5880
00000000006b5850
00000000006b7990
00000000006b7980
00000000006b5870
00000000006b79c0
0000000000415130
00000000006b4fe8
00000000006b50c0
00000000006b5280
00000000006b51a0
0000000000403950
000000000042d5c0
0000000000403c00
0000000000403500
0000000000403840
0000000000404440
0000000000404240
0000000000404410
00000000004043f0
00000000004038c0
00000000004034e0
00000000004033b0
0000000000404430
0000000000404400

r
r
r
d
d
d
b
b
d
b
W
d
D
D
D
T
T
T
T
T
T
T
T
T
T
T
T
T
T

...
000000000048f917
000000000048f909
000000000048f8fb
000000000048f8a0
000000000048f740
0000000000490a40
0000000000490b60
00000000006b8720

CSWTCH.11
CSWTCH.13
CSWTCH.15
LogFacility
LogFile
LogMask
LogStat
LogTag
LogType
SyslogAddr
_Exit
_GLOBAL_OFFSET_TABLE_
_IO_2_1_stderr_
_IO_2_1_stdin_
_IO_2_1_stdout_
_IO_adjust_column
_IO_adjust_wcolumn
_IO_cleanup
_IO_default_doallocate
_IO_default_finish
_IO_default_imbue
_IO_default_pbackfail
_IO_default_read
_IO_default_seek
_IO_default_seekoff
_IO_default_seekpos
_IO_default_setbuf
_IO_default_showmanyc
_IO_default_stat
// Many more symbols

r
r
r
r
r
r
r
b

yypgoto
yyr1
yyr2
yytable
yytranslate
zeroes
zeroes
zone_names

Conclusion: yes, the statically linked executable contains many more sym
bols and objects than the dynamically linked executable.
Since the linker will copy all the modules referenced by the statically
linked program to the executable, the statically linkned
executable contains the code of the library it was linked to, therefore
is both larger and more numerous in symbols contained.
The last few lines of this command show which the largest executable tha
t got added is:
nm --print-size --size-sort helloS
...
000000000047ac30 0000000000002636
000000000047ac30 0000000000002636
0000000000425bf0 00000000000029ad
0000000000425bf0 00000000000029ad
00000000004998c0 0000000000002a58

T
t
T
T
r

__GI___strncasecmp_l
__strncasecmp_l_sse2
___printf_fp
__printf_fp
translit_from_tbl

0000000000411b40
000000000040efc0
000000000049d860
0000000000420420
0000000000420420
0000000000420420
000000000045db70
000000000045db70
000000000045db70
000000000046a840
000000000046a840

0000000000002b06
0000000000002b67
0000000000004b18
0000000000005603
0000000000005603
0000000000005603
000000000000606c
000000000000606c
000000000000606c
0000000000007530
0000000000007530

T
T
r
T
T
T
T
T
W
T
T

__memmove_ssse3_back
__memmove_ssse3
translit_to_tbl
_IO_vfprintf
_IO_vfprintf_internal
vfprintf
_IO_vfwprintf
__vfwprintf
vfwprintf
_IO_vfscanf
_IO_vfscanf_internal

Conclusion: the largest object that god added is: _IO_vfscanf_internal (


vfscanf)
c)
nm --undefined-only helloD
w _Jv_RegisterClasses
w __gmon_start__
U __libc_start_main@@GLIBC_2.2.5
U puts@@GLIBC_2.2.5
objdump -T helloD
helloD:
file format elf64-x86-64
DYNAMIC SYMBOL TABLE:
0000000000000000
DF *UND* 0000000000000000 GLIBC_2.2.5 pu
ts
0000000000000000

DF *UND* 0000000000000000 GLIBC_2.2.5 __

0000000000000000 w

D *UND* 0000000000000000

libc_start_main
__

gmon_start__
From this we can see that the undefined reference to the function which
is not called by the program src code is the reference to puts().
This is due to optimization!
All identifiers specified in the ANSI C standard library to have externa
l linkage are always reserved for use as
identifiers with external linkage. Therefore, compilers can optimize cal
ls to library functions such as printf().the routine printf() has
external linkage, and therefore, is known to invoke the library function
printf().The format string can be parsed at compile time, and this
particular call to printf() can be replaced with a call to puts(), as sh
own below.
As for the function called by the source code that is not referemced, we
see that printf does not occur in any of the commands showd, therefore
printf() is called by the source code and not referenced. The reason sta
nds in the optimization that the compiler does, by substituting that call
with puts().
ltrace -S -tt ./helloD
17:10:56.860292 SYS_brk(NULL)

= 0x023d

e000
17:10:56.860518 SYS_access("/etc/ld.so.nohwcap", 00)
17:10:56.860668 SYS_mmap(0, 8192, 3, 34, 0xffffffff)

= -2
= 0x7fc2

17:10:56.860864
17:10:56.861005
17:10:56.861142
17:10:56.861216

=
=
=
=

c216a000
SYS_access("/etc/ld.so.preload", 04)
SYS_open("/etc/ld.so.cache", 0, 01)
SYS_fstat(3, 0x7ffff39264b0)
SYS_mmap(0, 132384, 1, 2, 3)

-2
3
0
0x7fc2

c2149000
17:10:56.861332 SYS_close(3)
= 0
17:10:56.861404 SYS_access("/etc/ld.so.nohwcap", 00)
= -2
17:10:56.861540 SYS_open("/lib/x86_64-linux-gnu/libc.so.6", 0, 0
0) = 3
17:10:56.861860 SYS_read(3, "\177ELF\002\001\001", 832) = 832
17:10:56.862035 SYS_fstat(3, 0x7ffff3926510)
= 0
17:10:56.862134 SYS_mmap(0, 0x3a0368, 5, 2050, 3)
= 0x7fc2
c1bab000
17:10:56.862314 SYS_mprotect(0x7fc2c1d42000, 2093056, 0) = 0
17:10:56.862426 SYS_mmap(0x7fc2c1f41000, 20480, 3, 2066, 3) = 0x
7fc2c1f41000
17:10:56.862626 SYS_mmap(0x7fc2c1f46000, 21352, 3, 50, 0xfffffff
f) = 0x7fc2c1f46000
17:10:56.862763 SYS_close(3)
= 0
17:10:56.862848 SYS_mmap(0, 4096, 3, 34, 0xffffffff)
= 0x7fc2
c2148000
17:10:56.862960 SYS_mmap(0, 8192, 3, 34, 0xffffffff)
= 0x7fc2
c2146000
17:10:56.863058 SYS_arch_prctl(4098, 0x7fc2c2146720, 0x7fc2c2147
020, 34, 0xffffffff) = 0
17:10:56.863257 SYS_mprotect(0x7fc2c1f41000, 16384, 1) = 0
17:10:56.863329 SYS_mprotect(0x00600000, 4096, 1)
= 0
17:10:56.863391 SYS_mprotect(0x7fc2c216c000, 4096, 1) = 0
17:10:56.863447 SYS_munmap(0x7fc2c2149000, 132384)
= 0
17:10:56.863587 __libc_start_main(0x4004f4, 1, 0x7ffff3926e98, 0
x400510, 0x4005a0 <unfinished ...>
-->
17:10:56.863729 puts("Hello world!" <unfinished ...>
17:10:56.863847 SYS_fstat(1, 0x7ffff3926c80)
= 0
17:10:56.863901 SYS_mmap(0, 4096, 3, 34, 0xffffffff)
= 0x7fc2
c2169000
17:10:56.864015 SYS_write(1, "Hello world!\n", 13Hello world!
)
= 13
17:10:56.864157 <... puts resumed> )
= 13
17:10:56.864214 SYS_exit_group(0 <no return ...>
17:10:56.864408 +++ exited (status 0) +++
reference: http://www.compileroptimizations.com/category/printf_optimization.htm
d)
The tool size reports
size helloS
text
739285

data
3800

bss
dec
13408 756493

hex filename
b8b0d helloS

Size
The segments reported by size are the text segment, the data segment and
the bss segment.
Running the size command extracts the magnitude of the text, data, and b
ss segments from the ELF file.
The compiler translates the program's executable statements into CPU ins
tructions, and declarations of static data
are translated into machine-specific data specifications. To create an e
xecutable file, the system linker aggregates
the instructions and the data into distinct segments.

Differences between text, data and bss:


All of the instructions go into one segment traditionally called text.
The text segment contains the program.
A text segment , also known
as a code segment or simply as text, is one of
the sections of a program in an object file or in memory, which contains
executable instructions. As a memory region, a
text segment may be placed below the heap or stack in order to prevent h
eaps and stack overflows from overwriting it.
The data segment essentially contains global data. The data are arrange
d in two segments, data segment and bss. The
data segment portion of virtual address space of a program which contain
s the initialized static data and literal
constants. So, the data area contains global and static variables used b
y the program that are explicitly
initialized with a value, by the programmer.
The other segment, bss, is for the uninitialized static data. The bss se
gment, also known as uninitialized data,
starts at the end of the data segment and contains all global variables
and static variables that are initialized to
zero or do not have explicit initialization in source code. Data in this
segment is initialized by the kernel before
the program starts executing. Bss once stood for "block started from sym
bol".
Refence: http://www.geeksforgeeks.org/archives/14268
http://www.ualberta.ca/CNS/RESEARCH/LinuxClusters/mem.ht
ml#ps
e)
As we saw running the size command extracts the magnitude of the text, d
ata, and bss segments from the ELF file.
This is because the compiler translates the program's executable stateme
nts into CPU instructions, and declarations of static data
are translated into machine-specific data specifications. To create an e
xecutable file, the system linker aggregates
the instructions and the data into distinct segments.
So, the memory that is allocated to a program upon linking into an execu
table takes into account the static memory needed
(executable statements -> CPU instructions and declarations of static da
ta -> machine-specific data specifications) and its usage,
which is why we recieve the data, bss and text segment sizes. Stack and
heap on the other side are determined during runtime/program
execution and is therefore dynamic.
For stack memory, as execution commences, main pushes its automatic vari
ables on top of the stack. This makes the stack "grow" towards
lower addresses. Stack frames accumulate on the stack as the program des
cends the call graph, and are dismantled as it ascends. In other
words, it is not known without actually analyzing the code to the point
of execution.
The heap on the other side grows by allocating memory dinamically inside
the program via either malloc (or some similar function, new for C++),
and shrinks when that memory is released (via free, C++ delete). This is
also allocated at runtime, and not prior to exeution and is done so
dynamically.

f)
Dynamically linked executable:
pmap 5247
5247: ./helloSleepD
0000000000400000
4K r-x-- /host/Users/fberisha/Documents/4
thSemester/OSLec/Assignments/Assignment3/helloSleepD
0000000000600000
4K r---- /host/Users/fberisha/Documents/4
thSemester/OSLec/Assignments/Assignment3/helloSleepD
0000000000601000
4K rw--- /host/Users/fberisha/Documents/4
thSemester/OSLec/Assignments/Assignment3/helloSleepD
00007f257f834000 1628K r-x-- /lib/x86_64-linux-gnu/libc-2.13.
so
00007f257f9cb000 2044K ----- /lib/x86_64-linux-gnu/libc-2.13.
so
00007f257fbca000
16K r---- /lib/x86_64-linux-gnu/libc-2.13.
so
00007f257fbce000
4K rw--- /lib/x86_64-linux-gnu/libc-2.13.
so
00007f257fbcf000
24K rw--[ anon ]
00007f257fbd5000
132K r-x-- /lib/x86_64-linux-gnu/ld-2.13.so
00007f257fdcf000
12K rw--[ anon ]
00007f257fdf3000
8K rw--[ anon ]
00007f257fdf5000
4K r---- /lib/x86_64-linux-gnu/ld-2.13.so
00007f257fdf6000
8K rw--- /lib/x86_64-linux-gnu/ld-2.13.so
00007fffd24e1000
132K rw--[ stack ]
00007fffd25ff000
4K r-x-[ anon ]
ffffffffff600000
4K r-x-[ anon ]
total
4032K
pmap -x 5242
5242: ./helloSleepD
Address
Kbytes
RSS Dirty
0000000000400000
0
4
0
0000000000600000
0
4
4
0000000000601000
0
4
4
00007f7aacb3b000
0
188
0
00007f7aaccd2000
0
0
0
00007f7aaced1000
0
16
16
00007f7aaced5000
0
4
4
00007f7aaced6000
0
12
12
00007f7aacedc000
0
104
0
00007f7aad0d6000
0
12
12
00007f7aad0fa000
0
8
8
00007f7aad0fc000
0
4
4
00007f7aad0fd000
0
8
8
00007fff21ef6000
0
12
12
00007fff21fff000
0
4
0
ffffffffff600000
0
0
0
---------------- ------ ------ -----total kB
4032
384
84

Mode
r-x-r---rw--r-x-----r---rw--rw--r-x-rw--rw--r---rw--rw--r-x-r-x--

Mapping
helloSleepD
helloSleepD
helloSleepD
libc-2.13.so
libc-2.13.so
libc-2.13.so
libc-2.13.so
[ anon ]
ld-2.13.so
[ anon ]
[ anon ]
ld-2.13.so
ld-2.13.so
[ stack ]
[ anon ]
[ anon ]

Statically linked executable:


pmap 5260
5260: ./helloSleepS
0000000000400000
724K r-x-- /host/Users/fberisha/Documents/4
thSemester/OSLec/Assignments/Assignment3/helloSleepS
00000000006b4000
8K rw--- /host/Users/fberisha/Documents/4
thSemester/OSLec/Assignments/Assignment3/helloSleepS

00000000006b6000
000000000138e000
00007fffd52b2000
00007fffd53c4000
ffffffffff600000
total

16K
140K
132K
4K
4K
1028K

rw--rw--rw--r-x-r-x--

[
[
[
[
[

anon ]
anon ]
stack ]
anon ]
anon ]

pmap -x 5265
5265: ./helloSleepS
Address
Kbytes
RSS Dirty
0000000000400000
0
120
0
00000000006b4000
0
8
8
00000000006b6000
0
16
16
000000000097c000
0
12
12
00007fffd7b74000
0
8
8
00007fffd7bff000
0
0
0
ffffffffff600000
0
0
0
---------------- ------ ------ -----total kB
1028
164
44

Mode Mapping
r-x-- helloSleepS
rw--- helloSleepS
rw--[ anon ]
rw--[ anon ]
rw--[ stack ]
r-x-[ anon ]
r-x-[ anon ]

Conclusion:
Form the comparison of the two executabl's memory usage we can see that
because the dynamicaly linked executable needs to actually link to the library d
ynamically during runtime, it uses more up more memory than the statically linke
d executable which contans the
library within itself.
The dynamically-linked executable uses more memory than the statically-l
inked one because it needs to link the libraries it relies on in order for them
to be available and accessible at runtime, while the statically-linked executabl
e includes a copy of the code that it requires from that library inside itself.
In the dynamically linked executable calls to /lib/x86_64-linux-gnu/libc
-2.13.so (static library) are made and in total cost a map entry size of about 3
000K.
********************************************************************************
******************/