File : s-objrea.ads


   1 ------------------------------------------------------------------------------
   2 --                                                                          --
   3 --                         GNAT COMPILER COMPONENTS                         --
   4 --                                                                          --
   5 --                 S Y S T E M . O B J E C T _ R E A D E R                  --
   6 --                                                                          --
   7 --                                 S p e c                                  --
   8 --                                                                          --
   9 --          Copyright (C) 2009-2015, Free Software Foundation, Inc.         --
  10 --                                                                          --
  11 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
  12 -- terms of the  GNU General Public License as published  by the Free Soft- --
  13 -- ware  Foundation;  either version 3,  or (at your option) any later ver- --
  14 -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
  15 -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
  16 -- or FITNESS FOR A PARTICULAR PURPOSE.                                     --
  17 --                                                                          --
  18 --                                                                          --
  19 --                                                                          --
  20 --                                                                          --
  21 --                                                                          --
  22 -- You should have received a copy of the GNU General Public License and    --
  23 -- a copy of the GCC Runtime Library Exception along with this program;     --
  24 -- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
  25 -- <http://www.gnu.org/licenses/>.                                          --
  26 --                                                                          --
  27 -- GNAT was originally developed  by the GNAT team at  New York University. --
  28 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
  29 --                                                                          --
  30 ------------------------------------------------------------------------------
  31 
  32 --  This package implements a simple, minimal overhead reader for object files
  33 --  composed of sections of untyped heterogeneous binary data.
  34 
  35 with Interfaces.C_Streams;
  36 
  37 package System.Object_Reader is
  38 
  39    --------------
  40    --  Limits  --
  41    --------------
  42 
  43    BUFFER_SIZE : constant := 8 * 1024;
  44 
  45    ------------------
  46    -- Object files --
  47    ------------------
  48 
  49    type Object_File (<>) is private;
  50 
  51    type Object_File_Access is access Object_File;
  52 
  53    ---------------------
  54    -- Object sections --
  55    ----------------------
  56 
  57    type Object_Section is private;
  58 
  59    Null_Section : constant Object_Section;
  60 
  61    --------------------
  62    -- Object symbols --
  63    --------------------
  64 
  65    type Object_Symbol is private;
  66 
  67    ------------------------
  68    -- Object format type --
  69    ------------------------
  70 
  71    type Object_Format is
  72      (ELF32,
  73       --  Object format is 32-bit ELF
  74 
  75       ELF64,
  76       --  Object format is 64-bit ELF
  77 
  78       PECOFF,
  79       --  Object format is Microsoft PECOFF
  80 
  81       PECOFF_PLUS,
  82       --  Object format is Microsoft PECOFF+
  83 
  84       XCOFF32);
  85       --  Object format is AIX 32-bit XCOFF
  86 
  87    --  PECOFF | PECOFF_PLUS appears so often as a case choice, would
  88    --  seem a good idea to have a subtype name covering these two choices ???
  89 
  90    ------------------------------
  91    -- Object architecture type --
  92    ------------------------------
  93 
  94    type Object_Arch is
  95      (Unknown,
  96       --  The target architecture has not yet been determined
  97 
  98       SPARC,
  99       --  32-bit SPARC
 100 
 101       SPARC64,
 102       --  64-bit SPARC
 103 
 104       i386,
 105       --  Intel IA32
 106 
 107       MIPS,
 108       --  MIPS Technologies MIPS
 109 
 110       x86_64,
 111       --  x86-64 (64-bit AMD/Intel)
 112 
 113       IA64,
 114       --  Intel IA64
 115 
 116       PPC,
 117       --  32-bit PowerPC
 118 
 119       PPC64);
 120       --  64-bit PowerPC
 121 
 122    ------------------
 123    -- Target types --
 124    ------------------
 125 
 126    subtype Offset is Interfaces.Integer_64;
 127 
 128    subtype uint8  is Interfaces.Unsigned_8;
 129    subtype uint16 is Interfaces.Unsigned_16;
 130    subtype uint32 is Interfaces.Unsigned_32;
 131    subtype uint64 is Interfaces.Unsigned_64;
 132 
 133    subtype int8  is Interfaces.Integer_8;
 134    subtype int16 is Interfaces.Integer_16;
 135    subtype int32 is Interfaces.Integer_32;
 136    subtype int64 is Interfaces.Integer_64;
 137 
 138    type Buffer is array (0 .. BUFFER_SIZE - 1) of uint8;
 139 
 140    -------------------------------------------
 141    -- Operations on buffers of untyped data --
 142    -------------------------------------------
 143 
 144    function To_String (Buf : Buffer) return String;
 145    --  Construct string from C style null-terminated string stored in a buffer
 146 
 147    function Strlen (Buf : Buffer) return int32;
 148    --  Return the length of a C style null-terminated string
 149 
 150    -------------------------
 151    -- Opening and closing --
 152    -------------------------
 153 
 154    function Open
 155      (File_Name    : String;
 156       In_Exception : Boolean := False) return Object_File_Access;
 157    --  Open the object file and initialize the reader. In_Exception is true
 158    --  when the parsing is done as part of an exception handler decorator. In
 159    --  this mode we do not want to raise an exception.
 160 
 161    procedure Close (Obj : in out Object_File);
 162    --  Close the object file
 163 
 164    -----------------------
 165    -- Sequential access --
 166    -----------------------
 167 
 168    procedure Read
 169      (Obj   : Object_File;
 170       Addr  : Address;
 171       Size  : uint32);
 172    --  Read a number of fixed sized records
 173 
 174    function Read (Obj : Object_File) return uint8;
 175    function Read (Obj : Object_File) return uint16;
 176    function Read (Obj : Object_File) return uint32;
 177    function Read (Obj : Object_File) return uint64;
 178    function Read (Obj : Object_File) return int8;
 179    function Read (Obj : Object_File) return int16;
 180    function Read (Obj : Object_File) return int32;
 181    function Read (Obj : Object_File) return int64;
 182    --  Read a scalar
 183 
 184    function Read_Address (Obj : Object_File) return uint64;
 185    --  Read either a 64 or 32 bit address from the file stream depending on the
 186    --  address size of the target architecture and promote it to a 64 bit type.
 187 
 188    function Read_LEB128 (Obj : Object_File) return uint32;
 189    function Read_LEB128 (Obj : Object_File) return int32;
 190    --  Read a value encoding in Little-Endian Base 128 format
 191 
 192    procedure Read_C_String (Obj : Object_File; B : out Buffer);
 193    --  Read a C style NULL terminated string at an offset
 194 
 195    function Offset_To_String
 196      (Obj : Object_File;
 197       Off : Offset) return String;
 198    --  Construct a string from a C style NULL terminated string located at an
 199    --  offset into the object file.
 200 
 201    -------------------
 202    -- Random access --
 203    -------------------
 204 
 205    procedure Seek (Obj : Object_File; Off : Offset);
 206    --  Seek to an absolute offset in bytes
 207 
 208    procedure Tell (Obj : Object_File; Off : out Offset);
 209    --  Fetch the current offset
 210 
 211    ------------------------
 212    -- Object information --
 213    ------------------------
 214 
 215    function Arch (Obj : Object_File) return Object_Arch;
 216    --  Return the object architecture
 217 
 218    function Format (Obj : Object_File) return Object_Format;
 219    --  Return the object file format
 220 
 221    function Get_Load_Address (Obj : Object_File) return uint64;
 222    --  Return the load address defined in Obj. May raise Format_Error if not
 223    --  implemented
 224 
 225    function Num_Sections (Obj : Object_File) return uint32;
 226    --  Return the number of sections composing the object file
 227 
 228    function Get_Section
 229      (Obj   : Object_File;
 230       Shnum : uint32) return Object_Section;
 231    --  Return the Nth section (numbered from zero)
 232 
 233    function Get_Section
 234      (Obj      : Object_File;
 235       Sec_Name : String) return Object_Section;
 236    --  Return a section by name
 237 
 238    -------------------------
 239    -- Section information --
 240    -------------------------
 241 
 242    procedure Seek (Obj : Object_File; Sec : Object_Section);
 243    --  Seek to a section
 244 
 245    function Name
 246      (Obj : Object_File;
 247       Sec : Object_Section) return String;
 248    --  Return the name of a section as a string
 249 
 250    function Size (Sec : Object_Section) return uint64;
 251    --  Return the size of a section in bytes
 252 
 253    function Num (Sec : Object_Section) return uint32;
 254    --  Return the index of a section from zero
 255 
 256    function Off (Sec : Object_Section) return Offset;
 257    --  Return the byte offset of the section within the object
 258 
 259    ------------------------------
 260    -- Symbol table information --
 261    ------------------------------
 262 
 263    Null_Symbol : constant Object_Symbol;
 264    --  An empty symbol table entry.
 265 
 266    function Num_Symbols (Obj : Object_File) return uint64;
 267    --  The number of symbols in the symbol table
 268 
 269    function First_Symbol (Obj : in out Object_File) return Object_Symbol;
 270    --  Return the first element in the symbol table or Null_Symbol if the
 271    --  symbol table is empty.
 272 
 273    function Next_Symbol
 274      (Obj  : in out Object_File;
 275       Prev : Object_Symbol) return Object_Symbol;
 276    --  Return the element following Prev in the symbol table, or Null_Symbol if
 277    --  Prev is the last symbol in the table.
 278 
 279    function Name
 280      (Obj : Object_File;
 281       Sym : Object_Symbol) return String;
 282    --  Return the name of the symbol
 283 
 284    function Decoded_Ada_Name
 285      (Obj : Object_File;
 286       Sym : Object_Symbol) return String;
 287    --  Return the decoded name of a symbol encoded as per exp_dbug.ads
 288 
 289    function Value (Sym : Object_Symbol) return uint64;
 290    --  Return the name of the symbol
 291 
 292    function Size (Sym : Object_Symbol) return uint64;
 293    --  Return the size of the symbol in bytes
 294 
 295    function Spans (Sym : Object_Symbol; Addr : uint64) return Boolean;
 296    --  Determine whether a particular address corresponds to the range
 297    --  referenced by this symbol.
 298 
 299    ----------------
 300    -- Exceptions --
 301    ----------------
 302 
 303    IO_Error : exception;
 304    --  Input/Output error reading file
 305 
 306    Format_Error : exception;
 307    --  Encountered a problem parsing the object
 308 
 309 private
 310 
 311    package ICS renames Interfaces.C_Streams;
 312 
 313    subtype ELF is Object_Format range ELF32 .. ELF64;
 314    subtype Any_PECOFF is Object_Format range PECOFF .. PECOFF_PLUS;
 315 
 316    type Object_File (Format : Object_Format) is record
 317       fp           : ICS.FILEs := ICS.NULL_Stream;
 318       Arch         : Object_Arch := Unknown;
 319 
 320       Num_Sections : uint32 := 0;
 321       Num_Symbols  : uint64 := 0;
 322 
 323       In_Exception : Boolean := False;
 324       --  True if the parsing is done as part of an exception handler
 325 
 326       Sectab : Offset := 0; -- Offset of the section table (XCOFF for XCOFF32)
 327       Symtab : Offset := 0; -- Offset of the symbol table (All for XCOFF32)
 328 
 329       case Format is
 330          when ELF =>
 331             Strtab : Offset := 0;  --  Offset of the string table
 332          when Any_PECOFF =>
 333             Symtab_Last : Offset := 0;  --  Offset past the symbol table
 334 
 335             ImageBase   : uint64;       --  ImageBase value from header
 336 
 337             --  Cache for latest result of Get_Section_Virtual_Address
 338 
 339             GSVA_Sec  : uint32 := uint32'Last;
 340             GSVA_Addr : uint64;
 341          when XCOFF32 =>
 342             null;
 343       end case;
 344    end record;
 345 
 346    subtype ELF_Object_File is Object_File; -- with
 347    --  Predicate => ELF_Object_File.Format in ELF;
 348    subtype PECOFF_Object_File is Object_File; -- with
 349    --  Predicate => PECOFF_Object_File.Format in Any_PECOFF;
 350    subtype XCOFF32_Object_File is Object_File; -- with
 351    --  Predicate => XCOFF32_Object_File.Format in XCOFF32;
 352    --  ???Above predicates cause the compiler to crash when instantiating
 353    --  ELF64_Ops (see package body).
 354 
 355    type Object_Section is record
 356       Num  : uint32 := 0;  --  Index of this section in the section table
 357       Off  : Offset := 0;  --  First byte of the section
 358       Size : uint64 := 0;  --  Length of the section in bytes
 359    end record;
 360 
 361    Null_Section : constant Object_Section := (0, 0, 0);
 362 
 363    type Object_Symbol is record
 364       Num   : uint64 := 0;  --  Index of this symbol in the symbol table
 365       Off   : Offset := 0;  --  Offset of underlying symbol on disk
 366       Next  : Offset := 0;  --  Offset of the following symbol
 367       Value : uint64 := 0;  --  Value associated with this symbol
 368       Size  : uint64 := 0;  --  Size of the referenced entity
 369    end record;
 370 
 371    Null_Symbol : constant Object_Symbol := (0, 0, 0, 0, 0);
 372 
 373 end System.Object_Reader;