* patch from Pavel with a new and much faster DLL Scanner for

automatic importing so $linklib works for DLLs. Thanks Pavel!
This commit is contained in:
peter 2001-03-06 18:28:02 +00:00
parent e49f13a393
commit aab27143a3
7 changed files with 419 additions and 153 deletions

View File

@ -52,6 +52,14 @@ interface
rr_asmolder,rr_crcchanged
);
TExternalsItem=class(TLinkedListItem)
public
found : longbool;
data : pstring;
constructor Create(const s:string);
Destructor Destroy;override;
end;
tlinkcontaineritem=class(tlinkedlistitem)
public
data : pstring;
@ -105,7 +113,7 @@ interface
uses_imports : boolean; { Set if the module imports from DLL's.}
imports : tlinkedlist;
_exports : tlinkedlist;
externals : tlinkedlist; {Only for DLL scanners by using Unix-style $LINKLIB }
resourcefiles : tstringlist;
linkunitofiles,
@ -286,6 +294,25 @@ uses
end;
{****************************************************************************
TExternalsItem
****************************************************************************}
constructor tExternalsItem.Create(const s:string);
begin
inherited Create;
found:=false;
data:=stringdup(s);
end;
destructor tExternalsItem.Destroy;
begin
stringdispose(data);
inherited;
end;
{****************************************************************************
TMODULE
****************************************************************************}
@ -614,6 +641,8 @@ uses
imports:=tlinkedlist.create;
_exports.free;
_exports:=tlinkedlist.create;
externals.free;
externals:=tlinkedlist.create;
used_units.free;
used_units:=TLinkedList.Create;
{ all units that depend on this one must be recompiled ! }
@ -745,6 +774,7 @@ uses
uses_imports:=false;
imports:=TLinkedList.Create;
_exports:=TLinkedList.Create;
externals:=TLinkedList.Create;
{ search the PPU file if it is an unit }
if is_unit then
begin
@ -776,6 +806,9 @@ uses
if assigned(_exports) then
_exports.free;
_exports:=nil;
if assigned(externals) then
externals.free;
externals:=nil;
if assigned(scanner) then
pscannerfile(scanner)^.invalid:=true;
if assigned(sourcefiles) then
@ -873,7 +906,11 @@ uses
end.
{
$Log$
Revision 1.7 2001-02-20 21:41:15 peter
Revision 1.8 2001-03-06 18:28:02 peter
* patch from Pavel with a new and much faster DLL Scanner for
automatic importing so $linklib works for DLLs. Thanks Pavel!
Revision 1.7 2001/02/20 21:41:15 peter
* new fixfilename, findfile for unix. Look first for lowercase, then
NormalCase and last for UPPERCASE names.

View File

@ -61,6 +61,19 @@ type
procedure generatesmartlib;virtual;
end;
TDLLScanner=class
public
f:file;
impname:string;
TheWord:array[0..1]of char;
HeaderOffset:cardinal;
loaded:integer;
function isSuitableFileType(x:cardinal):longbool;virtual;abstract;
function GetEdata(HeaderEntry:cardinal):longbool;virtual;abstract;
function Scan(const binname:string):longbool;virtual;abstract;
end;
var
importlib : timportlib;
@ -277,7 +290,11 @@ end;
end.
{
$Log$
Revision 1.10 2001-02-26 19:44:52 peter
Revision 1.11 2001-03-06 18:28:02 peter
* patch from Pavel with a new and much faster DLL Scanner for
automatic importing so $linklib works for DLLs. Thanks Pavel!
Revision 1.10 2001/02/26 19:44:52 peter
* merged generic m68k updates from fixes branch
Revision 1.9 2001/02/03 00:09:02 peter

View File

@ -1059,12 +1059,18 @@ begin
consume(_NAME);
import_name:=get_stringconst;
aktprocsym^.definition^.setmangledname(import_name);
if target_info.DllScanSupported then
current_module.externals.insert(tExternalsItem.create(import_name));
end
else
begin
{ external shouldn't override the cdecl/system name }
if not (pocall_clearstack in aktprocsym^.definition^.proccalloptions) then
aktprocsym^.definition^.setmangledname(aktprocsym^.realname);
begin
aktprocsym^.definition^.setmangledname(aktprocsym^.realname);
if target_info.DllScanSupported then
current_module.externals.insert(tExternalsItem.create(aktprocsym^.realname));
end;
end;
end;
end;
@ -1872,7 +1878,11 @@ end;
end.
{
$Log$
Revision 1.11 2001-01-08 21:40:26 peter
Revision 1.12 2001-03-06 18:28:02 peter
* patch from Pavel with a new and much faster DLL Scanner for
automatic importing so $linklib works for DLLs. Thanks Pavel!
Revision 1.11 2001/01/08 21:40:26 peter
* fixed crash with unsupported token overloading
Revision 1.10 2000/12/25 00:07:27 peter

View File

@ -402,6 +402,9 @@ implementation
end;
importlib.importvariable(aktvarsym^.mangledname,dll_name,C_name)
end
else
if target_info.DllScanSupported then
current_module.Externals.insert(tExternalsItem.create(aktvarsym^.mangledname));
end;
symdone:=true;
end
@ -538,7 +541,11 @@ implementation
end.
{
$Log$
Revision 1.9 2001-02-20 21:42:54 peter
Revision 1.10 2001-03-06 18:28:02 peter
* patch from Pavel with a new and much faster DLL Scanner for
automatic importing so $linklib works for DLLs. Thanks Pavel!
Revision 1.9 2001/02/20 21:42:54 peter
* record and object declaration with same field as type fixed
Revision 1.7 2001/02/20 11:19:45 marco

View File

@ -54,6 +54,9 @@ implementation
hcodegen,
{$ifdef i386}
cgai386,
{$ifndef NOTARGETWIN32}
t_win32,
{$endif}
{$endif i386}
{$endif newcg}
link,assemble,import,export,gendef,ppu,comprsrc,
@ -64,7 +67,43 @@ implementation
scanner,pbase,psystem,psub,parser;
procedure create_objectfile;
var
DLLScanner : TDLLScanner;
s : string;
begin
{ try to create import entries from system dlls }
if target_info.DllScanSupported and
(not current_module.linkOtherSharedLibs.Empty) then
begin
{ Init DLLScanner }
case target_info.target of
{$ifdef i386}
{$ifndef NOTARGETWIN32}
target_i386_win32 :
DLLScanner:=tDLLscannerWin32.create;
{$endif}
{$endif}
else
internalerror(769795413);
end;
{ Walk all shared libs }
While not current_module.linkOtherSharedLibs.Empty do
begin
S:=current_module.linkOtherSharedLibs.Getusemask(link_allways);
DLLScanner.scan(s)
end;
DLLscanner.Free;
{ Recreate import section }
if (target_info.target=target_i386_win32) then
begin
if assigned(importssection)then
importssection.clear
else
importssection:=taasmoutput.Create;
importlib.generatelib;
end;
end;
{ create the .s file and assemble it }
GenerateAsm(false);
@ -173,13 +212,9 @@ implementation
Inc(Count);
end;
{ TableCount }
{ doesn't work because of bug in the compiler !! (JM)
With ResourceStringTables do}
begin
ResourceStringTables.insert(Tai_const.Create_32bit(count));
ResourceStringTables.insert(Tai_symbol.Createdataname_global('FPC_RESOURCESTRINGTABLES',0));
ResourceStringTables.concat(Tai_symbol_end.Createname('FPC_RESOURCESTRINGTABLES'));
end;
ResourceStringTables.insert(Tai_const.Create_32bit(count));
ResourceStringTables.insert(Tai_symbol.Createdataname_global('FPC_RESOURCESTRINGTABLES',0));
ResourceStringTables.concat(Tai_symbol_end.Createname('FPC_RESOURCESTRINGTABLES'));
{ insert in data segment }
if (cs_create_smart in aktmoduleswitches) then
dataSegment.concat(Tai_cut.Create);
@ -1627,7 +1662,11 @@ implementation
end.
{
$Log$
Revision 1.23 2001-02-24 10:44:56 peter
Revision 1.24 2001-03-06 18:28:02 peter
* patch from Pavel with a new and much faster DLL Scanner for
automatic importing so $linklib works for DLLs. Thanks Pavel!
Revision 1.23 2001/02/24 10:44:56 peter
* generate .rst from ppufilename instead of modulename
Revision 1.22 2001/02/21 19:37:19 peter

View File

@ -214,6 +214,7 @@ interface
heapsize,
maxheapsize,
stacksize : longint;
DllScanSupported : boolean;
end;
tasmmodeinfo=packed record
@ -1080,7 +1081,8 @@ implementation
res : res_none;
heapsize : 2048*1024;
maxheapsize : 32768*1024;
stacksize : 16384
stacksize : 16384;
DllScanSupported:false
),
(
target : target_i386_GO32V2;
@ -1103,7 +1105,8 @@ implementation
res : res_none;
heapsize : 2048*1024;
maxheapsize : 32768*1024;
stacksize : 16384
stacksize : 16384;
DllScanSupported:false
),
(
target : target_i386_LINUX;
@ -1126,7 +1129,8 @@ implementation
res : res_none;
heapsize : 256*1024;
maxheapsize : 32768*1024;
stacksize : 8192
stacksize : 8192;
DllScanSupported:false
),
(
target : target_i386_FreeBSD;
@ -1149,7 +1153,8 @@ implementation
res : res_none;
heapsize : 256*1024;
maxheapsize : 32768*1024;
stacksize : 8192
stacksize : 8192;
DllScanSupported:false
),
(
target : target_i386_OS2;
@ -1172,7 +1177,8 @@ implementation
res : res_i386_emx;
heapsize : 256*1024;
maxheapsize : 32768*1024;
stacksize : 256*1024
stacksize : 256*1024;
DllScanSupported:true
),
(
target : target_i386_WIN32;
@ -1195,7 +1201,8 @@ implementation
res : res_i386_windres;
heapsize : 256*1024;
maxheapsize : 32*1024*1024;
stacksize : 32*1024*1024
stacksize : 32*1024*1024;
DllScanSupported:true
),
(
target : target_i386_NETWARE;
@ -1218,7 +1225,8 @@ implementation
res : res_none;
heapsize : 256*1024;
maxheapsize : 32768*1024;
stacksize : 8192
stacksize : 8192;
DllScanSupported:false
),
(
target : target_i386_sunos;
@ -1241,7 +1249,8 @@ implementation
res : res_none;
heapsize : 256*1024;
maxheapsize : 32768*1024;
stacksize : 8192
stacksize : 8192;
DllScanSupported:false
)
{$endif i386}
{$ifdef m68k}
@ -1266,7 +1275,8 @@ implementation
res : res_none;
heapsize : 128*1024;
maxheapsize : 32768*1024;
stacksize : 8192
stacksize : 8192;
DllScanSupported:false
),
(
target : target_m68k_Atari;
@ -1289,7 +1299,8 @@ implementation
res : res_none;
heapsize : 16*1024;
maxheapsize : 32768*1024;
stacksize : 8192
stacksize : 8192;
DllScanSupported:false
),
(
target : target_m68k_Mac;
@ -1312,7 +1323,8 @@ implementation
res : res_none;
heapsize : 128*1024;
maxheapsize : 32768*1024;
stacksize : 8192
stacksize : 8192;
DllScanSupported:false
),
(
target : target_m68k_linux;
@ -1335,7 +1347,8 @@ implementation
res : res_none;
heapsize : 128*1024;
maxheapsize : 32768*1024;
stacksize : 8192
stacksize : 8192;
DllScanSupported:false
),
(
target : target_m68k_PalmOS;
@ -1358,7 +1371,8 @@ implementation
res : res_none;
heapsize : 128*1024;
maxheapsize : 32768*1024;
stacksize : 8192
stacksize : 8192;
DllScanSupported:false
)
{$endif m68k}
{$ifdef alpha}
@ -1383,7 +1397,10 @@ implementation
res : res_none;
heapsize : 256*1024;
maxheapsize : 32768*1024;
stacksize : 8192
{*** Changes made by Ozerski at 05.03.2001}
stacksize : 8192;
DllScanSupported:false
{*** End changes}
)
{$endif}
{$ifdef powerpc}
@ -1408,7 +1425,8 @@ implementation
res : res_none;
heapsize : 256*1024;
maxheapsize : 32768*1024;
stacksize : 8192
stacksize : 8192;
DllScanSupported:false
),
(
target : target_powerpc_MACOS;
@ -1431,7 +1449,8 @@ implementation
res : res_powerpc_mpw;
heapsize : 256*1024;
maxheapsize : 32768*1024;
stacksize : 8192
stacksize : 8192;
DllScanSupported:false
)
{$endif}
);
@ -1763,7 +1782,11 @@ begin
end.
{
$Log$
Revision 1.14 2001-02-26 19:44:55 peter
Revision 1.15 2001-03-06 18:28:02 peter
* patch from Pavel with a new and much faster DLL Scanner for
automatic importing so $linklib works for DLLs. Thanks Pavel!
Revision 1.14 2001/02/26 19:44:55 peter
* merged generic m68k updates from fixes branch
Revision 1.13 2001/02/20 21:36:40 peter

View File

@ -63,6 +63,18 @@ interface
function MakeSharedLibrary:boolean;override;
end;
tDLLScannerWin32=class(tDLLScanner)
private
cstring : array[0..127]of char;
function DOSstubOK(var x:cardinal):longbool;
function FindDLL(const s:string;var founddll:string):boolean;
function DllName(Const Name : string) : string;
public
function isSuitableFileType(x:cardinal):longbool;override;
function GetEdata(HeaderEntry:cardinal):longbool;override;
function Scan(const binname:string):longbool;override;
end;
implementation
@ -74,7 +86,7 @@ implementation
{$endif Delphi}
cutils,cclasses,
aasm,fmodule,globtype,globals,systems,verbose,
script,gendef,impdef,
script,gendef,
cpubase,cpuasm
{$ifdef GDB}
,gdb
@ -92,34 +104,6 @@ implementation
end;
function FindDLL(const s:string):string;
var
sysdir : string;
FoundDll : string;
Found : boolean;
begin
Found:=false;
{ Look for DLL in:
1. Current dir
2. Library Path
3. windir,windir/system,windir/system32 }
Found:=FindFile(s,'.'+DirSep,founddll);
if (not found) then
Found:=includesearchpath.FindFile(s,founddll);
if (not found) then
begin
sysdir:=FixPath(GetEnv('windir'),false);
Found:=FindFile(s,sysdir+';'+sysdir+'system'+DirSep+';'+sysdir+'system32'+DirSep,founddll);
end;
if (not found) then
begin
message1(exec_w_libfile_not_found,s);
FoundDll:=s;
end;
FindDll:=FoundDll;
end;
{*****************************************************************************
TIMPORTLIBWIN32
*****************************************************************************}
@ -737,64 +721,15 @@ end;
Function TLinkerWin32.WriteResponseFile(isdll:boolean) : Boolean;
function do_makedef(const DllName,LibName:string):boolean;
var
CmdLine : string;
begin
if (not do_build) and
FileExists(LibName) then
begin
if GetNamedFileTime(LibName)>GetNamedFileTime(DllName) then
begin
do_makedef:=true;
exit;
end;
end;
asw_name:=FindUtil('asw');
arw_name:=FindUtil('arw');
if cs_link_extern in aktglobalswitches then
begin
CmdLine:='-l '+LibName+' -i '+DLLName;
if asw_name<>'' then
CmdLine:=CmdLine+' -a '+asw_name;
if arw_name<>'' then
CmdLine:=CmdLine+' -r '+arw_name;
do_makedef:=DoExec(FindUtil('fpimpdef'),CmdLine,false,false);
end
else
do_makedef:=makedef(DLLName,LIbName);
end;
Var
linkres : TLinkRes;
i : longint;
HPath : TStringListItem;
s,s2 : string;
found,
linklibc : boolean;
found:boolean;
begin
WriteResponseFile:=False;
{ Create static import libraries for DLL that are
included using the $linklib directive }
While not SharedLibFiles.Empty do
begin
s:=SharedLibFiles.GetFirst;
s2:=AddExtension(s,target_os.sharedlibext);
s:=target_os.libprefix+SplitName(s)+target_os.staticlibext;
if Do_makedef(FindDLL(s2),s) then
begin
if s<>''then
StaticLibFiles.insert(s);
end
else
begin
Message(exec_w_error_while_linking);
aktglobalswitches:=aktglobalswitches+[cs_link_extern];
end;
end;
{ Open link.res file }
LinkRes.Init(outputexedir+Info.ResName);
@ -838,48 +773,6 @@ begin
LinkRes.Add(')');
end;
{ Write sharedlibraries like -l<lib>, also add the needed dynamic linker
here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
if not SharedLibFiles.Empty then
begin
linklibc:=false;
LinkRes.Add('INPUT(');
While not SharedLibFiles.Empty do
begin
S:=SharedLibFiles.GetFirst;
if pos('.',s)=0 then
{ we never directly link a DLL
its allways through an import library PM }
{ libraries created by C compilers have .a extensions }
s2:=s+'.a'{ target_os.sharedlibext }
else
s2:=s;
s2:=FindLibraryFile(s2,'',found);
if found then
begin
LinkRes.Add(s2);
continue;
end;
if pos(target_os.libprefix,s)=1 then
s:=copy(s,length(target_os.libprefix)+1,255);
if s<>'c' then
begin
i:=Pos(target_os.sharedlibext,S);
if i>0 then
Delete(S,i,255);
LinkRes.Add('-l'+s);
end
else
begin
LinkRes.Add('-l'+s);
linklibc:=true;
end;
end;
{ be sure that libc is the last lib }
if linklibc then
LinkRes.Add('-lc');
LinkRes.Add(')');
end;
{ Write and Close response }
linkres.writetodisk;
linkres.done;
@ -1251,10 +1144,250 @@ begin
postprocessexecutable:=true;
end;
{****************************************************************************
TDLLScannerWin32
****************************************************************************}
function tDLLScannerWin32.DOSstubOK(var x:cardinal):longbool;
begin
blockread(f,TheWord,2,loaded);
if loaded<>2 then
DOSstubOK:=false
else
begin
DOSstubOK:=TheWord='MZ';
seek(f,$3C);
blockread(f,x,4,loaded);
if(loaded<>4)or(x>filesize(f))then
DOSstubOK:=false;
end;
end;
function TDLLScannerWin32.FindDLL(const s:string;var founddll:string):boolean;
var
sysdir : string;
Found : boolean;
begin
Found:=false;
{ Look for DLL in:
1. Current dir
2. Library Path
3. windir,windir/system,windir/system32 }
Found:=FindFile(s,'.'+DirSep,founddll);
if (not found) then
Found:=librarysearchpath.FindFile(s,founddll);
if (not found) then
begin
sysdir:=FixPath(GetEnv('windir'),false);
Found:=FindFile(s,sysdir+';'+sysdir+'system'+DirSep+';'+sysdir+'system32'+DirSep,founddll);
end;
if (not found) then
begin
message1(exec_w_libfile_not_found,s);
FoundDll:=s;
end;
FindDll:=Found;
end;
function tDLLScannerWin32.DllName(Const Name : string) : string;
var n : string;
begin
n:=Upper(SplitExtension(Name));
if (n='.DLL') or (n='.DRV') or (n='.EXE') then
DllName:=Name
else
DllName:=Name+target_os.sharedlibext;
end;
function tDLLScannerWin32.isSuitableFileType(x:cardinal):longbool;
begin
seek(f,x);
blockread(f,TheWord,2,loaded);
isSuitableFileType:=(loaded=2)and(TheWord='PE');
end;
function tDLLScannerWin32.GetEdata(HeaderEntry:cardinal):longbool;
type
TObjInfo=packed record
ObjName:array[0..7]of char;
VirtSize,
VirtAddr,
RawSize,
RawOffset,
Reloc,
LineNum:cardinal;
RelCount,
LineCount:word;
flags:cardinal;
end;
var
i:cardinal;
ObjOfs:cardinal;
Obj:TObjInfo;
APE_obj,APE_Optsize:word;
ExportRVA:cardinal;
delta:cardinal;
const
IMAGE_SCN_CNT_CODE=$00000020;
var
_d:dirstr;
_n:namestr;
_e:extstr;
function isUsedFunction(name:pchar):longbool;
var
hp:tExternalsItem;
begin
isUsedFunction:=false;
hp:=tExternalsItem(current_module.Externals.first);
while assigned(hp)do
begin
if(assigned(hp.data))and(not hp.found)then
if hp.data^=StrPas(name)then
begin
isUsedFunction:=true;
hp.found:=true;
exit;
end;
hp:=tExternalsItem(hp.next);
end;
end;
procedure Store(index:cardinal;name:pchar;isData:longbool);
begin
if not isUsedFunction(name)then
exit;
if not(current_module.uses_imports) then
begin
current_module.uses_imports:=true;
importlib.preparelib(current_module.modulename^);
end;
if IsData then
importlib.importvariable(name,_n,name)
else
importlib.importprocedure(name,_n,index,name);
end;
procedure ProcessEdata;
type
a8=array[0..7]of char;
function GetSectionName(rva:cardinal;var Flags:cardinal):a8;
var
i:cardinal;
LocObjOfs:cardinal;
LocObj:TObjInfo;
begin
GetSectionName:='';
Flags:=0;
LocObjOfs:=APE_OptSize+HeaderOffset+24;
for i:=1 to APE_obj do
begin
seek(f,LocObjOfs);
blockread(f,LocObj,sizeof(LocObj));
if(rva>=LocObj.VirtAddr)and(rva<=LocObj.VirtAddr+LocObj.RawSize)then
begin
GetSectionName:=a8(LocObj.ObjName);
Flags:=LocObj.flags;
end;
end;
end;
var
j,Fl:cardinal;
ulongval,procEntry:cardinal;
Ordinal:word;
isData:longbool;
ExpDir:packed record
flag,
stamp:cardinal;
Major,
Minor:word;
Name,
Base,
NumFuncs,
NumNames,
AddrFuncs,
AddrNames,
AddrOrds:cardinal;
end;
begin
with Obj do
begin
seek(f,RawOffset+delta);
blockread(f,ExpDir,sizeof(ExpDir));
fsplit(impname,_d,_n,_e);
for j:=0 to pred(ExpDir.NumNames)do
begin
seek(f,RawOffset-VirtAddr+ExpDir.AddrOrds+j*2);
blockread(f,Ordinal,2);
seek(f,RawOffset-VirtAddr+ExpDir.AddrFuncs+Ordinal*4);
blockread(f,ProcEntry,4);
seek(f,RawOffset-VirtAddr+ExpDir.AddrNames+j*4);
blockread(f,ulongval,4);
seek(f,RawOffset-VirtAddr+ulongval);
blockread(f,cstring,sizeof(cstring));
isData:=GetSectionName(procentry,Fl)='';
if not isData then
isData:=Fl and IMAGE_SCN_CNT_CODE<>IMAGE_SCN_CNT_CODE;
Store(succ(Ordinal),cstring,isData);
end;
end;
end;
begin
GetEdata:=false;
seek(f,HeaderEntry+120);
blockread(f,ExportRVA,4);
seek(f,HeaderEntry+6);
blockread(f,APE_Obj,2);
seek(f,HeaderEntry+20);
blockread(f,APE_OptSize,2);
ObjOfs:=APE_OptSize+HeaderOffset+24;
for i:=1 to APE_obj do
begin
seek(f,ObjOfs);
blockread(f,Obj,sizeof(Obj));
inc(ObjOfs,sizeof(Obj));
with Obj do
if(VirtAddr<=ExportRva)and(ExportRva<VirtAddr+VirtSize)then
begin
delta:=ExportRva-VirtAddr;
ProcessEdata;
GetEdata:=true;
end;
end;
end;
function tDLLScannerWin32.scan(const binname:string):longbool;
var
OldFileMode:longint;
begin
if not FindDll(DLLName(binname),impname) then
exit;
assign(f,impname);
OldFileMode:=filemode;
filemode:=0;
reset(f,1);
filemode:=OldFileMode;
if not DOSstubOK(HeaderOffset)then
scan:=false
else if not isSuitableFileType(HeaderOffset)then
scan:=false
else
scan:=GetEdata(HeaderOffset);
close(f);
end;
end.
{
$Log$
Revision 1.1 2001-02-26 19:43:11 peter
Revision 1.2 2001-03-06 18:28:02 peter
* patch from Pavel with a new and much faster DLL Scanner for
automatic importing so $linklib works for DLLs. Thanks Pavel!
Revision 1.1 2001/02/26 19:43:11 peter
* moved target units to subdir
Revision 1.10 2001/02/20 21:41:16 peter