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-2018, 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 with Ada
.Unchecked_Conversion
;
38 package body System
.Object_Reader
is
43 SSU
: constant := System
.Storage_Unit
;
45 function To_int32
is new Ada
.Unchecked_Conversion
(uint32
, int32
);
47 function Trim_Trailing_Nuls
(Str
: String) return String;
48 -- Return a copy of a string with any trailing NUL characters truncated
50 procedure Check_Read_Offset
(S
: in out Mapped_Stream
; Size
: uint32
);
51 -- Check that the SIZE bytes at the current offset are still in the stream
53 -------------------------------------
54 -- ELF object file format handling --
55 -------------------------------------
64 ELFCLASS32
: constant := 1; -- 32 bit ELF
65 ELFCLASS64
: constant := 2; -- 64 bit ELF
69 EM_NONE
: constant := 0; -- No machine
70 EM_SPARC
: constant := 2; -- SUN SPARC
71 EM_386
: constant := 3; -- Intel 80386
72 EM_MIPS
: constant := 8; -- MIPS RS3000 Big-Endian
73 EM_MIPS_RS3_LE
: constant := 10; -- MIPS RS3000 Little-Endian
74 EM_SPARC32PLUS
: constant := 18; -- Sun SPARC 32+
75 EM_PPC
: constant := 20; -- PowerPC
76 EM_PPC64
: constant := 21; -- PowerPC 64-bit
77 EM_ARM
: constant := 40; -- ARM
78 EM_SPARCV9
: constant := 43; -- SPARC v9 64-bit
79 EM_IA_64
: constant := 50; -- Intel Merced
80 EM_X86_64
: constant := 62; -- AMD x86-64 architecture
82 EN_NIDENT
: constant := 16;
84 type E_Ident_Type
is array (0 .. EN_NIDENT
- 1) of uint8
;
87 E_Ident
: E_Ident_Type
; -- Magic number and other info
88 E_Type
: uint16
; -- Object file type
89 E_Machine
: uint16
; -- Architecture
90 E_Version
: uint32
; -- Object file version
91 E_Entry
: uword
; -- Entry point virtual address
92 E_Phoff
: uword
; -- Program header table file offset
93 E_Shoff
: uword
; -- Section header table file offset
94 E_Flags
: uint32
; -- Processor-specific flags
95 E_Ehsize
: uint16
; -- ELF header size in bytes
96 E_Phentsize
: uint16
; -- Program header table entry size
97 E_Phnum
: uint16
; -- Program header table entry count
98 E_Shentsize
: uint16
; -- Section header table entry size
99 E_Shnum
: uint16
; -- Section header table entry count
100 E_Shstrndx
: uint16
; -- Section header string table index
103 type Section_Header
is record
104 Sh_Name
: uint32
; -- Section name string table index
105 Sh_Type
: uint32
; -- Section type
106 Sh_Flags
: uword
; -- Section flags
107 Sh_Addr
: uword
; -- Section virtual addr at execution
108 Sh_Offset
: uword
; -- Section file offset
109 Sh_Size
: uword
; -- Section size in bytes
110 Sh_Link
: uint32
; -- Link to another section
111 Sh_Info
: uint32
; -- Additional section information
112 Sh_Addralign
: uword
; -- Section alignment
113 Sh_Entsize
: uword
; -- Entry size if section holds table
116 SHF_ALLOC
: constant := 2;
118 type Symtab_Entry32
is record
119 St_Name
: uint32
; -- Name (string table index)
120 St_Value
: uint32
; -- Value
121 St_Size
: uint32
; -- Size in bytes
122 St_Info
: uint8
; -- Type and binding attributes
123 St_Other
: uint8
; -- Undefined
124 St_Shndx
: uint16
; -- Defining section
127 type Symtab_Entry64
is record
128 St_Name
: uint32
; -- Name (string table index)
129 St_Info
: uint8
; -- Type and binding attributes
130 St_Other
: uint8
; -- Undefined
131 St_Shndx
: uint16
; -- Defining section
132 St_Value
: uint64
; -- Value
133 St_Size
: uint64
; -- Size in bytes
136 function Read_Header
(F
: in out Mapped_Stream
) return Header
;
137 -- Read a header from an ELF format object
139 function First_Symbol
140 (Obj
: in out ELF_Object_File
) return Object_Symbol
;
141 -- Return the first element in the symbol table, or Null_Symbol if the
142 -- symbol table is empty.
145 (Obj
: in out ELF_Object_File
;
146 Off
: Offset
) return Object_Symbol
;
147 -- Read a symbol at offset Off
150 (Obj
: in out ELF_Object_File
;
151 Sym
: Object_Symbol
) return String_Ptr_Len
;
152 -- Return the name of the symbol
155 (Obj
: in out ELF_Object_File
;
156 Sec
: Object_Section
) return String;
157 -- Return the name of a section
160 (Obj
: in out ELF_Object_File
;
161 Shnum
: uint32
) return Object_Section
;
162 -- Fetch a section by index from zero
167 In_Exception
: Boolean) return ELF_Object_File
;
168 -- Initialize an object file
172 -----------------------------------
173 -- PECOFF object format handling --
174 -----------------------------------
176 package PECOFF_Ops
is
178 -- Constants and data layout are taken from the document "Microsoft
179 -- Portable Executable and Common Object File Format Specification"
182 Signature_Loc_Offset
: constant := 16#
3C#
;
183 -- Offset of pointer to the file signature
185 Size_Of_Standard_Header_Fields
: constant := 16#
18#
;
186 -- Length in bytes of the standard header record
188 Function_Symbol_Type
: constant := 16#
20#
;
189 -- Type field value indicating a symbol refers to a function
191 Not_Function_Symbol_Type
: constant := 16#
00#
;
192 -- Type field value indicating a symbol does not refer to a function
194 type Magic_Array
is array (0 .. 3) of uint8
;
195 -- Array of magic numbers from the header
197 -- Magic numbers for PECOFF variants
199 VARIANT_PE32
: constant := 16#
010B#
;
200 VARIANT_PE32_PLUS
: constant := 16#
020B#
;
202 -- PECOFF machine codes
204 IMAGE_FILE_MACHINE_I386
: constant := 16#
014C#
;
205 IMAGE_FILE_MACHINE_IA64
: constant := 16#
0200#
;
206 IMAGE_FILE_MACHINE_AMD64
: constant := 16#
8664#
;
208 -- PECOFF Data layout
210 type Header
is record
211 Magics
: Magic_Array
;
213 NumberOfSections
: uint16
;
214 TimeDateStamp
: uint32
;
215 PointerToSymbolTable
: uint32
;
216 NumberOfSymbols
: uint32
;
217 SizeOfOptionalHeader
: uint16
;
218 Characteristics
: uint16
;
222 pragma Pack
(Header
);
224 type Optional_Header_PE32
is record
226 MajorLinkerVersion
: uint8
;
227 MinorLinkerVersion
: uint8
;
229 SizeOfInitializedData
: uint32
;
230 SizeOfUninitializedData
: uint32
;
231 AddressOfEntryPoint
: uint32
;
233 BaseOfData
: uint32
; -- Note: not in PE32+
235 SectionAlignment
: uint32
;
236 FileAlignment
: uint32
;
237 MajorOperatingSystemVersion
: uint16
;
238 MinorOperationSystemVersion
: uint16
;
239 MajorImageVersion
: uint16
;
240 MinorImageVersion
: uint16
;
241 MajorSubsystemVersion
: uint16
;
242 MinorSubsystemVersion
: uint16
;
243 Win32VersionValue
: uint32
;
244 SizeOfImage
: uint32
;
245 SizeOfHeaders
: uint32
;
248 DllCharacteristics
: uint16
;
249 SizeOfStackReserve
: uint32
;
250 SizeOfStackCommit
: uint32
;
251 SizeOfHeapReserve
: uint32
;
252 SizeOfHeapCommit
: uint32
;
253 LoaderFlags
: uint32
;
254 NumberOfRvaAndSizes
: uint32
;
256 pragma Pack
(Optional_Header_PE32
);
257 pragma Assert
(Optional_Header_PE32
'Size = 96 * SSU
);
259 type Optional_Header_PE64
is record
261 MajorLinkerVersion
: uint8
;
262 MinorLinkerVersion
: uint8
;
264 SizeOfInitializedData
: uint32
;
265 SizeOfUninitializedData
: uint32
;
266 AddressOfEntryPoint
: uint32
;
269 SectionAlignment
: uint32
;
270 FileAlignment
: uint32
;
271 MajorOperatingSystemVersion
: uint16
;
272 MinorOperationSystemVersion
: uint16
;
273 MajorImageVersion
: uint16
;
274 MinorImageVersion
: uint16
;
275 MajorSubsystemVersion
: uint16
;
276 MinorSubsystemVersion
: uint16
;
277 Win32VersionValue
: uint32
;
278 SizeOfImage
: uint32
;
279 SizeOfHeaders
: uint32
;
282 DllCharacteristics
: uint16
;
283 SizeOfStackReserve
: uint64
;
284 SizeOfStackCommit
: uint64
;
285 SizeOfHeapReserve
: uint64
;
286 SizeOfHeapCommit
: uint64
;
287 LoaderFlags
: uint32
;
288 NumberOfRvaAndSizes
: uint32
;
290 pragma Pack
(Optional_Header_PE64
);
291 pragma Assert
(Optional_Header_PE64
'Size = 112 * SSU
);
293 subtype Name_Str
is String (1 .. 8);
295 type Section_Header
is record
297 VirtualSize
: uint32
;
298 VirtualAddress
: uint32
;
299 SizeOfRawData
: uint32
;
300 PointerToRawData
: uint32
;
301 PointerToRelocations
: uint32
;
302 PointerToLinenumbers
: uint32
;
303 NumberOfRelocations
: uint16
;
304 NumberOfLinenumbers
: uint16
;
305 Characteristics
: uint32
;
308 pragma Pack
(Section_Header
);
310 IMAGE_SCN_CNT_CODE
: constant := 16#
0020#
;
312 type Symtab_Entry
is record
315 SectionNumber
: int16
;
317 StorageClass
: uint8
;
318 NumberOfAuxSymbols
: uint8
;
321 pragma Pack
(Symtab_Entry
);
323 type Auxent_Section
is record
325 NumberOfRelocations
: uint16
;
326 NumberOfLinenumbers
: uint16
;
335 for Auxent_Section
'Size use 18 * 8;
337 function Read_Header
(F
: in out Mapped_Stream
) return Header
;
338 -- Read the object file header
340 function First_Symbol
341 (Obj
: in out PECOFF_Object_File
) return Object_Symbol
;
342 -- Return the first element in the symbol table, or Null_Symbol if the
343 -- symbol table is empty.
346 (Obj
: in out PECOFF_Object_File
;
347 Off
: Offset
) return Object_Symbol
;
348 -- Read a symbol at offset Off
351 (Obj
: in out PECOFF_Object_File
;
352 Sym
: Object_Symbol
) return String_Ptr_Len
;
353 -- Return the name of the symbol
356 (Obj
: in out PECOFF_Object_File
;
357 Sec
: Object_Section
) return String;
358 -- Return the name of a section
361 (Obj
: in out PECOFF_Object_File
;
362 Index
: uint32
) return Object_Section
;
363 -- Fetch a section by index from zero
368 In_Exception
: Boolean) return PECOFF_Object_File
;
369 -- Initialize an object file
373 -------------------------------------
374 -- XCOFF-32 object format handling --
375 -------------------------------------
377 package XCOFF32_Ops
is
381 type Header
is record
391 type Auxiliary_Header
is record
398 o_text_start
: uint32
;
399 o_data_start
: uint32
;
419 pragma Unreferenced
(Auxiliary_Header
);
420 -- Not used, but not removed (just in case)
422 subtype Name_Str
is String (1 .. 8);
424 type Section_Header
is record
437 pragma Pack
(Section_Header
);
439 STYP_TEXT
: constant := 16#
0020#
;
441 type Symbol_Entry
is record
449 for Symbol_Entry
'Size use 18 * 8;
451 type Aux_Entry
is record
460 for Aux_Entry
'Size use 18 * 8;
462 pragma Pack
(Aux_Entry
);
464 C_EXT
: constant := 2;
465 C_HIDEXT
: constant := 107;
466 C_WEAKEXT
: constant := 111;
468 XTY_LD
: constant := 2;
469 -- Magic constant should be documented, especially since it's changed???
471 function Read_Header
(F
: in out Mapped_Stream
) return Header
;
472 -- Read the object file header
474 function First_Symbol
475 (Obj
: in out XCOFF32_Object_File
) return Object_Symbol
;
476 -- Return the first element in the symbol table, or Null_Symbol if the
477 -- symbol table is empty.
480 (Obj
: in out XCOFF32_Object_File
;
481 Off
: Offset
) return Object_Symbol
;
482 -- Read a symbol at offset Off
485 (Obj
: in out XCOFF32_Object_File
;
486 Sym
: Object_Symbol
) return String_Ptr_Len
;
487 -- Return the name of the symbol
490 (Obj
: in out XCOFF32_Object_File
;
491 Sec
: Object_Section
) return String;
492 -- Return the name of a section
497 In_Exception
: Boolean) return XCOFF32_Object_File
;
498 -- Initialize an object file
501 (Obj
: in out XCOFF32_Object_File
;
502 Index
: uint32
) return Object_Section
;
503 -- Fetch a section by index from zero
511 package body ELF_Ops
is
513 function Get_String_Table
(Obj
: in out ELF_Object_File
)
514 return Object_Section
;
515 -- Fetch the section containing the string table
517 function Get_Symbol_Table
(Obj
: in out ELF_Object_File
)
518 return Object_Section
;
519 -- Fetch the section containing the symbol table
521 function Read_Section_Header
522 (Obj
: in out ELF_Object_File
;
523 Shnum
: uint32
) return Section_Header
;
524 -- Read the header for an ELF format object section indexed from zero
530 function First_Symbol
531 (Obj
: in out ELF_Object_File
) return Object_Symbol
534 if Obj
.Symtab_Last
= 0 then
537 return Read_Symbol
(Obj
, 0);
546 (Obj
: in out ELF_Object_File
;
547 Shnum
: uint32
) return Object_Section
549 SHdr
: constant Section_Header
:= Read_Section_Header
(Obj
, Shnum
);
552 Offset
(SHdr
.Sh_Offset
),
553 uint64
(SHdr
.Sh_Addr
),
554 uint64
(SHdr
.Sh_Size
),
555 (SHdr
.Sh_Flags
and SHF_ALLOC
) /= 0);
558 ------------------------
559 -- Get_String_Table --
560 ------------------------
562 function Get_String_Table
563 (Obj
: in out ELF_Object_File
) return Object_Section
566 -- All cases except MIPS IRIX, string table located in .strtab
568 if Obj
.Arch
/= MIPS
then
569 return Get_Section
(Obj
, ".strtab");
571 -- On IRIX only .dynstr is available
574 return Get_Section
(Obj
, ".dynstr");
576 end Get_String_Table
;
578 ------------------------
579 -- Get_Symbol_Table --
580 ------------------------
582 function Get_Symbol_Table
583 (Obj
: in out ELF_Object_File
) return Object_Section
586 -- All cases except MIPS IRIX, symbol table located in .symtab
588 if Obj
.Arch
/= MIPS
then
589 return Get_Section
(Obj
, ".symtab");
591 -- On IRIX, symbol table located somewhere other than .symtab
594 return Get_Section
(Obj
, ".dynsym");
596 end Get_Symbol_Table
;
605 In_Exception
: Boolean) return ELF_Object_File
607 Res
: ELF_Object_File
608 (Format
=> (case uword
'Size is
611 when others => raise Program_Error
));
612 Sec
: Object_Section
;
615 Res
.In_Exception
:= In_Exception
;
616 Res
.Num_Sections
:= uint32
(Hdr
.E_Shnum
);
618 case Hdr
.E_Machine
is
648 raise Format_Error
with "unrecognized architecture";
651 -- Map section table and section string table
652 Res
.Sectab_Stream
:= Create_Stream
653 (F
, File_Size
(Hdr
.E_Shoff
),
654 File_Size
(Hdr
.E_Shnum
) * File_Size
(Hdr
.E_Shentsize
));
655 Sec
:= Get_Section
(Res
, uint32
(Hdr
.E_Shstrndx
));
656 Res
.Secstr_Stream
:= Create_Stream
(Res
, Sec
);
658 -- Map symbol and string table
659 Sec
:= Get_Symbol_Table
(Res
);
660 Res
.Symtab_Stream
:= Create_Stream
(Res
, Sec
);
661 Res
.Symtab_Last
:= Offset
(Sec
.Size
);
663 Sec
:= Get_String_Table
(Res
);
664 Res
.Symstr_Stream
:= Create_Stream
(Res
, Sec
);
673 function Read_Header
(F
: in out Mapped_Stream
) return Header
is
677 Read_Raw
(F
, Hdr
'Address, uint32
(Hdr
'Size / SSU
));
681 -------------------------
682 -- Read_Section_Header --
683 -------------------------
685 function Read_Section_Header
686 (Obj
: in out ELF_Object_File
;
687 Shnum
: uint32
) return Section_Header
689 Shdr
: Section_Header
;
691 Seek
(Obj
.Sectab_Stream
, Offset
(Shnum
* Section_Header
'Size / SSU
));
692 Read_Raw
(Obj
.Sectab_Stream
, Shdr
'Address, Section_Header
'Size / SSU
);
694 end Read_Section_Header
;
701 (Obj
: in out ELF_Object_File
;
702 Off
: Offset
) return Object_Symbol
704 ST_Entry32
: Symtab_Entry32
;
705 ST_Entry64
: Symtab_Entry64
;
709 Seek
(Obj
.Symtab_Stream
, Off
);
713 Read_Raw
(Obj
.Symtab_Stream
, ST_Entry32
'Address,
714 uint32
(ST_Entry32
'Size / SSU
));
716 Off
+ ST_Entry32
'Size / SSU
,
717 uint64
(ST_Entry32
.St_Value
),
718 uint64
(ST_Entry32
.St_Size
));
721 Read_Raw
(Obj
.Symtab_Stream
, ST_Entry64
'Address,
722 uint32
(ST_Entry64
'Size / SSU
));
724 Off
+ ST_Entry64
'Size / SSU
,
740 (Obj
: in out ELF_Object_File
;
741 Sec
: Object_Section
) return String
743 SHdr
: Section_Header
;
745 SHdr
:= Read_Section_Header
(Obj
, Sec
.Num
);
746 return Offset_To_String
(Obj
.Secstr_Stream
, Offset
(SHdr
.Sh_Name
));
750 (Obj
: in out ELF_Object_File
;
751 Sym
: Object_Symbol
) return String_Ptr_Len
753 ST_Entry32
: Symtab_Entry32
;
754 ST_Entry64
: Symtab_Entry64
;
758 -- Test that this symbol is not null
760 if Sym
= Null_Symbol
then
764 -- Read the symbol table entry
766 Seek
(Obj
.Symtab_Stream
, Sym
.Off
);
770 Read_Raw
(Obj
.Symtab_Stream
, ST_Entry32
'Address,
771 uint32
(ST_Entry32
'Size / SSU
));
772 Name_Off
:= Offset
(ST_Entry32
.St_Name
);
775 Read_Raw
(Obj
.Symtab_Stream
, ST_Entry64
'Address,
776 uint32
(ST_Entry64
'Size / SSU
));
777 Name_Off
:= Offset
(ST_Entry64
.St_Name
);
783 -- Fetch the name from the string table
785 Seek
(Obj
.Symstr_Stream
, Name_Off
);
786 return Read
(Obj
.Symstr_Stream
);
791 package ELF32_Ops
is new ELF_Ops
(uint32
);
792 package ELF64_Ops
is new ELF_Ops
(uint64
);
798 package body PECOFF_Ops
is
801 (Obj
: in out PECOFF_Object_File
;
802 Raw_Name
: String) return String;
803 -- A section name is an 8 byte field padded on the right with null
804 -- characters, or a '\' followed by an ASCII decimal string indicating
805 -- an offset in to the string table. This routine decodes this
807 function Get_Section_Virtual_Address
808 (Obj
: in out PECOFF_Object_File
;
809 Index
: uint32
) return uint64
;
810 -- Fetch the address at which a section is loaded
812 function Read_Section_Header
813 (Obj
: in out PECOFF_Object_File
;
814 Index
: uint32
) return Section_Header
;
815 -- Read a header from section table
817 function String_Table
818 (Obj
: in out PECOFF_Object_File
;
819 Index
: Offset
) return String;
820 -- Return an entry from the string table
827 (Obj
: in out PECOFF_Object_File
;
828 Raw_Name
: String) return String
830 Name_Or_Ref
: constant String := Trim_Trailing_Nuls
(Raw_Name
);
834 -- We should never find a symbol with a zero length name. If we do it
835 -- probably means we are not parsing the symbol table correctly. If
836 -- this happens we raise a fatal error.
838 if Name_Or_Ref
'Length = 0 then
839 raise Format_Error
with
840 "found zero length symbol in symbol table";
843 if Name_Or_Ref
(1) /= '/' then
846 Off
:= Offset
'Value (Name_Or_Ref
(2 .. Name_Or_Ref
'Last));
847 return String_Table
(Obj
, Off
);
855 function First_Symbol
856 (Obj
: in out PECOFF_Object_File
) return Object_Symbol
is
858 -- Return Null_Symbol in the case that the symbol table is empty
860 if Obj
.Symtab_Last
= 0 then
864 return Read_Symbol
(Obj
, 0);
872 (Obj
: in out PECOFF_Object_File
;
873 Index
: uint32
) return Object_Section
875 Sec
: constant Section_Header
:= Read_Section_Header
(Obj
, Index
);
877 -- Use VirtualSize instead of SizeOfRawData. The latter is rounded to
878 -- the page size, so it may add garbage to the content. On the other
879 -- side, the former may be larger than the latter in case of 0
883 Offset
(Sec
.PointerToRawData
),
884 uint64
(Sec
.VirtualAddress
) + Obj
.ImageBase
,
885 uint64
(Sec
.VirtualSize
),
886 (Sec
.Characteristics
and IMAGE_SCN_CNT_CODE
) /= 0);
889 ---------------------------------
890 -- Get_Section_Virtual_Address --
891 ---------------------------------
893 function Get_Section_Virtual_Address
894 (Obj
: in out PECOFF_Object_File
;
895 Index
: uint32
) return uint64
897 Sec
: Section_Header
;
902 if Index
= Obj
.GSVA_Sec
then
903 return Obj
.GSVA_Addr
;
906 Obj
.GSVA_Sec
:= Index
;
907 Sec
:= Read_Section_Header
(Obj
, Index
);
908 Obj
.GSVA_Addr
:= Obj
.ImageBase
+ uint64
(Sec
.VirtualAddress
);
909 return Obj
.GSVA_Addr
;
910 end Get_Section_Virtual_Address
;
919 In_Exception
: Boolean) return PECOFF_Object_File
921 Res
: PECOFF_Object_File
922 (Format
=> (case Hdr
.Variant
is
923 when PECOFF_Ops
.VARIANT_PE32
=> PECOFF
,
924 when PECOFF_Ops
.VARIANT_PE32_PLUS
=> PECOFF_PLUS
,
925 when others => raise Program_Error
926 with "unrecognized PECOFF variant"));
927 Symtab_Size
: constant Offset
:=
928 Offset
(Hdr
.NumberOfSymbols
) * (Symtab_Entry
'Size / SSU
);
929 Strtab_Size
: uint32
;
931 Opt_Offset
: File_Size
;
932 Opt_Stream
: Mapped_Stream
;
935 Res
.In_Exception
:= In_Exception
;
938 when PECOFF_Ops
.IMAGE_FILE_MACHINE_I386
=>
940 when PECOFF_Ops
.IMAGE_FILE_MACHINE_IA64
=>
942 when PECOFF_Ops
.IMAGE_FILE_MACHINE_AMD64
=>
945 raise Format_Error
with "unrecognized architecture";
948 Res
.Num_Sections
:= uint32
(Hdr
.NumberOfSections
);
950 -- Map symbol table and the first following word (which is the length
951 -- of the string table).
953 Res
.Symtab_Last
:= Symtab_Size
;
954 Res
.Symtab_Stream
:= Create_Stream
956 File_Size
(Hdr
.PointerToSymbolTable
),
957 File_Size
(Symtab_Size
+ 4));
959 -- Map string table. The first 4 bytes are the length of the string
960 -- table and are part of it.
962 Seek
(Res
.Symtab_Stream
, Symtab_Size
);
963 Strtab_Size
:= Read
(Res
.Symtab_Stream
);
964 Res
.Symstr_Stream
:= Create_Stream
966 File_Size
(Hdr
.PointerToSymbolTable
) + File_Size
(Symtab_Size
),
967 File_Size
(Strtab_Size
));
971 Opt_Stream
:= Create_Stream
(Res
.Mf
, Signature_Loc_Offset
, 4);
972 Hdr_Offset
:= Offset
(uint32
'(Read (Opt_Stream)));
974 Res.Sectab_Stream := Create_Stream
976 File_Size (Hdr_Offset +
977 Size_Of_Standard_Header_Fields +
978 Offset (Hdr.SizeOfOptionalHeader)),
979 File_Size (Res.Num_Sections)
980 * File_Size (Section_Header'Size / SSU));
982 -- Read optional header and extract image base
984 Opt_Offset := File_Size (Hdr_Offset + Size_Of_Standard_Header_Fields);
986 if Res.Format = PECOFF then
988 Opt_32 : Optional_Header_PE32;
990 Opt_Stream := Create_Stream
991 (Res.Mf, Opt_Offset, Opt_32'Size / SSU);
993 (Opt_Stream, Opt_32'Address, uint32 (Opt_32'Size / SSU));
994 Res.ImageBase := uint64 (Opt_32.ImageBase);
1000 Opt_64 : Optional_Header_PE64;
1002 Opt_Stream := Create_Stream
1003 (Res.Mf, Opt_Offset, Opt_64'Size / SSU);
1005 (Opt_Stream, Opt_64'Address, uint32 (Opt_64'Size / SSU));
1006 Res.ImageBase := Opt_64.ImageBase;
1018 function Read_Symbol
1019 (Obj : in out PECOFF_Object_File;
1020 Off : Offset) return Object_Symbol
1022 ST_Entry : Symtab_Entry;
1023 ST_Last : Symtab_Entry;
1024 Aux_Entry : Auxent_Section;
1025 Sz : constant Offset := ST_Entry'Size / SSU;
1026 Result : Object_Symbol;
1031 -- Seek to the successor of Prev
1038 Seek (Obj.Symtab_Stream, Sym_Off);
1039 Read_Raw (Obj.Symtab_Stream, ST_Entry'Address, uint32 (Sz));
1043 Noff := Noff + Offset (1 + ST_Entry.NumberOfAuxSymbols) * Sz;
1045 exit when ST_Entry.TypeField = Function_Symbol_Type
1046 and then ST_Entry.SectionNumber > 0;
1048 if Noff >= Obj.Symtab_Last then
1053 -- Construct the symbol
1058 Value => uint64 (ST_Entry.Value),
1061 -- Set the size as accurately as possible
1063 -- The size of a symbol is not directly available so we try scanning
1064 -- to the next function and assuming the code ends there.
1067 -- Read symbol and AUX entries
1070 Seek (Obj.Symtab_Stream, Sym_Off);
1071 Read_Raw (Obj.Symtab_Stream, ST_Last'Address, uint32 (Sz));
1073 for I in 1 .. ST_Last.NumberOfAuxSymbols loop
1074 Read_Raw (Obj.Symtab_Stream, Aux_Entry'Address, uint32 (Sz));
1077 Noff := Noff + Offset (1 + ST_Last.NumberOfAuxSymbols) * Sz;
1079 if ST_Last.TypeField = Function_Symbol_Type then
1080 if ST_Last.SectionNumber = ST_Entry.SectionNumber
1081 and then ST_Last.Value >= ST_Entry.Value
1083 -- Symbol is a function past ST_Entry
1085 Result.Size := uint64 (ST_Last.Value - ST_Entry.Value);
1088 -- Not correlated function
1090 Result.Next := Sym_Off;
1095 elsif ST_Last.SectionNumber = ST_Entry.SectionNumber
1096 and then ST_Last.TypeField = Not_Function_Symbol_Type
1097 and then ST_Last.StorageClass = 3
1098 and then ST_Last.NumberOfAuxSymbols = 1
1100 -- Symbol is a section
1102 Result.Size := uint64 (ST_Last.Value + Aux_Entry.Length
1104 Result.Next := Noff;
1108 exit when Noff >= Obj.Symtab_Last;
1111 -- Relocate the address
1114 Result.Value + Get_Section_Virtual_Address
1115 (Obj, uint32 (ST_Entry.SectionNumber - 1));
1124 function Read_Header (F : in out Mapped_Stream) return Header is
1129 -- Skip the MSDOS stub, and seek directly to the file offset
1131 Seek (F, Signature_Loc_Offset);
1134 -- Read the COFF file header
1136 Seek (F, Offset (Off));
1137 Read_Raw (F, Hdr'Address, uint32 (Hdr'Size / SSU));
1141 -------------------------
1142 -- Read_Section_Header --
1143 -------------------------
1145 function Read_Section_Header
1146 (Obj : in out PECOFF_Object_File;
1147 Index : uint32) return Section_Header
1149 Sec : Section_Header;
1151 Seek (Obj.Sectab_Stream, Offset (Index * Section_Header'Size / SSU));
1152 Read_Raw (Obj.Sectab_Stream, Sec'Address, Section_Header'Size / SSU);
1154 end Read_Section_Header;
1161 (Obj : in out PECOFF_Object_File;
1162 Sec : Object_Section) return String
1164 Shdr : constant Section_Header := Read_Section_Header (Obj, Sec.Num);
1166 return Decode_Name (Obj, Shdr.Name);
1173 function String_Table
1174 (Obj : in out PECOFF_Object_File;
1175 Index : Offset) return String is
1177 -- An index of zero is used to represent an empty string, as the
1178 -- first word of the string table is specified to contain the length
1179 -- of the table rather than its contents.
1185 return Offset_To_String (Obj.Symstr_Stream, Index);
1194 (Obj : in out PECOFF_Object_File;
1195 Sym : Object_Symbol) return String_Ptr_Len
1197 ST_Entry : Symtab_Entry;
1200 Seek (Obj.Symtab_Stream, Sym.Off);
1201 Read_Raw (Obj.Symtab_Stream, ST_Entry'Address, ST_Entry'Size / SSU);
1204 -- Symbol table entries are packed and Table_Entry.Name may not be
1205 -- sufficiently aligned to interpret as a 32 bit word, so it is
1206 -- copied to a temporary
1208 Aligned_Name : Name_Str := ST_Entry.Name;
1209 for Aligned_Name'Alignment use 4;
1211 First_Word : uint32;
1212 pragma Import (Ada, First_Word);
1213 -- Suppress initialization in Normalized_Scalars mode
1214 for First_Word'Address use Aligned_Name (1)'Address;
1216 Second_Word : uint32;
1217 pragma Import (Ada, Second_Word);
1218 -- Suppress initialization in Normalized_Scalars mode
1219 for Second_Word'Address use Aligned_Name (5)'Address;
1222 if First_Word = 0 then
1223 -- Second word is an offset in the symbol table
1224 if Second_Word = 0 then
1227 Seek (Obj.Symstr_Stream, int64 (Second_Word));
1228 return Read (Obj.Symstr_Stream);
1231 -- Inlined symbol name
1232 Seek (Obj.Symtab_Stream, Sym.Off);
1233 return To_String_Ptr_Len (Read (Obj.Symtab_Stream), 8);
1244 package body XCOFF32_Ops is
1246 function Read_Section_Header
1247 (Obj : in out XCOFF32_Object_File;
1248 Index : uint32) return Section_Header;
1249 -- Read a header from section table
1255 function Read_Symbol
1256 (Obj : in out XCOFF32_Object_File;
1257 Off : Offset) return Object_Symbol
1260 Sz : constant Offset := Symbol_Entry'Size / SSU;
1262 Result : Object_Symbol;
1266 procedure Read_LD_Symbol;
1267 -- Read the next LD symbol
1269 --------------------
1270 -- Read_LD_Symbol --
1271 --------------------
1273 procedure Read_LD_Symbol is
1278 Read_Raw (Obj.Symtab_Stream, Sym'Address, uint32 (Sz));
1280 Noff := Noff + Offset (1 + Sym.n_numaux) * Sz;
1282 for J in 1 .. Sym.n_numaux loop
1283 Read_Raw (Obj.Symtab_Stream, Aux'Address, uint32 (Sz));
1286 exit when Noff >= Obj.Symtab_Last;
1288 exit when Sym.n_numaux = 1
1289 and then Sym.n_scnum /= 0
1290 and then (Sym.n_sclass = C_EXT
1291 or else Sym.n_sclass = C_HIDEXT
1292 or else Sym.n_sclass = C_WEAKEXT)
1293 and then Aux.x_smtyp = XTY_LD;
1297 -- Start of processing for Read_Symbol
1300 Seek (Obj.Symtab_Stream, Off);
1304 if Noff >= Obj.Symtab_Last then
1308 -- Construct the symbol
1310 Result := (Off => Sym_Off,
1312 Value => uint64 (Sym.n_value),
1315 -- Look for the next symbol to compute the size
1319 if Noff >= Obj.Symtab_Last then
1323 Result.Size := uint64 (Sym.n_value) - Result.Value;
1324 Result.Next := Sym_Off;
1332 function First_Symbol
1333 (Obj : in out XCOFF32_Object_File) return Object_Symbol
1336 -- Return Null_Symbol in the case that the symbol table is empty
1338 if Obj.Symtab_Last = 0 then
1342 return Read_Symbol (Obj, 0);
1352 In_Exception : Boolean) return XCOFF32_Object_File
1354 Res : XCOFF32_Object_File (Format => XCOFF32);
1358 Res.In_Exception := In_Exception;
1362 -- Map sections table
1363 Res.Num_Sections := uint32 (Hdr.f_nscns);
1364 Res.Sectab_Stream := Create_Stream
1366 File_Size (Header'Size / SSU) + File_Size (Hdr.f_opthdr),
1367 File_Size (Hdr.f_nscns) * (Section_Header'Size / SSU));
1369 -- Map symbols table
1370 Res.Symtab_Last := Offset (Hdr.f_nscns) * (Symbol_Entry'Size / SSU);
1371 Res.Symtab_Stream := Create_Stream
1373 File_Size (Hdr.f_symptr),
1374 File_Size (Res.Symtab_Last) + 4);
1377 Seek (Res.Symtab_Stream, Res.Symtab_Last);
1378 Strtab_Sz := Read (Res.Symtab_Stream);
1379 Res.Symstr_Stream := Create_Stream
1381 File_Size (Res.Symtab_Last) + 4,
1382 File_Size (Strtab_Sz) - 4);
1391 function Get_Section
1392 (Obj : in out XCOFF32_Object_File;
1393 Index : uint32) return Object_Section
1395 Sec : constant Section_Header := Read_Section_Header (Obj, Index);
1397 return (Index, Offset (Sec.s_scnptr),
1398 uint64 (Sec.s_vaddr),
1399 uint64 (Sec.s_size),
1400 (Sec.s_flags and STYP_TEXT) /= 0);
1407 function Read_Header (F : in out Mapped_Stream) return Header is
1411 Read_Raw (F, Hdr'Address, uint32 (Hdr'Size / SSU));
1415 -------------------------
1416 -- Read_Section_Header --
1417 -------------------------
1419 function Read_Section_Header
1420 (Obj : in out XCOFF32_Object_File;
1421 Index : uint32) return Section_Header
1423 Sec : Section_Header;
1426 -- Seek to the end of the object header
1428 Seek (Obj.Sectab_Stream, Offset (Index * Section_Header'Size / SSU));
1432 Read_Raw (Obj.Sectab_Stream, Sec'Address, Section_Header'Size / SSU);
1435 end Read_Section_Header;
1442 (Obj : in out XCOFF32_Object_File;
1443 Sec : Object_Section) return String
1445 Hdr : Section_Header;
1447 Hdr := Read_Section_Header (Obj, Sec.Num);
1448 return Trim_Trailing_Nuls (Hdr.s_name);
1456 (Obj : in out XCOFF32_Object_File;
1457 Sym : Object_Symbol) return String_Ptr_Len
1459 Symbol : Symbol_Entry;
1462 Seek (Obj.Symtab_Stream, Sym.Off);
1463 Read_Raw (Obj.Symtab_Stream, Symbol'Address, Symbol'Size / SSU);
1466 First_Word : uint32;
1467 pragma Import (Ada, First_Word);
1468 -- Suppress initialization in Normalized_Scalars mode
1469 for First_Word'Address use Symbol.n_name (1)'Address;
1471 Second_Word : uint32;
1472 pragma Import (Ada, Second_Word);
1473 -- Suppress initialization in Normalized_Scalars mode
1474 for Second_Word'Address use Symbol.n_name (5)'Address;
1477 if First_Word = 0 then
1478 if Second_Word = 0 then
1481 Seek (Obj.Symstr_Stream, int64 (Second_Word));
1482 return Read (Obj.Symstr_Stream);
1485 Seek (Obj.Symtab_Stream, Sym.Off);
1486 return To_String_Ptr_Len (Read (Obj.Symstr_Stream), 8);
1496 function Arch (Obj : Object_File) return Object_Arch is
1501 function Create_Stream
1503 File_Offset : File_Size;
1504 File_Length : File_Size)
1505 return Mapped_Stream
1507 Region : Mapped_Region;
1509 Read (Mf, Region, File_Offset, File_Length, False);
1510 return (Region, 0, Offset (File_Length));
1513 function Create_Stream
1515 Sec : Object_Section) return Mapped_Stream is
1517 return Create_Stream (Obj.Mf, File_Size (Sec.Off), File_Size (Sec.Size));
1520 procedure Tell (Obj : in out Mapped_Stream; Off : out Offset) is
1525 function Tell (Obj : Mapped_Stream) return Offset is
1530 function Length (Obj : Mapped_Stream) return Offset is
1539 procedure Close (S : in out Mapped_Stream) is
1544 procedure Close (Obj : in out Object_File) is
1546 Close (Obj.Symtab_Stream);
1547 Close (Obj.Symstr_Stream);
1548 Close (Obj.Sectab_Stream);
1552 Close (Obj.Secstr_Stream);
1562 ------------------------
1563 -- Strip_Leading_Char --
1564 ------------------------
1566 function Strip_Leading_Char
1567 (Obj : in out Object_File;
1568 Sym : String_Ptr_Len) return Positive is
1570 if (Obj.Format = PECOFF and then Sym.Ptr (1) = '_
')
1572 (Obj.Format = XCOFF32 and then Sym.Ptr (1) = '.')
1578 end Strip_Leading_Char;
1580 ----------------------
1581 -- Decoded_Ada_Name --
1582 ----------------------
1584 function Decoded_Ada_Name
1585 (Obj : in out Object_File;
1586 Sym : String_Ptr_Len) return String
1588 procedure gnat_decode
1589 (Coded_Name_Addr : Address;
1590 Ada_Name_Addr : Address;
1592 pragma Import (C, gnat_decode, "__gnat_decode");
1594 subtype size_t is Interfaces.C.size_t;
1596 Sym_Name : constant String :=
1597 String (Sym.Ptr (1 .. Sym.Len)) & ASCII.NUL;
1598 Decoded : char_array (0 .. size_t (Sym.Len) * 2 + 60);
1601 -- In the PECOFF case most but not all symbol table entries have an
1602 -- extra leading underscore. In this case we trim it.
1604 Off := Strip_Leading_Char (Obj, Sym);
1606 gnat_decode (Sym_Name (Off)'Address, Decoded'Address, 0);
1608 return To_Ada (Decoded);
1609 end Decoded_Ada_Name;
1615 function First_Symbol (Obj : in out Object_File) return Object_Symbol is
1618 when ELF32 => return ELF32_Ops.First_Symbol (Obj);
1619 when ELF64 => return ELF64_Ops.First_Symbol (Obj);
1620 when Any_PECOFF => return PECOFF_Ops.First_Symbol (Obj);
1621 when XCOFF32 => return XCOFF32_Ops.First_Symbol (Obj);
1629 function Format (Obj : Object_File) return Object_Format is
1634 ----------------------
1635 -- Get_Load_Address --
1636 ----------------------
1638 function Get_Load_Address (Obj : Object_File) return uint64 is
1640 raise Format_Error with "Get_Load_Address not implemented";
1642 end Get_Load_Address;
1648 function Get_Section
1649 (Obj : in out Object_File;
1650 Shnum : uint32) return Object_Section is
1653 when ELF32 => return ELF32_Ops.Get_Section (Obj, Shnum);
1654 when ELF64 => return ELF64_Ops.Get_Section (Obj, Shnum);
1655 when Any_PECOFF => return PECOFF_Ops.Get_Section (Obj, Shnum);
1656 when XCOFF32 => return XCOFF32_Ops.Get_Section (Obj, Shnum);
1660 function Get_Section
1661 (Obj : in out Object_File;
1662 Sec_Name : String) return Object_Section
1664 Sec : Object_Section;
1667 for J in 0 .. Obj.Num_Sections - 1 loop
1668 Sec := Get_Section (Obj, J);
1670 if Name (Obj, Sec) = Sec_Name then
1675 if Obj.In_Exception then
1676 return Null_Section;
1678 raise Format_Error with "could not find section in object file";
1682 -----------------------
1683 -- Get_Memory_Bounds --
1684 -----------------------
1686 procedure Get_Memory_Bounds
1687 (Obj : in out Object_File;
1688 Low, High : out uint64) is
1689 Sec : Object_Section;
1691 -- First set as an empty range
1693 High := uint64'First;
1695 for Idx in 1 .. Num_Sections (Obj) loop
1696 Sec := Get_Section (Obj, Idx - 1);
1697 if Sec.Flag_Alloc then
1698 if Sec.Addr < Low then
1701 if Sec.Addr + Sec.Size > High then
1702 High := Sec.Addr + Sec.Size;
1706 end Get_Memory_Bounds;
1713 (Obj : in out Object_File;
1714 Sec : Object_Section) return String is
1717 when ELF32 => return ELF32_Ops.Name (Obj, Sec);
1718 when ELF64 => return ELF64_Ops.Name (Obj, Sec);
1719 when Any_PECOFF => return PECOFF_Ops.Name (Obj, Sec);
1720 when XCOFF32 => return XCOFF32_Ops.Name (Obj, Sec);
1725 (Obj : in out Object_File;
1726 Sym : Object_Symbol) return String_Ptr_Len is
1729 when ELF32 => return ELF32_Ops.Name (Obj, Sym);
1730 when ELF64 => return ELF64_Ops.Name (Obj, Sym);
1731 when Any_PECOFF => return PECOFF_Ops.Name (Obj, Sym);
1732 when XCOFF32 => return XCOFF32_Ops.Name (Obj, Sym);
1740 function Next_Symbol
1741 (Obj : in out Object_File;
1742 Prev : Object_Symbol) return Object_Symbol is
1744 -- Test whether we've reached the end of the symbol table
1746 if Prev.Next >= Obj.Symtab_Last then
1750 return Read_Symbol (Obj, Prev.Next);
1757 function Num (Sec : Object_Section) return uint32 is
1766 function Num_Sections (Obj : Object_File) return uint32 is
1768 return Obj.Num_Sections;
1775 function Off (Sec : Object_Section) return Offset is
1780 function Off (Sym : Object_Symbol) return Offset is
1785 ----------------------
1786 -- Offset_To_String --
1787 ----------------------
1789 function Offset_To_String
1790 (S : in out Mapped_Stream;
1791 Off : Offset) return String
1796 Read_C_String (S, Buf);
1797 return To_String (Buf);
1798 end Offset_To_String;
1805 (File_Name : String;
1806 In_Exception : Boolean := False) return Object_File_Access
1809 Hdr_Stream : Mapped_Stream;
1814 F := Open_Read_No_Exception (File_Name);
1816 if F = Invalid_Mapped_File then
1817 if In_Exception then
1820 raise IO_Error with "could not open object file";
1824 Hdr_Stream := Create_Stream (F, 0, 4096);
1827 Hdr : constant ELF32_Ops.Header := ELF32_Ops.Read_Header (Hdr_Stream);
1830 -- Look for the magic numbers for the ELF case
1832 if Hdr.E_Ident (0) = 16#7F# and then
1833 Hdr.E_Ident (1) = Character'Pos ('E
') and then
1834 Hdr.E_Ident (2) = Character'Pos ('L
') and then
1835 Hdr.E_Ident (3) = Character'Pos ('F
') and then
1836 Hdr.E_Ident (4) = ELF32_Ops.ELFCLASS32
1839 return new Object_File'
1840 (ELF32_Ops
.Initialize
(F
, Hdr
, In_Exception
));
1845 Hdr
: constant ELF64_Ops
.Header
:=
1846 ELF64_Ops
.Read_Header
(Hdr_Stream
);
1849 -- Look for the magic numbers for the ELF case
1851 if Hdr
.E_Ident
(0) = 16#
7F#
and then
1852 Hdr
.E_Ident
(1) = Character'Pos ('E') and then
1853 Hdr
.E_Ident
(2) = Character'Pos ('L') and then
1854 Hdr
.E_Ident
(3) = Character'Pos ('F') and then
1855 Hdr
.E_Ident
(4) = ELF32_Ops
.ELFCLASS64
1858 return new Object_File
'
1859 (ELF64_Ops.Initialize (F, Hdr, In_Exception));
1864 Hdr : constant PECOFF_Ops.Header :=
1865 PECOFF_Ops.Read_Header (Hdr_Stream);
1868 -- Test the magic numbers
1870 if Hdr.Magics (0) = Character'Pos ('P
') and then
1871 Hdr.Magics (1) = Character'Pos ('E
') and then
1872 Hdr.Magics (2) = 0 and then
1876 return new Object_File'
1877 (PECOFF_Ops
.Initialize
(F
, Hdr
, In_Exception
));
1881 -- If this is not a PECOFF file then we've done a seek and read to a
1882 -- random address, possibly raising IO_Error
1889 Hdr
: constant XCOFF32_Ops
.Header
:=
1890 XCOFF32_Ops
.Read_Header
(Hdr_Stream
);
1893 -- Test the magic numbers
1895 if Hdr
.f_magic
= 8#
0737#
then
1897 return new Object_File
'
1898 (XCOFF32_Ops.Initialize (F, Hdr, In_Exception));
1904 if In_Exception then
1907 raise Format_Error with "unrecognized object format";
1915 function Read (S : in out Mapped_Stream) return Mmap.Str_Access
1917 function To_Str_Access is
1918 new Ada.Unchecked_Conversion (Address, Str_Access);
1920 return To_Str_Access (Data (S.Region) (Natural (S.Off + 1))'Address);
1923 function Read (S : in out Mapped_Stream) return String_Ptr_Len is
1925 return To_String_Ptr_Len (Read (S));
1928 procedure Check_Read_Offset (S : in out Mapped_Stream; Size : uint32) is
1930 if S.Off + Offset (Size) > Offset (Last (S.Region)) then
1931 raise IO_Error with "could not read from object file";
1933 end Check_Read_Offset;
1936 (S : in out Mapped_Stream;
1940 function To_Str_Access is
1941 new Ada.Unchecked_Conversion (Address, Str_Access);
1943 Sz : constant Offset := Offset (Size);
1947 pragma Debug (Check_Read_Offset (S, Size));
1951 To_Str_Access (Addr) (1 .. Positive (Sz)) :=
1952 Data (S.Region) (Positive (S.Off + 1) .. Positive (S.Off + Sz));
1956 S.Off := S.Off + Sz;
1959 function Read (S : in out Mapped_Stream) return uint8 is
1962 Read_Raw (S, Data'Address, Data'Size / SSU);
1966 function Read (S : in out Mapped_Stream) return uint16 is
1969 Read_Raw (S, Data'Address, Data'Size / SSU);
1973 function Read (S : in out Mapped_Stream) return uint32 is
1976 Read_Raw (S, Data'Address, Data'Size / SSU);
1980 function Read (S : in out Mapped_Stream) return uint64 is
1983 Read_Raw (S, Data'Address, Data'Size / SSU);
1987 function Read (S : in out Mapped_Stream) return int8 is
1990 Read_Raw (S, Data'Address, Data'Size / SSU);
1994 function Read (S : in out Mapped_Stream) return int16 is
1997 Read_Raw (S, Data'Address, Data'Size / SSU);
2001 function Read (S : in out Mapped_Stream) return int32 is
2004 Read_Raw (S, Data'Address, Data'Size / SSU);
2008 function Read (S : in out Mapped_Stream) return int64 is
2011 Read_Raw (S, Data'Address, Data'Size / SSU);
2019 function Read_Address
2020 (Obj : Object_File; S : in out Mapped_Stream) return uint64 is
2021 Address_32 : uint32;
2022 Address_64 : uint64;
2031 Address_32 := Read (S);
2032 return uint64 (Address_32);
2039 Address_64 := Read (S);
2043 raise Format_Error with "unrecognized machine architecture";
2051 procedure Read_C_String (S : in out Mapped_Stream; B : out Buffer) is
2056 -- Handle overflow case
2064 exit when B (J) = 0;
2073 function Read_C_String (S : in out Mapped_Stream) return Str_Access is
2074 Res : constant Str_Access := Read (S);
2077 for J in Res'Range loop
2078 if S.Off + Offset (J - 1) > Offset (Last (S.Region)) then
2079 raise IO_Error with "could not read from object file";
2082 if Res (J) = ASCII.NUL then
2083 S.Off := S.Off + Offset (J);
2089 raise Constraint_Error;
2096 function Read_LEB128 (S : in out Mapped_Stream) return uint32 is
2098 Shift : Integer := 0;
2104 Res := Res or Shift_Left (uint32 (B and 16#7f#), Shift);
2105 exit when (B and 16#80#) = 0;
2112 function Read_LEB128 (S : in out Mapped_Stream) return int32 is
2114 Shift : Integer := 0;
2120 Res := Res or Shift_Left (uint32 (B and 16#7f#), Shift);
2122 exit when (B and 16#80#) = 0;
2125 if Shift < 32 and then (Res and Shift_Left (1, Shift - 1)) /= 0 then
2126 Res := Res or Shift_Left (-1, Shift);
2129 return To_int32 (Res);
2136 function Read_Symbol
2137 (Obj : in out Object_File;
2138 Off : Offset) return Object_Symbol is
2141 when ELF32 => return ELF32_Ops.Read_Symbol (Obj, Off);
2142 when ELF64 => return ELF64_Ops.Read_Symbol (Obj, Off);
2143 when Any_PECOFF => return PECOFF_Ops.Read_Symbol (Obj, Off);
2144 when XCOFF32 => return XCOFF32_Ops.Read_Symbol (Obj, Off);
2152 procedure Seek (S : in out Mapped_Stream; Off : Offset) is
2154 if Off < 0 or else Off > Offset (Last (S.Region)) then
2155 raise IO_Error with "could not seek to offset in object file";
2165 function Size (Sec : Object_Section) return uint64 is
2170 function Size (Sym : Object_Symbol) return uint64 is
2179 function Strlen (Buf : Buffer) return int32 is
2181 return int32 (CRTL.strlen (Buf'Address));
2188 function Spans (Sym : Object_Symbol; Addr : uint64) return Boolean is
2190 return Addr >= Sym.Value and then Addr < Sym.Value + Sym.Size;
2197 function To_String (Buf : Buffer) return String is
2198 Result : String (1 .. Integer (CRTL.strlen (Buf'Address)));
2199 for Result'Address use Buf'Address;
2200 pragma Import (Ada, Result);
2206 -----------------------
2207 -- To_String_Ptr_Len --
2208 -----------------------
2210 function To_String_Ptr_Len
2211 (Ptr : Mmap.Str_Access;
2212 Max_Len : Natural := Natural'Last) return String_Ptr_Len is
2214 for I in 1 .. Max_Len loop
2215 if Ptr (I) = ASCII.NUL then
2216 return (Ptr, I - 1);
2219 return (Ptr, Max_Len);
2220 end To_String_Ptr_Len;
2222 ------------------------
2223 -- Trim_Trailing_Nuls --
2224 ------------------------
2226 function Trim_Trailing_Nuls (Str : String) return String is
2228 for J in Str'Range loop
2229 if Str (J) = ASCII.NUL then
2230 return Str (Str'First .. J - 1);
2235 end Trim_Trailing_Nuls;
2241 function Value (Sym : Object_Symbol) return uint64 is
2246 end System.Object_Reader;