* fixed GOT loading for i386 in stubs for external procedures whose external

name is (re)defined in the implementation (mantis #14221)

git-svn-id: trunk@13469 -
This commit is contained in:
Jonas Maebe 2009-07-28 17:28:17 +00:00
parent 1ca34ee146
commit f265fbe343
5 changed files with 37 additions and 14 deletions

View File

@ -484,7 +484,7 @@ unit cgobj;
procedure g_external_wrapper(list : TAsmList; procdef: tprocdef; const externalname: string); virtual; procedure g_external_wrapper(list : TAsmList; procdef: tprocdef; const externalname: string); virtual;
{ initialize the pic/got register } { initialize the pic/got register }
procedure g_maybe_got_init(list: TAsmList); virtual; function g_maybe_got_init(list: TAsmList; force: boolean): tregister; virtual;
protected protected
procedure get_subsetref_load_info(const sref: tsubsetreference; out loadsize: tcgsize; out extra_load: boolean); procedure get_subsetref_load_info(const sref: tsubsetreference; out loadsize: tcgsize; out extra_load: boolean);
procedure a_load_subsetref_regs_noindex(list: TAsmList; subsetsize: tcgsize; loadbitsize: byte; const sref: tsubsetreference; valuereg, extra_value_reg: tregister); virtual; procedure a_load_subsetref_regs_noindex(list: TAsmList; subsetsize: tcgsize; loadbitsize: byte; const sref: tsubsetreference; valuereg, extra_value_reg: tregister); virtual;
@ -3832,8 +3832,9 @@ implementation
end; end;
procedure tcg.g_maybe_got_init(list: TAsmList); function tcg.g_maybe_got_init(list: TAsmList; force: boolean): tregister;
begin begin
result:=NR_NO;
end; end;

View File

@ -52,7 +52,7 @@ unit cgcpu;
procedure g_exception_reason_save_const(list : TAsmList; const href : treference; a: aint);override; procedure g_exception_reason_save_const(list : TAsmList; const href : treference; a: aint);override;
procedure g_exception_reason_load(list : TAsmList; const href : treference);override; procedure g_exception_reason_load(list : TAsmList; const href : treference);override;
procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override; procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
procedure g_maybe_got_init(list: TAsmList); override; function g_maybe_got_init(list: TAsmList; force: boolean): tregister; override;
end; end;
tcg64f386 = class(tcg64f32) tcg64f386 = class(tcg64f32)
@ -494,12 +494,13 @@ unit cgcpu;
end; end;
procedure tcg386.g_maybe_got_init(list: TAsmList); function tcg386.g_maybe_got_init(list: TAsmList; force: boolean): tregister;
begin begin
{ allocate PIC register } { allocate PIC register }
if (cs_create_pic in current_settings.moduleswitches) and if (cs_create_pic in current_settings.moduleswitches) and
(tf_pic_uses_got in target_info.flags) and (tf_pic_uses_got in target_info.flags) and
(pi_needs_got in current_procinfo.flags) then (force or
(pi_needs_got in current_procinfo.flags)) then
begin begin
if (target_info.system<>system_i386_darwin) then if (target_info.system<>system_i386_darwin) then
begin begin
@ -507,11 +508,14 @@ unit cgcpu;
cg.a_call_name_static(list,'fpc_geteipasebx'); cg.a_call_name_static(list,'fpc_geteipasebx');
list.concat(taicpu.op_sym_ofs_reg(A_ADD,S_L,current_asmdata.RefAsmSymbol('_GLOBAL_OFFSET_TABLE_'),0,NR_PIC_OFFSET_REG)); list.concat(taicpu.op_sym_ofs_reg(A_ADD,S_L,current_asmdata.RefAsmSymbol('_GLOBAL_OFFSET_TABLE_'),0,NR_PIC_OFFSET_REG));
list.concat(tai_regalloc.alloc(NR_PIC_OFFSET_REG,nil)); list.concat(tai_regalloc.alloc(NR_PIC_OFFSET_REG,nil));
{ ecx could be used in leaf procedures } { ecx could be used for a parameter register }
current_procinfo.got:=NR_EBX; result:=NR_EBX;
end end
else else
begin begin
{ is not called for darwin/i386 for external stubs }
if not assigned(current_procinfo) then
internalerror(2009072801);
{ can't use ecx, since that one may overwrite a parameter } { can't use ecx, since that one may overwrite a parameter }
current_module.requires_ebx_pic_helper:=true; current_module.requires_ebx_pic_helper:=true;
cg.a_call_name_static(list,'fpc_geteipasebx'); cg.a_call_name_static(list,'fpc_geteipasebx');
@ -520,6 +524,7 @@ unit cgcpu;
{ got is already set by ti386procinfo.allocate_got_register } { got is already set by ti386procinfo.allocate_got_register }
list.concat(tai_regalloc.dealloc(NR_EBX,nil)); list.concat(tai_regalloc.dealloc(NR_EBX,nil));
a_load_reg_reg(list,OS_ADDR,OS_ADDR,NR_EBX,current_procinfo.got); a_load_reg_reg(list,OS_ADDR,OS_ADDR,NR_EBX,current_procinfo.got);
result:=current_procinfo.got;
end; end;
end; end;
end; end;

View File

@ -62,7 +62,7 @@ unit cgppc;
procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override; procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
procedure g_maybe_got_init(list: TAsmList); override; function g_maybe_got_init(list: TAsmList; force: boolean): tregister; override;
protected protected
function get_darwin_call_stub(const s: string; weak: boolean): tasmsymbol; function get_darwin_call_stub(const s: string; weak: boolean): tasmsymbol;
procedure a_load_subsetref_regs_noindex(list: TAsmList; subsetsize: tcgsize; loadbitsize: byte; const sref: tsubsetreference; valuereg, extra_value_reg: tregister); override; procedure a_load_subsetref_regs_noindex(list: TAsmList; subsetsize: tcgsize; loadbitsize: byte; const sref: tsubsetreference; valuereg, extra_value_reg: tregister); override;
@ -204,16 +204,19 @@ unit cgppc;
end; end;
procedure tcgppcgen.g_maybe_got_init(list: TAsmList); function tcgppcgen.g_maybe_got_init(list: TAsmList; force: boolean): tregister;
var var
instr: taicpu; instr: taicpu;
cond: tasmcond; cond: tasmcond;
savedlr: boolean; savedlr: boolean;
begin begin
if not assigned(current_procinfo) then
internalerror(2009072802);
if not(po_assembler in current_procinfo.procdef.procoptions) then if not(po_assembler in current_procinfo.procdef.procoptions) then
begin begin
if (cs_create_pic in current_settings.moduleswitches) and if (cs_create_pic in current_settings.moduleswitches) and
(pi_needs_got in current_procinfo.flags) then (force or
(pi_needs_got in current_procinfo.flags)) then
case target_info.system of case target_info.system of
system_powerpc_darwin, system_powerpc_darwin,
system_powerpc64_darwin: system_powerpc64_darwin:
@ -237,6 +240,7 @@ unit cgppc;
{ procedures) } { procedures) }
not(pi_do_call in current_procinfo.flags) then not(pi_do_call in current_procinfo.flags) then
list.concat(taicpu.op_reg_reg(A_MTSPR,NR_LR,NR_R0)); list.concat(taicpu.op_reg_reg(A_MTSPR,NR_LR,NR_R0));
result:=current_procinfo.got;
end; end;
end; end;
end; end;

View File

@ -1026,7 +1026,7 @@ implementation
cg.set_regalloc_live_range_direction(rad_backwards_reinit); cg.set_regalloc_live_range_direction(rad_backwards_reinit);
current_filepos:=entrypos; current_filepos:=entrypos;
{ load got if necessary } { load got if necessary }
cg.g_maybe_got_init(templist); current_procinfo.got:=cg.g_maybe_got_init(templist,false);
aktproccode.insertlistafter(headertai,templist); aktproccode.insertlistafter(headertai,templist);

View File

@ -2124,11 +2124,24 @@ unit cgx86;
{ darwin/x86_64's assembler doesn't want @PLT after call symbols } { darwin/x86_64's assembler doesn't want @PLT after call symbols }
(target_info.system<>system_x86_64_darwin) then (target_info.system<>system_x86_64_darwin) then
begin begin
ref.refaddr:=addr_pic;
{$ifdef i386}
{ it could be that we're called from a procedure not having the { it could be that we're called from a procedure not having the
got loaded got loaded. Since all volatile registers can contain parameters,
we have to use the stack.
} }
g_maybe_got_init(list); list.concat(taicpu.op_reg(A_PUSH,S_L,NR_EBX));
ref.refaddr:=addr_pic ref.base:=g_maybe_got_init(list,true);
if (ref.base<>NR_EBX) then
internalerror(2009072801);
list.concat(taicpu.op_ref_reg(A_MOV,S_L,ref,NR_EBX));
reference_reset_base(ref,NR_ESP,0,sizeof(pint));
{ restore ebx to its original value, and place target address
on the stack }
list.concat(taicpu.op_reg_ref(A_XCHG,S_L,NR_EBX,ref));
list.concat(taicpu.op_none(A_RET));
exit;
{$endif i386}
end end
else else
ref.refaddr:=addr_full; ref.refaddr:=addr_full;