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