summaryrefslogtreecommitdiff
path: root/ortho/mcode/elfdumper.adb
diff options
context:
space:
mode:
Diffstat (limited to 'ortho/mcode/elfdumper.adb')
-rw-r--r--ortho/mcode/elfdumper.adb2818
1 files changed, 2818 insertions, 0 deletions
diff --git a/ortho/mcode/elfdumper.adb b/ortho/mcode/elfdumper.adb
new file mode 100644
index 0000000..b3a3b70
--- /dev/null
+++ b/ortho/mcode/elfdumper.adb
@@ -0,0 +1,2818 @@
+-- ELF dumper (library).
+-- Copyright (C) 2006 Tristan Gingold
+--
+-- GHDL is free software; you can redistribute it and/or modify it under
+-- the terms of the GNU General Public License as published by the Free
+-- Software Foundation; either version 2, or (at your option) any later
+-- version.
+--
+-- GHDL is distributed in the hope that it will be useful, but WITHOUT ANY
+-- WARRANTY; without even the implied warranty of MERCHANTABILITY or
+-- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+-- for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with GCC; see the file COPYING. If not, write to the Free
+-- Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+-- 02111-1307, USA.
+with System.Storage_Elements; use System.Storage_Elements;
+with Ada.Text_IO; use Ada.Text_IO;
+with Ada.Unchecked_Deallocation;
+with GNAT.OS_Lib;
+with Interfaces; use Interfaces;
+with Hex_Images; use Hex_Images;
+with Elf_Common; use Elf_Common;
+with Dwarf;
+
+package body Elfdumper is
+ function Get_String (Strtab : Strtab_Type; N : Elf_Size) return String
+ is
+ E : Elf_Size;
+ begin
+ E := N;
+ while Strtab.Base (E) /= Nul loop
+ E := E + 1;
+ end loop;
+ if E = N then
+ return "";
+ else
+ return String (Strtab.Base (N .. E - 1));
+ end if;
+ end Get_String;
+
+ procedure Disp_Ehdr (Ehdr : Elf_Ehdr) is
+ begin
+ Put ("File class: ");
+ case Ehdr.E_Ident (EI_CLASS) is
+ when ELFCLASSNONE =>
+ Put ("none");
+ when ELFCLASS32 =>
+ Put ("class_32");
+ when ELFCLASS64 =>
+ Put ("class_64");
+ when others =>
+ Put ("others");
+ end case;
+ New_Line;
+
+ Put ("encoding : ");
+ case Ehdr.E_Ident (EI_DATA) is
+ when ELFDATANONE =>
+ Put ("none");
+ when ELFDATA2LSB =>
+ Put ("LSB byte order");
+ when ELFDATA2MSB =>
+ Put ("MSB byte order");
+ when others =>
+ Put ("unknown");
+ end case;
+ New_Line;
+
+ Put ("version : ");
+ case Ehdr.E_Ident (EI_VERSION) is
+ when EV_NONE =>
+ Put ("none");
+ when EV_CURRENT =>
+ Put ("current (1)");
+ when others =>
+ Put ("future");
+ end case;
+ New_Line;
+
+ if Ehdr.E_Ident (EI_CLASS) /= Elf_Arch_Class
+-- or Ehdr.E_Ident (EI_DATA) /= ELFDATA2LSB
+ or Ehdr.E_Ident (EI_VERSION) /= EV_CURRENT
+ then
+ Put_Line ("bad class/data encoding/version");
+ return;
+ end if;
+
+ Put ("File type : ");
+ case Ehdr.E_Type is
+ when ET_NONE =>
+ Put ("no file type");
+ when ET_REL =>
+ Put ("relocatable file");
+ when ET_EXEC =>
+ Put ("executable file");
+ when ET_CORE =>
+ Put ("core file");
+ when ET_LOPROC .. ET_HIPROC =>
+ Put ("processor-specific");
+ when others =>
+ Put ("unknown");
+ end case;
+ New_Line;
+
+ Put ("machine : ");
+ case Ehdr.E_Machine is
+ when EM_NONE =>
+ Put ("no machine");
+ when EM_M32 =>
+ Put ("AT&T WE 32100");
+ when EM_SPARC =>
+ Put ("SPARC");
+ when EM_386 =>
+ Put ("Intel architecture");
+ when EM_68K =>
+ Put ("Motorola 68000");
+ when EM_88K =>
+ Put ("Motorola 88000");
+ when EM_860 =>
+ Put ("Intel 80860");
+ when EM_MIPS =>
+ Put ("MIPS RS3000 Big-Endian");
+ when EM_MIPS_RS4_BE =>
+ Put ("MIPS RS4000 Big-Endian");
+ when others =>
+ Put ("unknown");
+ end case;
+ New_Line;
+
+ Put_Line ("Version : " & Hex_Image (Ehdr.E_Version));
+ Put_Line ("Phoff : " & Hex_Image (Ehdr.E_Phoff));
+ Put_Line ("Shoff : " & Hex_Image (Ehdr.E_Shoff));
+ Put_Line ("flags : " & Hex_Image (Ehdr.E_Flags));
+ Put_Line ("phentsize : " & Hex_Image (Ehdr.E_Ehsize));
+ Put_Line ("phnum : " & Hex_Image (Ehdr.E_Phentsize));
+ Put_Line ("shentsize : " & Hex_Image (Ehdr.E_Shentsize));
+ Put_Line ("shnum : " & Hex_Image (Ehdr.E_Shnum));
+ Put_Line ("shstrndx : " & Hex_Image (Ehdr.E_Shstrndx));
+ end Disp_Ehdr;
+
+ function Get_Shdr_Type_Name (Stype : Elf_Word) return String is
+ begin
+ case Stype is
+ when SHT_NULL =>
+ return "NULL";
+ when SHT_PROGBITS =>
+ return "PROGBITS";
+ when SHT_SYMTAB =>
+ return "SYMTAB";
+ when SHT_STRTAB =>
+ return "STRTAB";
+ when SHT_RELA =>
+ return "RELA";
+ when SHT_HASH =>
+ return "HASH";
+ when SHT_DYNAMIC =>
+ return "DYNAMIC";
+ when SHT_NOTE =>
+ return "NOTE";
+ when SHT_NOBITS =>
+ return "NOBITS";
+ when SHT_REL =>
+ return "REL";
+ when SHT_SHLIB =>
+ return "SHLIB";
+ when SHT_DYNSYM =>
+ return "DYNSYM";
+ when SHT_INIT_ARRAY =>
+ return "INIT_ARRAY";
+ when SHT_FINI_ARRAY =>
+ return "FINI_ARRAY";
+ when SHT_PREINIT_ARRAY =>
+ return "PREINIT_ARRAY";
+ when SHT_GROUP =>
+ return "GROUP";
+ when SHT_SYMTAB_SHNDX =>
+ return "SYMTAB_SHNDX";
+ when SHT_NUM =>
+ return "NUM";
+ when SHT_LOOS =>
+ return "LOOS";
+ when SHT_GNU_LIBLIST =>
+ return "GNU_LIBLIST";
+ when SHT_CHECKSUM =>
+ return "CHECKSUM";
+ when SHT_SUNW_Move =>
+ return "SUNW_move";
+ when SHT_SUNW_COMDAT =>
+ return "SUNW_COMDAT";
+ when SHT_SUNW_Syminfo =>
+ return "SUNW_syminfo";
+ when SHT_GNU_Verdef =>
+ return "GNU_verdef";
+ when SHT_GNU_Verneed =>
+ return "GNU_verneed";
+ when SHT_GNU_Versym =>
+ return "GNU_versym";
+ when SHT_LOPROC .. SHT_HIPROC =>
+ return "Processor dependant";
+ when SHT_LOUSER .. SHT_HIUSER =>
+ return "User dependant";
+ when others =>
+ return "unknown";
+ end case;
+ end Get_Shdr_Type_Name;
+
+ procedure Disp_Shdr (Shdr : Elf_Shdr; Sh_Strtab : Strtab_Type)
+ is
+ begin
+ Put_Line ("name : " & Hex_Image (Shdr.Sh_Name) & " """
+ & Get_String (Sh_Strtab, Elf_Size (Shdr.Sh_Name)) & """");
+ Put ("type : " & Hex_Image (Shdr.Sh_Type) & " ");
+ Put (Get_Shdr_Type_Name (Shdr.Sh_Type));
+ New_Line;
+ Put ("flags : " & Hex_Image (Shdr.Sh_Flags));
+ if (Shdr.Sh_Flags and SHF_WRITE) /= 0 then
+ Put (" WRITE");
+ end if;
+ if (Shdr.Sh_Flags and SHF_ALLOC) /= 0 then
+ Put (" ALLOC");
+ end if;
+ if (Shdr.Sh_Flags and SHF_EXECINSTR) /= 0 then
+ Put (" EXEC");
+ end if;
+ New_Line;
+ Put ("addr : " & Hex_Image (Shdr.Sh_Addr));
+ Put (" offset : " & Hex_Image (Shdr.Sh_Offset));
+ Put (" size : " & Hex_Image (Shdr.Sh_Size));
+ New_Line;
+ Put ("link : " & Hex_Image (Shdr.Sh_Link));
+ Put (" info : " & Hex_Image (Shdr.Sh_Info));
+ Put (" addralign : " & Hex_Image (Shdr.Sh_Addralign));
+ Put (" entsize : " & Hex_Image (Shdr.Sh_Entsize));
+ New_Line;
+ end Disp_Shdr;
+
+ procedure Disp_Sym (File : Elf_File;
+ Sym : Elf_Sym;
+ Strtab : Strtab_Type)
+ is
+ begin
+ Put (Hex_Image (Sym.St_Value));
+ Put (" " & Hex_Image (Sym.St_Size));
+ Put (' ');
+ --Put (" info:" & Hex_Image (Sym.St_Info) & " ");
+ case Elf_St_Bind (Sym.St_Info) is
+ when STB_LOCAL =>
+ Put ("loc ");
+ when STB_GLOBAL =>
+ Put ("glob");
+ when STB_WEAK =>
+ Put ("weak");
+ when others =>
+ Put ("? ");
+ end case;
+ Put (' ');
+ case Elf_St_Type (Sym.St_Info) is
+ when STT_NOTYPE =>
+ Put ("none");
+ when STT_OBJECT =>
+ Put ("obj ");
+ when STT_FUNC =>
+ Put ("func");
+ when STT_SECTION =>
+ Put ("sect");
+ when STT_FILE =>
+ Put ("file");
+ when others =>
+ Put ("? ");
+ end case;
+ --Put (" other:" & Hex_Image (Sym.St_Other));
+ Put (' ');
+ case Sym.St_Shndx is
+ when SHN_UNDEF =>
+ Put ("UNDEF ");
+ when 1 .. SHN_LORESERVE - 1 =>
+ declare
+ S : String := Get_Section_Name (File, Sym.St_Shndx);
+ Max : constant Natural := 8;
+ begin
+ if S'Length <= Max then
+ Put (S);
+ for I in S'Length + 1 .. Max loop
+ Put (' ');
+ end loop;
+ else
+ Put (S (S'First .. S'First + Max - 1));
+ end if;
+ end;
+ when SHN_LOPROC .. SHN_HIPROC =>
+ Put ("*proc* ");
+ when SHN_ABS =>
+ Put ("*ABS* ");
+ when SHN_COMMON =>
+ Put ("*COMMON*");
+ when others =>
+ Put ("?? ");
+ end case;
+ --Put (" sect:" & Hex_Image (Sym.St_Shndx));
+ Put (' ');
+ Put_Line (Get_String (Strtab, Elf_Size (Sym.St_Name)));
+ end Disp_Sym;
+
+ function Get_Offset (File : Elf_File; Off : Elf_Off; Size : Elf_Size)
+ return Address
+ is
+ begin
+ if Off > File.Length or Off + Size > File.Length then
+ return Null_Address;
+ end if;
+ return File.Base + Storage_Offset (Off);
+ end Get_Offset;
+
+ function Get_Section_Base (File : Elf_File; Shdr : Elf_Shdr)
+ return Address
+ is
+ begin
+ return Get_Offset (File, Shdr.Sh_Offset, Shdr.Sh_Size);
+ end Get_Section_Base;
+
+ function Get_Section_Base (File : Elf_File; Index : Elf_Half)
+ return Address
+ is
+ Shdr : Elf_Shdr_Acc;
+ begin
+ Shdr := Get_Shdr (File, Index);
+ return Get_Section_Base (File, Shdr.all);
+ end Get_Section_Base;
+
+ function Get_Segment_Base (File : Elf_File; Phdr : Elf_Phdr)
+ return Address
+ is
+ begin
+ return Get_Offset (File, Phdr.P_Offset, Phdr.P_Filesz);
+ end Get_Segment_Base;
+
+ function Get_Segment_Base (File : Elf_File; Index : Elf_Half)
+ return Address
+ is
+ Phdr : Elf_Phdr_Acc;
+ begin
+ Phdr := Get_Phdr (File, Index);
+ return Get_Segment_Base (File, Phdr.all);
+ end Get_Segment_Base;
+
+ procedure Open_File (File : out Elf_File; Filename : String)
+ is
+ function Malloc (Size : Integer) return Address;
+ pragma Import (C, Malloc);
+
+ use GNAT.OS_Lib;
+ Length : Long_Integer;
+ Len : Integer;
+ Fd : File_Descriptor;
+ begin
+ File := (Filename => new String'(Filename),
+ Status => Status_Ok,
+ Length => 0,
+ Base => Null_Address,
+ Ehdr => null,
+ Shdr_Base => Null_Address,
+ Sh_Strtab => (null, 0),
+ Phdr_Base => Null_Address);
+
+ -- Open the file.
+ Fd := Open_Read (Filename, Binary);
+ if Fd = Invalid_FD then
+ File.Status := Status_Open_Failure;
+ return;
+ end if;
+
+ -- Get length.
+ Length := File_Length (Fd);
+ Len := Integer (Length);
+ if Len < Elf_Ehdr_Size then
+ File.Status := Status_Bad_File;
+ Close (Fd);
+ return;
+ end if;
+
+ File.Length := Elf_Off (Len);
+
+ -- Allocate memory for the file.
+ File.Base := Malloc (Len);
+ if File.Base = Null_Address then
+ File.Status := Status_Memory;
+ Close (Fd);
+ return;
+ end if;
+
+ -- Read the whole file.
+ if Read (Fd, File.Base, Integer (Length)) /= Integer (Length) then
+ File.Status := Status_Read_Error;
+ Close (Fd);
+ return;
+ end if;
+
+ Close (Fd);
+
+ File.Ehdr := To_Elf_Ehdr_Acc (File.Base);
+
+ if File.Ehdr.E_Ident (EI_MAG0) /= ELFMAG0
+ or File.Ehdr.E_Ident (EI_MAG1) /= ELFMAG1
+ or File.Ehdr.E_Ident (EI_MAG2) /= ELFMAG2
+ or File.Ehdr.E_Ident (EI_MAG3) /= ELFMAG3
+ then
+ File.Status := Status_Bad_Magic;
+ return;
+ end if;
+
+ if File.Ehdr.E_Ident (EI_CLASS) /= Elf_Arch_Class
+-- or Ehdr.E_Ident (EI_DATA) /= ELFDATA2LSB
+ or File.Ehdr.E_Ident (EI_VERSION) /= EV_CURRENT
+ then
+ File.Status := Status_Bad_Class;
+ return;
+ end if;
+ end Open_File;
+
+ function Get_Status (File : Elf_File) return Elf_File_Status is
+ begin
+ return File.Status;
+ end Get_Status;
+
+ function Get_Ehdr (File : Elf_File) return Elf_Ehdr_Acc is
+ begin
+ return File.Ehdr;
+ end Get_Ehdr;
+
+ function Get_Shdr (File : Elf_File; Index : Elf_Half)
+ return Elf_Shdr_Acc
+ is
+ begin
+ if Index >= File.Ehdr.E_Shnum then
+ raise Constraint_Error;
+ end if;
+ return To_Elf_Shdr_Acc
+ (File.Shdr_Base
+ + Storage_Offset (Index * Elf_Half (Elf_Shdr_Size)));
+ end Get_Shdr;
+
+ procedure Load_Phdr (File : in out Elf_File)
+ is
+ begin
+ if Get_Ehdr (File).E_Phentsize /= Elf_Half (Elf_Phdr_Size) then
+ return;
+ end if;
+
+ File.Phdr_Base :=
+ Get_Offset (File, Get_Ehdr (File).E_Phoff,
+ Elf_Size (Get_Ehdr (File).E_Phnum
+ * Elf_Half (Elf_Phdr_Size)));
+ end Load_Phdr;
+
+ function Get_Phdr (File : Elf_File; Index : Elf_Half)
+ return Elf_Phdr_Acc
+ is
+ begin
+ if Index >= File.Ehdr.E_Phnum then
+ raise Constraint_Error;
+ end if;
+ return To_Elf_Phdr_Acc
+ (File.Phdr_Base
+ + Storage_Offset (Index * Elf_Half (Elf_Phdr_Size)));
+ end Get_Phdr;
+
+ function Get_Strtab (File : Elf_File; Index : Elf_Half)
+ return Strtab_Type
+ is
+ Shdr : Elf_Shdr_Acc;
+ begin
+ Shdr := Get_Shdr (File, Index);
+ if Shdr = null or Shdr.Sh_Type /= SHT_STRTAB then
+ return Null_Strtab;
+ end if;
+ return (Base => To_Strtab_Fat_Acc (Get_Section_Base (File, Shdr.all)),
+ Length => Shdr.Sh_Size);
+ end Get_Strtab;
+
+ procedure Load_Shdr (File : in out Elf_File)
+ is
+ begin
+ if Get_Ehdr (File).E_Shentsize /= Elf_Half (Elf_Shdr_Size) then
+ return;
+ end if;
+
+ File.Shdr_Base :=
+ Get_Offset (File, Get_Ehdr (File).E_Shoff,
+ Elf_Size (Get_Ehdr (File).E_Shnum
+ * Elf_Half (Elf_Shdr_Size)));
+ File.Sh_Strtab := Get_Strtab (File, Get_Ehdr (File).E_Shstrndx);
+ end Load_Shdr;
+
+ function Get_Sh_Strtab (File : Elf_File) return Strtab_Type is
+ begin
+ return File.Sh_Strtab;
+ end Get_Sh_Strtab;
+
+ function Get_Section_Name (File : Elf_File; Index : Elf_Half)
+ return String
+ is
+ begin
+ return Get_String (Get_Sh_Strtab (File),
+ Elf_Size (Get_Shdr (File, Index).Sh_Name));
+ end Get_Section_Name;
+
+ function Get_Section_By_Name (File : Elf_File; Name : String)
+ return Elf_Half
+ is
+ Ehdr : Elf_Ehdr_Acc;
+ Shdr : Elf_Shdr_Acc;
+ Sh_Strtab : Strtab_Type;
+ begin
+ Ehdr := Get_Ehdr (File);
+ Sh_Strtab := Get_Sh_Strtab (File);
+ for I in 1 .. Ehdr.E_Shnum - 1 loop
+ Shdr := Get_Shdr (File, I);
+ if Get_String (Sh_Strtab, Elf_Size (Shdr.Sh_Name)) = Name then
+ return I;
+ end if;
+ end loop;
+ return 0;
+ end Get_Section_By_Name;
+
+ procedure Disp_Symtab (File : Elf_File; Index : Elf_Half)
+ is
+ Shdr : Elf_Shdr_Acc;
+ S_Strtab : Strtab_Type;
+ Base : Address;
+ Off : Storage_Offset;
+ begin
+ Shdr := Get_Shdr (File, Index);
+ if Shdr.Sh_Entsize /= Elf_Size (Elf_Sym_Size) then
+ return;
+ end if;
+ S_Strtab := Get_Strtab (File, Elf_Half (Shdr.Sh_Link));
+ Base := Get_Section_Base (File, Shdr.all);
+ Off := 0;
+ while Off < Storage_Offset (Shdr.Sh_Size) loop
+ Disp_Sym (File, To_Elf_Sym_Acc (Base + Off).all, S_Strtab);
+ Off := Off + Storage_Offset (Elf_Sym_Size);
+ end loop;
+ end Disp_Symtab;
+
+ procedure Disp_Strtab (File : Elf_File; Index : Elf_Half)
+ is
+ Strtab : Strtab_Type;
+ S, E : Elf_Size;
+ begin
+ Strtab := Get_Strtab (File, Index);
+ S := 1;
+ while S < Strtab.Length loop
+ E := S;
+ while Strtab.Base (E) /= Nul loop
+ E := E + 1;
+ end loop;
+ Put_Line (Hex_Image (S) & ": "
+ & String (Strtab.Base (S .. E - 1)));
+ S := E + 1;
+ end loop;
+ end Disp_Strtab;
+
+ function Read_Byte (Addr : Address) return Unsigned_8
+ is
+ type Unsigned_8_Acc is access all Unsigned_8;
+ function To_Unsigned_8_Acc is new Ada.Unchecked_Conversion
+ (Address, Unsigned_8_Acc);
+ begin
+ return To_Unsigned_8_Acc (Addr).all;
+ end Read_Byte;
+
+ procedure Read_ULEB128 (Base : Address;
+ Off : in out Storage_Offset;
+ Res : out Unsigned_32)
+ is
+ B : Unsigned_8;
+ Shift : Integer;
+ begin
+ Res := 0;
+ Shift := 0;
+ loop
+ B := Read_Byte (Base + Off);
+ Off := Off + 1;
+ Res := Res or Shift_Left (Unsigned_32 (B and 16#7f#), Shift);
+ exit when (B and 16#80#) = 0;
+ Shift := Shift + 7;
+ end loop;
+ end Read_ULEB128;
+
+ procedure Read_SLEB128 (Base : Address;
+ Off : in out Storage_Offset;
+ Res : out Unsigned_32)
+ is
+ B : Unsigned_8;
+ Shift : Integer;
+ begin
+ Res := 0;
+ Shift := 0;
+ loop
+ B := Read_Byte (Base + Off);
+ Off := Off + 1;
+ Res := Res or Shift_Left (Unsigned_32 (B and 16#7f#), Shift);
+ Shift := Shift + 7;
+ exit when (B and 16#80#) = 0;
+ end loop;
+ if Shift < 32 and (Res and Shift_Left (1, Shift - 1)) /= 0 then
+ Res := Res or Shift_Left (-1, Shift);
+ end if;
+ end Read_SLEB128;
+
+ procedure Read_Word4 (Base : Address;
+ Off : in out Storage_Offset;
+ Res : out Unsigned_32)
+ is
+ B0, B1, B2, B3 : Unsigned_8;
+ begin
+ B0 := Read_Byte (Base + Off + 0);
+ B1 := Read_Byte (Base + Off + 1);
+ B2 := Read_Byte (Base + Off + 2);
+ B3 := Read_Byte (Base + Off + 3);
+ Res := Shift_Left (Unsigned_32 (B3), 24)
+ or Shift_Left (Unsigned_32 (B2), 16)
+ or Shift_Left (Unsigned_32 (B1), 8)
+ or Shift_Left (Unsigned_32 (B0), 0);
+ Off := Off + 4;
+ end Read_Word4;
+
+ procedure Read_Word2 (Base : Address;
+ Off : in out Storage_Offset;
+ Res : out Unsigned_16)
+ is
+ B0, B1 : Unsigned_8;
+ begin
+ B0 := Read_Byte (Base + Off + 0);
+ B1 := Read_Byte (Base + Off + 1);
+ Res := Shift_Left (Unsigned_16 (B1), 8)
+ or Shift_Left (Unsigned_16 (B0), 0);
+ Off := Off + 2;
+ end Read_Word2;
+
+ procedure Read_Byte (Base : Address;
+ Off : in out Storage_Offset;
+ Res : out Unsigned_8)
+ is
+ begin
+ Res := Read_Byte (Base + Off);
+ Off := Off + 1;
+ end Read_Byte;
+
+ procedure Disp_Note (Base : Address; Size : Storage_Offset)
+ is
+ Off : Storage_Offset;
+ Namesz : Unsigned_32;
+ Descsz : Unsigned_32;
+ Ntype : Unsigned_32;
+ B : Unsigned_8;
+ Is_Full : Boolean;
+ begin
+ Off := 0;
+ while Off < Size loop
+ Read_Word4 (Base, Off, Namesz);
+ Read_Word4 (Base, Off, Descsz);
+ Read_Word4 (Base, Off, Ntype);
+ Put ("type : ");
+ Put (Hex_Image (Ntype));
+ New_Line;
+ Put ("name : ");
+ Put (Hex_Image (Namesz));
+ Put (" ");
+ for I in 1 .. Namesz loop
+ Read_Byte (Base, Off, B);
+ if B /= 0 then
+ Put (Character'Val (B));
+ end if;
+ end loop;
+ if Namesz mod 4 /= 0 then
+ for I in (Namesz mod 4) .. 3 loop
+ Read_Byte (Base, Off, B);
+ end loop;
+ end if;
+ New_Line;
+ Put ("desc : ");
+ Put (Hex_Image (Descsz));
+ Put (" ");
+ Is_Full := Descsz >= 20;
+ for I in 1 .. Descsz loop
+ if Is_Full and (I mod 16) = 1 then
+ New_Line;
+ end if;
+ Read_Byte (Base, Off, B);
+ Put (' ');
+ Put (Hex_Image (B));
+ end loop;
+ if Descsz mod 4 /= 0 then
+ for I in (Descsz mod 4) .. 3 loop
+ Read_Byte (Base, Off, B);
+ end loop;
+ end if;
+ New_Line;
+ end loop;
+ end Disp_Note;
+
+ procedure Disp_Section_Note (File : Elf_File; Index : Elf_Half)
+ is
+ Shdr : Elf_Shdr_Acc;
+ Base : Address;
+ begin
+ Shdr := Get_Shdr (File, Index);
+ Base := Get_Section_Base (File, Shdr.all);
+ Disp_Note (Base, Storage_Offset (Shdr.Sh_Size));
+ end Disp_Section_Note;
+
+ procedure Disp_Segment_Note (File : Elf_File; Index : Elf_Half)
+ is
+ Phdr : Elf_Phdr_Acc;
+ Base : Address;
+ begin
+ Phdr := Get_Phdr (File, Index);
+ Base := Get_Segment_Base (File, Phdr.all);
+ Disp_Note (Base, Storage_Offset (Phdr.P_Filesz));
+ end Disp_Segment_Note;
+
+
+ function Get_Dt_Name (Name : Elf_Word) return String is
+ begin
+ case Name is
+ when DT_NULL =>
+ return "NULL";
+ when DT_NEEDED =>
+ return "NEEDED";
+ when DT_PLTRELSZ =>
+ return "PLTRELSZ";
+ when DT_PLTGOT =>
+ return "PLTGOT";
+ when DT_HASH =>
+ return "HASH";
+ when DT_STRTAB =>
+ return "STRTAB";
+ when DT_SYMTAB =>
+ return "SYMTAB";
+ when DT_RELA =>
+ return "RELA";
+ when DT_RELASZ =>
+ return "RELASZ";
+ when DT_RELAENT =>
+ return "RELAENT";
+ when DT_STRSZ =>
+ return "STRSZ";
+ when DT_SYMENT =>
+ return "SYMENT";
+ when DT_INIT =>
+ return "INIT";
+ when DT_FINI =>
+ return "FINI";
+ when DT_SONAME =>
+ return "SONAME";
+ when DT_RPATH =>
+ return "RPATH";
+ when DT_SYMBOLIC =>
+ return "SYMBOLIC";
+ when DT_REL =>
+ return "REL";
+ when DT_RELSZ =>
+ return "RELSZ";
+ when DT_RELENT =>
+ return "RELENT";
+ when DT_PLTREL =>
+ return "PLTREL";
+ when DT_DEBUG =>
+ return "DEBUG";
+ when DT_TEXTREL =>
+ return "TEXTREL";
+ when DT_JMPREL =>
+ return "JMPREL";
+ when DT_BIND_NOW =>
+ return "BIND_NOW";
+ when DT_INIT_ARRAY =>
+ return "INIT_ARRAY";
+ when DT_FINI_ARRAY =>
+ return "FINI_ARRAY";
+ when DT_INIT_ARRAYSZ =>
+ return "INIT_ARRAYSZ";
+ when DT_FINI_ARRAYSZ =>
+ return "FINI_ARRAYSZ";
+ when DT_RUNPATH =>
+ return "RUNPATH";
+ when DT_FLAGS =>
+ return "FLAGS";
+-- when DT_ENCODING =>
+-- return "ENCODING";
+ when DT_PREINIT_ARRAY =>
+ return "PREINIT_ARRAY";
+ when DT_PREINIT_ARRAYSZ =>
+ return "PREINIT_ARRAYSZ";
+ when DT_NUM =>
+ return "NUM";
+ when DT_LOOS =>
+ return "LOOS";
+-- when DT_HIOS =>
+-- return "HIOS";
+ when DT_LOPROC =>
+ return "LOPROC";
+-- when DT_HIPROC =>
+-- return "HIPROC";
+ when DT_VALRNGLO =>
+ return "VALRNGLO";
+ when DT_GNU_PRELINKED =>
+ return "GNU_PRELINKED";
+ when DT_GNU_CONFLICTSZ =>
+ return "GNU_CONFLICTSZ";
+ when DT_GNU_LIBLISTSZ =>
+ return "GNU_LIBLISTSZ";
+ when DT_CHECKSUM =>
+ return "CHECKSUM";
+ when DT_PLTPADSZ =>
+ return "PLTPADSZ";
+ when DT_MOVEENT =>
+ return "MOVEENT";
+ when DT_MOVESZ =>
+ return "MOVESZ";
+ when DT_FEATURE_1 =>
+ return "FEATURE_1";
+ when DT_POSFLAG_1 =>
+ return "POSFLAG_1";
+ when DT_SYMINSZ =>
+ return "SYMINSZ";
+ when DT_SYMINENT =>
+ return "SYMINENT";
+-- when DT_VALRNGHI =>
+-- return "VALRNGHI";
+ when DT_ADDRRNGLO =>
+ return "ADDRRNGLO";
+ when DT_GNU_CONFLICT =>
+ return "GNU_CONFLICT";
+ when DT_GNU_LIBLIST =>
+ return "GNU_LIBLIST";
+ when DT_CONFIG =>
+ return "CONFIG";
+ when DT_DEPAUDIT =>
+ return "DEPAUDIT";
+ when DT_AUDIT =>
+ return "AUDIT";
+ when DT_PLTPAD =>
+ return "PLTPAD";
+ when DT_MOVETAB =>
+ return "MOVETAB";
+ when DT_SYMINFO =>
+ return "SYMINFO";
+-- when DT_ADDRRNGHI =>
+-- return "ADDRRNGHI";
+ when DT_VERSYM =>
+ return "VERSYM";
+ when DT_RELACOUNT =>
+ return "RELACOUNT";
+ when DT_RELCOUNT =>
+ return "RELCOUNT";
+ when DT_FLAGS_1 =>
+ return "FLAGS_1";
+ when DT_VERDEF =>
+ return "VERDEF";
+ when DT_VERDEFNUM =>
+ return "VERDEFNUM";
+ when DT_VERNEED =>
+ return "VERNEED";
+ when DT_VERNEEDNUM =>
+ return "VERNEEDNUM";
+ when DT_AUXILIARY =>
+ return "AUXILIARY";
+ when DT_FILTER =>
+ return "FILTER";
+ when others =>
+ return "?unknown?";
+ end case;
+ end Get_Dt_Name;
+
+ procedure Disp_Dynamic (File : Elf_File; Index : Elf_Half)
+ is
+ Shdr : Elf_Shdr_Acc;
+ Base : Address;
+ Off : Storage_Offset;
+ Tag : Unsigned_32;
+ Val : Unsigned_32;
+ begin
+ Shdr := Get_Shdr (File, Index);
+ Base := Get_Section_Base (File, Shdr.all);
+ Off := 0;
+ while Off < Storage_Offset (Shdr.Sh_Size) loop
+ Read_Word4 (Base, Off, Tag);
+ Read_Word4 (Base, Off, Val);
+ Put ("tag : ");
+ Put (Hex_Image (Tag));
+ Put (" (");
+ Put (Get_Dt_Name (Tag));
+ Put (")");
+ Set_Col (34);
+ Put ("val : ");
+ Put (Hex_Image (Val));
+ New_Line;
+ end loop;
+ end Disp_Dynamic;
+
+ function Get_Dwarf_Form_Name (Name : Unsigned_32) return String
+ is
+ use Dwarf;
+ begin
+ case Name is
+ when DW_FORM_Addr =>
+ return "addr";
+ when DW_FORM_Block2 =>
+ return "block2";
+ when DW_FORM_Block4 =>
+ return "block4";
+ when DW_FORM_Data2 =>
+ return "data2";
+ when DW_FORM_Data4 =>
+ return "data4";
+ when DW_FORM_Data8 =>
+ return "data8";
+ when DW_FORM_String =>
+ return "string";
+ when DW_FORM_Block =>
+ return "block";
+ when DW_FORM_Block1 =>
+ return "block1";
+ when DW_FORM_Data1 =>
+ return "data1";
+ when DW_FORM_Flag =>
+ return "flag";
+ when DW_FORM_Sdata =>
+ return "sdata";
+ when DW_FORM_Strp =>
+ return "strp";
+ when DW_FORM_Udata =>
+ return "udata";
+ when DW_FORM_Ref_Addr =>
+ return "ref_addr";
+ when DW_FORM_Ref1 =>
+ return "ref1";
+ when DW_FORM_Ref2 =>
+ return "ref2";
+ when DW_FORM_Ref4 =>
+ return "ref4";
+ when DW_FORM_Ref8 =>
+ return "ref8";
+ when DW_FORM_Ref_Udata =>
+ return "ref_udata";
+ when DW_FORM_Indirect =>
+ return "indirect";
+ when others =>
+ return "unknown";
+ end case;
+ end Get_Dwarf_Form_Name;
+
+ function Get_Dwarf_Tag_Name (Tag : Unsigned_32) return String
+ is
+ use Dwarf;
+ begin
+ case Tag is
+ when DW_TAG_Array_Type =>
+ return "array_type";
+ when DW_TAG_Class_Type =>
+ return "class_type";
+ when DW_TAG_Entry_Point =>
+ return "entry_point";
+ when DW_TAG_Enumeration_Type =>
+ return "enumeration_type";
+ when DW_TAG_Formal_Parameter =>
+ return "formal_parameter";
+ when DW_TAG_Imported_Declaration =>
+ return "imported_declaration";
+ when DW_TAG_Label =>
+ return "label";
+ when DW_TAG_Lexical_Block =>
+ return "lexical_block";
+ when DW_TAG_Member =>
+ return "member";
+ when DW_TAG_Pointer_Type =>
+ return "pointer_type";
+ when DW_TAG_Reference_Type =>
+ return "reference_type";
+ when DW_TAG_Compile_Unit =>
+ return "compile_unit";
+ when DW_TAG_String_Type =>
+ return "string_type";
+ when DW_TAG_Structure_Type =>
+ return "structure_type";
+ when DW_TAG_Subroutine_Type =>
+ return "subroutine_type";
+ when DW_TAG_Typedef =>
+ return "typedef";
+ when DW_TAG_Union_Type =>
+ return "union_type";
+ when DW_TAG_Unspecified_Parameters =>
+ return "unspecified_parameters";
+ when DW_TAG_Variant =>
+ return "variant";
+ when DW_TAG_Common_Block =>
+ return "common_block";
+ when DW_TAG_Common_Inclusion =>
+ return "common_inclusion";
+ when DW_TAG_Inheritance =>
+ return "inheritance";
+ when DW_TAG_Inlined_Subroutine =>
+ return "inlined_subroutine";
+ when DW_TAG_Module =>
+ return "module";
+ when DW_TAG_Ptr_To_Member_Type =>
+ return "ptr_to_member_type";
+ when DW_TAG_Set_Type =>
+ return "set_type";
+ when DW_TAG_Subrange_Type =>
+ return "subrange_type";
+ when DW_TAG_With_Stmt =>
+ return "with_stmt";
+ when DW_TAG_Access_Declaration =>
+ return "access_declaration";
+ when DW_TAG_Base_Type =>
+ return "base_type";
+ when DW_TAG_Catch_Block =>
+ return "catch_block";
+ when DW_TAG_Const_Type =>
+ return "const_type";
+ when DW_TAG_Constant =>
+ return "constant";
+ when DW_TAG_Enumerator =>
+ return "enumerator";
+ when DW_TAG_File_Type =>
+ return "file_type";
+ when DW_TAG_Friend =>
+ return "friend";
+ when DW_TAG_Namelist =>
+ return "namelist";
+ when DW_TAG_Namelist_Item =>
+ return "namelist_item";
+ when DW_TAG_Packed_Type =>
+ return "packed_type";
+ when DW_TAG_Subprogram =>
+ return "subprogram";
+ when DW_TAG_Template_Type_Parameter =>
+ return "template_type_parameter";
+ when DW_TAG_Template_Value_Parameter =>
+ return "template_value_parameter";
+ when DW_TAG_Thrown_Type =>
+ return "thrown_type";
+ when DW_TAG_Try_Block =>
+ return "try_block";
+ when DW_TAG_Variant_Part =>
+ return "variant_part";
+ when DW_TAG_Variable =>
+ return "variable";
+ when DW_TAG_Volatile_Type =>
+ return "volatile_type";
+ when DW_TAG_Dwarf_Procedure =>
+ return "dwarf_procedure";
+ when DW_TAG_Restrict_Type =>
+ return "restrict_type";
+ when DW_TAG_Interface_Type =>
+ return "interface_type";
+ when DW_TAG_Namespace =>
+ return "namespace";
+ when DW_TAG_Imported_Module =>
+ return "imported_module";
+ when DW_TAG_Unspecified_Type =>
+ return "unspecified_type";
+ when DW_TAG_Partial_Unit =>
+ return "partial_unit";
+ when DW_TAG_Imported_Unit =>
+ return "imported_unit";
+ when DW_TAG_Mutable_Type =>
+ return "mutable_type";
+ when others =>
+ return "unknown";
+ end case;
+ end Get_Dwarf_Tag_Name;
+
+ function Get_Dwarf_At_Name (Attr : Unsigned_32) return String
+ is
+ use Dwarf;
+ begin
+ case Attr is
+ when DW_AT_Sibling =>
+ return "sibling";
+ when DW_AT_Location =>
+ return "location";
+ when DW_AT_Name =>
+ return "name";
+ when DW_AT_Ordering =>
+ return "ordering";
+ when DW_AT_Byte_Size =>
+ return "byte_size";
+ when DW_AT_Bit_Offset =>
+ return "bit_offset";
+ when DW_AT_Bit_Size =>
+ return "bit_size";
+ when DW_AT_Stmt_List =>
+ return "stmt_list";
+ when DW_AT_Low_Pc =>
+ return "low_pc";
+ when DW_AT_High_Pc =>
+ return "high_pc";
+ when DW_AT_Language =>
+ return "language";
+ when DW_AT_Discr =>
+ return "discr";
+ when DW_AT_Discr_Value =>
+ return "discr_value";
+ when DW_AT_Visibility =>
+ return "visibility";
+ when DW_AT_Import =>
+ return "import";
+ when DW_AT_String_Length =>
+ return "string_length";
+ when DW_AT_Common_Reference =>
+ return "common_reference";
+ when DW_AT_Comp_Dir =>
+ return "comp_dir";
+ when DW_AT_Const_Value =>
+ return "const_value";
+ when DW_AT_Containing_Type =>
+ return "containing_type";
+ when DW_AT_Default_Value =>
+ return "default_value";
+ when DW_AT_Inline =>
+ return "inline";
+ when DW_AT_Is_Optional =>
+ return "is_optional";
+ when DW_AT_Lower_Bound =>
+ return "lower_bound";
+ when DW_AT_Producer =>
+ return "producer";
+ when DW_AT_Prototyped =>
+ return "prototyped";
+ when DW_AT_Return_Addr =>
+ return "return_addr";
+ when DW_AT_Start_Scope =>
+ return "start_scope";
+ when DW_AT_Stride_Size =>
+ return "stride_size";
+ when DW_AT_Upper_Bound =>
+ return "upper_bound";
+ when DW_AT_Abstract_Origin =>
+ return "abstract_origin";
+ when DW_AT_Accessibility =>
+ return "accessibility";
+ when DW_AT_Address_Class =>
+ return "address_class";
+ when DW_AT_Artificial =>
+ return "artificial";
+ when DW_AT_Base_Types =>
+ return "base_types";
+ when DW_AT_Calling_Convention =>
+ return "calling_convention";
+ when DW_AT_Count =>
+ return "count";
+ when DW_AT_Data_Member_Location =>
+ return "data_member_location";
+ when DW_AT_Decl_Column =>
+ return "decl_column";
+ when DW_AT_Decl_File =>
+ return "decl_file";
+ when DW_AT_Decl_Line =>
+ return "decl_line";
+ when DW_AT_Declaration =>
+ return "declaration";
+ when DW_AT_Discr_List =>
+ return "discr_list";
+ when DW_AT_Encoding =>
+ return "encoding";
+ when DW_AT_External =>
+ return "external";
+ when DW_AT_Frame_Base =>
+ return "frame_base";
+ when DW_AT_Friend =>
+ return "friend";
+ when DW_AT_Identifier_Case =>
+ return "identifier_case";
+ when DW_AT_Macro_Info =>
+ return "macro_info";
+ when DW_AT_Namelist_Item =>
+ return "namelist_item";
+ when DW_AT_Priority =>
+ return "priority";
+ when DW_AT_Segment =>
+ return "segment";
+ when DW_AT_Specification =>
+ return "specification";
+ when DW_AT_Static_Link =>
+ return "static_link";
+ when DW_AT_Type =>
+ return "type";
+ when DW_AT_Use_Location =>
+ return "use_location";
+ when DW_AT_Variable_Parameter =>
+ return "variable_parameter";
+ when DW_AT_Virtuality =>
+ return "virtuality";
+ when DW_AT_Vtable_Elem_Location =>
+ return "vtable_elem_location";
+ when DW_AT_Allocated =>
+ return "allocated";
+ when DW_AT_Associated =>
+ return "associated";
+ when DW_AT_Data_Location =>
+ return "data_location";
+ when DW_AT_Stride =>
+ return "stride";
+ when DW_AT_Entry_Pc =>
+ return "entry_pc";
+ when DW_AT_Use_UTF8 =>
+ return "use_utf8";
+ when DW_AT_Extension =>
+ return "extension";
+ when DW_AT_Ranges =>
+ return "ranges";
+ when DW_AT_Trampoline =>
+ return "trampoline";
+ when DW_AT_Call_Column =>
+ return "call_column";
+ when DW_AT_Call_File =>
+ return "call_file";
+ when DW_AT_Call_Line =>
+ return "call_line";
+ when DW_AT_Description =>
+ return "description";
+ when others =>
+ return "unknown";
+ end case;
+ end Get_Dwarf_At_Name;
+
+ procedure Disp_Debug_Abbrev (File : Elf_File; Index : Elf_Half)
+ is
+ Shdr : Elf_Shdr_Acc;
+ Base : Address;
+ Old_Off : Storage_Offset;
+ Off : Storage_Offset;
+ V : Unsigned_32;
+ Tag : Unsigned_32;
+ Name : Unsigned_32;
+ Form : Unsigned_32;
+ begin
+ Shdr := Get_Shdr (File, Index);
+ Base := Get_Section_Base (File, Shdr.all);
+
+ Off := 0;
+ while Off < Storage_Offset (Shdr.Sh_Size) loop
+ Old_Off := Off;
+ Read_ULEB128 (Base, Off, V);
+ Put_Line ("abbrev #" & Hex_Image (V) & " at "
+ & Hex_Image (Unsigned_32 (Old_Off)) & ':');
+ if V = 0 then
+ Put_Line ("pad");
+ goto Again;
+ end if;
+ Read_ULEB128 (Base, Off, Tag);
+ Put (" tag: " & Hex_Image (Tag));
+ Put (" (");
+ Put (Get_Dwarf_Tag_Name (Tag));
+ Put ("), children: " & Hex_Image (Read_Byte (Base + Off)));
+ New_Line;
+ Off := Off + 1;
+ loop
+ Read_ULEB128 (Base, Off, Name);
+ Read_ULEB128 (Base, Off, Form);
+ Put (" name: " & Hex_Image (Name));
+ Put (" (");
+ Put (Get_Dwarf_At_Name (Name));
+ Put (")");
+ Set_Col (42);
+ Put ("form: " & Hex_Image (Form));
+ Put (" (");
+ Put (Get_Dwarf_Form_Name (Form));
+ Put (")");
+ New_Line;
+ exit when Name = 0 and Form = 0;
+ end loop;
+ << Again >> null;
+ end loop;
+ end Disp_Debug_Abbrev;
+
+ type Abbrev_Map_Type is array (Unsigned_32 range <>) of Address;
+ type Abbrev_Map_Acc is access Abbrev_Map_Type;
+ procedure Unchecked_Deallocation is new Ada.Unchecked_Deallocation
+ (Abbrev_Map_Type, Abbrev_Map_Acc);
+
+ procedure Build_Abbrev_Map (Base : Address; Res : out Abbrev_Map_Acc)
+ is
+ Max : Unsigned_32;
+ Off : Storage_Offset;
+ V : Unsigned_32;
+ V1 : Unsigned_32;
+ N_Res : Abbrev_Map_Acc;
+ begin
+ Off := 0;
+ Max := 0;
+ Res := new Abbrev_Map_Type (0 .. 128);
+ Res.all := (others => Null_Address);
+ loop
+ Read_ULEB128 (Base, Off, V);
+ if V > Max then
+ Max := V;
+ end if;
+ exit when V = 0;
+ if Max > Res.all'Last then
+ N_Res := new Abbrev_Map_Type (0 .. 2 * Max);
+ N_Res (Res'Range) := Res.all;
+ N_Res (Res'Last + 1 .. N_Res'Last) := (others => Null_Address);
+ Unchecked_Deallocation (Res);
+ Res := N_Res;
+ end if;
+ if Res (V) /= Null_Address then
+ Put_Line ("!! abbrev override !!");
+ return;
+ end if;
+ Res (V) := Base + Off;
+ Read_ULEB128 (Base, Off, V);
+ -- Skip child flag.
+ Off := Off + 1;
+ loop
+ Read_ULEB128 (Base, Off, V);
+ Read_ULEB128 (Base, Off, V1);
+ exit when V = 0 and V1 = 0;
+ end loop;
+ end loop;
+ end Build_Abbrev_Map;
+
+ procedure Disp_Block (Base : Address;
+ Off : in out Storage_Offset;
+ Cnt : Unsigned_32)
+ is
+ begin
+ for I in 1 .. Cnt loop
+ Put (" ");
+ Put (Hex_Image (Read_Byte (Base + Off + Storage_Offset (I - 1))));
+ end loop;
+ Off := Off + Storage_Offset (Cnt);
+ end Disp_Block;
+
+ procedure Disp_Dwarf_Form (Base : Address;
+ Off : in out Storage_Offset;
+ Form : Unsigned_32)
+ is
+ use Dwarf;
+ begin
+ case Form is
+ when DW_FORM_Addr =>
+ declare
+ V : Unsigned_32;
+ begin
+ Read_Word4 (Base, Off, V);
+ Put ("address: " & Hex_Image (V));
+ end;
+ when DW_FORM_Flag =>
+ declare
+ V : Unsigned_8;
+ begin
+ Read_Byte (Base, Off, V);
+ Put ("flag: " & Hex_Image (V));
+ end;
+ when DW_FORM_Block1 =>
+ declare
+ V : Unsigned_8;
+ begin
+ Read_Byte (Base, Off, V);
+ Put ("block1: " & Hex_Image (V));
+ Disp_Block (Base, Off, Unsigned_32 (V));
+ end;
+ when DW_FORM_Data1 =>
+ declare
+ V : Unsigned_8;
+ begin
+ Read_Byte (Base, Off, V);
+ Put ("data1: " & Hex_Image (V));
+ end;
+ when DW_FORM_Data2 =>
+ declare
+ V : Unsigned_16;
+ begin
+ Read_Word2 (Base, Off, V);
+ Put ("data2: " & Hex_Image (V));
+ end;
+ when DW_FORM_Data4 =>
+ declare
+ V : Unsigned_32;
+ begin
+ Read_Word4 (Base, Off, V);
+ Put ("data4: " & Hex_Image (V));
+ end;
+ when DW_FORM_Sdata =>
+ declare
+ V : Unsigned_32;
+ begin
+ Read_SLEB128 (Base, Off, V);
+ Put ("sdata: " & Hex_Image (V));
+ end;
+ when DW_FORM_Udata =>
+ declare
+ V : Unsigned_32;
+ begin
+ Read_ULEB128 (Base, Off, V);
+ Put ("udata: " & Hex_Image (V));
+ end;
+ when DW_FORM_Ref4 =>
+ declare
+ V : Unsigned_32;
+ begin
+ Read_Word4 (Base, Off, V);
+ Put ("ref4: " & Hex_Image (V));
+ end;
+ when DW_FORM_Strp =>
+ declare
+ V : Unsigned_32;
+ begin
+ Read_Word4 (Base, Off, V);
+ Put ("strp: " & Hex_Image (V));
+ end;
+ when DW_FORM_String =>
+ declare
+ C : Unsigned_8;
+ begin
+ Put ("string: ");
+ loop
+ Read_Byte (Base, Off, C);
+ exit when C = 0;
+ Put (Character'Val (C));
+ end loop;
+ end;
+ when others =>
+ Put ("???");
+ raise Program_Error;
+ end case;
+ end Disp_Dwarf_Form;
+
+ function Get_Dwarf_ATE_Name (Val : Unsigned_32) return String
+ is
+ use Dwarf;
+ begin
+ case Val is
+ when DW_ATE_Address =>
+ return "address";
+ when DW_ATE_Boolean =>
+ return "boolean";
+ when DW_ATE_Complex_Float =>
+ return "complex_float";
+ when DW_ATE_Float =>
+ return "float";
+ when DW_ATE_Signed =>
+ return "signed";
+ when DW_ATE_Signed_Char =>
+ return "signed_char";
+ when DW_ATE_Unsigned =>
+ return "unsigned";
+ when DW_ATE_Unsigned_Char =>
+ return "unsigned_char";
+ when DW_ATE_Imaginary_Float =>
+ return "imaginary_float";
+ when others =>
+ return "unknown";
+ end case;
+ end Get_Dwarf_ATE_Name;
+
+ procedure Read_Dwarf_Constant (Base : Address;
+ Off : in out Storage_Offset;
+ Form : Unsigned_32;
+ Res : out Unsigned_32)
+ is
+ use Dwarf;
+ begin
+ case Form is
+ when DW_FORM_Data1 =>
+ declare
+ V : Unsigned_8;
+ begin
+ Read_Byte (Base, Off, V);
+ Res := Unsigned_32 (V);
+ end;
+ when DW_FORM_Data2 =>
+ declare
+ V : Unsigned_16;
+ begin
+ Read_Word2 (Base, Off, V);
+ Res := Unsigned_32 (V);
+ end;
+ when DW_FORM_Data4 =>
+ declare
+ V : Unsigned_32;
+ begin
+ Read_Word4 (Base, Off, V);
+ Res := V;
+ end;
+ when DW_FORM_Sdata =>
+ declare
+ V : Unsigned_32;
+ begin
+ Read_SLEB128 (Base, Off, V);
+ Res := V;
+ end;
+ when others =>
+ raise Program_Error;
+ end case;
+ end Read_Dwarf_Constant;
+
+ procedure Disp_Dwarf_Encoding
+ (Base : Address; Off : in out Storage_Offset; Form : Unsigned_32)
+ is
+ Val : Unsigned_32;
+ begin
+ Read_Dwarf_Constant (Base, Off, Form, Val);
+ Put (Get_Dwarf_ATE_Name (Val));
+ end Disp_Dwarf_Encoding;
+
+ function Get_Dwarf_Lang_Name (Lang : Unsigned_32) return String
+ is
+ use Dwarf;
+ begin
+ case Lang is
+ when DW_LANG_C89 =>
+ return "C89";
+ when DW_LANG_C =>
+ return "C";
+ when DW_LANG_Ada83 =>
+ return "Ada83";
+ when DW_LANG_C_Plus_Plus =>
+ return "C_Plus_Plus";
+ when DW_LANG_Cobol74 =>
+ return "Cobol74";
+ when DW_LANG_Cobol85 =>
+ return "Cobol85";
+ when DW_LANG_Fortran77 =>
+ return "Fortran77";
+ when DW_LANG_Fortran90 =>
+ return "Fortran90";
+ when DW_LANG_Pascal83 =>
+ return "Pascal83";
+ when DW_LANG_Modula2 =>
+ return "Modula2";
+ when DW_LANG_Java =>
+ return "Java";
+ when DW_LANG_C99 =>
+ return "C99";
+ when DW_LANG_Ada95 =>
+ return "Ada95";
+ when DW_LANG_Fortran95 =>
+ return "Fortran95";
+ when DW_LANG_PLI =>
+ return "PLI";
+ when others =>
+ return "?unknown?";
+ end case;
+ end Get_Dwarf_Lang_Name;
+
+ procedure Disp_Dwarf_Language
+ (Base : Address; Off : in out Storage_Offset; Form : Unsigned_32)
+ is
+ Val : Unsigned_32;
+ begin
+ Read_Dwarf_Constant (Base, Off, Form, Val);
+ Put (Get_Dwarf_Lang_Name (Val));
+ end Disp_Dwarf_Language;
+
+ function Get_Dwarf_Op_Name (Op : Unsigned_8) return String
+ is
+ use Dwarf;
+ begin
+ case Op is
+ when DW_OP_Addr =>
+ return "addr";
+ when DW_OP_Deref =>
+ return "deref";
+ when DW_OP_Const1u =>
+ return "const1u";
+ when DW_OP_Const1s =>
+ return "const1s";
+ when DW_OP_Const2u =>
+ return "const2u";
+ when DW_OP_Const2s =>
+ return "const2s";
+ when DW_OP_Const4u =>
+ return "const4u";
+ when DW_OP_Const4s =>
+ return "const4s";
+ when DW_OP_Const8u =>
+ return "const8u";
+ when DW_OP_Const8s =>
+ return "const8s";
+ when DW_OP_Constu =>
+ return "constu";
+ when DW_OP_Consts =>
+ return "consts";
+ when DW_OP_Dup =>
+ return "dup";
+ when DW_OP_Drop =>
+ return "drop";
+ when DW_OP_Over =>
+ return "over";
+ when DW_OP_Pick =>
+ return "pick";
+ when DW_OP_Swap =>
+ return "swap";
+ when DW_OP_Rot =>
+ return "rot";
+ when DW_OP_Xderef =>
+ return "xderef";
+ when DW_OP_Abs =>
+ return "abs";
+ when DW_OP_And =>
+ return "and";
+ when DW_OP_Div =>
+ return "div";
+ when DW_OP_Minus =>
+ return "minus";
+ when DW_OP_Mod =>
+ return "mod";
+ when DW_OP_Mul =>
+ return "mul";
+ when DW_OP_Neg =>
+ return "neg";
+ when DW_OP_Not =>
+ return "not";
+ when DW_OP_Or =>
+ return "or";
+ when DW_OP_Plus =>
+ return "plus";
+ when DW_OP_Plus_Uconst =>
+ return "plus_uconst";
+ when DW_OP_Shl =>
+ return "shl";
+ when DW_OP_Shr =>
+ return "shr";
+ when DW_OP_Shra =>
+ return "shra";
+ when DW_OP_Xor =>
+ return "xor";
+ when DW_OP_Skip =>
+ return "skip";
+ when DW_OP_Bra =>
+ return "bra";
+ when DW_OP_Eq =>
+ return "eq";
+ when DW_OP_Ge =>
+ return "ge";
+ when DW_OP_Gt =>
+ return "gt";
+ when DW_OP_Le =>
+ return "le";
+ when DW_OP_Lt =>
+ return "lt";
+ when DW_OP_Ne =>
+ return "ne";
+ when DW_OP_Lit0 =>
+ return "lit0";
+ when DW_OP_Lit1 =>
+ return "lit1";
+ when DW_OP_Lit2 =>
+ return "lit2";
+ when DW_OP_Lit3 =>
+ return "lit3";
+ when DW_OP_Lit4 =>
+ return "lit4";
+ when DW_OP_Lit5 =>
+ return "lit5";
+ when DW_OP_Lit6 =>
+ return "lit6";
+ when DW_OP_Lit7 =>
+ return "lit7";
+ when DW_OP_Lit8 =>
+ return "lit8";
+ when DW_OP_Lit9 =>
+ return "lit9";
+ when DW_OP_Lit10 =>
+ return "lit10";
+ when DW_OP_Lit11 =>
+ return "lit11";
+ when DW_OP_Lit12 =>
+ return "lit12";
+ when DW_OP_Lit13 =>
+ return "lit13";
+ when DW_OP_Lit14 =>
+ return "lit14";
+ when DW_OP_Lit15 =>
+ return "lit15";
+ when DW_OP_Lit16 =>
+ return "lit16";
+ when DW_OP_Lit17 =>
+ return "lit17";
+ when DW_OP_Lit18 =>
+ return "lit18";
+ when DW_OP_Lit19 =>
+ return "lit19";
+ when DW_OP_Lit20 =>
+ return "lit20";
+ when DW_OP_Lit21 =>
+ return "lit21";
+ when DW_OP_Lit22 =>
+ return "lit22";
+ when DW_OP_Lit23 =>
+ return "lit23";
+ when DW_OP_Lit24 =>
+ return "lit24";
+ when DW_OP_Lit25 =>
+ return "lit25";
+ when DW_OP_Lit26 =>
+ return "lit26";
+ when DW_OP_Lit27 =>
+ return "lit27";
+ when DW_OP_Lit28 =>
+ return "lit28";
+ when DW_OP_Lit29 =>
+ return "lit29";
+ when DW_OP_Lit30 =>
+ return "lit30";
+ when DW_OP_Lit31 =>
+ return "lit31";
+ when DW_OP_Reg0 =>
+ return "reg0";
+ when DW_OP_Reg1 =>
+ return "reg1";
+ when DW_OP_Reg2 =>
+ return "reg2";
+ when DW_OP_Reg3 =>
+ return "reg3";
+ when DW_OP_Reg4 =>
+ return "reg4";
+ when DW_OP_Reg5 =>
+ return "reg5";
+ when DW_OP_Reg6 =>
+ return "reg6";
+ when DW_OP_Reg7 =>
+ return "reg7";
+ when DW_OP_Reg8 =>
+ return "reg8";
+ when DW_OP_Reg9 =>
+ return "reg9";
+ when DW_OP_Reg10 =>
+ return "reg10";
+ when DW_OP_Reg11 =>
+ return "reg11";
+ when DW_OP_Reg12 =>
+ return "reg12";
+ when DW_OP_Reg13 =>
+ return "reg13";
+ when DW_OP_Reg14 =>
+ return "reg14";
+ when DW_OP_Reg15 =>
+ return "reg15";
+ when DW_OP_Reg16 =>
+ return "reg16";
+ when DW_OP_Reg17 =>
+ return "reg17";
+ when DW_OP_Reg18 =>
+ return "reg18";
+ when DW_OP_Reg19 =>
+ return "reg19";
+ when DW_OP_Reg20 =>
+ return "reg20";
+ when DW_OP_Reg21 =>
+ return "reg21";
+ when DW_OP_Reg22 =>
+ return "reg22";
+ when DW_OP_Reg23 =>
+ return "reg23";
+ when DW_OP_Reg24 =>
+ return "reg24";
+ when DW_OP_Reg25 =>
+ return "reg25";
+ when DW_OP_Reg26 =>
+ return "reg26";
+ when DW_OP_Reg27 =>
+ return "reg27";
+ when DW_OP_Reg28 =>
+ return "reg28";
+ when DW_OP_Reg29 =>
+ return "reg29";
+ when DW_OP_Reg30 =>
+ return "reg30";
+ when DW_OP_Reg31 =>
+ return "reg31";
+ when DW_OP_Breg0 =>
+ return "breg0";
+ when DW_OP_Breg1 =>
+ return "breg1";
+ when DW_OP_Breg2 =>
+ return "breg2";
+ when DW_OP_Breg3 =>
+ return "breg3";
+ when DW_OP_Breg4 =>
+ return "breg4";
+ when DW_OP_Breg5 =>
+ return "breg5";
+ when DW_OP_Breg6 =>
+ return "breg6";
+ when DW_OP_Breg7 =>
+ return "breg7";
+ when DW_OP_Breg8 =>
+ return "breg8";
+ when DW_OP_Breg9 =>
+ return "breg9";
+ when DW_OP_Breg10 =>
+ return "breg10";
+ when DW_OP_Breg11 =>
+ return "breg11";
+ when DW_OP_Breg12 =>
+ return "breg12";
+ when DW_OP_Breg13 =>
+ return "breg13";
+ when DW_OP_Breg14 =>
+ return "breg14";
+ when DW_OP_Breg15 =>
+ return "breg15";
+ when DW_OP_Breg16 =>
+ return "breg16";
+ when DW_OP_Breg17 =>
+ return "breg17";
+ when DW_OP_Breg18 =>
+ return "breg18";
+ when DW_OP_Breg19 =>
+ return "breg19";
+ when DW_OP_Breg20 =>
+ return "breg20";
+ when DW_OP_Breg21 =>
+ return "breg21";
+ when DW_OP_Breg22 =>
+ return "breg22";
+ when DW_OP_Breg23 =>
+ return "breg23";
+ when DW_OP_Breg24 =>
+ return "breg24";
+ when DW_OP_Breg25 =>
+ return "breg25";
+ when DW_OP_Breg26 =>
+ return "breg26";
+ when DW_OP_Breg27 =>
+ return "breg27";
+ when DW_OP_Breg28 =>
+ return "breg28";
+ when DW_OP_Breg29 =>
+ return "breg29";
+ when DW_OP_Breg30 =>
+ return "breg30";
+ when DW_OP_Breg31 =>
+ return "breg31";
+ when DW_OP_Regx =>
+ return "regx";
+ when DW_OP_Fbreg =>
+ return "fbreg";
+ when DW_OP_Bregx =>
+ return "bregx";
+ when DW_OP_Piece =>
+ return "piece";
+ when DW_OP_Deref_Size =>
+ return "deref_size";
+ when DW_OP_Xderef_Size =>
+ return "xderef_size";
+ when DW_OP_Nop =>
+ return "nop";
+ when DW_OP_Push_Object_Address =>
+ return "push_object_address";
+ when DW_OP_Call2 =>
+ return "call2";
+ when DW_OP_Call4 =>
+ return "call4";
+ when DW_OP_Call_Ref =>
+ return "call_ref";
+ when others =>
+ return "unknown";
+ end case;
+ end Get_Dwarf_Op_Name;
+
+ procedure Read_Dwarf_Block (Base : Address;
+ Off : in out Storage_Offset;
+ Form : Unsigned_32;
+ B : out Address;
+ L : out Unsigned_32)
+ is
+ use Dwarf;
+ begin
+ case Form is
+ when DW_FORM_Block1 =>
+ B := Base + Off + 1;
+ L := Unsigned_32 (Read_Byte (Base + Off));
+ Off := Off + 1;
+ when others =>
+ raise Program_Error;
+ end case;
+ Off := Off + Storage_Offset (L);
+ end Read_Dwarf_Block;
+
+ procedure Disp_Dwarf_Location
+ (Base : Address; Off : in out Storage_Offset; Form : Unsigned_32)
+ is
+ use Dwarf;
+ B : Address;
+ L : Unsigned_32;
+ Op : Unsigned_8;
+ Boff : Storage_Offset;
+ Is_Full : Boolean;
+ begin
+ Read_Dwarf_Block (Base, Off, Form, B, L);
+ if L = 0 then
+ return;
+ end if;
+ Is_Full := L > 6;
+ Boff := 0;
+ while Boff < Storage_Offset (L) loop
+ if Is_Full then
+ New_Line;
+ Put (" ");
+ Put (Hex_Image (Unsigned_32 (Boff)));
+ Put (": ");
+ end if;
+ Op := Read_Byte (B + Boff);
+ Put (' ');
+ Put (Get_Dwarf_Op_Name (Op));
+ Boff := Boff + 1;
+ case Op is
+ when DW_OP_Addr =>
+ declare
+ V : Unsigned_32;
+ begin
+ Read_Word4 (B, Boff, V);
+ Put (':');
+ Put (Hex_Image (V));
+ end;
+ when DW_OP_Deref =>
+ null;
+ when DW_OP_Const1u
+ | DW_OP_Const1s =>
+ declare
+ V : Unsigned_8;
+ begin
+ Read_Byte (B, Boff, V);
+ Put (':');
+ Put (Hex_Image (V));
+ end;
+-- DW_OP_Const2u : constant := 16#0a#; -- 1 2-byte constant
+-- DW_OP_Const2s : constant := 16#0b#; -- 1 2-byte constant
+-- DW_OP_Const4u : constant := 16#0c#; -- 1 4-byte constant
+-- DW_OP_Const4s : constant := 16#0d#; -- 1 4-byte constant
+-- DW_OP_Const8u : constant := 16#0e#; -- 1 8-byte constant
+-- DW_OP_Const8s : constant := 16#0f#; -- 1 8-byte constant
+-- DW_OP_Constu : constant := 16#10#; -- 1 ULEB128 constant
+-- DW_OP_Consts : constant := 16#11#; -- 1 SLEB128 constant
+-- DW_OP_Dup : constant := 16#12#; -- 0
+-- DW_OP_Drop : constant := 16#13#; -- 0
+-- DW_OP_Over : constant := 16#14#; -- 0
+-- DW_OP_Pick : constant := 16#15#; -- 1 1-byte stack index
+
+ when DW_OP_Swap
+ | DW_OP_Rot
+ | DW_OP_Xderef
+ | DW_OP_Abs
+ | DW_OP_And
+ | DW_OP_Div
+ | DW_OP_Minus
+ | DW_OP_Mod
+ | DW_OP_Mul
+ | DW_OP_Neg
+ | DW_OP_Not
+ | DW_OP_Or
+ | DW_OP_Plus =>
+ null;
+ when DW_OP_Plus_Uconst
+ | DW_OP_Piece
+ | DW_OP_Regx =>
+ declare
+ V : Unsigned_32;
+ begin
+ Read_ULEB128 (B, Boff, V);
+ Put (':');
+ Put (Hex_Image (V));
+ end;
+ when DW_OP_Shl
+ | DW_OP_Shr
+ | DW_OP_Shra
+ | DW_OP_Xor =>
+ null;
+ when DW_OP_Skip
+ | DW_OP_Bra =>
+ declare
+ V : Unsigned_16;
+ begin
+ Read_Word2 (B, Boff, V);
+ Put (':');
+ Put (Hex_Image (V));
+ Put (" (@");
+ -- FIXME: signed
+ Put (Hex_Image (Unsigned_32 (Boff) + Unsigned_32 (V)));
+ Put (")");
+ end;
+ when DW_OP_Eq
+ | DW_OP_Ge
+ | DW_OP_Gt
+ | DW_OP_Le
+ | DW_OP_Lt
+ | DW_OP_Ne =>
+ null;
+ when DW_OP_Lit0 .. DW_OP_Lit31 =>
+ null;
+ when DW_OP_Reg0 .. DW_OP_Reg31 =>
+ null;
+ when DW_OP_Breg0 .. DW_OP_Breg31
+ | DW_OP_Fbreg =>
+ declare
+ V : Unsigned_32;
+ begin
+ Read_SLEB128 (B, Boff, V);
+ Put (':');
+ Put (Hex_Image (V));
+ end;
+
+-- DW_OP_Regx : constant := 16#90#; -- 1 ULEB128 register
+-- DW_OP_Bregx : constant := 16#92#; -- 2 ULEB128 reg + SLEB128 offset
+-- DW_OP_Deref_Size : constant := 16#94#; -- 1 1-byte size of data retrieved
+-- DW_OP_Xderef_Size : constant := 16#95#; -- 1 1-byte size of data retrieved
+ when DW_OP_Nop =>
+ null;
+-- DW_OP_Push_Object_Address : constant := 16#97#; -- 0
+-- DW_OP_Call2 : constant := 16#98#; -- 1 2-byte offset of DIE
+-- DW_OP_Call4 : constant := 16#99#; -- 1 4-byte offset of DIE
+-- DW_OP_Call_Ref : constant := 16#9a#; -- 1 4- or 8-byte offset of DIE
+ when others =>
+ raise Program_Error;
+ end case;
+ end loop;
+ end Disp_Dwarf_Location;
+
+ procedure Disp_Debug_Info (File : Elf_File; Index : Elf_Half)
+ is
+ use Dwarf;
+
+ Abbrev_Index : Elf_Half;
+ Abbrev_Base : Address;
+ Map : Abbrev_Map_Acc;
+ Abbrev : Address;
+
+ Shdr : Elf_Shdr_Acc;
+ Base : Address;
+ Off : Storage_Offset;
+ Aoff : Storage_Offset;
+ Old_Off : Storage_Offset;
+
+ Len : Unsigned_32;
+ Ver : Unsigned_16;
+ Abbrev_Off : Unsigned_32;
+ Ptr_Sz : Unsigned_8;
+ Last : Storage_Offset;
+ Num : Unsigned_32;
+
+ Tag : Unsigned_32;
+ Name : Unsigned_32;
+ Form : Unsigned_32;
+
+ Level : Unsigned_8;
+ begin
+ Abbrev_Index := Get_Section_By_Name (File, ".debug_abbrev");
+ Abbrev_Base := Get_Section_Base (File, Abbrev_Index);
+ Map := null;
+
+ Shdr := Get_Shdr (File, Index);
+ Base := Get_Section_Base (File, Shdr.all);
+
+ Off := 0;
+ while Off < Storage_Offset (Shdr.Sh_Size) loop
+ Put_Line ("Compilation unit at #"
+ & Hex_Image (Unsigned_32 (Off)) & ":");
+ Read_Word4 (Base, Off, Len);
+ Last := Off + Storage_Offset (Len);
+ Read_Word2 (Base, Off, Ver);
+ Read_Word4 (Base, Off, Abbrev_Off);
+ Read_Byte (Base, Off, Ptr_Sz);
+ Put (' ');
+ Put ("length: " & Hex_Image (Len));
+ Put (", version: " & Hex_Image (Ver));
+ Put (", abbrev offset: " & Hex_Image (Abbrev_Off));
+ Put (", ptr_sz: " & Hex_Image (Ptr_Sz));
+ New_Line;
+ Level := 0;
+
+ Build_Abbrev_Map (Abbrev_Base + Storage_Offset (Abbrev_Off), Map);
+ loop
+ << Again >> null;
+ exit when Off >= Last;
+ Old_Off := Off;
+ Read_ULEB128 (Base, Off, Num);
+ Put ("<" & Hex_Image (Unsigned_32 (Old_Off)) & ">");
+ Put ("<" & Hex_Image (Level) & ">");
+ Put (" with abbrev #" & Hex_Image (Num));
+ if Num = 0 then
+ Level := Level - 1;
+ New_Line;
+ goto Again;
+ end if;
+ if Num <= Map.all'Last then
+ Abbrev := Map (Num);
+ else
+ Abbrev := Null_Address;
+ end if;
+ if Abbrev = Null_Address then
+ New_Line;
+ Put ("!! abbrev #" & Hex_Image (Num) & " does not exist !!");
+ New_Line;
+ return;
+ end if;
+ Aoff := 0;
+ Read_ULEB128 (Abbrev, Aoff, Tag);
+ if Read_Byte (Abbrev + Aoff) /= 0 then
+ Put (" [has_child]");
+ Level := Level + 1;
+ end if;
+ New_Line;
+
+ -- skip child.
+ Aoff := Aoff + 1;
+ Put (" tag: " & Hex_Image (Tag));
+ Put (" (");
+ Put (Get_Dwarf_Tag_Name (Tag));
+ Put (")");
+ New_Line;
+
+ loop
+ Read_ULEB128 (Abbrev, Aoff, Name);
+ Read_ULEB128 (Abbrev, Aoff, Form);
+ exit when Name = 0 and Form = 0;
+ Put (" ");
+ Put (Get_Dwarf_At_Name (Name));
+ Set_Col (24);
+ Put (": ");
+ Old_Off := Off;
+ Disp_Dwarf_Form (Base, Off, Form);
+ case Name is
+ when DW_AT_Encoding =>
+ Put (": ");
+ Disp_Dwarf_Encoding (Base, Old_Off, Form);
+ when DW_AT_Location
+ | DW_AT_Frame_Base
+ | DW_AT_Data_Member_Location =>
+ Put (":");
+ Disp_Dwarf_Location (Base, Old_Off, Form);
+ when DW_AT_Language =>
+ Put (": ");
+ Disp_Dwarf_Language (Base, Old_Off, Form);
+ when others =>
+ null;
+ end case;
+ New_Line;
+ end loop;
+ end loop;
+ Unchecked_Deallocation (Map);
+ New_Line;
+ end loop;
+ end Disp_Debug_Info;
+
+ function Get_Phdr_Type_Name (Ptype : Elf_Word) return String is
+ begin
+ case Ptype is
+ when PT_NULL =>
+ return "NULL";
+ when PT_LOAD =>
+ return "LOAD";
+ when PT_DYNAMIC =>
+ return "DYNAMIC";
+ when PT_INTERP =>
+ return "INTERP";
+ when PT_NOTE =>
+ return "NOTE";
+ when PT_SHLIB =>
+ return "SHLIB";
+ when PT_PHDR =>
+ return "PHDR";
+ when PT_TLS =>
+ return "TLS";
+ when PT_NUM =>
+ return "NUM";
+ when PT_GNU_EH_FRAME =>
+ return "GNU_EH_FRAME";
+ when PT_SUNWBSS =>
+ return "SUNWBSS";
+ when PT_SUNWSTACK =>
+ return "SUNWSTACK";
+ when others =>
+ return "?unknown?";
+ end case;
+ end Get_Phdr_Type_Name;
+
+ procedure Disp_Phdr (Phdr : Elf_Phdr)
+ is
+ begin
+ Put ("type : " & Hex_Image (Phdr.P_Type));
+ Put (" ");
+ Put (Get_Phdr_Type_Name (Phdr.P_Type));
+ New_Line;
+ Put ("offset: " & Hex_Image (Phdr.P_Offset));
+ Put (" vaddr: " & Hex_Image (Phdr.P_Vaddr));
+ Put (" paddr: " & Hex_Image (Phdr.P_Paddr));
+ New_Line;
+ Put ("filesz: " & Hex_Image (Phdr.P_Filesz));
+ Put (" memsz: " & Hex_Image (Phdr.P_Memsz));
+ Put (" align: " & Hex_Image (Phdr.P_Align));
+ --New_Line;
+ Put (" flags: " & Hex_Image (Phdr.P_Flags));
+ Put (" (");
+ if (Phdr.P_Flags and PF_X) /= 0 then
+ Put ('X');
+ end if;
+ if (Phdr.P_Flags and PF_W) /= 0 then
+ Put ('W');
+ end if;
+ if (Phdr.P_Flags and PF_R) /= 0 then
+ Put ('R');
+ end if;
+ Put (")");
+ New_Line;
+ end Disp_Phdr;
+
+ procedure Disp_Debug_Pubnames (File : Elf_File; Index : Elf_Half)
+ is
+ Shdr : Elf_Shdr_Acc;
+ Base : Address;
+ Off : Storage_Offset;
+ B : Unsigned_8;
+
+ Len : Unsigned_32;
+ Ver : Unsigned_16;
+ Info_Off : Unsigned_32;
+ Info_Length : Unsigned_32;
+ Last : Storage_Offset;
+ Ioff : Unsigned_32;
+ begin
+ Shdr := Get_Shdr (File, Index);
+ Base := Get_Section_Base (File, Shdr.all);
+
+ Off := 0;
+ while Off < Storage_Offset (Shdr.Sh_Size) loop
+ Read_Word4 (Base, Off, Len);
+ Last := Off + Storage_Offset (Len);
+ Read_Word2 (Base, Off, Ver);
+ Read_Word4 (Base, Off, Info_Off);
+ Read_Word4 (Base, Off, Info_Length);
+ Put ("length: " & Hex_Image (Len));
+ Put (", version: " & Hex_Image (Ver));
+ Put (", offset: " & Hex_Image (Info_Off));
+ Put (", length: " & Hex_Image (Info_Length));
+ New_Line;
+
+ loop
+ Read_Word4 (Base, Off, Ioff);
+ Put (" ");
+ Put (Hex_Image (Ioff));
+ if Ioff /= 0 then
+ Put (": ");
+ loop
+ Read_Byte (Base, Off, B);
+ exit when B = 0;
+ Put (Character'Val (B));
+ end loop;
+ end if;
+ New_Line;
+ exit when Ioff = 0;
+ end loop;
+ end loop;
+ end Disp_Debug_Pubnames;
+
+ procedure Disp_Debug_Aranges (File : Elf_File; Index : Elf_Half)
+ is
+ Shdr : Elf_Shdr_Acc;
+ Base : Address;
+ Off : Storage_Offset;
+
+ Set_Len : Unsigned_32;
+ Ver : Unsigned_16;
+ Info_Off : Unsigned_32;
+ Last : Storage_Offset;
+ Addr_Sz : Unsigned_8;
+ Seg_Sz : Unsigned_8;
+ Pad : Unsigned_32;
+
+ Addr : Unsigned_32;
+ Len : Unsigned_32;
+ begin
+ Shdr := Get_Shdr (File, Index);
+ Base := Get_Section_Base (File, Shdr.all);
+
+ Off := 0;
+ while Off < Storage_Offset (Shdr.Sh_Size) loop
+ Read_Word4 (Base, Off, Set_Len);
+ Last := Off + Storage_Offset (Set_Len);
+ Read_Word2 (Base, Off, Ver);
+ Read_Word4 (Base, Off, Info_Off);
+ Read_Byte (Base, Off, Addr_Sz);
+ Read_Byte (Base, Off, Seg_Sz);
+ Read_Word4 (Base, Off, Pad);
+ Put ("length: " & Hex_Image (Set_Len));
+ Put (", version: " & Hex_Image (Ver));
+ Put (", offset: " & Hex_Image (Info_Off));
+ Put (", ptr_sz: " & Hex_Image (Addr_Sz));
+ Put (", seg_sz: " & Hex_Image (Seg_Sz));
+ New_Line;
+
+ loop
+ Read_Word4 (Base, Off, Addr);
+ Read_Word4 (Base, Off, Len);
+ Put (" ");
+ Put (Hex_Image (Addr));
+ Put ('+');
+ Put (Hex_Image (Len));
+ New_Line;
+ exit when Addr = 0 and Len = 0;
+ end loop;
+ end loop;
+ end Disp_Debug_Aranges;
+
+ procedure Disp_String (Base : Address; Off : in out Storage_Offset)
+ is
+ B : Unsigned_8;
+ begin
+ loop
+ B := Read_Byte (Base + Off);
+ Off := Off + 1;
+ exit when B = 0;
+ Put (Character'Val (B));
+ end loop;
+ end Disp_String;
+
+ procedure Read_String (Base : Address; Off : in out Storage_Offset)
+ is
+ B : Unsigned_8;
+ begin
+ loop
+ Read_Byte (Base, Off, B);
+ exit when B = 0;
+ end loop;
+ end Read_String;
+
+ function Get_Dwarf_LNS_Name (Lns : Unsigned_8) return String
+ is
+ use Dwarf;
+ begin
+ case Lns is
+ when DW_LNS_Copy =>
+ return "copy";
+ when DW_LNS_Advance_Pc =>
+ return "advance_pc";
+ when DW_LNS_Advance_Line =>
+ return "advance_line";
+ when DW_LNS_Set_File =>
+ return "set_file";
+ when DW_LNS_Set_Column =>
+ return "set_column";
+ when DW_LNS_Negate_Stmt =>
+ return "negate_stmt";
+ when DW_LNS_Set_Basic_Block =>
+ return "set_basic_block";
+ when DW_LNS_Const_Add_Pc =>
+ return "const_add_pc";
+ when DW_LNS_Fixed_Advance_Pc =>
+ return "fixed_advance_pc";
+ when DW_LNS_Set_Prologue_End =>
+ return "set_prologue_end";
+ when DW_LNS_Set_Epilogue_Begin =>
+ return "set_epilogue_begin";
+ when DW_LNS_Set_Isa =>
+ return "set_isa";
+ when others =>
+ return "?unknown?";
+ end case;
+ end Get_Dwarf_LNS_Name;
+
+ procedure Disp_Debug_Line (File : Elf_File; Index : Elf_Half)
+ is
+ use Dwarf;
+ Shdr : Elf_Shdr_Acc;
+ Base : Address;
+ Off : Storage_Offset;
+
+ type Opc_Length_Type is array (Unsigned_8 range <>) of Unsigned_8;
+ type Opc_Length_Acc is access Opc_Length_Type;
+ Opc_Length : Opc_Length_Acc;
+
+ Total_Len : Unsigned_32;
+ Version : Unsigned_16;
+ Prolog_Len : Unsigned_32;
+ Min_Insn_Len : Unsigned_8;
+ Dflt_Is_Stmt : Unsigned_8;
+ Line_Base : Unsigned_8;
+ Line_Range : Unsigned_8;
+ Opc_Base : Unsigned_8;
+
+ B : Unsigned_8;
+ Arg : Unsigned_32;
+
+ Old_Off : Storage_Offset;
+ File_Dir : Unsigned_32;
+ File_Time : Unsigned_32;
+ File_Len : Unsigned_32;
+
+ Ext_Len : Unsigned_32;
+ Ext_Opc : Unsigned_8;
+
+ Last : Storage_Offset;
+
+ Pc : Unsigned_32;
+ Line : Unsigned_32;
+ Line_Base2 : Unsigned_32;
+ begin
+ Shdr := Get_Shdr (File, Index);
+ Base := Get_Section_Base (File, Shdr.all);
+
+ Off := 0;
+ while Off < Storage_Offset (Shdr.Sh_Size) loop
+ Read_Word4 (Base, Off, Total_Len);
+ Last := Off + Storage_Offset (Total_Len);
+ Read_Word2 (Base, Off, Version);
+ Read_Word4 (Base, Off, Prolog_Len);
+ Read_Byte (Base, Off, Min_Insn_Len);
+ Read_Byte (Base, Off, Dflt_Is_Stmt);
+ Read_Byte (Base, Off, Line_Base);
+ Read_Byte (Base, Off, Line_Range);
+ Read_Byte (Base, Off, Opc_Base);
+
+ Pc := 0;
+ Line := 1;
+
+ Put ("length: " & Hex_Image (Total_Len));
+ Put (", version: " & Hex_Image (Version));
+ Put (", prolog_len: " & Hex_Image (Prolog_Len));
+ New_Line;
+ Put (" minimum_instruction_len: " & Hex_Image (Min_Insn_Len));
+ Put (", default_is_stmt: " & Hex_Image (Dflt_Is_Stmt));
+ New_Line;
+ Put (" line_base: " & Hex_Image (Line_Base));
+ Put (", line_range: " & Hex_Image (Line_Range));
+ Put (", opc_base: " & Hex_Image (Opc_Base));
+ New_Line;
+ Line_Base2 := Unsigned_32 (Line_Base);
+ if (Line_Base and 16#80#) /= 0 then
+ Line_Base2 := Line_Base2 or 16#Ff_Ff_Ff_00#;
+ end if;
+ Put_Line ("standard_opcode_length:");
+ Opc_Length := new Opc_Length_Type (1 .. Opc_Base - 1);
+ for I in 1 .. Opc_Base - 1 loop
+ Read_Byte (Base, Off, B);
+ Put (' ');
+ Put (Hex_Image (I));
+ Put (" => ");
+ Put (Hex_Image (B));
+ Opc_Length (I) := B;
+ New_Line;
+ end loop;
+ Put_Line ("include_directories:");
+ loop
+ B := Read_Byte (Base + Off);
+ exit when B = 0;
+ Put (' ');
+ Disp_String (Base, Off);
+ New_Line;
+ end loop;
+ Off := Off + 1;
+ Put_Line ("file_names:");
+ loop
+ B := Read_Byte (Base + Off);
+ exit when B = 0;
+ Old_Off := Off;
+ Read_String (Base, Off);
+ Read_ULEB128 (Base, Off, File_Dir);
+ Read_ULEB128 (Base, Off, File_Time);
+ Read_ULEB128 (Base, Off, File_Len);
+ Put (' ');
+ Put (Hex_Image (File_Dir));
+ Put (' ');
+ Put (Hex_Image (File_Time));
+ Put (' ');
+ Put (Hex_Image (File_Len));
+ Put (' ');
+ Disp_String (Base, Old_Off);
+ New_Line;
+ end loop;
+ Off := Off + 1;
+
+ while Off < Last loop
+ Put (" ");
+ Read_Byte (Base, Off, B);
+ Put (Hex_Image (B));
+ Old_Off := Off;
+ if B < Opc_Base then
+ case B is
+ when 0 =>
+ Put (" (extended)");
+ Read_ULEB128 (Base, Off, Ext_Len);
+ Put (", len: ");
+ Put (Hex_Image (Ext_Len));
+ Old_Off := Off;
+ Read_Byte (Base, Off, Ext_Opc);
+ Put (" opc:");
+ Put (Hex_Image (Ext_Opc));
+ Off := Old_Off + Storage_Offset (Ext_Len);
+ when others =>
+ Put (" (");
+ Put (Get_Dwarf_LNS_Name (B));
+ Put (")");
+ Set_Col (20);
+ for J in 1 .. Opc_Length (B) loop
+ Read_ULEB128 (Base, Off, Arg);
+ Put (" ");
+ Put (Hex_Image (Arg));
+ end loop;
+ end case;
+ case B is
+ when DW_LNS_Copy =>
+ Put (" pc=");
+ Put (Hex_Image (Pc));
+ Put (", line=");
+ Put (Unsigned_32'Image (Line));
+ when DW_LNS_Advance_Pc =>
+ Read_ULEB128 (Base, Old_Off, Arg);
+ Pc := Pc + Arg * Unsigned_32 (Min_Insn_Len);
+ Put (" pc=");
+ Put (Hex_Image (Pc));
+ when DW_LNS_Advance_Line =>
+ Read_SLEB128 (Base, Old_Off, Arg);
+ Line := Line + Arg;
+ Put (" line=");
+ Put (Unsigned_32'Image (Line));
+ when DW_LNS_Set_File =>
+ null;
+ when DW_LNS_Set_Column =>
+ null;
+ when DW_LNS_Negate_Stmt =>
+ null;
+ when DW_LNS_Set_Basic_Block =>
+ null;
+ when DW_LNS_Const_Add_Pc =>
+ Pc := Pc + Unsigned_32 ((255 - Opc_Base) / Line_Range)
+ * Unsigned_32 (Min_Insn_Len);
+ Put (" pc=");
+ Put (Hex_Image (Pc));
+ when others =>
+ null;
+ end case;
+ New_Line;
+ else
+ B := B - Opc_Base;
+ Pc := Pc + Unsigned_32 (B / Line_Range)
+ * Unsigned_32 (Min_Insn_Len);
+ Line := Line + Line_Base2 + Unsigned_32 (B mod Line_Range);
+ Put (" pc=");
+ Put (Hex_Image (Pc));
+ Put (", line=");
+ Put (Unsigned_32'Image (Line));
+ New_Line;
+ end if;
+ end loop;
+ end loop;
+ end Disp_Debug_Line;
+
+ function Get_Dwarf_Cfi_Name (Cfi : Unsigned_8) return String
+ is
+ use Dwarf;
+ begin
+ case Cfi is
+ when DW_CFA_Advance_Loc_Min .. DW_CFA_Advance_Loc_Max =>
+ return "advance_loc";
+ when DW_CFA_Offset_Min .. DW_CFA_Offset_Max =>
+ return "offset";
+ when DW_CFA_Restore_Min .. DW_CFA_Restore_Max =>
+ return "restore";
+ when DW_CFA_Nop =>
+ return "nop";
+ when DW_CFA_Set_Loc =>
+ return "set_loc";
+ when DW_CFA_Advance_Loc1 =>
+ return "advance_loc1";
+ when DW_CFA_Advance_Loc2 =>
+ return "advance_loc2";
+ when DW_CFA_Advance_Loc4 =>
+ return "advance_loc4";
+ when DW_CFA_Offset_Extended =>
+ return "offset_extended";
+ when DW_CFA_Restore_Extended =>
+ return "restore_extended";
+ when DW_CFA_Undefined =>
+ return "undefined";
+ when DW_CFA_Same_Value =>
+ return "same_value";
+ when DW_CFA_Register =>
+ return "register";
+ when DW_CFA_Remember_State =>
+ return "remember_state";
+ when DW_CFA_Restore_State =>
+ return "restore_state";
+ when DW_CFA_Def_Cfa =>
+ return "def_cfa";
+ when DW_CFA_Def_Cfa_Register =>
+ return "def_cfa_register";
+ when DW_CFA_Def_Cfa_Offset =>
+ return "def_cfa_offset";
+ when DW_CFA_Def_Cfa_Expression =>
+ return "def_cfa_expression";
+ when others =>
+ return "?unknown?";
+ end case;
+ end Get_Dwarf_Cfi_Name;
+
+ procedure Disp_Cfi (Base : Address; Length : Storage_Count)
+ is
+ use Dwarf;
+ L : Storage_Offset;
+ Op : Unsigned_8;
+ Off : Unsigned_32;
+ Reg : Unsigned_32;
+ begin
+ L := 0;
+ while L < Length loop
+ Op := Read_Byte (Base + L);
+ Put (" ");
+ Put (Hex_Image (Op));
+ Put (" ");
+ Put (Get_Dwarf_Cfi_Name (Op));
+ Put (" ");
+ L := L + 1;
+ case Op is
+ when DW_CFA_Nop =>
+ null;
+ when DW_CFA_Advance_Loc_Min .. DW_CFA_Advance_Loc_Max =>
+ Put (Hex_Image (Op and 16#3f#));
+ when DW_CFA_Offset_Min .. DW_CFA_Offset_Max =>
+ Read_ULEB128 (Base, L, Off);
+ Put ("reg:");
+ Put (Hex_Image (Op and 16#3f#));
+ Put (", offset:");
+ Put (Hex_Image (Off));
+ when DW_CFA_Def_Cfa =>
+ Read_ULEB128 (Base, L, Reg);
+ Read_ULEB128 (Base, L, Off);
+ Put ("reg:");
+ Put (Hex_Image (Reg));
+ Put (", offset:");
+ Put (Hex_Image (Off));
+ when DW_CFA_Def_Cfa_Offset =>
+ Read_ULEB128 (Base, L, Off);
+ Put (Hex_Image (Off));
+ when DW_CFA_Def_Cfa_Register =>
+ Read_ULEB128 (Base, L, Reg);
+ Put ("reg:");
+ Put (Hex_Image (Reg));
+ when others =>
+ Put ("?unknown?");
+ New_Line;
+ exit;
+ end case;
+ New_Line;
+ end loop;
+ end Disp_Cfi;
+
+ procedure Disp_Debug_Frame (File : Elf_File; Index : Elf_Half)
+ is
+ Shdr : Elf_Shdr_Acc;
+ Base : Address;
+ Off : Storage_Offset;
+ Old_Off : Storage_Offset;
+
+ Length : Unsigned_32;
+ Cie_Id : Unsigned_32;
+ Version : Unsigned_8;
+ Augmentation : Unsigned_8;
+ Code_Align : Unsigned_32;
+ Data_Align : Unsigned_32;
+ Ret_Addr_Reg : Unsigned_8;
+
+ Init_Loc : Unsigned_32;
+ Addr_Rng : Unsigned_32;
+ begin
+ Shdr := Get_Shdr (File, Index);
+ Base := Get_Section_Base (File, Shdr.all);
+
+ Off := 0;
+ while Off < Storage_Offset (Shdr.Sh_Size) loop
+ Read_Word4 (Base, Off, Length);
+ Old_Off := Off;
+
+ Read_Word4 (Base, Off, Cie_Id);
+ if Cie_Id = 16#Ff_Ff_Ff_Ff# then
+ Read_Byte (Base, Off, Version);
+ Read_Byte (Base, Off, Augmentation);
+ Put ("length: ");
+ Put (Hex_Image (Length));
+ Put (", CIE_id: ");
+ Put (Hex_Image (Cie_Id));
+ Put (", version: ");
+ Put (Hex_Image (Version));
+ if Augmentation /= 0 then
+ Put (" +augmentation");
+ New_Line;
+ else
+ New_Line;
+ Read_ULEB128 (Base, Off, Code_Align);
+ Read_SLEB128 (Base, Off, Data_Align);
+ Read_Byte (Base, Off, Ret_Addr_Reg);
+ Put ("code_align: ");
+ Put (Hex_Image (Code_Align));
+ Put (", data_align: ");
+ Put (Hex_Image (Data_Align));
+ Put (", ret_addr_reg: ");
+ Put (Hex_Image (Ret_Addr_Reg));
+ New_Line;
+ Put ("initial instructions:");
+ New_Line;
+ Disp_Cfi (Base + Off, Old_Off + Storage_Offset (Length) - Off);
+ end if;
+ else
+ Read_Word4 (Base, Off, Init_Loc);
+ Read_Word4 (Base, Off, Addr_Rng);
+ Put ("length: ");
+ Put (Hex_Image (Length));
+ Put (", CIE_pointer: ");
+ Put (Hex_Image (Cie_Id));
+ Put (", address_range: ");
+ Put (Hex_Image (Init_Loc));
+ Put ("-");
+ Put (Hex_Image (Init_Loc + Addr_Rng));
+ New_Line;
+ Put ("instructions:");
+ New_Line;
+ Disp_Cfi (Base + Off, Old_Off + Storage_Offset (Length) - Off);
+ end if;
+ Off := Old_Off + Storage_Offset (Length);
+ end loop;
+ end Disp_Debug_Frame;
+
+ procedure Read_Coded (Base : Address;
+ Offset : in out Storage_Offset;
+ Code : Unsigned_8;
+ Val : out Unsigned_32)
+ is
+ use Dwarf;
+
+ V2 : Unsigned_16;
+ begin
+ if Code = DW_EH_PE_Omit then
+ return;
+ end if;
+ case Code and DW_EH_PE_Format_Mask is
+ when DW_EH_PE_Uleb128 =>
+ Read_ULEB128 (Base, Offset, Val);
+ when DW_EH_PE_Udata2 =>
+ Read_Word2 (Base, Offset, V2);
+ Val := Unsigned_32 (V2);
+ when DW_EH_PE_Udata4 =>
+ Read_Word4 (Base, Offset, Val);
+ when DW_EH_PE_Sleb128 =>
+ Read_SLEB128 (Base, Offset, Val);
+ when DW_EH_PE_Sdata2 =>
+ Read_Word2 (Base, Offset, V2);
+ Val := Unsigned_32 (V2);
+ if (V2 and 16#80_00#) /= 0 then
+ Val := Val or 16#Ff_Ff_00_00#;
+ end if;
+ when DW_EH_PE_Sdata4 =>
+ Read_Word4 (Base, Offset, Val);
+ when others =>
+ raise Program_Error;
+ end case;
+ end Read_Coded;
+
+ procedure Disp_Eh_Frame_Hdr (File : Elf_File; Index : Elf_Half)
+ is
+ Shdr : Elf_Shdr_Acc;
+ Base : Address;
+ Off : Storage_Offset;
+
+ Version : Unsigned_8;
+ Eh_Frame_Ptr_Enc : Unsigned_8;
+ Fde_Count_Enc : Unsigned_8;
+ Table_Enc : Unsigned_8;
+
+ Eh_Frame_Ptr : Unsigned_32;
+ Fde_Count : Unsigned_32;
+
+ Loc : Unsigned_32;
+ Addr : Unsigned_32;
+ begin
+ Shdr := Get_Shdr (File, Index);
+ Base := Get_Section_Base (File, Shdr.all);
+
+ Off := 0;
+ while Off < Storage_Offset (Shdr.Sh_Size) loop
+ Read_Byte (Base, Off, Version);
+ Read_Byte (Base, Off, Eh_Frame_Ptr_Enc);
+ Read_Byte (Base, Off, Fde_Count_Enc);
+ Read_Byte (Base, Off, Table_Enc);
+ Put ("version: ");
+ Put (Hex_Image (Version));
+ Put (", encodings: ptr:");
+ Put (Hex_Image (Eh_Frame_Ptr_Enc));
+ Put (" count:");
+ Put (Hex_Image (Fde_Count_Enc));
+ Put (" table:");
+ Put (Hex_Image (Table_Enc));
+ New_Line;
+ Read_Coded (Base, Off, Eh_Frame_Ptr_Enc, Eh_Frame_Ptr);
+ Read_Coded (Base, Off, Fde_Count_Enc, Fde_Count);
+ Put ("eh_frame_ptr: ");
+ Put (Hex_Image (Eh_Frame_Ptr));
+ Put (", fde_count: ");
+ Put (Hex_Image (Fde_Count));
+ New_Line;
+ for I in 1 .. Fde_Count loop
+ Read_Coded (Base, Off, Table_Enc, Loc);
+ Read_Coded (Base, Off, Table_Enc, Addr);
+ Put (" init loc: ");
+ Put (Hex_Image (Loc));
+ Put (", addr : ");
+ Put (Hex_Image (Addr));
+ New_Line;
+ end loop;
+ end loop;
+ end Disp_Eh_Frame_Hdr;
+end Elfdumper;