aboutsummaryrefslogtreecommitdiffstats
path: root/src/ortho/mcode/binary_file-memory.adb
diff options
context:
space:
mode:
Diffstat (limited to 'src/ortho/mcode/binary_file-memory.adb')
-rw-r--r--src/ortho/mcode/binary_file-memory.adb47
1 files changed, 45 insertions, 2 deletions
diff --git a/src/ortho/mcode/binary_file-memory.adb b/src/ortho/mcode/binary_file-memory.adb
index c9bb8ae2d..99789c602 100644
--- a/src/ortho/mcode/binary_file-memory.adb
+++ b/src/ortho/mcode/binary_file-memory.adb
@@ -21,17 +21,60 @@ package body Binary_File.Memory is
-- Absolute section.
Sect_Abs : Section_Acc;
+ -- PLT section (for x86-64).
+ Sect_Plt : Section_Acc;
+
procedure Set_Symbol_Address (Sym : Symbol; Addr : System.Address) is
begin
- Set_Symbol_Value (Sym, To_Pc_Type (Addr));
+ if Arch = Arch_X86_64 and then Is_Symbol_Code (Sym) then
+ -- Branches are limited on x86-64 to a 32 bit offset. Create a
+ -- trampoline so that functions created outside of the module could
+ -- be reached using the standard ABI.
+ --
+ -- This works only for code, not for data. Therefore we assume that
+ -- data symbols are correctly handled.
+ declare
+ V : Unsigned_64;
+ Pc : constant Pc_Type := Sect_Plt.Pc;
+ begin
+ Set_Current_Section (Sect_Plt);
+ Prealloc (16);
+
+ -- Emit: movabs $ADDR, %r11
+ V := Unsigned_64 (To_Pc_Type (Addr));
+ Sect_Plt.Data (Pc + 0) := 16#49#;
+ Sect_Plt.Data (Pc + 1) := 16#BB#;
+ for I in Pc_Type range 0 .. 7 loop
+ Sect_Plt.Data (Pc + 2 + I) := Byte (V and 16#ff#);
+ V := Shift_Right (V, 8);
+ end loop;
+
+ -- Emit: jmp *%r11
+ Sect_Plt.Data (Pc + 10) := 16#41#;
+ Sect_Plt.Data (Pc + 11) := 16#FF#;
+ Sect_Plt.Data (Pc + 12) := 16#E3#;
+
+ Sect_Plt.Pc := Pc + 13;
+ Set_Symbol_Value (Sym, Pc);
+ Set_Section (Sym, Sect_Plt);
+ end;
+ else
+ Set_Symbol_Value (Sym, To_Pc_Type (Addr));
+ Set_Section (Sym, Sect_Abs);
+ end if;
+
+ -- Symbol is not anymore undefined.
Set_Scope (Sym, Sym_Global);
- Set_Section (Sym, Sect_Abs);
end Set_Symbol_Address;
procedure Write_Memory_Init is
begin
Create_Section (Sect_Abs, "*ABS*", Section_Exec);
Sect_Abs.Vaddr := 0;
+
+ if Arch = Arch_X86_64 then
+ Create_Section (Sect_Plt, ".plt", Section_Exec);
+ end if;
end Write_Memory_Init;
procedure Write_Memory_Relocate (Error : out Boolean)