|
@@ -84,6 +84,9 @@ interface
|
|
|
Function MakeStaticLibrary:boolean;override;
|
|
|
end;
|
|
|
|
|
|
+ TBooleanArray = array [1..1024] of boolean;
|
|
|
+ PBooleanArray = ^TBooleanArray;
|
|
|
+
|
|
|
TInternalLinker = class(TLinker)
|
|
|
private
|
|
|
FCExeOutput : TExeOutputClass;
|
|
@@ -94,6 +97,7 @@ interface
|
|
|
procedure Load_ReadObject(const para:TCmdStr);
|
|
|
procedure Load_ReadStaticLibrary(const para:TCmdStr);
|
|
|
procedure ParseScript_Handle;
|
|
|
+ procedure ParseScript_PostCheck;
|
|
|
procedure ParseScript_Load;
|
|
|
procedure ParseScript_Order;
|
|
|
procedure ParseScript_MemPos;
|
|
@@ -102,6 +106,8 @@ interface
|
|
|
function RunLinkScript(const outputname:TCmdStr):boolean;
|
|
|
protected
|
|
|
linkscript : TCmdStrList;
|
|
|
+ ScriptCount : longint;
|
|
|
+ IsHandled : PBooleanArray;
|
|
|
property CObjInput:TObjInputClass read FCObjInput write FCObjInput;
|
|
|
property CExeOutput:TExeOutputClass read FCExeOutput write FCExeOutput;
|
|
|
property StaticLibraryList:TFPHashObjectList read FStaticLibraryList;
|
|
@@ -109,6 +115,7 @@ interface
|
|
|
procedure DefaultLinkScript;virtual;abstract;
|
|
|
public
|
|
|
IsSharedLibrary : boolean;
|
|
|
+ UseStabs : boolean;
|
|
|
Constructor Create;override;
|
|
|
Destructor Destroy;override;
|
|
|
Function MakeExecutable:boolean;override;
|
|
@@ -811,7 +818,10 @@ Implementation
|
|
|
FImportLibraryList:=TFPHashObjectList.Create(true);
|
|
|
exemap:=nil;
|
|
|
exeoutput:=nil;
|
|
|
+ UseStabs:=false;
|
|
|
CObjInput:=TObjInput;
|
|
|
+ ScriptCount:=0;
|
|
|
+ IsHandled:=nil;
|
|
|
end;
|
|
|
|
|
|
|
|
@@ -820,6 +830,12 @@ Implementation
|
|
|
linkscript.free;
|
|
|
StaticLibraryList.Free;
|
|
|
ImportLibraryList.Free;
|
|
|
+ if assigned(IsHandled) then
|
|
|
+ begin
|
|
|
+ FreeMem(IsHandled,sizeof(boolean)*ScriptCount);
|
|
|
+ IsHandled:=nil;
|
|
|
+ ScriptCount:=0;
|
|
|
+ end;
|
|
|
if assigned(exeoutput) then
|
|
|
begin
|
|
|
exeoutput.free;
|
|
@@ -887,15 +903,15 @@ Implementation
|
|
|
|
|
|
procedure TInternalLinker.ParseScript_Handle;
|
|
|
var
|
|
|
- s,
|
|
|
- para,
|
|
|
- keyword : String;
|
|
|
+ s, para, keyword : String;
|
|
|
hp : TCmdStrListItem;
|
|
|
+ i : longint;
|
|
|
begin
|
|
|
- exeoutput.Load_Start;
|
|
|
hp:=TCmdStrListItem(linkscript.first);
|
|
|
+ i:=0;
|
|
|
while assigned(hp) do
|
|
|
begin
|
|
|
+ inc(i);
|
|
|
s:=hp.str;
|
|
|
if (s='') or (s[1]='#') then
|
|
|
continue;
|
|
@@ -904,8 +920,10 @@ Implementation
|
|
|
if Trim(s)<>'' then
|
|
|
Comment(V_Warning,'Unknown part "'+s+'" in "'+hp.str+'" internal linker script');
|
|
|
if (keyword<>'SYMBOL') and
|
|
|
+ (keyword<>'SYMBOLS') and
|
|
|
+ (keyword<>'STABS') and
|
|
|
(keyword<>'PROVIDE') and
|
|
|
- (keyword<>'ZEROES') and
|
|
|
+ (keyword<>'ZEROS') and
|
|
|
(keyword<>'BYTE') and
|
|
|
(keyword<>'WORD') and
|
|
|
(keyword<>'LONG') and
|
|
@@ -924,6 +942,33 @@ Implementation
|
|
|
+'" internal linker script');
|
|
|
hp:=TCmdStrListItem(hp.next);
|
|
|
end;
|
|
|
+ ScriptCount:=i;
|
|
|
+ if ScriptCount>0 then
|
|
|
+ begin
|
|
|
+ GetMem(IsHandled,sizeof(boolean)*ScriptCount);
|
|
|
+ Fillchar(IsHandled^,sizeof(boolean)*ScriptCount,#0);
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+ procedure TInternalLinker.ParseScript_PostCheck;
|
|
|
+ var
|
|
|
+ s : String;
|
|
|
+ hp : TCmdStrListItem;
|
|
|
+ i : longint;
|
|
|
+ begin
|
|
|
+ hp:=TCmdStrListItem(linkscript.first);
|
|
|
+ i:=0;
|
|
|
+ while assigned(hp) do
|
|
|
+ begin
|
|
|
+ inc(i);
|
|
|
+ if not IsHandled^[i] then
|
|
|
+ begin
|
|
|
+ s:=hp.str;
|
|
|
+ Comment(V_Warning,'"'+hp.str+
|
|
|
+ '" internal linker script not handled');
|
|
|
+ end;
|
|
|
+ hp:=TCmdStrListItem(hp.next);
|
|
|
+ end;
|
|
|
end;
|
|
|
|
|
|
procedure TInternalLinker.ParseScript_Load;
|
|
@@ -932,14 +977,22 @@ Implementation
|
|
|
para,
|
|
|
keyword : String;
|
|
|
hp : TCmdStrListItem;
|
|
|
+ i : longint;
|
|
|
+ handled : boolean;
|
|
|
begin
|
|
|
exeoutput.Load_Start;
|
|
|
hp:=TCmdStrListItem(linkscript.first);
|
|
|
+ i:=0;
|
|
|
while assigned(hp) do
|
|
|
begin
|
|
|
+ inc(i);
|
|
|
s:=hp.str;
|
|
|
if (s='') or (s[1]='#') then
|
|
|
- continue;
|
|
|
+ begin
|
|
|
+ IsHandled^[i]:=true;
|
|
|
+ continue;
|
|
|
+ end;
|
|
|
+ handled:=true;
|
|
|
keyword:=Upper(GetToken(s,' '));
|
|
|
para:=GetToken(s,' ');
|
|
|
if keyword='SYMBOL' then
|
|
@@ -954,8 +1007,14 @@ Implementation
|
|
|
ExeOutput.Load_ImageBase(para)
|
|
|
else if keyword='READOBJECT' then
|
|
|
Load_ReadObject(para)
|
|
|
+ else if keyword='STABS' then
|
|
|
+ UseStabs:=true
|
|
|
else if keyword='READSTATICLIBRARY' then
|
|
|
- Load_ReadStaticLibrary(para);
|
|
|
+ Load_ReadStaticLibrary(para)
|
|
|
+ else
|
|
|
+ handled:=false;
|
|
|
+ if handled then
|
|
|
+ IsHandled^[i]:=true;
|
|
|
hp:=TCmdStrListItem(hp.next);
|
|
|
end;
|
|
|
end;
|
|
@@ -967,14 +1026,19 @@ Implementation
|
|
|
para,
|
|
|
keyword : String;
|
|
|
hp : TCmdStrListItem;
|
|
|
+ i : longint;
|
|
|
+ handled : boolean;
|
|
|
begin
|
|
|
exeoutput.Order_Start;
|
|
|
hp:=TCmdStrListItem(linkscript.first);
|
|
|
+ i:=0;
|
|
|
while assigned(hp) do
|
|
|
begin
|
|
|
+ inc(i);
|
|
|
s:=hp.str;
|
|
|
if (s='') or (s[1]='#') then
|
|
|
continue;
|
|
|
+ handled:=true;
|
|
|
keyword:=Upper(GetToken(s,' '));
|
|
|
para:=GetToken(s,' ');
|
|
|
if keyword='EXESECTION' then
|
|
@@ -996,7 +1060,11 @@ Implementation
|
|
|
else if keyword='SYMBOL' then
|
|
|
ExeOutput.Order_Symbol(para)
|
|
|
else if keyword='PROVIDE' then
|
|
|
- ExeOutput.Order_ProvideSymbol(para);
|
|
|
+ ExeOutput.Order_ProvideSymbol(para)
|
|
|
+ else
|
|
|
+ handled:=false;
|
|
|
+ if handled then
|
|
|
+ IsHandled^[i]:=true;
|
|
|
hp:=TCmdStrListItem(hp.next);
|
|
|
end;
|
|
|
exeoutput.Order_End;
|
|
@@ -1009,14 +1077,19 @@ Implementation
|
|
|
para,
|
|
|
keyword : String;
|
|
|
hp : TCmdStrListItem;
|
|
|
+ i : longint;
|
|
|
+ handled : boolean;
|
|
|
begin
|
|
|
exeoutput.MemPos_Start;
|
|
|
hp:=TCmdStrListItem(linkscript.first);
|
|
|
+ i:=0;
|
|
|
while assigned(hp) do
|
|
|
begin
|
|
|
+ inc(i);
|
|
|
s:=hp.str;
|
|
|
if (s='') or (s[1]='#') then
|
|
|
continue;
|
|
|
+ handled:=true;
|
|
|
keyword:=Upper(GetToken(s,' '));
|
|
|
para:=GetToken(s,' ');
|
|
|
if keyword='EXESECTION' then
|
|
@@ -1024,7 +1097,11 @@ Implementation
|
|
|
else if keyword='ENDEXESECTION' then
|
|
|
ExeOutput.MemPos_EndExeSection
|
|
|
else if keyword='HEADER' then
|
|
|
- ExeOutput.MemPos_Header;
|
|
|
+ ExeOutput.MemPos_Header
|
|
|
+ else
|
|
|
+ handled:=false;
|
|
|
+ if handled then
|
|
|
+ IsHandled^[i]:=true;
|
|
|
hp:=TCmdStrListItem(hp.next);
|
|
|
end;
|
|
|
end;
|
|
@@ -1036,14 +1113,19 @@ Implementation
|
|
|
para,
|
|
|
keyword : String;
|
|
|
hp : TCmdStrListItem;
|
|
|
+ i : longint;
|
|
|
+ handled : boolean;
|
|
|
begin
|
|
|
exeoutput.DataPos_Start;
|
|
|
hp:=TCmdStrListItem(linkscript.first);
|
|
|
+ i:=0;
|
|
|
while assigned(hp) do
|
|
|
begin
|
|
|
+ inc(i);
|
|
|
s:=hp.str;
|
|
|
if (s='') or (s[1]='#') then
|
|
|
continue;
|
|
|
+ handled:=true;
|
|
|
keyword:=Upper(GetToken(s,' '));
|
|
|
para:=GetToken(s,' ');
|
|
|
if keyword='EXESECTION' then
|
|
@@ -1053,7 +1135,11 @@ Implementation
|
|
|
else if keyword='HEADER' then
|
|
|
ExeOutput.DataPos_Header
|
|
|
else if keyword='SYMBOLS' then
|
|
|
- ExeOutput.DataPos_Symbols;
|
|
|
+ ExeOutput.DataPos_Symbols
|
|
|
+ else
|
|
|
+ handled:=false;
|
|
|
+ if handled then
|
|
|
+ IsHandled^[i]:=true;
|
|
|
hp:=TCmdStrListItem(hp.next);
|
|
|
end;
|
|
|
end;
|
|
@@ -1099,6 +1185,8 @@ Implementation
|
|
|
|
|
|
PrintLinkerScript;
|
|
|
|
|
|
+ { Check that syntax is OK }
|
|
|
+ ParseScript_Handle;
|
|
|
{ Load .o files and resolve symbols }
|
|
|
ParseScript_Load;
|
|
|
exeoutput.ResolveSymbols(StaticLibraryList);
|
|
@@ -1115,7 +1203,9 @@ Implementation
|
|
|
{ Create .exe sections and add .o sections }
|
|
|
ParseScript_Order;
|
|
|
exeoutput.RemoveUnreferencedSections;
|
|
|
- exeoutput.MergeStabs;
|
|
|
+ { if UseStabs then, this would remove
|
|
|
+ STABS for empty linker scripts }
|
|
|
+ exeoutput.MergeStabs;
|
|
|
exeoutput.RemoveEmptySections;
|
|
|
if ErrorCount>0 then
|
|
|
goto myexit;
|
|
@@ -1149,6 +1239,9 @@ Implementation
|
|
|
exeoutput.WriteExeFile(outputname);
|
|
|
end;
|
|
|
|
|
|
+ { Post check that everything was handled }
|
|
|
+ ParseScript_PostCheck;
|
|
|
+
|
|
|
{ TODO: fixed section names}
|
|
|
status.codesize:=exeoutput.findexesection('.text').size;
|
|
|
status.datasize:=exeoutput.findexesection('.data').size;
|