mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-16 20:39:13 +02:00
+ Darwin support for routines imported from external libraries (not yet
ideal, we should generate stubs in all files where the routines are used -> these are automatically merged by the linker; now we generate one global symbol with a jump to a stub in unit where the routine is declared) + (not yet working) Darwin support for imported variables + Darwin support for linking
This commit is contained in:
parent
0f4ea52793
commit
e55860fdd8
@ -32,13 +32,32 @@ interface
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
|
{$ifdef gdb}
|
||||||
|
gdb,
|
||||||
|
{$endif gdb}
|
||||||
cutils,cclasses,
|
cutils,cclasses,
|
||||||
verbose,systems,globtype,globals,
|
verbose,systems,globtype,globals,
|
||||||
symconst,script,
|
symconst,script,
|
||||||
fmodule,aasmbase,aasmtai,aasmcpu,cpubase,symsym,symdef,
|
fmodule,aasmbase,aasmtai,aasmcpu,cpubase,symsym,symdef,
|
||||||
import,export,link,i_bsd;
|
import,export,link,i_bsd,
|
||||||
|
cgobj;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
tdarwinimported_item = class(timported_item)
|
||||||
|
procdef : tprocdef;
|
||||||
|
end;
|
||||||
|
|
||||||
|
timportlibdarwin=class(timportlib)
|
||||||
|
procedure preparelib(const s:string);override;
|
||||||
|
procedure importprocedure(aprocdef:tprocdef;const module:string;index:longint;const name:string);override;
|
||||||
|
procedure importvariable(vs:tvarsym;const name,module:string);override;
|
||||||
|
procedure generatelib;override;
|
||||||
|
procedure generatesmartlib;override;
|
||||||
|
private
|
||||||
|
procedure darwinimportproc(aprocdef:tprocdef;const func,module : string;index : longint;const name : string);
|
||||||
|
procedure importvariable_str(const s:string;const name,module:string);
|
||||||
|
end;
|
||||||
|
|
||||||
timportlibbsd=class(timportlib)
|
timportlibbsd=class(timportlib)
|
||||||
procedure preparelib(const s:string);override;
|
procedure preparelib(const s:string);override;
|
||||||
procedure importprocedure(aprocdef:tprocdef;const module:string;index:longint;const name:string);override;
|
procedure importprocedure(aprocdef:tprocdef;const module:string;index:longint;const name:string);override;
|
||||||
@ -68,8 +87,193 @@ implementation
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{*****************************************************************************
|
{*****************************************************************************
|
||||||
TIMPORTLIBLINUX
|
TIMPORTLIBDARWIN
|
||||||
|
*****************************************************************************}
|
||||||
|
|
||||||
|
procedure timportlibdarwin.preparelib(const s : string);
|
||||||
|
begin
|
||||||
|
if not(assigned(importssection)) then
|
||||||
|
importssection:=TAAsmoutput.create;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure timportlibdarwin.darwinimportproc(aprocdef:tprocdef;const func,module : string;index : longint;const name : string);
|
||||||
|
var
|
||||||
|
hp1 : timportlist;
|
||||||
|
hp2 : tdarwinimported_item;
|
||||||
|
begin
|
||||||
|
{ force the current mangledname }
|
||||||
|
if assigned(aprocdef) then
|
||||||
|
aprocdef.has_mangledname:=true;
|
||||||
|
{ search for the module }
|
||||||
|
hp1:=timportlist(current_module.imports.first);
|
||||||
|
{ generate a new item ? }
|
||||||
|
if not(assigned(hp1)) then
|
||||||
|
begin
|
||||||
|
{ we don't need an import section per library }
|
||||||
|
hp1:=timportlist.create('imports');
|
||||||
|
current_module.imports.concat(hp1);
|
||||||
|
end;
|
||||||
|
{ search for reuse of old import item }
|
||||||
|
hp2:=tdarwinimported_item(hp1.imported_items.first);
|
||||||
|
while assigned(hp2) do
|
||||||
|
begin
|
||||||
|
if hp2.func^=func then
|
||||||
|
break;
|
||||||
|
{ there's already another declaration refering to this imported symbol }
|
||||||
|
{ -> make this declaration refer to that entry as well }
|
||||||
|
if (hp2.name^ = name) then
|
||||||
|
begin
|
||||||
|
if not assigned(aprocdef) then
|
||||||
|
internalerror(2004010306);
|
||||||
|
if assigned(aprocdef) then
|
||||||
|
aprocdef.setmangledname(hp2.func^);
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
hp2:=tdarwinimported_item(hp2.next);
|
||||||
|
end;
|
||||||
|
if not assigned(hp2) then
|
||||||
|
begin
|
||||||
|
hp2:=tdarwinimported_item.create(func,name,index);
|
||||||
|
hp2.procdef:=aprocdef;
|
||||||
|
hp1.imported_items.concat(hp2);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure timportlibdarwin.importprocedure(aprocdef:tprocdef;const module : string;index : longint;const name : string);
|
||||||
|
begin
|
||||||
|
darwinimportproc(aprocdef,aprocdef.mangledname,module,index,name);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure timportlibdarwin.importvariable(vs:tvarsym;const name,module:string);
|
||||||
|
begin
|
||||||
|
importvariable_str(vs.mangledname,name,module);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure timportlibdarwin.importvariable_str(const s:string;const name,module:string);
|
||||||
|
var
|
||||||
|
hp1 : timportlist;
|
||||||
|
hp2 : tdarwinimported_item;
|
||||||
|
begin
|
||||||
|
{ search for the module }
|
||||||
|
hp1:=timportlist(current_module.imports.first);
|
||||||
|
{ generate a new item ? }
|
||||||
|
if not(assigned(hp1)) then
|
||||||
|
begin
|
||||||
|
hp1:=timportlist.create('imports');
|
||||||
|
current_module.imports.concat(hp1);
|
||||||
|
end;
|
||||||
|
hp2:=tdarwinimported_item.create_var(s,name);
|
||||||
|
hp2.procdef:=nil;
|
||||||
|
hp1.imported_items.concat(hp2);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure timportlibdarwin.generatesmartlib;
|
||||||
|
begin
|
||||||
|
generatelib;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure timportlibdarwin.generatelib;
|
||||||
|
var
|
||||||
|
hp1 : timportlist;
|
||||||
|
hp2 : tdarwinimported_item;
|
||||||
|
l1 : tasmsymbol;
|
||||||
|
symname: string;
|
||||||
|
mangledstring : string;
|
||||||
|
{$ifdef GDB}
|
||||||
|
importname : string;
|
||||||
|
suffix : integer;
|
||||||
|
{$endif GDB}
|
||||||
|
href : treference;
|
||||||
|
begin
|
||||||
|
hp1:=timportlist(current_module.imports.first);
|
||||||
|
while assigned(hp1) do
|
||||||
|
begin
|
||||||
|
hp2:=tdarwinimported_item(hp1.imported_items.first);
|
||||||
|
while assigned(hp2) do
|
||||||
|
begin
|
||||||
|
if not assigned(hp2.name) then
|
||||||
|
internalerror(2004010302);
|
||||||
|
symname := hp2.name^;
|
||||||
|
if assigned(tdarwinimported_item(hp2).procdef) and
|
||||||
|
(tdarwinimported_item(hp2).procdef.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
|
||||||
|
symname := target_info.Cprefix+symname;
|
||||||
|
if not hp2.is_var then
|
||||||
|
begin
|
||||||
|
{$IfDef GDB}
|
||||||
|
if (cs_debuginfo in aktmoduleswitches) then
|
||||||
|
importssection.concat(tai_stab_function_name.create(nil));
|
||||||
|
{$EndIf GDB}
|
||||||
|
if not assigned(hp2.procdef) then
|
||||||
|
internalerror(2004010306);
|
||||||
|
mangledstring := hp2.func^;
|
||||||
|
if (po_public in hp2.procdef.procoptions) then
|
||||||
|
begin
|
||||||
|
importsSection.concat(Tai_section.Create(sec_code));
|
||||||
|
importsSection.concat(Tai_symbol.createname_global(mangledstring,0));
|
||||||
|
mangledstring := '_$'+mangledstring;
|
||||||
|
importsSection.concat(taicpu.op_sym(A_B,objectlibrary.newasmsymbol(mangledstring)));
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
importsSection.concat(Tai_section.Create(sec_data));
|
||||||
|
importsSection.concat(Tai_direct.create(strpnew('.section __TEXT,__symbol_stub1,symbol_stubs,pure_instructions,16')));
|
||||||
|
importsSection.concat(Tai_align.Create(4));
|
||||||
|
importsSection.concat(Tai_symbol.Createname(mangledstring,0));
|
||||||
|
importsSection.concat(Tai_direct.create(strpnew((#9+'.indirect_symbol ')+symname)));
|
||||||
|
l1 := objectlibrary.newasmsymbol(mangledstring+'$lazy_ptr');
|
||||||
|
reference_reset_symbol(href,l1,0);
|
||||||
|
{$IfDef GDB}
|
||||||
|
if (cs_debuginfo in aktmoduleswitches) and assigned(hp2.procdef) then
|
||||||
|
begin
|
||||||
|
mangledstring:=hp2.procdef.mangledname;
|
||||||
|
hp2.procdef.setmangledname(mangledstring);
|
||||||
|
hp2.procdef.concatstabto(importssection);
|
||||||
|
hp2.procdef.setmangledname(mangledstring);
|
||||||
|
end;
|
||||||
|
{$EndIf GDB}
|
||||||
|
{$ifdef CPUPOWERPC}
|
||||||
|
href.symaddr := refs_ha;
|
||||||
|
importsSection.concat(taicpu.op_reg_ref(A_LIS,NR_R11,href));
|
||||||
|
href.symaddr := refs_l;
|
||||||
|
href.base := NR_R11;
|
||||||
|
importsSection.concat(taicpu.op_reg_ref(A_LWZU,NR_R12,href));
|
||||||
|
importsSection.concat(taicpu.op_reg(A_MTCTR,NR_R12));
|
||||||
|
importsSection.concat(taicpu.op_none(A_BCTR));
|
||||||
|
{$else CPUPOWERPC}
|
||||||
|
{$error fixme for darwin x86}
|
||||||
|
{$endif CPUPOWERPC}
|
||||||
|
importsSection.concat(Tai_section.Create(sec_data));
|
||||||
|
importsSection.concat(Tai_direct.create(strpnew('.lazy_symbol_pointer')));
|
||||||
|
importsSection.concat(Tai_symbol.Create(l1,0));
|
||||||
|
importsSection.concat(Tai_direct.create(strpnew((#9+'.indirect_symbol ')+symname)));
|
||||||
|
importsSection.concat(tai_const_symbol.createname(strpnew('dyld_stub_binding_helper')));
|
||||||
|
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
importsSection.concat(Tai_section.Create(sec_data));
|
||||||
|
importsSection.concat(Tai_direct.create(strpnew('.non_lazy_symbol_pointer')));
|
||||||
|
importsSection.concat(Tai_symbol.Createname(hp2.func^,0));
|
||||||
|
importsSection.concat(Tai_direct.create(strpnew((#9+'.indirect_symbol ')+hp2.name^)));
|
||||||
|
importsSection.concat(Tai_const.create_32bit(0));
|
||||||
|
end;
|
||||||
|
hp2:=tdarwinimported_item(hp2.next);
|
||||||
|
end;
|
||||||
|
hp1:=timportlist(hp1.next);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
{*****************************************************************************
|
||||||
|
TIMPORTLIBBSD
|
||||||
*****************************************************************************}
|
*****************************************************************************}
|
||||||
|
|
||||||
procedure timportlibbsd.preparelib(const s : string);
|
procedure timportlibbsd.preparelib(const s : string);
|
||||||
@ -107,7 +311,7 @@ end;
|
|||||||
|
|
||||||
|
|
||||||
{*****************************************************************************
|
{*****************************************************************************
|
||||||
TEXPORTLIBLINUX
|
TEXPORTLIBBSD
|
||||||
*****************************************************************************}
|
*****************************************************************************}
|
||||||
|
|
||||||
procedure texportlibbsd.preparelib(const s:string);
|
procedure texportlibbsd.preparelib(const s:string);
|
||||||
@ -196,8 +400,12 @@ end;
|
|||||||
Constructor TLinkerBSD.Create;
|
Constructor TLinkerBSD.Create;
|
||||||
begin
|
begin
|
||||||
Inherited Create;
|
Inherited Create;
|
||||||
IF NOT Dontlinkstdlibpath Then
|
if not Dontlinkstdlibpath Then
|
||||||
LibrarySearchPath.AddPath('/lib;/usr/lib;/usr/X11R6/lib',true);
|
if (target_info.system <> system_powerpc_darwin) then
|
||||||
|
LibrarySearchPath.AddPath('/lib;/usr/lib;/usr/X11R6/lib',true)
|
||||||
|
else
|
||||||
|
{ Mac OS X doesn't have a /lib }
|
||||||
|
LibrarySearchPath.AddPath('/usr/lib',true)
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -207,22 +415,12 @@ procedure TLinkerBSD.SetDefaultInfo;
|
|||||||
}
|
}
|
||||||
begin
|
begin
|
||||||
LibrarySuffix:=' ';
|
LibrarySuffix:=' ';
|
||||||
{$ifdef NETBSD}
|
LdSupportsNoResponseFile := (target_info.system in [system_m68k_netbsd,system_powerpc_darwin]);
|
||||||
{$ifdef M68K}
|
|
||||||
LdSupportsNoResponseFile:=true;
|
|
||||||
{$else : not M68K}
|
|
||||||
LdSupportsNoResponseFile:=false;
|
|
||||||
{$endif M68K}
|
|
||||||
{$else : not NETBSD}
|
|
||||||
LdSupportsNoResponseFile:=false;
|
|
||||||
{$endif NETBSD}
|
|
||||||
with Info do
|
with Info do
|
||||||
begin
|
begin
|
||||||
if LdSupportsNoResponseFile then
|
if LdSupportsNoResponseFile then
|
||||||
begin
|
begin
|
||||||
ExeCmd[1]:='ld $OPT $DYNLINK $STATIC $STRIP -L. -o $EXE `cat $RES`';
|
ExeCmd[1]:='ld $OPT $DYNLINK $STATIC $STRIP -L. -o $EXE `cat $RES`';
|
||||||
{ We need external linking to interpret the `cat $RES` PM }
|
|
||||||
include(aktglobalswitches,cs_link_extern);
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
ExeCmd[1]:='ld $OPT $DYNLINK $STATIC $STRIP -L. -o $EXE $RES';
|
ExeCmd[1]:='ld $OPT $DYNLINK $STATIC $STRIP -L. -o $EXE $RES';
|
||||||
@ -266,32 +464,44 @@ Var
|
|||||||
begin
|
begin
|
||||||
WriteResponseFile:=False;
|
WriteResponseFile:=False;
|
||||||
{ set special options for some targets }
|
{ set special options for some targets }
|
||||||
linkdynamic:=not(SharedLibFiles.empty);
|
if target_info.system <> system_powerpc_darwin then
|
||||||
linklibc:=(SharedLibFiles.Find('c')<>nil);
|
begin
|
||||||
prtobj:='prt0';
|
linkdynamic:=not(SharedLibFiles.empty);
|
||||||
cprtobj:='cprt0';
|
linklibc:=(SharedLibFiles.Find('c')<>nil);
|
||||||
gprtobj:='gprt0';
|
prtobj:='prt0';
|
||||||
if glibc21 then
|
cprtobj:='cprt0';
|
||||||
begin
|
gprtobj:='gprt0';
|
||||||
cprtobj:='cprt21';
|
if glibc21 then
|
||||||
gprtobj:='gprt21';
|
begin
|
||||||
end;
|
cprtobj:='cprt21';
|
||||||
if cs_profile in aktmoduleswitches then
|
gprtobj:='gprt21';
|
||||||
begin
|
end;
|
||||||
prtobj:=gprtobj;
|
if cs_profile in aktmoduleswitches then
|
||||||
{
|
begin
|
||||||
if not glibc2 then
|
prtobj:=gprtobj;
|
||||||
AddSharedLibrary('gmon');
|
{
|
||||||
}
|
if not glibc2 then
|
||||||
AddSharedLibrary('c');
|
AddSharedLibrary('gmon');
|
||||||
LibrarySuffix:='p';
|
}
|
||||||
linklibc:=true;
|
AddSharedLibrary('c');
|
||||||
end
|
LibrarySuffix:='p';
|
||||||
|
linklibc:=true;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
if linklibc then
|
||||||
|
prtobj:=cprtobj;
|
||||||
|
end;
|
||||||
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
if linklibc then
|
{ for darwin: always link dynamically against libc }
|
||||||
prtobj:=cprtobj;
|
linklibc := true;
|
||||||
end;
|
if not(cs_profile in aktmoduleswitches) then
|
||||||
|
prtobj:='/usr/lib/crt1.o'
|
||||||
|
else
|
||||||
|
prtobj:='/usr/lib/gcrt1.o';
|
||||||
|
end;
|
||||||
|
|
||||||
{ Open link.res file }
|
{ Open link.res file }
|
||||||
LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
|
LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
|
||||||
@ -322,7 +532,8 @@ begin
|
|||||||
if prtobj<>'' then
|
if prtobj<>'' then
|
||||||
LinkRes.AddFileName(FindObjectFile(prtobj,'',false));
|
LinkRes.AddFileName(FindObjectFile(prtobj,'',false));
|
||||||
{ try to add crti and crtbegin if linking to C }
|
{ try to add crti and crtbegin if linking to C }
|
||||||
if linklibc then
|
if linklibc and
|
||||||
|
(target_info.system <> system_powerpc_darwin) then
|
||||||
begin
|
begin
|
||||||
if librarysearchpath.FindFile('crtbegin.o',s) then
|
if librarysearchpath.FindFile('crtbegin.o',s) then
|
||||||
LinkRes.AddFileName(s);
|
LinkRes.AddFileName(s);
|
||||||
@ -392,7 +603,8 @@ begin
|
|||||||
LinkRes.Add(')');
|
LinkRes.Add(')');
|
||||||
end;
|
end;
|
||||||
{ objects which must be at the end }
|
{ objects which must be at the end }
|
||||||
if linklibc then
|
if linklibc and
|
||||||
|
(target_info.system <> system_powerpc_darwin) then
|
||||||
begin
|
begin
|
||||||
Fl1:=librarysearchpath.FindFile('crtend.o',s1);
|
Fl1:=librarysearchpath.FindFile('crtend.o',s1);
|
||||||
Fl2:=librarysearchpath.FindFile('crtn.o',s2);
|
Fl2:=librarysearchpath.FindFile('crtn.o',s2);
|
||||||
@ -458,7 +670,7 @@ begin
|
|||||||
Replace(cmdstr,'$STATIC',StaticStr);
|
Replace(cmdstr,'$STATIC',StaticStr);
|
||||||
Replace(cmdstr,'$STRIP',StripStr);
|
Replace(cmdstr,'$STRIP',StripStr);
|
||||||
Replace(cmdstr,'$DYNLINK',DynLinkStr);
|
Replace(cmdstr,'$DYNLINK',DynLinkStr);
|
||||||
success:=DoExec(FindUtil(utilsprefix+BinStr),CmdStr,true,false);
|
success:=DoExec(FindUtil(utilsprefix+BinStr),CmdStr,true,LdSupportsNoResponseFile);
|
||||||
|
|
||||||
{ Remove ReponseFile }
|
{ Remove ReponseFile }
|
||||||
if (success) and not(cs_link_extern in aktglobalswitches) then
|
if (success) and not(cs_link_extern in aktglobalswitches) then
|
||||||
@ -529,7 +741,7 @@ initialization
|
|||||||
{$ifdef powerpc}
|
{$ifdef powerpc}
|
||||||
// RegisterExternalLinker(system_m68k_FreeBSD_info,TLinkerBSD);
|
// RegisterExternalLinker(system_m68k_FreeBSD_info,TLinkerBSD);
|
||||||
RegisterExternalLinker(system_powerpc_darwin_info,TLinkerBSD);
|
RegisterExternalLinker(system_powerpc_darwin_info,TLinkerBSD);
|
||||||
RegisterImport(system_powerpc_darwin,timportlibbsd);
|
RegisterImport(system_powerpc_darwin,timportlibdarwin);
|
||||||
RegisterExport(system_powerpc_darwin,texportlibbsd);
|
RegisterExport(system_powerpc_darwin,texportlibbsd);
|
||||||
RegisterTarget(system_powerpc_darwin_info);
|
RegisterTarget(system_powerpc_darwin_info);
|
||||||
RegisterExternalLinker(system_powerpc_netbsd_info,TLinkerBSD);
|
RegisterExternalLinker(system_powerpc_netbsd_info,TLinkerBSD);
|
||||||
@ -540,7 +752,16 @@ initialization
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.5 2003-10-30 18:35:30 marco
|
Revision 1.6 2004-01-04 21:26:31 jonas
|
||||||
|
+ Darwin support for routines imported from external libraries (not yet
|
||||||
|
ideal, we should generate stubs in all files where the routines are
|
||||||
|
used -> these are automatically merged by the linker; now we generate
|
||||||
|
one global symbol with a jump to a stub in unit where the routine is
|
||||||
|
declared)
|
||||||
|
+ (not yet working) Darwin support for imported variables
|
||||||
|
+ Darwin support for linking
|
||||||
|
|
||||||
|
Revision 1.5 2003/10/30 18:35:30 marco
|
||||||
* librarysuffix + profiling
|
* librarysuffix + profiling
|
||||||
|
|
||||||
Revision 1.4 2003/10/11 19:32:04 marco
|
Revision 1.4 2003/10/11 19:32:04 marco
|
||||||
|
Loading…
Reference in New Issue
Block a user