111
|
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 -- --
|
145
|
9 -- Copyright (C) 2009-2019, Free Software Foundation, Inc. --
|
111
|
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
|
|
35 with Interfaces;
|
|
36 with System.Mmap;
|
|
37
|
|
38 package 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
|
131
|
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
|
111
|
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
|
131
|
280 procedure Get_Xcode_Bounds
|
111
|
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
|
|
367 private
|
|
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
|
131
|
437 Flag_Xcode : Boolean := False;
|
|
438 -- True if the section is advertised to contain executable code
|
111
|
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);
|
|
451 end System.Object_Reader;
|