1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
5 """Helper script for extracting information from ELF files"""
10 class Error(Exception):
11 '''Local Error class for this file.'''
15 def ParseElfHeader(path
):
16 """Determine properties of a nexe by parsing elf header.
17 Return tuple of architecture and boolean signalling whether
18 the executable is dynamic (has INTERP header) or static.
23 # unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
24 # Elf64_Half e_type; /* Object file type */
25 # Elf64_Half e_machine; /* Architecture */
28 elf_header_format
= '16s2H'
29 elf_header_size
= struct
.calcsize(elf_header_format
)
31 with
open(path
, 'rb') as f
:
32 header
= f
.read(elf_header_size
)
35 header
= struct
.unpack(elf_header_format
, header
)
37 raise Error("error parsing elf header: %s" % path
)
38 e_ident
, _
, e_machine
= header
[:3]
41 if e_ident
[:4] != elf_magic
:
42 raise Error('Not a valid NaCl executable: %s' % path
)
50 if e_machine
not in e_machine_mapping
:
51 raise Error('Unknown machine type: %s' % e_machine
)
53 # Set arch based on the machine type in the elf header
54 arch
= e_machine_mapping
[e_machine
]
56 # Now read the full header in either 64bit or 32bit mode
57 dynamic
= IsDynamicElf(path
, arch
== 'x86-64')
61 def IsDynamicElf(path
, is64bit
):
62 """Examine an elf file to determine if it is dynamically
64 This is determined by searching the program headers for
65 a header of type PT_INTERP.
68 elf_header_format
= '16s2HI3QI3H'
70 elf_header_format
= '16s2HI3II3H'
72 elf_header_size
= struct
.calcsize(elf_header_format
)
74 with
open(path
, 'rb') as f
:
75 header
= f
.read(elf_header_size
)
76 header
= struct
.unpack(elf_header_format
, header
)
77 p_header_offset
= header
[5]
78 p_header_entry_size
= header
[9]
79 num_p_header
= header
[10]
80 f
.seek(p_header_offset
)
81 p_headers
= f
.read(p_header_entry_size
*num_p_header
)
83 # Read the first word of each Phdr to find out its type.
87 # Elf32_Word p_type; /* Segment type */
94 p_header
= p_headers
[:p_header_entry_size
]
95 p_headers
= p_headers
[p_header_entry_size
:]
96 phdr_type
= struct
.unpack(elf_phdr_format
, p_header
[:4])[0]
97 if phdr_type
== PT_INTERP
: