In Pass 2 of the linking loader, the actual linking and loading of the program occur. The loader uses the information gathered in Pass 1, including the symbol table and relocation details, to resolve external references and adjust memory addresses. It updates the object code by replacing placeholders with correct addresses and combines multiple modules into a single executable program. Pass 2 also involves loading the program into memory, ensuring that all modules are properly linked and ready for execution. This pass generates the final executable, which can be run on the target machine.
The objective of Linking Loader Pass2:
The objective of the second pass of a linking loader is to perform the final link and relocation of the program by replacing symbols with their addresses.
Here are some other functions of a linking loader:
Allocate space: Allocate space for the program in the memory
Resolve symbolic references: Resolve symbolic references between the object modules by assigning addresses to user and library subroutines
Perform relocation: Perform relocation for address dependent instructions
Place machine instructions: Place all the machine instructions into the memory
A linking loader uses a two-pass algorithm to load and link programs into memory. The first pass builds symbol tables and resolves external references.
The data structure used in Linking Loader Pass2:
External Symbol Table (ESTAB): Resolves references to external symbols by storing their addresses and associated modules.
Memory Allocation Table: Ensures proper placement of object code in allocated memory regions.
Relocation Records: Adjusts addresses in object code based on module base addresses.
Object Code Buffer: Temporarily holds object code segments before writing them to memory.
Program Header Table (Optional): Provides module-specific metadata like size, start address, and entry points.
begin
set CSADDR to PROGADDR
set EXECADDR to PROGADDR
while
not end of input
do
begin
read next input record {header record}
set CSLTH to control section length
while
record type ≠ ‘E’
do
begin
read next input record
if
record type = ‘T’
then
begin
{if object code is in character form,
convert into internal representation}
move object code from record to
location (CSADDR + Specified address)
end
{if ‘T’}
else if
record type = ‘M’
then
begin
search ESTAB for modifying symbol
name
if
found
then
add or subtract symbol value at
location (CSADDR + specified
address)
else
set error flag (undefined
external symbol)
end
{if ‘M’}
end
{while ≠ ‘E’}
if
an address is specified {in End record}
then
set EXECADDR to (CSADDR + specified address)
add CSLTH to CSADDR
end
{while not EOF}
Jump to location given by EXECADDR {to start execution of
loaded program}
End
{pass 2}
H PROGD 000000 000081
D LISTX 000050
R LISTY ENDX LISTZ ENDY
T 000024 0A 04201D 88100008 060014
T 000050 0F 110014 00000C 005051 000008 120000
M 000028 05 +LISTY
M 000050 06 +LISTZ
M 000058 06 +LISTY
M 000058 06 -LISTX
E 000024
H PROGE 000000 00009F
D LISTY 000070 ENDY 000090
R LISTX LISTZ ENDZ
T 000046 0B 04100000 882037 06100000
T 000090 0F 110000 00000C 005051 000008 120070
M 000047 05 +LISTX
M 00004E 05 -LISTX
M 000090 06 -LISTX
M 000090 06 +LISTZ
M 00009C 06 +PROGE
M 00009C 06 -LISTX
E 000000
H PROGF 000000 000067
D LISTZ 000040 ENDZ 000052
R LISTX LISTY ENDY
T 000028 0C 04100000 88100008 06100000
T 000052 0F 110040 00000C 005051 000008 120000
M 00002D 05 +LISTY
M 000031 05 -LISTX
M 000052 06 -LISTX
M 000052 06 +PROGF
M 00005E 06 +LISTY
M 00005E 06 -LISTX
E
END
ESTAB:
PROGD ** 2000 81
** LISTX 2050
PROGE ** 2081 9f
** LISTY 20f1
** ENDY 2111
PROGF ** 2120 67
** LISTZ 2160
** ENDZ 2172
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct exttable
{
char cextsym[20], extsym[20];
int address,length;
}estab[20];
struct objectcode
{
unsigned char code[15];
int add;
}obcode[500];
void main()
{
char temp[10];
FILE *fp1,*fp2,*fp3;
int i,j,x,y,pstart,exeloc,start,textloc,loc,textlen,length,location,st,s;
int n=0,num=0,inc=0,count=0,record=0,mloc[30],mlen[30];
signed long int newadd;
char operation,lbl[10],input[10],label[50][10],opr[30],ch,*add1,address[10];
fp1=fopen("INPUT.DAT","r");
fp2=fopen("ESTAB.DAT","r");
fp3=fopen("OUTPUT.DAT","w");
while(!feof(fp2))
{
fscanf(fp2,"%s %s %x %x", estab[num].cextsym, estab[num].extsym, &estab[num].address,
&estab[num].length);
num++;
}
exeloc=estab[0].address;
loc=exeloc;
start=loc;
st=start;
while(!feof(fp1))
{
fscanf(fp1,"%s",input);
if(strcmp(input,"H")==0)
{
fscanf(fp1,"%s",input);
for(i=0;i<num;i++)
if(strcmp(input,estab[i].cextsym)==0)
{
pstart=estab[i].address;
break;
}
while(strcmp(input,"T")!=0)
fscanf(fp1,"%s",input);
}
do
{
if(strcmp(input,"T")==0)
{
fscanf(fp1,"%x",&textloc);
textloc=textloc+pstart;
for(i=0;i<(textloc-loc);i++)
{
strcpy(obcode[inc].code,"..");
obcode[inc++].add=start++;
}
fscanf(fp1,"%x",&textlen);
loc=textloc+textlen;
}
else if(strcmp(input,"M")==0)
{
fscanf(fp1,"%x",&mloc[record]);
mloc[record]=mloc[record]+pstart;
fscanf(fp1,"%x",&mlen[record]);
fscanf(fp1,"%s",label[record++]);
}
else
{
length=strlen(input);
x=0;
for(i=0;i<length;i++)
{
obcode[inc].code[x++]=input[i];
if(x>1)
{
obcode[inc++].add=start++;
x=0;
}
}
}
fscanf(fp1,"%s",input);
}while(strcmp(input,"E")!=0);
if(strcmp(input,"E")==0)
fscanf(fp1,"%s",input);
}
for(n=0;n<record;n++)
{
operation=label[n][0];
length=strlen(label[n]);
for(i=1;i<length;i++)
{
lbl[i-1]=label[n][i];
}
lbl[length-1]='\0';
length=0;
strcpy(address,"\0");
location=mloc[n]-exeloc;
loc=location;
count=0;
while(length<mlen[n])
{
strcat(address,obcode[location++].code);
count++;
length+=2;
}
for(i=0;i<num;i++)
{
if(strcmp(lbl,estab[i].cextsym)==0)
break;
if(strcmp(lbl,estab[i].extsym)==0)
break;
}
switch(operation)
{
case '+':
newadd=strtol(address,&add1,16)+(long int)estab[i].address;
break;
case '-':
newadd=strtol(address,&add1,16)-(long int)estab[i].address;
break;
}
ltoa(newadd,address,16);
x=0; y=0;
while(count>0)
{
obcode[loc].code[x++]=address[y++];
if(x>1)
{
x=0; loc++;
count--;
}
}
}
count=0;
n=0;
s=st-16;
fprintf(fp3,"%x\t",s);
for(i=1;i<=16;i++)
{
fprintf(fp3,"xx");
if(i==4||i==8||i==12)
{
fprintf(fp3,"\t");
}
}
fprintf(fp3,"\n\n%x\t",obcode[0].add);
for(i=0;i<inc;i++)
{
fprintf(fp3,"%s",obcode[i].code);
n++;
if(n>3)
{
fprintf(fp3,"\t");
n=0;
count++;
}
if(count>3)
{
fprintf(fp3,"\n\n%x\t",obcode[i+1].add);
count=0;
}
}
fclose(fp1);
fclose(fp2);
fclose(fp3);
printf("\n\t***** PASS TWO OF A DIRECT-LINKING LOADER *****\n");
printf("\nThe contents of the output file :");
printf("\n---------------------------------------------------------------");
printf("\nAddress\t\t\t\tContents");
printf("\n---------------------------------------------------------------\n");
fp3=fopen("OUTPUT.DAT","r");
ch=fgetc(fp3);
while(ch!=EOF)
{
printf("%c",ch);
ch=fgetc(fp3);
}
fclose(fp3);
}
Pass 2 Output