0% found this document useful (0 votes)
32 views21 pages

Linker and Loader

The document discusses the process of linking object modules into an executable program. It explains that the linker combines object files and libraries, resolves external references, and produces the executable file and external tables. Static and dynamic linking are also briefly described.

Uploaded by

Ishita Mahajan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
32 views21 pages

Linker and Loader

The document discusses the process of linking object modules into an executable program. It explains that the linker combines object files and libraries, resolves external references, and produces the executable file and external tables. Static and dynamic linking are also briefly described.

Uploaded by

Ishita Mahajan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 21

Chapter 4

Linker and Loader

Tabing is the process ofcombining different object modules (developed in different


ably by different people) into one executable file. As seen in the files, prob-
nroduces code assunming the start address of each
last chapter,
an assembler
section to be zero. Now, when all
sections are put together into one file, the offsets these
the symbols in the
program need
recomputation. This is because at assembly time, all offsets were calculated from themay
start of
the sections. However after linking, the offsets should be calculated
starting from the begin-
ning of the program. Apart from that, sections may have a set of attributes
placement requirements in the memory. Symbols defined in a section of someidentifying
their
object module
may be used as an external reference in some other module. The assembler could not resolve
these external references due to the non-availability of information about these
assembly time. Now it is the responsibility of the linker to fill up these blanks symbols
at
left by the
assembler. Symbol table produced by the assembler holds
necessary information regarding the
external symbols used in a module and the global
symbols defined in it. Thus, the linker
produces the executable version of the program. Loader is responsible for introduction of a
program into physical memory or virtual memory. A major problem here is the conversion of
logical program addresses to physical machine addresses.

4.1 LINKING
As pointed out earlier, the objectives of linking are as follows:
To combine several object modules
Resolve external references
The inputs of a linker are the following:
1. Object files:
0gect files: These are the modules to be combined to create the executabie versioo
program. As noted in Section 3.4, the object modúles are specified in some standard
format.
2. Static ibraries: distributed as
nese are the standard pre-compiled libraries often
V e file containing individual obiect files for the library modules. Libraries are

63
64 CHAPTER 4. LINKER AND
LOADER
handled by a recursive searching process. If an object module refers to a
an extern
symbol of a library module, then that object file tor the library module is inclhi
the set of files that need to be linked. In turn, other library modules
containino
cluded in
referred to by the first library module are also included. "The process
complete set of required library modules have been determined.
continues nt a

3. Shared library stubs: Shared libraries contain the common set of


functions to be is.
by almost all the programs running in a system. Thus, instead of used
set of routines several times,
loading the s
they are loaded at a single place in the memory. me
routines written Position Tho
are as
Independent Code (PIC) to be explained later.
No:in
the individual programs, some stub routines are placed that will call these
routines
turn, if required. In

The outputs of linker the


a are
following:
1. Erecutable file: The program is ready for
the memory and start
now execution, that is, it may be loaded into
executing.
2. External tables: These correspond to the shared
resolve these references as the library routines. The linker cannot
the time of linking the
position where these libraries are loaded is not
knowm at
program. Moreover, this position may vary from one
of the program to another.
Thus, the linker leaves a table of all such external execution
for the loader to fill up and make the references
program fully ready for execution.
Figure 4.l shows the inputs and outputs of the linker.

Static libraries

Object file-1

Executable
module

Object file-2 Linker

External table

Object file-n

Shared library
stubs

FIGURE 4.1 Inputs and outputs of a


linker.
4.1. LINKING
65

4.1.1 Static vs. Dynamic Linking


the linking that we have discussed so far and that we will be
to discussing in this chapter
pertains static linking, in which all addresses are resolved before the
to star
program is links
into the memory for execution. On the other hand, dynamic inking or deferred inkingloaded
dules on demand. In this case, when an address exception occurs, the erception handler is

called which does the following.


The logical address is checked to determine it it refers to a routine or variable that must
he dvnamically linked. The information regarding the dynamically linkable objects are
kept in a link table.

Tf the address referred to is a valid one, the


memory management state of the program
is adjusted to reflect the allowed address range for the program.

. The instruction causing exception is then restarted.

4.1.2 Combining Object Modules


The sections of object modules are combined to produce a single executable module. In the
discussion to follow, we assume the flat or unsegmented memory model, as this model is followed
in almost all the modern operating systems. However, the SECTION directive can have some
associated attributes specified. All object file formats like elf, _obj, ete. discussed in the
last chapter have their corresponding similar set of attributes. To carry out our discussion,
we assume the elf format for the object files. NASM allows the following qualifiers to the
SECTION declaration:
alloc defines the section to be one which is loaded into memory when the program is
run. noalloc defines it to be one which is not, such as an informational or comment
section.

exec defines the section to be one which should have execute permission when the
program is run. noexec defines it as one which should not.
write defines the section to be one which should be writable when the program is run.
nowrite defines it as one which should not.
progbits defines the section to be one with explicit contents stored in the object ile:
nobits defines the section to be one with
ordnary code or data section, for example,
no
explicit contents given, such as a BSS section.
the section.
align= used with trailing number, gives the alignment requirements of
a
igmz means that the segment can start only at an address divisible by z

delaults assumed of the above qualifers are specified, are


by NASM if none
section text alloc exec nowrite align=16
progbits
section .rodata alloc noexec nowrite align=4
progbits
section data progbits alloc noexec
wTite align=4
section .bss nobits alloc noexec
write
align=4
section other progbits alloc noexec
nowrite
align=1
CHAPTER 4.
LIVAER AND LOADER
66
.rodata, .data and.bss is trpat
ated
name
other than . t e x t ,
section
that any
It may be noted
assembler and used by the lin ker
above.
as shown
default like other table by the
by is added to
the section
c a n be divided int
All the information ol this combining
file. The process
computed, assurnino th.
executable
sections into the
to combine the relative position of all s e c t i o n s is
the the code into the file
two passes. In
the first pass,
The second pass actually puts
file to be zero.
start offset of the

4.1.3 Pass I of Linking


input object modules and collecte
sections in the
Pass I computes the
start addresses ofdifferent tables to constryct
the section tables and symbol
a

the symbols defined public. It looks into Table (PDT). The structure of these
(CST) and a Public Definition
Comb1ned Sectron Table followed in this pass has
shown in Fig. and (b) respectively. The procedure
4.2 (a)
tables
flowchart. Here lc is used to keep track of how
is

in 4.3 in the form of a


Fig.
been explained
is already occupied and thus the place where a
much of the output ile (executable module)
that the executable module will
new segment can be
stored. It is initialized to zero assuming
sections are read from the object
files one after the other. Possible
start at offset zero. Now the
section with the same
start address of the section in
the executable module is computed. If a
is a new one, its
name as the one just read
does not exist in the CST, that is, this section
start address is computed by considering
the current lc value and alignment requirements of
the section. If lc does not satisfy the align specification, the immediate next address satisfying
it is selected as the start address. On the other hand, if the section is already present in the
cST. the possible start address is computed as the current start address (of the section) in
the CST plus the current size of the section as noted in CST. This is because the section that
has just been read will be concatenated to the end of the section with the same name as in
CST. Next, the current size of the section in CST is added to the offsets of all public symbols
defined in this section. It may be recalled that the assembler had noted the offsets of symbols
assuming a start address of zero for the section, which is no more valid when the sections are
getting combined in the executable module. All public definitions are now put into the Publie
Definition Table (PDT). The Combined Section Table (CST) is updated next. If a new section
is being considered, entries are made into CST and le is updated by the start address plus the
size of the section. No other modification is needed for the CST. However, if the section name
is already present in the CST, only the size field needs to be increased for that entry. For
subsequent entries, the start addresses are to be increased by the size of the current section
being considered. It may be noted that the alignment requirements of the sections should be
considered while modifying the start addresses of
subsequent entries. The process
considered. Then control passes to Pass II continues
till all sections in all object files have been
of linking
producing the executable file. Next, we consider an example to understand the
process.
Start
Section name address Size Align Symbol name Section name Offset

(a)
(b)
wICURE 4.2 (a) Combined section table
(CST), and (b) Public definition table
(PDT).
4.1. LINKING
67

START

Ic-0

Read next object file

Read next name in


section table

Compute possible
start address

Add computed start address to the


offsets of all public symbols
in this section

Put all public symbols in the


public definition table
(PDT)

Update CST

Update Ic

Yes All sections No


read

No All object Yes


files read

Go to
PASS II

FIGURE 4.3 Pass I of the linker.

EXAMPLE 44.1. LLet


et a set of
to the linker
object files named a.obj, b.obj, and c.obj be given declarations
toproduce th
to
the eutable file. The section and symbol tables (showing the public
68 CHAPTER 4. LINKER AND LOADER

only) be as noted in Tables 4.1 through 4.3. The linking proceeds as follows. le is initialized
ed
to zero. The sections are now read one after the other. First, from a.obj, section .tezt is fou
ound
with size 145 and align = 16. Since current le value 0 is divisible by 16, the section is placed
at this address, an entry is made into CST as shown in Fig. 4.4(a) and lc is updated to 145
Also, in this section, public definition L1 is found, which is entered into the PDT (Fig. 4.4(b1
Next, section .data is found with align = 4. Since the next lc value divisible by 4 is 148. i
is placed at that offset and le is updated to l48 + 47 = 195. Similarly, section .tert! with

align 16 is assigned the address 208, the next address divisible by 16. The object file b.ohs
is considered next. For section .tezt, it is already there in CST. So, its size is increased to 14
+77 222. Now, the subsequent start addresses of the sections need to be changed, Tho
section .data can now start at address 224 only. Subsequently, the start address of tezt!i
modifed to 272. Similarly, consideration of section .data in b.obj modifies the start address
of tertl to 464. For .test2, the start address is computed as 544, the next number of 464 4
79 543, divisible by 16. The symbol
L2is
entered into PDT. For file c.obj, consideration
section .teart1 increases the section size by 25 bytes. However, before this, the symbol L3 s
of
enteredinto PDT with offset = current size of tert! + 10 = 79 +10 = 89. Start address of
tert2 is modified to 576. Next, the section .data of c.obj modifies the start address of
.tezt1
and .tert2 to 560 and 672 respectively. The final .tert2 section only increases the size to
155
bytes.

Table 4.l: (a) Section, and (b) Symbol table of a.obj


Name Size | Align
text 145 16 | Name | Location
.data | 47
Section-id|Isglobal
4 L1 1 true
textl 79 16
(a) (b)

Table 4.2: (a) Section, and (b) Symbol table of b.obj


Name Size Align
text 77 16
Name | Location Section-id | Isglobal|
.data 179 4
text2 85 1 16
L2 23 3 true

(a) (b)

Table 4.3: (a) Section, and (b) Symbol table of c.obj


Name Size|Align |
.text1 25 16
4
Name Location Section-id Isglobal
.data 99
.text2 70 16
L3 10 1 true

(a) (b)
4.1. LINKING
69

Section Start
address Size
Symbol Section
name Align name name Offset
text 0 145 16 L1 .text
222

data 148 47 4 L2 text2 23


224 226
325

.text1 208 16 L3 .text1 89


272 104
484 H6H
560

.text2 544 85 16
S76 155
672

(a) (6)
FIGURE 4.4 (a) Combined section table, and (b) public deinition table.

4.1.4 Pass II of Linking


Pass II of linking is responsible for writing the final code into the executable file. The Combined
Section Table (CST) contains information about the relative positions of sections within this
final file to be created. Thus, the main task of this phase is to copy the object files into their
corresponding locations. Another very important task to be accomplished in this phase is that
of offset correction or relocation which we discuss next before going into the algorithm for
Pass II.

Relocation. As noted in the assembler design phase, the assembler, while generating object
module, assumes the start addresses of individual sections to be zero. All references to
variables in a program are translated to their distances from the beginning of the section
containing them. However, later on, all the object modules are to be combined into one
executable module and all offsets should be taken with respect to the start of the module.
Thus, the code corresponding to instructions containing memory references needs to be
corrected. This process is called relocation. It is useful for,

1. moving around object files during linking, and


2. loading a piece of code at a specified address.

Relocation needs to be carried out both at link-time and at load-time. At link-time,


at
relocation is needed to arrange the object files into the executable module starting
offset zero. At load-time, relocation is needed for arranging shared libraries and the
link-
time being, we concentrate on
executable module into the address space. For the
n e relocation strategies only. Link-time relocation is performed using direct eutng tna
wl modify the address sensitive locations within the code during concatenating object
70 CHAPTER 4. LINKER AND LOADER

modules. There can be two different ways in which the locations requiring relocation
can be specified.

Relocation bitmap: Here, for every instruction, the assembler associates a relocation bit
If the instruction does not need any relocation (that is, instructions not involving memory
addresses), the bit is set to zero, else the bit is set to one. For cases with relocation bit = i.
Pass II of linking does the necessary modifications to the code
Relocation table: It is a table consisting of locations requiring corrections and a Delta value
that should be added to the ofset of the symbol to get the address corrected.
Table 4.4 shows the relocation bits for the program of Program 2.1 reproduced in columns
1,2, and 3 ofthe table. Column 4 shows the relocation bits. For the same program, Table 4.5
shows the relocation table.

Algorithm for Pass II


In Pass II, the are read again per section and the
object files corresponding codes with necessary
relocatio changes are put into the executable file. For each section that is read, its start
address is looked for in the CST produced in Pass I. The code corresponding to this section
is next put into the executable module. The CST entries for the section are updated by
incrementing the start address of the section by the size of the current section read, and the
size field in CST is decremented
by the size of the section. This ensures that a subsequent
occurrence of a section with the same name will get concatenated to the end of this section.
Moreover, when all sections have been put into the executable module, the size field of all
entries in CST will become zero. Next, the code written into the file is modified to sort out
the relocation problems (if any). For each
entry marked as requiring relocation, the start
address of the section in which the symbol has been defined is added to
the code. This ensures
that all offsets are now with
respect to the start address of the executable module. The
locations referring to the shared
library functions and/or variables cannot be corrected at this
stage, as their addresses are not knowm. These relocations are to be
performed at the time or
loading the program into memory for execution. The entries should then point to the actual
location of those shared elements at that time of
execution. It may be noted that the
of those shared library elements can addresses
vary from execution to execution of the program,
thus be handled best by the loader in and
association with the memory management module or
the operating system. The linker will
produce a list of such locations requiring load-time
relocations. Another important information
address ot the program. The
passed by the linker to the loader is the start
specification the start address
of depends the
language. For example, the language C expects a unique function main, upon underiying
to be present in
executable module that defines the start address. In our
a global symbol main which is used
examples in this book, we have useu
by gcc linker to pass on the start address information
the loader.

EXAMPLE 4.2 Continuing Example 4.1, the Pass II algorithm first looks into the sections
of a.obi. For section .tert, it puts the code into the executable file as shown in Fig. 4.6,
the start address in CST to 145 and size to 77. Next, .data is put into the file. Start address updates
and size are updated to 27l and 278 respectively. The section .tezt1 is next put into the file
at offset 560. Start address and size tor .tertl in CST are
updated to 639 and 25 respectively.
4.1. LINkING
71
Table 4.4: Program with relocation bits
Line no. Code Source line
global main Relocation bit
extern printf

section .data
my_array:
6
7
00000000 OA0000001140000001E | dd 10, 20, 30, 100, 200, 56, 45,
0
00000009 00000064000000C800- 67, 89, 77
8 00000012 0000380000002D0000-
0
9 0000001B 004300000059000000-
0
10 00000024 4D000000
0
11
format:
12 00000028 25640A00 db %d, 10, 0 0
13 section .text
14 main:
15 00000000 B900000000 MOV ECX, 0 0
16 00000005 A1 00000000] MOV EAX. [my.array
17 L2:
18 0000000A 41 INC ECXX 0
19 0000000B 81F90A000000 CMP ECX, 10 0
20 00000011 7412 JZ over 0
21
22 00000013 3B048D[00000000] CMPEAX, [my_array ECX*4 1
23 0000001A 7DO07 JGE LI
24 0000001C 8B048D[00000000]
MOV EAX, [my_aray + ECX*41
25 Li:
26 00000023 EBE5 JMP L2
27
28
Over
29 00000025 50 PUSH EAX 0
30 00000026 68[28000000 PUSH dword format
31 0000002B E8(00000000) CALL printf
32 00000030 81C408000000 ADD ESP, 8
33
34
35 00000036 C3 RET

OT.ob, section .tert is put at address 145. Start address and size fields of CST are updated
974 and 0 respectively. Next, section .data of b.obj is placed into the object file at offset
art address and size are updated to 450 and 99 respectively. The section .tert? is put
s e t 62. Start address and size in CST for .tezt2 are updated to 757 and 70 respectively.
C.oby, section .tertl is placed at offset 639. Start address and size are to 6
updated
pectively. The section .data from c.obj is placed at offset 450. Start address andse are
uplated to 549 and 0 respectively. Finally, section .tert2 of c.obj is placed at offset 757. The
72 CHAPTER 4. LINKER AND
LOADER
Table 4.5: Relocation table

|Offset Delta
00000005 .data
00000013 .data
0000001 C
data
00000026 .data
0000002B | External

START

Read next object file

Read next name in


section table

Sstart address
ofthe section in CST

Put code for this section


into the executable file
at offsets

Update start address and


size of the section in CST

Perform relocation
of the code

Yes All sections No


read

No All object Yes


files read
Mark locations requiring
load-time relocation

Mark start address


of the program

Close executable file


FIGURE 4.5 Algorithm for Pass II of linking8
4.2. LIBRARY LINKING
73
start address and size fields are accordingly updated to 827 and 0
the sections in the executable file has been shown in respectively. The layout of
Fig 4.7.

Section
name Start address Size
Align
text
222 16
445
222

.data 224 325


27t 278
A50 99
549

text1 560 404 16


639 25
664

text2 S72 455 16


757
827
FIGURE 4.6 Modifications in CST for
Example 4.2.
EXAMPLE 4.3 Next we consider another
relocation. For this, we have split the example of Pass II of linking to elaborate the
inprogram Program 2.1 into two files al.asm and
a2.asm. File al.asm contains the data
the function get.mar to determine the declarations, input and output, while a2.asm contains
maximum element in an array defined external
in it. The
corresponding list files a1.lst and a2.lst have been shownmy.array
in Table 4.6, which also
shows the code generated
are assumed. The
side-by-side. The default alignments of 16 for .tezt and 4
for .data
Combined Section Table (CST) after Pass I of
4.7. Relocation tables after Pass I linking
of linking is as shown in Table 4.8. It
is as shown in Table
at the end of Pass I may also be noted that
of linking, the Public
public symbols defined in the two Definition Table (PDT) holds information about all
Pass II object modules. The PDT has been shown in Table 4.9. The
process will put the sections into the final
at offsets executable module with relocation carried
out 00000007 of al.obj for format and at offsets
ot
a2.obj for my.array. However, for the symbol printf at 00000006,
offset
00000016 and 00000011F
0000000C
module, the relocation address is not known. Thus it is left for the loader withofantheindication
executable
to
De resolved at the time of loading the program into
at nmain/virtual
offset zero is marked as the start address of the entire module. The memory. The
symbol main
pertorming relocations has been shown in Table 4.10. The relocated executable modulé after
in boldface for values have been shown
clarity.

4.2 LIBRARY LINKING

18ve noted earlier, apart from the


symbols defined by the user in different object
i e s , the program
may also contain references to external
symbols that are denned in
74
CHAPTER 4. LINKER AND
LOADEFD

.text of a .obj

144
145
.text of b .obj

222ZIZIIIIIIIIIIILITIIT
224
data of a .obj
00
270
271

data of b .obj

449
450

data of c .obj
548
549
560
IIIIITIITITITIIIZZ
text1 of a .obj
638
639
663 text1 of c.obj
664
672 IIIIIIIIIIIIIIIIZ

text2 of b.obj
756
757
text2 of c .obj
826
FIGURE 4.7 Layout of the executable file for Example 4.2.

library modules. For example, the mathematical


routines
string functions may be kept together into another one. are clubbed together into a library
This facilitates
a particular library and
incudeareit along with other object modules for the users to reter
of programs. External libraries
usually provided in two forms: static complete executo
ibraries. In Linux, for example, static braries have extension "s" libraries and shar
in their ile names, whereas
.2 LIBRARY LINKING
75

Table 4.6: List files for Example 4.3


al.lst 2.1st
global nmain, my_array cxtcm nuy _array
extern printl, get_max
global get_ina
section .text
Ction.text
main:
get_max:
00000000 ES(00000000) CALL get_nmax O0000000 B90000000o MOV ECX, 0
00000005 50 PUSH EAAX 00000005 A1[00000000 MOV EAX. (my_aray]
00000006 68/28000000 PUSH dword format L2:
0000000A 41 INC ECX
0000000B E8(00000000) CALL printf
00000010 81C408000000 ADD ESP, 8 0000000B 81F90A000000 CMP ECX, 10
RET
00000011 7412 JZ over
00000016 C3

section data
00000013 3B018D|00000000 CMP EAX. (my_array
+ECX*4
my_array: 0000001A 7D07 JGE LI
0000000 0A000000140000001E- dd 10, 20, 30, 100, 200 0000001C 8B048DI00000000) MOV EAx, [y_arrav
00000009 0000006-1000000C800-
+ECX*4
00000012 0000 L:
00000014 380000002DO0000043- dd 56, 45, 67, 89, 77 00000023 EBE5 JMP L2
0000001D 000000590000004D00-
over:
00000026 0000
00000025 C3 RET
format:
00000028 25640A00 db %d'. 10, 0

Table 4.7: Combined section table for Example 4.3.

Section name Start address Size Align


tert 0 61 16
.data 64 43 4

Table 4.8: Relocation tables for Example 4.3

al.obj a2.0bj
Offset Delta Symbol Offset Delta Symbol
00000001 External get.ma 00000006 External myarray
00000007 . data format 00000016 External my.arra
0000000C External printf 0000001F External|my.array

Table 4.9: Public definition table for Example 4.3

Symbol name Section name | Offset


main .tert 0

my-arra .data 64-0


get.mar .tert 23
76 CHAPTER 4. LINKER AND
LOADE
Table 4.10: Executable module for Example 4.3.

Address Code Comments


00000000 ES(17000000)
00000005 50
00000006 68 68000000] .text of al.obj
0000000B E8(00000000)
00000010 81C408000000
00000016 C3
00000017 B900000000
0000001C A1(40000000
00000021 41
00000022 | 81F90A000000
00000028 | 7412
0000002A | 3B048D 40000000] text of a2.obj
000000311 7DO7
00000033 | 8B048D40000000)
o000003A EBE5
0000003C | C3
00000040OA000000140000001E
00000049 00000064000000C800
000000520000 .data of al.obj
00000054 380000002D00000043
0000005D 000000590000004DOO
000000660000
00000068 | 25640A00

for shared libraries, the extension is ".so". When a program is linked against a static library,
for each of the external functions used by the program, the corresponding machine code 1S
copied from the object file containing the library. The extracted code is attached with other
modules to create the overall executable module. However, in some linkers, instead of including
the particular function, the entire library
object module is included in the code. In turn, any
library module containing symbols referred to by the first library module are also included.
The process continues until a complete set of required library modules have been determineu
and included in the code.
The term shared library is a bit
ambiguous, as it covers at least two different concepts. Fu
it is the sharing of code located on disk
by unrelated programs. On the other hand, it can
sharing of code in memory. In this case, the programs execute the same
at the same physical page of the memory, but
piece of code loaue
mapped to the address spaces of the pron
Obviously, the second approach has got a lot of advantages. For example, the applicao
may now be only a few hundred kilobytes in size and loaded instantly-the majority of u
code being in the libraries that has been loaded for other purposes by the operating
syse
However, the major price paid is that the shared code must be specifically written in a
tasking environment, and this has effects on performance. Main memory sharing can
m be
accomplished by using Postion Independent Code (PIC) as in UNIX, leading to a complex
comple
4.3. POSITION INDEPENDENT CODE (PIC)
77
hut flexible architecture, or by using normal (that is, non-PIC) code as in Windows and OS/2.
These systems make sure, by various tricks such as pre-mapping the address space, reserving
slots for the shared library modules. In Windows environment, such modules are called DLL
(Dumamic Link Libary). It may be noted that Windows DLLs are not shared libraries in the
UNIX sense. In most modern operating systems including Windows, shared libraries can be
af the same format as the regular executables. This provides two nain advantages: first, it
reauires making only one loader for both of them, rather than two. The added complexity of
the one loader is considered well worth the cost. Secondly, it allows the executables also to be
1Sed as DLLs, if they have a symbol table. Most dynamic library systerms link a symbol table
with blank addresses into the program at compile/assemble time. All references to code or data
in the library pass through this table, the import directory. At load time, the table is modified
with the location of the library code/data by the linker/loader. The biggest disad/vantage of
this shared library is that the executables depend on the separately stored libraries in order to
function properly. If the library is deleted, moved, or renamed, or if an incompatible version
of the DLL is copied to a place that is earlier in the search, the executable could malfunction
or even fail to load. This impedes the performance and stability of the operating system also.
On Windows, this is commonly known as DLL hell

4.3 POSITION INDEPENDENT CODE (PIC)


Position independent code (PIC) is a form of absolute object code that does not contain
any absolute addresses and therefore does not depend on where it is loaded in the process's
virtual address space. This is an important property for building shared libraries. Most
modern compilers can be asked to generate PIC (for example, -spic option for gec). Position
independence is achieved via the following wo mechanisms:
i/enlNÄali
1. IP-felative addressing is used wherever possible for branches within modules.
2. Indirect addressing is used for all accesses to global variables, or for intermodule pro
cedure calls and other branches and literal accesses where IP-relative addressing cannot
be used.
For example, the following is a coding technique that may be used to implement function-
calls in a position independent manner.

MOV EAX, ESI|format


CALL EAX

format:

lere, if ESI is preloaded with the start address of the module containing this piece ofcode,
a shared library
CALL EAX will call the function format indirectly. In general,
ement the object code for such
horary
a number of related functions. As noted earlier,
Contain functions and variabies na
Odule will also contain a symbol table containing all thefor the C language containing the
E a
by other modules. Consider a shared library
78 CHAPTER 4. LINKER AND
LOADER
functions printf, format, and atoi. In the module, let printf be defined at offset 0, form
rTmat:
offset 1000, and atoi at offset 1100. Then the symbol table will look as shown in Table d1
.l1.
Table 4.11: Symbol table

printf
format 1000
atoi 1100

Any program using calls to these functions should first locate the position of the library
module either in the main memory or in the virtual memory and use indirect addressing (a
shown earlier for the function format) to access them. A program named Program-A can be
like the following.

Initialize LIBC_VECTOR
MOV ESI, LIBC-VECTOR
MOV EAX, ESIprintf
CALL EAX

Whereas another program named Program-B can use the same library similarly, as shown
below.

Initialize LIBC-VECTOR
MOV ESI, LIBC.VECTOR
MOV EAX, ESI[atoi
CALL EAX

For Program-A, if the virtual address at which the library has been attached is 50000, the
Initialize LIBC. VECTOR should get this value, so that ESI is adjusted accordingly. On the
other hand, for Program-B, the virtual address may be 20000. Thus, the initialization should
get this value to set ESI. The virtual memory manager may identify that the virtual pages at
address 50000 for Program-A and at address 20000 for Program-B are referring to the same
code, and thus decide to load the corresponding pages only once in the main memory with
shared-bit turned ON for the pages. Thus, the processes maintain implicitly some table or
addresses for the shared library functions and call the routines via this table. The variabies
in the shared library can be accessed in a similar manner by maintaining another table, may
be named as Global Ofset Table and using another register to hold the address of this tabie
All accesses to shared variables thus need two memory references--one to read the offset ro
the table and the other one to actually access the variable.
To summarize, PIC enjoys the following advantages over the ordinary executables.

.No need to relocate.


disk.
.Library is shared on

Library is shared in primary memory as wel. All the page tables of various procesS
trames for the library.
can share the main memory
4.4. SHARED LIBRARY LINKING
79

On the other hand, it has the following drawbacks.


.We sacrifice one register to hold pointer to the indirect table.
.Each method invocation needs two memory accesses.
.We have to use another register to access the variables in the shared library.
Each access to variables in the shared library requires two memory accesses.

4.4 SHARED LIBRARY LINKING


Shared libraries are compiled and linked independently from the application. However, when
used in conjunction with the application, the following problems come up.
.Offset of various routine can now change.

The linking process of the application cannot take care of the shared libraries, because
it has no idea where the shared library is actually located at the time of execution.
Moreover, the position may vary from one execution to another.
.Loader has to take care of the situation. PIC provides a nice solution. However, the
scheme is improved further by using stub routines in the individual processes.
For example, an application program may have a call to a shared library routine atoi like,
PUSH 25
CALL atoi
The application is augmented with a dummy (stub) atoi function, which, in turn, calls the
realatoi function residing in the shared library as follows.

atoi: MOV ESI, LIBC-VECTOR


MOV EAX, ESI{real.atoi
JMP EAX
On the other hand, the shared library may be located in another file Libc.so containing the
actual routines, that is real.atoi, etc. Let the file contain three such routines with their offsets
S Snown in Table 4.12. This table is called Procedure Linkage Table (PLI). As is obvious, tor
ot
of the the application, LIBC.VECTOR should contain the start address
Correct execution
the memory at which Libc.so has been loaded.

Table 4.12: Symbol table for the library

real.printf 0
real format 1000
realatoi 1100

and library cancontinue


such a scheme, object code generation for the application
"n the object modules
of the application
indep Linker resolves the undeined entries in LIBC.VECTOR BKh
with PIT ntiy. During loading, the value of time). Thus,
(sincelentries of the shared library.
o r it is loaded at this
present in the memory,
n e library is already execution of the applicacion
resolve reference ensuring a smooth
this
CHAPTER 4. LINKER AND LOADE
80 R

Versioning. A typical problem arises if several versions of the same library are present
the system simultaneously. Some programs use the older version, while some others
in
use
newer ones. Versions are not downward compatible, mainly because due to the addis.
and deletion of code, the offsets of the routines within the library will vary from
dition
one
version to another. Ensuring correct execution of all applications in such a situation
is
really a challenge. The situation is the DLL Hell as mentioned earlier.

Among the probable solutions, the following may be tried out.

1. Rename the shared library every time. In this case, the system does not provide any
support for versioning. The burden is entirely on the programmer. A variant of this
puts a copy of the library in each program directory. However, in this case, all forms of
sharing are lost!

2. Integrate numbering scheme in the file name. For example, libc.so.5.1. Here, 5 is the
major revision number and 1 is the minor revision number. Major upgrade increments
the major version number. It is better than renaming, however, still rely on basic
convention.

4.5 LOADER
Loading is the process of making a program ready for execution by copying the fle from
secondary storage to the primary or virtual memory. It is often a part of the operating
system, and thus not visible to the system user directly. The major objectives of a loader are
as follows.

Bring a binary image into memory.


.Bind relocatable addresses to absolute addresses.
As pointed out earlier, at the end of linking, we are left with a
which needs to be further coupled with the single executable module
shared libraries that may or may not be
loaded. The task of the loader is now to locate the already
position of the shared library, correct tne
appropriate entries in the executable referring to shared library routines and variables,
hence create the binary image that is and
ready for execution from all angles. Thus, the inputs to
the loader are the following.

One executable
Zero or more shared libraries

The output of the loader is:

A usable binary image at an absolute address in the


virtual address space. The virtua
memory manager takes care of the image now for its correct
execution.
The inputs and outputs of a loader have been shown in Fig. 4.8.
4.5. LOADER
81

Executable

(Shared library Loader Binary image

Shared library
FIGURE 4.8 Input-Output of the loader.

4.5.1 Binary Image


The binary image of a program consists of the following components.

1. A header. It indicates the type of the image. An image may be an executable file, some
ibrary, etc. Some of the images are to be loaded at some preassigned address, or it may
be determined by consulting the memory management routine.

2. Tert of the program. It consists of the actual piece of code. The code may be in some
specific format, like Intel Hex format, elf, etc. It holds the object files, static libraries,
and stub tables for shared libraries.

3. List of shared libraries. The shared library routines that are called by the module. The
loader needs to resolve the addresses accordingly.

The loader checks the file header to determine how to load the program. A virtual memory
is the the The memory area is backed up by the
area added for text of program. virtual
ile containing the code. When a page fault occurs, the virtual memory subsystem goes to
the backing store (the file) and maps the missing page. A complete discussion on virtual
nemory manager to load and manage the executable modules is beyond the scope of this
OK. nterested
readers are requested to refer to some book on Operating System
4.5.2 Types of Loaders
There are three main
categories of loaders, namely:
1. Absolute loaders
2. Relocating loaders
3. Linking loaders

Absolute loaders. This is the simplistic type of situation in which the assembler generates
The ader ac
ndwrites instructions in a fle together with their load addresses.
n l e and places the code at the absolute address given in ne

Relocating
The
loaders. ere the assembler produces code and
the relocation
intormation.

loa
While loading the program performs relocation as well.
82 CHAPTER 4. LINKER AND
LOADE
Linking loaders. This type of loaders will do the linking with shared libraries
discussed earlier, the linking is normally carried out in a separate phase to well. As
complexity. reduce the
Another class of loaders known as Botstrap loader is executed when the
turned on or restarted. It is a simple absolute loader. Its function is to
comnuta is irst
load the first:
program to be
run the computer, which is the operating system or a
by system
more
that loads the rest of the system. Bootstrap loader is coded as aa fixed-length complex
recordloader
added to the beginning of the system programs that are to be loaded fixed-length
A built-in hardware or a very simple program in ROM reads this
into
into an
an emptv
empty syst
record into the memor
transfers control to it. When it is executed, it loads the
program which is either the oneras
system itself or other system programs to be run without the
operating system.
4.6 CONCLUSION
In this chapter, we have seen how the
can be combined
object modules created by an assembler or compiler
together using the process of linking. The task often
be done to rectify the address
references within the module. requires relocation to
independent-code have been detailed that can be used for Techniques to create
position
shared-library development.
like how a program be loaded intoLoading
process has also been discussed. However, the details
memory has been skipped, as it is covered virtual
rigorously
chapter, we will see another feature used in both
in books on
operating systems. the next
In
to reduce the assembly-
program size. The technique is called macro.
and high-level-language
programs
done in a separate preprocessing phase known Processing of these macrOs is often
as
macroprocessing.

EXERCISES
4.1 Explain the responsibilitiesof the linker and the
loader in program
4.2 What is the development.
difference between static and shared
libraries only as static or libraries? Can a system have all ts
only as dynamic? Is it advisable? t
4.3 What advantage does dynamic linking provide over static
4.4 Explain the linking process for the
linking?
shown in Fig. 4.9. object file r, y, and z for which the section
Also, show the layout of the final executable module. tables are
Name Size Align Name Size Align Name Size Align
text 305 16 text 200 16 text 75 4
.data 59
.data 175 4 data 89 4
data1 65
data2 300 4 .data2 76 16
Section table for x
Section table for y
Section table for z
FIGURE 4.9 Section tables for
Erercise 4.4.
4.6. CONCLUSION
83
A.5 What is relocation? Explain different
information to the linker. ways by which the assembler can pass relocation
4.6 What is
Explain.
position-independent-code? How does it help in solving the relocation problem?
4.7 How does DLL work in windows
platform? What is meant by DLL Hel?
4.8 Identify the
instruction-set features useful to
develop PIC.
4.9 How is shared library linking
performed using the PIC method?
4.10 Explain the different types of loaders commonly available.

You might also like