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