Linker and Loader
Linker and Loader
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
Static libraries
Object file-1
Executable
module
External table
Object file-n
Shared library
stubs
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
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
(a)
(b)
wICURE 4.2 (a) Combined section table
(CST), and (b) Public definition table
(PDT).
4.1. LINKING
67
START
Ic-0
Compute possible
start address
Update CST
Update Ic
Go to
PASS II
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.
(a) (b)
(a) (b)
4.1. LINKING
69
Section Start
address Size
Symbol Section
name Align name name Offset
text 0 145 16 L1 .text
222
.text2 544 85 16
S76 155
672
(a) (6)
FIGURE 4.4 (a) Combined section table, and (b) public deinition table.
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,
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.
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
Sstart address
ofthe section in CST
Perform relocation
of the code
Section
name Start address Size
Align
text
222 16
445
222
.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.
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
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
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
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.
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
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.
real.printf 0
real format 1000
realatoi 1100
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.
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.
One executable
Zero or more shared libraries
Executable
Shared library
FIGURE 4.8 Input-Output of the loader.
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.