Autofill: Add WalletIntegrationAvailable() to components.
[chromium-blink-merge.git] / native_client_sdk / src / tools / lib / elf.py
blob84519de544e1a192432a1a3ce0b2ba84d768c72e
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"""
7 import struct
10 class Error(Exception):
11 '''Local Error class for this file.'''
12 pass
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.
19 """
20 # From elf.h:
21 # typedef struct
22 # {
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 */
26 # ...
27 # } Elf32_Ehdr;
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)
34 try:
35 header = struct.unpack(elf_header_format, header)
36 except struct.error:
37 raise Error("error parsing elf header: %s" % path)
38 e_ident, _, e_machine = header[:3]
40 elf_magic = '\x7fELF'
41 if e_ident[:4] != elf_magic:
42 raise Error('Not a valid NaCl executable: %s' % path)
44 e_machine_mapping = {
45 3 : 'x86-32',
46 8 : 'mips32',
47 40 : 'arm',
48 62 : 'x86-64'
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')
58 return arch, dynamic
61 def IsDynamicElf(path, is64bit):
62 """Examine an elf file to determine if it is dynamically
63 linked or not.
64 This is determined by searching the program headers for
65 a header of type PT_INTERP.
66 """
67 if is64bit:
68 elf_header_format = '16s2HI3QI3H'
69 else:
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.
85 # typedef struct
86 # {
87 # Elf32_Word p_type; /* Segment type */
88 # ...
89 # } Elf32_Phdr;
90 elf_phdr_format = 'I'
91 PT_INTERP = 3
93 while p_headers:
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:
98 return True
100 return False