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-2018, 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-- As a special exception under Section 7 of GPL version 3, you are granted -- 19-- additional permissions described in the GCC Runtime Library Exception, -- 20-- version 3.1, as published by the Free Software Foundation. -- 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 35with Interfaces; 36with System.Mmap; 37 38package System.Object_Reader is 39 40 -------------- 41 -- Limits -- 42 -------------- 43 44 BUFFER_SIZE : constant := 8 * 1024; 45 46 ------------------ 47 -- Object files -- 48 ------------------ 49 50 type Object_File (<>) is private; 51 52 type Object_File_Access is access Object_File; 53 54 --------------------- 55 -- Object sections -- 56 ---------------------- 57 58 type Object_Section is private; 59 60 Null_Section : constant Object_Section; 61 62 -------------------- 63 -- Object symbols -- 64 -------------------- 65 66 type Object_Symbol is private; 67 68 ------------------------ 69 -- Object format type -- 70 ------------------------ 71 72 type Object_Format is 73 (ELF32, 74 -- Object format is 32-bit ELF 75 76 ELF64, 77 -- Object format is 64-bit ELF 78 79 PECOFF, 80 -- Object format is Microsoft PECOFF 81 82 PECOFF_PLUS, 83 -- Object format is Microsoft PECOFF+ 84 85 XCOFF32); 86 -- Object format is AIX 32-bit XCOFF 87 88 -- PECOFF | PECOFF_PLUS appears so often as a case choice, would 89 -- seem a good idea to have a subtype name covering these two choices ??? 90 91 ------------------------------ 92 -- Object architecture type -- 93 ------------------------------ 94 95 type Object_Arch is 96 (Unknown, 97 -- The target architecture has not yet been determined 98 99 SPARC, 100 -- 32-bit SPARC 101 102 SPARC64, 103 -- 64-bit SPARC 104 105 i386, 106 -- Intel IA32 107 108 MIPS, 109 -- MIPS Technologies MIPS 110 111 x86_64, 112 -- x86-64 (64-bit AMD/Intel) 113 114 IA64, 115 -- Intel IA64 116 117 PPC, 118 -- 32-bit PowerPC 119 120 PPC64); 121 -- 64-bit PowerPC 122 123 ------------------ 124 -- Target types -- 125 ------------------ 126 127 subtype Offset is Interfaces.Integer_64; 128 129 subtype uint8 is Interfaces.Unsigned_8; 130 subtype uint16 is Interfaces.Unsigned_16; 131 subtype uint32 is Interfaces.Unsigned_32; 132 subtype uint64 is Interfaces.Unsigned_64; 133 134 subtype int8 is Interfaces.Integer_8; 135 subtype int16 is Interfaces.Integer_16; 136 subtype int32 is Interfaces.Integer_32; 137 subtype int64 is Interfaces.Integer_64; 138 139 type Buffer is array (0 .. BUFFER_SIZE - 1) of uint8; 140 141 type String_Ptr_Len is record 142 Ptr : Mmap.Str_Access; 143 Len : Natural; 144 end record; 145 -- A string made from a pointer and a length. Not all strings for name 146 -- are C strings: COFF inlined symbol names have a max length of 8. 147 148 ------------------------------------------- 149 -- Operations on buffers of untyped data -- 150 ------------------------------------------- 151 152 function To_String (Buf : Buffer) return String; 153 -- Construct string from C style null-terminated string stored in a buffer 154 155 function To_String_Ptr_Len 156 (Ptr : Mmap.Str_Access; 157 Max_Len : Natural := Natural'Last) return String_Ptr_Len; 158 -- Convert PTR to a String_Ptr_Len. 159 160 function Strlen (Buf : Buffer) return int32; 161 -- Return the length of a C style null-terminated string 162 163 ------------------------- 164 -- Opening and closing -- 165 ------------------------- 166 167 function Open 168 (File_Name : String; 169 In_Exception : Boolean := False) return Object_File_Access; 170 -- Open the object file and initialize the reader. In_Exception is true 171 -- when the parsing is done as part of an exception handler decorator. In 172 -- this mode we do not want to raise an exception. 173 174 procedure Close (Obj : in out Object_File); 175 -- Close the object file 176 177 ----------------------- 178 -- Sequential access -- 179 ----------------------- 180 181 type Mapped_Stream is private; 182 -- Provide an abstraction of a stream on a memory mapped file 183 184 function Create_Stream (Mf : System.Mmap.Mapped_File; 185 File_Offset : System.Mmap.File_Size; 186 File_Length : System.Mmap.File_Size) 187 return Mapped_Stream; 188 -- Create a stream from Mf 189 190 procedure Close (S : in out Mapped_Stream); 191 -- Close the stream (deallocate memory) 192 193 procedure Read_Raw 194 (S : in out Mapped_Stream; 195 Addr : Address; 196 Size : uint32); 197 pragma Inline (Read_Raw); 198 -- Read a number of fixed sized records 199 200 procedure Seek (S : in out Mapped_Stream; Off : Offset); 201 -- Seek to an absolute offset in bytes 202 203 procedure Tell (Obj : in out Mapped_Stream; Off : out Offset) 204 with Inline; 205 function Tell (Obj : Mapped_Stream) return Offset 206 with Inline; 207 -- Fetch the current offset 208 209 function Length (Obj : Mapped_Stream) return Offset 210 with Inline; 211 -- Length of the stream 212 213 function Read (S : in out Mapped_Stream) return Mmap.Str_Access; 214 -- Provide a pointer in memory at the current offset 215 216 function Read (S : in out Mapped_Stream) return String_Ptr_Len; 217 -- Provide a pointer in memory at the current offset 218 219 function Read (S : in out Mapped_Stream) return uint8; 220 function Read (S : in out Mapped_Stream) return uint16; 221 function Read (S : in out Mapped_Stream) return uint32; 222 function Read (S : in out Mapped_Stream) return uint64; 223 function Read (S : in out Mapped_Stream) return int8; 224 function Read (S : in out Mapped_Stream) return int16; 225 function Read (S : in out Mapped_Stream) return int32; 226 function Read (S : in out Mapped_Stream) return int64; 227 -- Read a scalar 228 229 function Read_Address 230 (Obj : Object_File; S : in out Mapped_Stream) return uint64; 231 -- Read either a 64 or 32 bit address from the file stream depending on the 232 -- address size of the target architecture and promote it to a 64 bit type. 233 234 function Read_LEB128 (S : in out Mapped_Stream) return uint32; 235 function Read_LEB128 (S : in out Mapped_Stream) return int32; 236 -- Read a value encoding in Little-Endian Base 128 format 237 238 procedure Read_C_String (S : in out Mapped_Stream; B : out Buffer); 239 function Read_C_String (S : in out Mapped_Stream) return Mmap.Str_Access; 240 -- Read a C style NULL terminated string 241 242 function Offset_To_String 243 (S : in out Mapped_Stream; 244 Off : Offset) return String; 245 -- Construct a string from a C style NULL terminated string located at an 246 -- offset into the object file. 247 248 ------------------------ 249 -- Object information -- 250 ------------------------ 251 252 function Arch (Obj : Object_File) return Object_Arch; 253 -- Return the object architecture 254 255 function Format (Obj : Object_File) return Object_Format; 256 -- Return the object file format 257 258 function Get_Load_Address (Obj : Object_File) return uint64; 259 -- Return the load address defined in Obj. May raise Format_Error if not 260 -- implemented 261 262 function Num_Sections (Obj : Object_File) return uint32; 263 -- Return the number of sections composing the object file 264 265 function Get_Section 266 (Obj : in out Object_File; 267 Shnum : uint32) return Object_Section; 268 -- Return the Nth section (numbered from zero) 269 270 function Get_Section 271 (Obj : in out Object_File; 272 Sec_Name : String) return Object_Section; 273 -- Return a section by name 274 275 function Create_Stream 276 (Obj : Object_File; 277 Sec : Object_Section) return Mapped_Stream; 278 -- Create a stream for section Sec 279 280 procedure Get_Memory_Bounds 281 (Obj : in out Object_File; 282 Low, High : out uint64); 283 -- Return the low and high addresses of the code for the object file. Can 284 -- be used to check if an address in within this object file. This 285 -- procedure is not efficient and the result should be saved to avoid 286 -- recomputation. 287 288 ------------------------- 289 -- Section information -- 290 ------------------------- 291 292 function Name 293 (Obj : in out Object_File; 294 Sec : Object_Section) return String; 295 -- Return the name of a section as a string 296 297 function Size (Sec : Object_Section) return uint64; 298 -- Return the size of a section in bytes 299 300 function Num (Sec : Object_Section) return uint32; 301 -- Return the index of a section from zero 302 303 function Off (Sec : Object_Section) return Offset; 304 -- Return the byte offset of the section within the object 305 306 ------------------------------ 307 -- Symbol table information -- 308 ------------------------------ 309 310 Null_Symbol : constant Object_Symbol; 311 -- An empty symbol table entry. 312 313 function First_Symbol (Obj : in out Object_File) return Object_Symbol; 314 -- Return the first element in the symbol table or Null_Symbol if the 315 -- symbol table is empty. 316 317 function Next_Symbol 318 (Obj : in out Object_File; 319 Prev : Object_Symbol) return Object_Symbol; 320 -- Return the element following Prev in the symbol table, or Null_Symbol if 321 -- Prev is the last symbol in the table. 322 323 function Read_Symbol 324 (Obj : in out Object_File; 325 Off : Offset) return Object_Symbol; 326 -- Read symbol at Off 327 328 function Name 329 (Obj : in out Object_File; 330 Sym : Object_Symbol) return String_Ptr_Len; 331 -- Return the name of the symbol 332 333 function Decoded_Ada_Name 334 (Obj : in out Object_File; 335 Sym : String_Ptr_Len) return String; 336 -- Return the decoded name of a symbol encoded as per exp_dbug.ads 337 338 function Strip_Leading_Char 339 (Obj : in out Object_File; 340 Sym : String_Ptr_Len) return Positive; 341 -- Return the index of the first character to decode the name. This can 342 -- strip one character for ABI with a prefix (like x86 for PECOFF). 343 344 function Value (Sym : Object_Symbol) return uint64; 345 -- Return the name of the symbol 346 347 function Size (Sym : Object_Symbol) return uint64; 348 -- Return the size of the symbol in bytes 349 350 function Spans (Sym : Object_Symbol; Addr : uint64) return Boolean; 351 -- Determine whether a particular address corresponds to the range 352 -- referenced by this symbol. 353 354 function Off (Sym : Object_Symbol) return Offset; 355 -- Return the offset of the symbol. 356 357 ---------------- 358 -- Exceptions -- 359 ---------------- 360 361 IO_Error : exception; 362 -- Input/Output error reading file 363 364 Format_Error : exception; 365 -- Encountered a problem parsing the object 366 367private 368 type Mapped_Stream is record 369 Region : System.Mmap.Mapped_Region; 370 Off : Offset; 371 Len : Offset; 372 end record; 373 374 subtype ELF is Object_Format range ELF32 .. ELF64; 375 subtype Any_PECOFF is Object_Format range PECOFF .. PECOFF_PLUS; 376 377 type Object_File (Format : Object_Format) is record 378 Mf : System.Mmap.Mapped_File := 379 System.Mmap.Invalid_Mapped_File; 380 Arch : Object_Arch := Unknown; 381 382 Num_Sections : uint32 := 0; 383 -- Number of sections 384 385 Symtab_Last : Offset; -- Last offset of symbol table 386 387 In_Exception : Boolean := False; 388 -- True if the parsing is done as part of an exception handler 389 390 Sectab_Stream : Mapped_Stream; 391 -- Section table 392 393 Symtab_Stream : Mapped_Stream; 394 -- Symbol table 395 396 Symstr_Stream : Mapped_Stream; 397 -- Symbol strings 398 399 case Format is 400 when ELF => 401 Secstr_Stream : Mapped_Stream; 402 -- Section strings 403 when Any_PECOFF => 404 ImageBase : uint64; -- ImageBase value from header 405 406 -- Cache for latest result of Get_Section_Virtual_Address 407 408 GSVA_Sec : uint32 := uint32'Last; 409 GSVA_Addr : uint64; 410 when XCOFF32 => 411 null; 412 end case; 413 end record; 414 415 subtype ELF_Object_File is Object_File; -- with 416 -- Predicate => ELF_Object_File.Format in ELF; 417 subtype PECOFF_Object_File is Object_File; -- with 418 -- Predicate => PECOFF_Object_File.Format in Any_PECOFF; 419 subtype XCOFF32_Object_File is Object_File; -- with 420 -- Predicate => XCOFF32_Object_File.Format in XCOFF32; 421 -- ???Above predicates cause the compiler to crash when instantiating 422 -- ELF64_Ops (see package body). 423 424 type Object_Section is record 425 Num : uint32 := 0; 426 -- Section index in the section table 427 428 Off : Offset := 0; 429 -- First byte of the section in the object file 430 431 Addr : uint64 := 0; 432 -- Load address of the section. Valid only when Flag_Alloc is true. 433 434 Size : uint64 := 0; 435 -- Length of the section in bytes 436 437 Flag_Alloc : Boolean := False; 438 -- True if the section is mapped in memory by the OS loader 439 end record; 440 441 Null_Section : constant Object_Section := (0, 0, 0, 0, False); 442 443 type Object_Symbol is record 444 Off : Offset := 0; -- Offset of underlying symbol on disk 445 Next : Offset := 0; -- Offset of the following symbol 446 Value : uint64 := 0; -- Value associated with this symbol 447 Size : uint64 := 0; -- Size of the referenced entity 448 end record; 449 450 Null_Symbol : constant Object_Symbol := (0, 0, 0, 0); 451end System.Object_Reader; 452