diff options
author | Tristan Gingold | 2016-01-05 06:44:53 +0100 |
---|---|---|
committer | Tristan Gingold | 2016-01-06 18:38:37 +0100 |
commit | b5797a5cef6d25817da7998f6263afa53e196d25 (patch) | |
tree | ad3b67a93d16e8a06fab2d7a8c4d8993ff101b8a /src/ortho/mcode/binary_file-elf.adb | |
parent | 955e964b024de556c4c0db8fd745c6abdb8052fe (diff) | |
download | ghdl-b5797a5cef6d25817da7998f6263afa53e196d25.tar.gz ghdl-b5797a5cef6d25817da7998f6263afa53e196d25.tar.bz2 ghdl-b5797a5cef6d25817da7998f6263afa53e196d25.zip |
mcode: add support for x86-64
Diffstat (limited to 'src/ortho/mcode/binary_file-elf.adb')
-rw-r--r-- | src/ortho/mcode/binary_file-elf.adb | 323 |
1 files changed, 167 insertions, 156 deletions
diff --git a/src/ortho/mcode/binary_file-elf.adb b/src/ortho/mcode/binary_file-elf.adb index 94f04e3..4732af9 100644 --- a/src/ortho/mcode/binary_file-elf.adb +++ b/src/ortho/mcode/binary_file-elf.adb @@ -18,6 +18,8 @@ with Ada.Text_IO; use Ada.Text_IO; with Elf_Common; with Elf32; +with Elf64; +with Elf_Arch; package body Binary_File.Elf is NUL : Character renames ASCII.NUL; @@ -25,13 +27,14 @@ package body Binary_File.Elf is type Arch_Bool is array (Arch_Kind) of Boolean; Is_Rela : constant Arch_Bool := (Arch_Unknown => False, Arch_X86 => False, + Arch_X86_64 => True, Arch_Sparc => True, Arch_Ppc => True); procedure Write (Fd : GNAT.OS_Lib.File_Descriptor) is use Elf_Common; - use Elf32; + use Elf_Arch; use GNAT.OS_Lib; procedure Xwrite (Data : System.Address; Len : Natural) is @@ -41,22 +44,22 @@ package body Binary_File.Elf is end if; end Xwrite; - procedure Check_File_Pos (Off : Elf32_Off) + procedure Check_File_Pos (Off : Elf_Off) is L : Long_Integer; begin L := File_Length (Fd); if L /= Long_Integer (Off) then Put_Line (Standard_Error, "check_file_pos error: expect " - & Elf32_Off'Image (Off) & ", found " + & Elf_Off'Image (Off) & ", found " & Long_Integer'Image (L)); raise Write_Error; end if; end Check_File_Pos; - function Sect_Align (V : Elf32_Off) return Elf32_Off + function Sect_Align (V : Elf_Off) return Elf_Off is - Tmp : Elf32_Off; + Tmp : Elf_Off; begin Tmp := V + 2 ** 2 - 1; return Tmp - (Tmp mod 2 ** 2); @@ -65,14 +68,14 @@ package body Binary_File.Elf is type Section_Info_Type is record Sect : Section_Acc; -- Index of the section symbol (in symtab). - Sym : Elf32_Word; + Sym : Elf_Word; -- Number of relocs to write. --Nbr_Relocs : Natural; end record; type Section_Info_Array is array (Natural range <>) of Section_Info_Type; Sections : Section_Info_Array (0 .. 3 + 2 * Nbr_Sections); - type Elf32_Shdr_Array is array (Natural range <>) of Elf32_Shdr; - Shdr : Elf32_Shdr_Array (0 .. 3 + 2 * Nbr_Sections); + type Elf_Shdr_Array is array (Natural range <>) of Elf_Shdr; + Shdr : Elf_Shdr_Array (0 .. 3 + 2 * Nbr_Sections); Nbr_Sect : Natural; Sect : Section_Acc; @@ -83,7 +86,7 @@ package body Binary_File.Elf is Sect_Strtab : constant Natural := 3; Sect_First : constant Natural := 4; - Offset : Elf32_Off; + Offset : Elf_Off; -- Size of a relocation entry. Rel_Size : Natural; @@ -104,87 +107,90 @@ package body Binary_File.Elf is -- Set size of a relocation entry. This avoids severals conditionnal. if Is_Rela (Arch) then - Rel_Size := Elf32_Rela_Size; + Rel_Size := Elf_Rela_Size; else - Rel_Size := Elf32_Rel_Size; + Rel_Size := Elf_Rel_Size; end if; -- Set section header. -- SHT_NULL. Shdr (Sect_Null) := - Elf32_Shdr'(Sh_Name => 0, - Sh_Type => SHT_NULL, - Sh_Flags => 0, - Sh_Addr => 0, - Sh_Offset => 0, - Sh_Size => 0, - Sh_Link => 0, - Sh_Info => 0, - Sh_Addralign => 0, - Sh_Entsize => 0); + Elf_Shdr'(Sh_Name => 0, + Sh_Type => SHT_NULL, + Sh_Flags => 0, + Sh_Addr => 0, + Sh_Offset => 0, + Sh_Size => 0, + Sh_Link => 0, + Sh_Info => 0, + Sh_Addralign => 0, + Sh_Entsize => 0); -- shstrtab. Shdr (Sect_Shstrtab) := - Elf32_Shdr'(Sh_Name => 1, - Sh_Type => SHT_STRTAB, - Sh_Flags => 0, - Sh_Addr => 0, - Sh_Offset => 0, -- Filled latter. - -- NUL: 1, .symtab: 8, .strtab: 8 and .shstrtab: 10. - Sh_Size => 1 + 10 + 8 + 8, - Sh_Link => 0, - Sh_Info => 0, - Sh_Addralign => 1, - Sh_Entsize => 0); + Elf_Shdr'(Sh_Name => 1, + Sh_Type => SHT_STRTAB, + Sh_Flags => 0, + Sh_Addr => 0, + Sh_Offset => 0, -- Filled latter. + -- NUL: 1, .symtab: 8, .strtab: 8 and .shstrtab: 10. + Sh_Size => 1 + 10 + 8 + 8, + Sh_Link => 0, + Sh_Info => 0, + Sh_Addralign => 1, + Sh_Entsize => 0); -- Symtab Shdr (Sect_Symtab) := - Elf32_Shdr'(Sh_Name => 11, - Sh_Type => SHT_SYMTAB, - Sh_Flags => 0, - Sh_Addr => 0, - Sh_Offset => 0, - Sh_Size => 0, - Sh_Link => Elf32_Word (Sect_Strtab), - Sh_Info => 0, -- FIXME - Sh_Addralign => 4, - Sh_Entsize => Elf32_Word (Elf32_Sym_Size)); + Elf_Shdr'(Sh_Name => 11, + Sh_Type => SHT_SYMTAB, + Sh_Flags => 0, + Sh_Addr => 0, + Sh_Offset => 0, + Sh_Size => 0, + Sh_Link => Elf_Word (Sect_Strtab), + Sh_Info => 0, -- FIXME + Sh_Addralign => 4, + Sh_Entsize => Elf_Size (Elf_Sym_Size)); -- strtab. Shdr (Sect_Strtab) := - Elf32_Shdr'(Sh_Name => 19, - Sh_Type => SHT_STRTAB, - Sh_Flags => 0, - Sh_Addr => 0, - Sh_Offset => 0, - Sh_Size => 0, - Sh_Link => 0, - Sh_Info => 0, - Sh_Addralign => 1, - Sh_Entsize => 0); + Elf_Shdr'(Sh_Name => 19, + Sh_Type => SHT_STRTAB, + Sh_Flags => 0, + Sh_Addr => 0, + Sh_Offset => 0, + Sh_Size => 0, + Sh_Link => 0, + Sh_Info => 0, + Sh_Addralign => 1, + Sh_Entsize => 0); -- Fill sections. Sect := Section_Chain; Nbr_Sect := Sect_First; Nbr_Symbols := 1; while Sect /= null loop + -- For Size to word conversion. + pragma Warnings (Off); + Sections (Nbr_Sect) := (Sect => Sect, - Sym => Elf32_Word (Nbr_Symbols)); + Sym => Elf_Word (Nbr_Symbols)); Nbr_Symbols := Nbr_Symbols + 1; Sect.Number := Nbr_Sect; Shdr (Nbr_Sect) := - Elf32_Shdr'(Sh_Name => Shdr (Sect_Shstrtab).Sh_Size, - Sh_Type => SHT_PROGBITS, - Sh_Flags => 0, - Sh_Addr => Elf32_Addr (Sect.Vaddr), - Sh_Offset => 0, - Sh_Size => 0, - Sh_Link => 0, - Sh_Info => 0, - Sh_Addralign => 2 ** Sect.Align, - Sh_Entsize => Elf32_Word (Sect.Esize)); + Elf_Shdr'(Sh_Name => Elf_Word (Shdr (Sect_Shstrtab).Sh_Size), + Sh_Type => SHT_PROGBITS, + Sh_Flags => 0, + Sh_Addr => Elf_Addr (Sect.Vaddr), + Sh_Offset => 0, + Sh_Size => 0, + Sh_Link => 0, + Sh_Info => 0, + Sh_Addralign => 2 ** Sect.Align, + Sh_Entsize => Elf_Size (Sect.Esize)); if Sect.Data = null then Shdr (Nbr_Sect).Sh_Type := SHT_NOBITS; end if; @@ -217,17 +223,17 @@ package body Binary_File.Elf is end if; if Sect.First_Reloc /= null then -- Add a section for the relocs. - Shdr (Nbr_Sect) := Elf32_Shdr' - (Sh_Name => Shdr (Sect_Shstrtab).Sh_Size, + Shdr (Nbr_Sect) := Elf_Shdr' + (Sh_Name => Elf_Word (Shdr (Sect_Shstrtab).Sh_Size), Sh_Type => SHT_NULL, Sh_Flags => 0, Sh_Addr => 0, Sh_Offset => 0, Sh_Size => 0, - Sh_Link => Elf32_Word (Sect_Symtab), - Sh_Info => Elf32_Word (Nbr_Sect - 1), + Sh_Link => Elf_Word (Sect_Symtab), + Sh_Info => Elf_Word (Nbr_Sect - 1), Sh_Addralign => 4, - Sh_Entsize => Elf32_Word (Rel_Size)); + Sh_Entsize => Elf_Size (Rel_Size)); if Is_Rela (Arch) then Shdr (Nbr_Sect).Sh_Type := SHT_RELA; @@ -241,13 +247,15 @@ package body Binary_File.Elf is Nbr_Sect := Nbr_Sect + 1; end if; Sect := Sect.Next; + + pragma Warnings (On); end loop; -- Lay-out sections. - Offset := Elf32_Off (Elf32_Ehdr_Size); + Offset := Elf_Off (Elf_Ehdr_Size); -- Section table - Offset := Offset + Elf32_Off (Nbr_Sect * Elf32_Shdr_Size); + Offset := Offset + Elf_Off (Nbr_Sect * Elf_Shdr_Size); -- shstrtab. Shdr (Sect_Shstrtab).Sh_Offset := Offset; @@ -259,7 +267,7 @@ package body Binary_File.Elf is Sect := Sections (I).Sect; if Sect /= null then Sect.Pc := Pow_Align (Sect.Pc, Sect.Align); - Shdr (Sect.Number).Sh_Size := Elf32_Word (Sect.Pc); + Shdr (Sect.Number).Sh_Size := Elf_Size (Sect.Pc); if Sect.Data /= null then -- Set data offset. Shdr (Sect.Number).Sh_Offset := Offset; @@ -269,13 +277,13 @@ package body Binary_File.Elf is if Sect.First_Reloc /= null then Shdr (Sect.Number + 1).Sh_Offset := Offset; Shdr (Sect.Number + 1).Sh_Size := - Elf32_Word (Sect.Nbr_Relocs * Rel_Size); + Elf_Size (Sect.Nbr_Relocs * Rel_Size); Offset := Offset + Shdr (Sect.Number + 1).Sh_Size; end if; end if; -- Set link. if Sect.Link /= null then - Shdr (Sect.Number).Sh_Link := Elf32_Word (Sect.Link.Number); + Shdr (Sect.Number).Sh_Link := Elf_Word (Sect.Link.Number); end if; end if; end loop; @@ -300,7 +308,7 @@ package body Binary_File.Elf is end case; end loop; - Shdr (Sect_Symtab).Sh_Info := Elf32_Word (Nbr_Symbols); + Shdr (Sect_Symtab).Sh_Info := Elf_Word (Nbr_Symbols); -- Then globals. for I in Symbols.First .. Symbols.Last loop @@ -322,7 +330,7 @@ package body Binary_File.Elf is -- Symtab. Shdr (Sect_Symtab).Sh_Offset := Offset; -- 1 for nul. - Shdr (Sect_Symtab).Sh_Size := Elf32_Word (Nbr_Symbols * Elf32_Sym_Size); + Shdr (Sect_Symtab).Sh_Size := Elf_Size (Nbr_Symbols * Elf_Sym_Size); Offset := Offset + Shdr (Sect_Symtab).Sh_Size; @@ -364,49 +372,55 @@ package body Binary_File.Elf is end loop; Shdr (Sect_Strtab).Sh_Size := - Shdr (Sect_Strtab).Sh_Size + Elf32_Word (Len); + Shdr (Sect_Strtab).Sh_Size + Elf_Size (Len); end; -- Write file header. declare - Ehdr : Elf32_Ehdr; + Ehdr : Elf_Ehdr; begin Ehdr := (E_Ident => (EI_MAG0 => ELFMAG0, EI_MAG1 => ELFMAG1, EI_MAG2 => ELFMAG2, EI_MAG3 => ELFMAG3, - EI_CLASS => ELFCLASS32, + EI_CLASS => ELFCLASSNONE, EI_DATA => ELFDATANONE, EI_VERSION => EV_CURRENT, EI_PAD .. 15 => 0), E_Type => ET_REL, E_Machine => EM_NONE, - E_Version => Elf32_Word (EV_CURRENT), + E_Version => Elf_Word (EV_CURRENT), E_Entry => 0, E_Phoff => 0, - E_Shoff => Elf32_Off (Elf32_Ehdr_Size), + E_Shoff => Elf_Off (Elf_Ehdr_Size), E_Flags => 0, - E_Ehsize => Elf32_Half (Elf32_Ehdr_Size), + E_Ehsize => Elf_Half (Elf_Ehdr_Size), E_Phentsize => 0, E_Phnum => 0, - E_Shentsize => Elf32_Half (Elf32_Shdr_Size), - E_Shnum => Elf32_Half (Nbr_Sect), + E_Shentsize => Elf_Half (Elf_Shdr_Size), + E_Shnum => Elf_Half (Nbr_Sect), E_Shstrndx => 1); case Arch is when Arch_X86 => Ehdr.E_Ident (EI_DATA) := ELFDATA2LSB; + Ehdr.E_Ident (EI_CLASS) := ELFCLASS32; Ehdr.E_Machine := EM_386; + when Arch_X86_64 => + Ehdr.E_Ident (EI_DATA) := ELFDATA2LSB; + Ehdr.E_Ident (EI_CLASS) := ELFCLASS64; + Ehdr.E_Machine := EM_X86_64; when Arch_Sparc => Ehdr.E_Ident (EI_DATA) := ELFDATA2MSB; + Ehdr.E_Ident (EI_CLASS) := ELFCLASS32; Ehdr.E_Machine := EM_SPARC; when others => raise Program_Error; end case; - Xwrite (Ehdr'Address, Elf32_Ehdr_Size); + Xwrite (Ehdr'Address, Elf_Ehdr_Size); end; -- Write shdr. - Xwrite (Shdr'Address, Nbr_Sect * Elf32_Shdr_Size); + Xwrite (Shdr'Address, Nbr_Sect * Elf_Shdr_Size); -- Write shstrtab Check_File_Pos (Shdr (Sect_Shstrtab).Sh_Offset); @@ -433,7 +447,7 @@ package body Binary_File.Elf is end; -- Pad. declare - Delt : Elf32_Word; + Delt : Elf_Size; Nul_Str : String (1 .. 4) := (others => NUL); begin Delt := Shdr (Sect_Shstrtab).Sh_Size and 3; @@ -452,9 +466,10 @@ package body Binary_File.Elf is end if; declare R : Reloc_Acc; - Rel : Elf32_Rel; - Rela : Elf32_Rela; - S : Elf32_Word; + Rel : Elf_Rel; + Rela : Elf_Rela; + S : Elf_Word; + T : Elf_Word; Nbr_Reloc : Natural; begin R := Sect.First_Reloc; @@ -463,40 +478,54 @@ package body Binary_File.Elf is if R.Done then S := Sections (Get_Section (R.Sym).Number).Sym; else - S := Elf32_Word (Get_Number (R.Sym)); + S := Elf_Word (Get_Number (R.Sym)); end if; if Is_Rela (Arch) then - case R.Kind is - when Reloc_Disp22 => - Rela.R_Info := Elf32_R_Info (S, R_SPARC_WDISP22); - when Reloc_Disp30 => - Rela.R_Info := Elf32_R_Info (S, R_SPARC_WDISP30); - when Reloc_Hi22 => - Rela.R_Info := Elf32_R_Info (S, R_SPARC_HI22); - when Reloc_Lo10 => - Rela.R_Info := Elf32_R_Info (S, R_SPARC_LO10); - when Reloc_32 => - Rela.R_Info := Elf32_R_Info (S, R_SPARC_32); - when Reloc_Ua_32 => - Rela.R_Info := Elf32_R_Info (S, R_SPARC_UA32); + case Arch is + when Arch_X86_64 => + case R.Kind is + when Reloc_Pc32 => + T := Elf64.R_X86_64_PC32; + when others => + raise Program_Error; + end case; + when Arch_Sparc => + case R.Kind is + when Reloc_Disp22 => + T := Elf32.R_SPARC_WDISP22; + when Reloc_Disp30 => + T := Elf32.R_SPARC_WDISP30; + when Reloc_Hi22 => + T := Elf32.R_SPARC_HI22; + when Reloc_Lo10 => + T := Elf32.R_SPARC_LO10; + when Reloc_32 => + T := Elf32.R_SPARC_32; + when Reloc_Ua_32 => + T := Elf32.R_SPARC_UA32; + when others => + raise Program_Error; + end case; when others => raise Program_Error; end case; Rela.R_Addend := 0; - Rela.R_Offset := Elf32_Addr (R.Addr); - Xwrite (Rela'Address, Elf32_Rela_Size); + Rela.R_Offset := Elf_Addr (R.Addr); + Rela.R_Info := Elf_R_Info (S, T); + Xwrite (Rela'Address, Elf_Rela_Size); else case R.Kind is when Reloc_32 => - Rel.R_Info := Elf32_R_Info (S, R_386_32); + T := Elf32.R_386_32; when Reloc_Pc32 => - Rel.R_Info := Elf32_R_Info (S, R_386_PC32); + T := Elf32.R_386_PC32; when others => raise Program_Error; end case; - Rel.R_Offset := Elf32_Addr (R.Addr); - Xwrite (Rel'Address, Elf32_Rel_Size); + Rel.R_Offset := Elf_Addr (R.Addr); + Rela.R_Info := Elf_R_Info (S, T); + Xwrite (Rel'Address, Elf_Rel_Size); end if; Nbr_Reloc := Nbr_Reloc + 1; R := R.Sect_Next; @@ -511,22 +540,22 @@ package body Binary_File.Elf is -- Write symbol table. Check_File_Pos (Shdr (Sect_Symtab).Sh_Offset); declare - Str_Off : Elf32_Word; + Str_Off : Elf_Off; procedure Gen_Sym (S : Symbol) is - Sym : Elf32_Sym; - Bind : Elf32_Uchar; - Typ : Elf32_Uchar; + Sym : Elf_Sym; + Bind : Elf_Uchar; + Typ : Elf_Uchar; begin - Sym := Elf32_Sym'(St_Name => Str_Off, - St_Value => Elf32_Addr (Get_Symbol_Value (S)), - St_Size => 0, - St_Info => 0, - St_Other => 0, - St_Shndx => SHN_UNDEF); + Sym := Elf_Sym'(St_Name => Elf_Word (Str_Off), + St_Value => Elf_Addr (Get_Symbol_Value (S)), + St_Size => 0, + St_Info => 0, + St_Other => 0, + St_Shndx => SHN_UNDEF); if Get_Section (S) /= null then - Sym.St_Shndx := Elf32_Half (Get_Section (S).Number); + Sym.St_Shndx := Elf_Half (Get_Section (S).Number); end if; case Get_Scope (S) is when Sym_Private @@ -546,48 +575,37 @@ package body Binary_File.Elf is Bind := STB_GLOBAL; Typ := STT_NOTYPE; end case; - Sym.St_Info := Elf32_St_Info (Bind, Typ); + Sym.St_Info := Elf_St_Info (Bind, Typ); - Xwrite (Sym'Address, Elf32_Sym_Size); + Xwrite (Sym'Address, Elf_Sym_Size); - Str_Off := Str_Off + Elf32_Off (Get_Symbol_Name_Length (S) + 1); + Str_Off := Str_Off + Elf_Off (Get_Symbol_Name_Length (S) + 1); end Gen_Sym; - Sym : Elf32_Sym; + Sym : Elf_Sym; begin Str_Off := 1; -- write null entry - Sym := Elf32_Sym'(St_Name => 0, - St_Value => 0, - St_Size => 0, - St_Info => 0, - St_Other => 0, - St_Shndx => SHN_UNDEF); - Xwrite (Sym'Address, Elf32_Sym_Size); + Sym := Elf_Sym'(St_Name => 0, + St_Value => 0, + St_Size => 0, + St_Info => 0, + St_Other => 0, + St_Shndx => SHN_UNDEF); + Xwrite (Sym'Address, Elf_Sym_Size); -- write section entries Sect := Section_Chain; while Sect /= null loop --- Sym := Elf32_Sym'(St_Name => Str_Off, --- St_Value => 0, --- St_Size => 0, --- St_Info => Elf32_St_Info (STB_LOCAL, --- STT_NOTYPE), --- St_Other => 0, --- St_Shndx => Elf32_Half (Sect.Number)); --- Xwrite (Sym'Address, Elf32_Sym_Size); --- Str_Off := Str_Off + Sect.Name'Length + 1; - - Sym := Elf32_Sym'(St_Name => 0, - St_Value => 0, - St_Size => 0, - St_Info => Elf32_St_Info (STB_LOCAL, - STT_SECTION), - St_Other => 0, - St_Shndx => Elf32_Half (Sect.Number)); - Xwrite (Sym'Address, Elf32_Sym_Size); + Sym := Elf_Sym'(St_Name => 0, + St_Value => 0, + St_Size => 0, + St_Info => Elf_St_Info (STB_LOCAL, STT_SECTION), + St_Other => 0, + St_Shndx => Elf_Half (Sect.Number)); + Xwrite (Sym'Address, Elf_Sym_Size); Sect := Sect.Next; end loop; @@ -626,13 +644,6 @@ package body Binary_File.Elf is Check_File_Pos (Shdr (Sect_Strtab).Sh_Offset); -- First is NUL. Xwrite (NUL'Address, 1); - -- Then the sections name. --- Sect := Section_List; --- while Sect /= null loop --- Xwrite (Sect.Name.all'Address, Sect.Name'Length); --- Xwrite (NUL'Address, 1); --- Sect := Sect.Prev; --- end loop; -- Then the symbols name. declare |