1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
5 -- S Y S T E M . O B J E C T _ R E A D E R --
9 -- Copyright (C) 2009-2017, Free Software Foundation, Inc. --
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. --
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. --
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/>. --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
30 ------------------------------------------------------------------------------
32 -- This package implements a simple, minimal overhead reader for object files
33 -- composed of sections of untyped heterogeneous binary data.
38 package System
.Object_Reader
is
44 BUFFER_SIZE
: constant := 8 * 1024;
50 type Object_File
(<>) is private;
52 type Object_File_Access
is access Object_File
;
56 ----------------------
58 type Object_Section
is private;
60 Null_Section
: constant Object_Section
;
66 type Object_Symbol
is private;
68 ------------------------
69 -- Object format type --
70 ------------------------
74 -- Object format is 32-bit ELF
77 -- Object format is 64-bit ELF
80 -- Object format is Microsoft PECOFF
83 -- Object format is Microsoft PECOFF+
86 -- Object format is AIX 32-bit XCOFF
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 ???
91 ------------------------------
92 -- Object architecture type --
93 ------------------------------
97 -- The target architecture has not yet been determined
109 -- MIPS Technologies MIPS
112 -- x86-64 (64-bit AMD/Intel)
127 subtype Offset
is Interfaces
.Integer_64
;
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
;
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
;
139 type Buffer
is array (0 .. BUFFER_SIZE
- 1) of uint8
;
141 type String_Ptr_Len
is record
142 Ptr
: Mmap
.Str_Access
;
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.
148 -------------------------------------------
149 -- Operations on buffers of untyped data --
150 -------------------------------------------
152 function To_String
(Buf
: Buffer
) return String;
153 -- Construct string from C style null-terminated string stored in a buffer
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.
160 function Strlen
(Buf
: Buffer
) return int32
;
161 -- Return the length of a C style null-terminated string
163 -------------------------
164 -- Opening and closing --
165 -------------------------
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.
174 procedure Close
(Obj
: in out Object_File
);
175 -- Close the object file
177 -----------------------
178 -- Sequential access --
179 -----------------------
181 type Mapped_Stream
is private;
182 -- Provide an abstraction of a stream on a memory mapped file
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
190 procedure Close
(S
: in out Mapped_Stream
);
191 -- Close the stream (deallocate memory)
194 (S
: in out Mapped_Stream
;
197 pragma Inline
(Read_Raw
);
198 -- Read a number of fixed sized records
200 procedure Seek
(S
: in out Mapped_Stream
; Off
: Offset
);
201 -- Seek to an absolute offset in bytes
203 procedure Tell
(Obj
: in out Mapped_Stream
; Off
: out Offset
)
205 function Tell
(Obj
: Mapped_Stream
) return Offset
207 -- Fetch the current offset
209 function Length
(Obj
: Mapped_Stream
) return Offset
211 -- Length of the stream
213 function Read
(S
: in out Mapped_Stream
) return Mmap
.Str_Access
;
214 -- Provide a pointer in memory at the current offset
216 function Read
(S
: in out Mapped_Stream
) return String_Ptr_Len
;
217 -- Provide a pointer in memory at the current offset
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
;
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.
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
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
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.
248 ------------------------
249 -- Object information --
250 ------------------------
252 function Arch
(Obj
: Object_File
) return Object_Arch
;
253 -- Return the object architecture
255 function Format
(Obj
: Object_File
) return Object_Format
;
256 -- Return the object file format
258 function Get_Load_Address
(Obj
: Object_File
) return uint64
;
259 -- Return the load address defined in Obj. May raise Format_Error if not
262 function Num_Sections
(Obj
: Object_File
) return uint32
;
263 -- Return the number of sections composing the object file
266 (Obj
: in out Object_File
;
267 Shnum
: uint32
) return Object_Section
;
268 -- Return the Nth section (numbered from zero)
271 (Obj
: in out Object_File
;
272 Sec_Name
: String) return Object_Section
;
273 -- Return a section by name
275 function Create_Stream
277 Sec
: Object_Section
) return Mapped_Stream
;
278 -- Create a stream for section Sec
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
288 -------------------------
289 -- Section information --
290 -------------------------
293 (Obj
: in out Object_File
;
294 Sec
: Object_Section
) return String;
295 -- Return the name of a section as a string
297 function Size
(Sec
: Object_Section
) return uint64
;
298 -- Return the size of a section in bytes
300 function Num
(Sec
: Object_Section
) return uint32
;
301 -- Return the index of a section from zero
303 function Off
(Sec
: Object_Section
) return Offset
;
304 -- Return the byte offset of the section within the object
306 ------------------------------
307 -- Symbol table information --
308 ------------------------------
310 Null_Symbol
: constant Object_Symbol
;
311 -- An empty symbol table entry.
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.
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.
324 (Obj
: in out Object_File
;
325 Off
: Offset
) return Object_Symbol
;
326 -- Read symbol at Off
329 (Obj
: in out Object_File
;
330 Sym
: Object_Symbol
) return String_Ptr_Len
;
331 -- Return the name of the symbol
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
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).
344 function Value
(Sym
: Object_Symbol
) return uint64
;
345 -- Return the name of the symbol
347 function Size
(Sym
: Object_Symbol
) return uint64
;
348 -- Return the size of the symbol in bytes
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.
354 function Off
(Sym
: Object_Symbol
) return Offset
;
355 -- Return the offset of the symbol.
361 IO_Error
: exception;
362 -- Input/Output error reading file
364 Format_Error
: exception;
365 -- Encountered a problem parsing the object
368 type Mapped_Stream
is record
369 Region
: System
.Mmap
.Mapped_Region
;
374 subtype ELF
is Object_Format
range ELF32
.. ELF64
;
375 subtype Any_PECOFF
is Object_Format
range PECOFF
.. PECOFF_PLUS
;
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
;
382 Num_Sections
: uint32
:= 0;
383 -- Number of sections
385 Symtab_Last
: Offset
; -- Last offset of symbol table
387 In_Exception
: Boolean := False;
388 -- True if the parsing is done as part of an exception handler
390 Sectab_Stream
: Mapped_Stream
;
393 Symtab_Stream
: Mapped_Stream
;
396 Symstr_Stream
: Mapped_Stream
;
401 Secstr_Stream
: Mapped_Stream
;
404 ImageBase
: uint64
; -- ImageBase value from header
406 -- Cache for latest result of Get_Section_Virtual_Address
408 GSVA_Sec
: uint32
:= uint32
'Last;
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).
424 type Object_Section
is record
426 -- Section index in the section table
429 -- First byte of the section in the object file
432 -- Load address of the section. Valid only when Flag_Alloc is true.
435 -- Length of the section in bytes
437 Flag_Alloc
: Boolean := False;
438 -- True if the section is mapped in memory by the OS loader
441 Null_Section
: constant Object_Section
:= (0, 0, 0, 0, False);
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
450 Null_Symbol
: constant Object_Symbol
:= (0, 0, 0, 0);
451 end System
.Object_Reader
;