-
Notifications
You must be signed in to change notification settings - Fork 97
/
elf.py
93 lines (74 loc) · 3.1 KB
/
elf.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# Copyright (C) 2017 Linaro Limited
# Author: Milo Casagrande <milo.casagrande@linaro.org>
# Author: Matt Hart <matthew.hart@linaro.org>
#
# Copyright (C) 2017 Baylibre SAS
# Author: Kevin Hilman <khilman@baylibre.com>
#
# This module is free software; you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation; either version 2.1 of the License, or (at your option)
# any later version.
#
# This library is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
"""Open the ELF file and read some of its content."""
import elftools.elf.constants as elfconst
import elftools.elf.elffile as elffile
import io
import os
# Default section names and their build document keys to look in the ELF file.
# These are supposed to always be available.
DEFAULT_ELF_SECTIONS = [
(".bss", "vmlinux_bss_size"),
(".text", "vmlinux_text_size")
]
# Write/Alloc & Alloc constant we need to check for in the ELF sections.
ELF_WA_FLAG = elfconst.SH_FLAGS.SHF_WRITE | elfconst.SH_FLAGS.SHF_ALLOC
ELF_A_FLAG = elfconst.SH_FLAGS.SHF_ALLOC
def calculate_data_size(elf_file):
"""Loop through the ELF file sections and compute the .data size.
It will look for all SHT_PROGBITS type sections that have the
SHF_ALLOC or SHF_ALLOC+SHF_WRITE flag set and sum their sizes.
:param elf_file: The open ELF file.
:return The .data size or 0.
"""
data_size = 0
for section in elf_file.iter_sections():
elf_flags = section["sh_flags"]
if all([section["sh_type"] == "SHT_PROGBITS",
any([elf_flags == ELF_WA_FLAG, elf_flags == ELF_A_FLAG])]):
data_size += section["sh_size"]
return data_size
def read(path):
"""Read a vmlinux file and extract some info from it.
Update the build document in place.
Info extracted:
0. Size of the .text section.
1. Size of the .data section.
2. Size of the .bss section.
:param path: The path to the vmlinux file.
:type path: str
:return A dictionary with the extracted values.
"""
extracted = {}
if os.path.isfile(path):
with io.open(path, mode="rb") as vmlinux_strm:
elf_file = elffile.ELFFile(vmlinux_strm)
for elf_sect in DEFAULT_ELF_SECTIONS:
sect = elf_file.get_section_by_name(elf_sect[0])
if sect:
extracted[elf_sect[1]] = sect["sh_size"]
data_sect = elf_file.get_section_by_name(".data")
if data_sect:
extracted["vmlinux_data_size"] = data_sect["sh_size"]
else:
extracted["vmlinux_data_size"] = \
calculate_data_size(elf_file)
return extracted