mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-16 12:59:24 +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
|
||||
|
||||
uses
|
||||
{$ifdef gdb}
|
||||
gdb,
|
||||
{$endif gdb}
|
||||
cutils,cclasses,
|
||||
verbose,systems,globtype,globals,
|
||||
symconst,script,
|
||||
fmodule,aasmbase,aasmtai,aasmcpu,cpubase,symsym,symdef,
|
||||
import,export,link,i_bsd;
|
||||
import,export,link,i_bsd,
|
||||
cgobj;
|
||||
|
||||
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)
|
||||
procedure preparelib(const s:string);override;
|
||||
procedure importprocedure(aprocdef:tprocdef;const module:string;index:longint;const name:string);override;
|
||||
@ -68,8 +87,193 @@ implementation
|
||||
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);
|
||||
@ -107,7 +311,7 @@ end;
|
||||
|
||||
|
||||
{*****************************************************************************
|
||||
TEXPORTLIBLINUX
|
||||
TEXPORTLIBBSD
|
||||
*****************************************************************************}
|
||||
|
||||
procedure texportlibbsd.preparelib(const s:string);
|
||||
@ -196,8 +400,12 @@ end;
|
||||
Constructor TLinkerBSD.Create;
|
||||
begin
|
||||
Inherited Create;
|
||||
IF NOT Dontlinkstdlibpath Then
|
||||
LibrarySearchPath.AddPath('/lib;/usr/lib;/usr/X11R6/lib',true);
|
||||
if not Dontlinkstdlibpath Then
|
||||
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;
|
||||
|
||||
|
||||
@ -207,22 +415,12 @@ procedure TLinkerBSD.SetDefaultInfo;
|
||||
}
|
||||
begin
|
||||
LibrarySuffix:=' ';
|
||||
{$ifdef NETBSD}
|
||||
{$ifdef M68K}
|
||||
LdSupportsNoResponseFile:=true;
|
||||
{$else : not M68K}
|
||||
LdSupportsNoResponseFile:=false;
|
||||
{$endif M68K}
|
||||
{$else : not NETBSD}
|
||||
LdSupportsNoResponseFile:=false;
|
||||
{$endif NETBSD}
|
||||
LdSupportsNoResponseFile := (target_info.system in [system_m68k_netbsd,system_powerpc_darwin]);
|
||||
with Info do
|
||||
begin
|
||||
if LdSupportsNoResponseFile then
|
||||
begin
|
||||
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
|
||||
else
|
||||
ExeCmd[1]:='ld $OPT $DYNLINK $STATIC $STRIP -L. -o $EXE $RES';
|
||||
@ -266,32 +464,44 @@ Var
|
||||
begin
|
||||
WriteResponseFile:=False;
|
||||
{ set special options for some targets }
|
||||
linkdynamic:=not(SharedLibFiles.empty);
|
||||
linklibc:=(SharedLibFiles.Find('c')<>nil);
|
||||
prtobj:='prt0';
|
||||
cprtobj:='cprt0';
|
||||
gprtobj:='gprt0';
|
||||
if glibc21 then
|
||||
begin
|
||||
cprtobj:='cprt21';
|
||||
gprtobj:='gprt21';
|
||||
end;
|
||||
if cs_profile in aktmoduleswitches then
|
||||
begin
|
||||
prtobj:=gprtobj;
|
||||
{
|
||||
if not glibc2 then
|
||||
AddSharedLibrary('gmon');
|
||||
}
|
||||
AddSharedLibrary('c');
|
||||
LibrarySuffix:='p';
|
||||
linklibc:=true;
|
||||
end
|
||||
if target_info.system <> system_powerpc_darwin then
|
||||
begin
|
||||
linkdynamic:=not(SharedLibFiles.empty);
|
||||
linklibc:=(SharedLibFiles.Find('c')<>nil);
|
||||
prtobj:='prt0';
|
||||
cprtobj:='cprt0';
|
||||
gprtobj:='gprt0';
|
||||
if glibc21 then
|
||||
begin
|
||||
cprtobj:='cprt21';
|
||||
gprtobj:='gprt21';
|
||||
end;
|
||||
if cs_profile in aktmoduleswitches then
|
||||
begin
|
||||
prtobj:=gprtobj;
|
||||
{
|
||||
if not glibc2 then
|
||||
AddSharedLibrary('gmon');
|
||||
}
|
||||
AddSharedLibrary('c');
|
||||
LibrarySuffix:='p';
|
||||
linklibc:=true;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if linklibc then
|
||||
prtobj:=cprtobj;
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if linklibc then
|
||||
prtobj:=cprtobj;
|
||||
end;
|
||||
begin
|
||||
{ for darwin: always link dynamically against libc }
|
||||
linklibc := true;
|
||||
if not(cs_profile in aktmoduleswitches) then
|
||||
prtobj:='/usr/lib/crt1.o'
|
||||
else
|
||||
prtobj:='/usr/lib/gcrt1.o';
|
||||
end;
|
||||
|
||||
{ Open link.res file }
|
||||
LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
|
||||
@ -322,7 +532,8 @@ begin
|
||||
if prtobj<>'' then
|
||||
LinkRes.AddFileName(FindObjectFile(prtobj,'',false));
|
||||
{ try to add crti and crtbegin if linking to C }
|
||||
if linklibc then
|
||||
if linklibc and
|
||||
(target_info.system <> system_powerpc_darwin) then
|
||||
begin
|
||||
if librarysearchpath.FindFile('crtbegin.o',s) then
|
||||
LinkRes.AddFileName(s);
|
||||
@ -392,7 +603,8 @@ begin
|
||||
LinkRes.Add(')');
|
||||
end;
|
||||
{ objects which must be at the end }
|
||||
if linklibc then
|
||||
if linklibc and
|
||||
(target_info.system <> system_powerpc_darwin) then
|
||||
begin
|
||||
Fl1:=librarysearchpath.FindFile('crtend.o',s1);
|
||||
Fl2:=librarysearchpath.FindFile('crtn.o',s2);
|
||||
@ -458,7 +670,7 @@ begin
|
||||
Replace(cmdstr,'$STATIC',StaticStr);
|
||||
Replace(cmdstr,'$STRIP',StripStr);
|
||||
Replace(cmdstr,'$DYNLINK',DynLinkStr);
|
||||
success:=DoExec(FindUtil(utilsprefix+BinStr),CmdStr,true,false);
|
||||
success:=DoExec(FindUtil(utilsprefix+BinStr),CmdStr,true,LdSupportsNoResponseFile);
|
||||
|
||||
{ Remove ReponseFile }
|
||||
if (success) and not(cs_link_extern in aktglobalswitches) then
|
||||
@ -529,7 +741,7 @@ initialization
|
||||
{$ifdef powerpc}
|
||||
// RegisterExternalLinker(system_m68k_FreeBSD_info,TLinkerBSD);
|
||||
RegisterExternalLinker(system_powerpc_darwin_info,TLinkerBSD);
|
||||
RegisterImport(system_powerpc_darwin,timportlibbsd);
|
||||
RegisterImport(system_powerpc_darwin,timportlibdarwin);
|
||||
RegisterExport(system_powerpc_darwin,texportlibbsd);
|
||||
RegisterTarget(system_powerpc_darwin_info);
|
||||
RegisterExternalLinker(system_powerpc_netbsd_info,TLinkerBSD);
|
||||
@ -540,7 +752,16 @@ initialization
|
||||
end.
|
||||
{
|
||||
$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
|
||||
|
||||
Revision 1.4 2003/10/11 19:32:04 marco
|
||||
|
Loading…
Reference in New Issue
Block a user