1#
2# Copyright (C) 2018 The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#      http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16"""This file contains ELF C structs and data types."""
17
18import ctypes
19
20from vts.utils.python.library.elf import consts
21
22
23# ELF data types.
24
25
26Elf32_Addr = ctypes.c_uint32
27Elf32_Off = ctypes.c_uint32
28Elf32_Half = ctypes.c_uint16
29Elf32_Word = ctypes.c_uint32
30Elf32_Sword = ctypes.c_int32
31
32Elf64_Addr = ctypes.c_uint64
33Elf64_Off = ctypes.c_uint64
34Elf64_Half = ctypes.c_uint16
35Elf64_Word = ctypes.c_uint32
36Elf64_Sword = ctypes.c_int32
37Elf64_Xword = ctypes.c_uint64
38Elf64_Sxword = ctypes.c_int64
39
40
41# ELF C structs.
42
43
44class CStructure(ctypes.LittleEndianStructure):
45    """Little endian C structure base class."""
46    pass
47
48
49class CUnion(ctypes.Union):
50    """Native endian C union base class."""
51    pass
52
53
54class _Ehdr(CStructure):
55    """ELF header base class."""
56
57    def GetFileClass(self):
58        """Returns the file class."""
59        return self.e_ident[consts.EI_CLASS]
60
61    def GetDataEncoding(self):
62        """Returns the data encoding of the file."""
63        return self.e_ident[consts.EI_DATA]
64
65
66class Elf32_Ehdr(_Ehdr):
67    """ELF 32-bit header."""
68    _fields_ = [('e_ident', ctypes.c_uint8 * consts.EI_NIDENT),
69                ('e_type', Elf32_Half),
70                ('e_machine', Elf32_Half),
71                ('e_version', Elf32_Word),
72                ('e_entry', Elf32_Addr),
73                ('e_phoff', Elf32_Off),
74                ('e_shoff', Elf32_Off),
75                ('e_flags', Elf32_Word),
76                ('e_ehsize', Elf32_Half),
77                ('e_phentsize', Elf32_Half),
78                ('e_phnum', Elf32_Half),
79                ('e_shentsize', Elf32_Half),
80                ('e_shnum', Elf32_Half),
81                ('e_shstrndx', Elf32_Half)]
82
83
84class Elf64_Ehdr(_Ehdr):
85    """ELF 64-bit header."""
86    _fields_ = [('e_ident', ctypes.c_uint8 * consts.EI_NIDENT),
87                ('e_type', Elf64_Half),
88                ('e_machine', Elf64_Half),
89                ('e_version', Elf64_Word),
90                ('e_entry', Elf64_Addr),
91                ('e_phoff', Elf64_Off),
92                ('e_shoff', Elf64_Off),
93                ('e_flags', Elf64_Word),
94                ('e_ehsize', Elf64_Half),
95                ('e_phentsize', Elf64_Half),
96                ('e_phnum', Elf64_Half),
97                ('e_shentsize', Elf64_Half),
98                ('e_shnum', Elf64_Half),
99                ('e_shstrndx', Elf64_Half)]
100
101
102class Elf32_Shdr(CStructure):
103    """ELF 32-bit section header."""
104    _fields_ = [('sh_name', Elf32_Word),
105                ('sh_type', Elf32_Word),
106                ('sh_flags', Elf32_Word),
107                ('sh_addr', Elf32_Addr),
108                ('sh_offset', Elf32_Off),
109                ('sh_size', Elf32_Word),
110                ('sh_link', Elf32_Word),
111                ('sh_info', Elf32_Word),
112                ('sh_addralign', Elf32_Word),
113                ('sh_entsize', Elf32_Word)]
114
115
116class Elf64_Shdr(CStructure):
117    """ELF 64-bit section header."""
118    _fields_ = [('sh_name', Elf64_Word),
119                ('sh_type', Elf64_Word),
120                ('sh_flags', Elf64_Xword),
121                ('sh_addr', Elf64_Addr),
122                ('sh_offset', Elf64_Off),
123                ('sh_size', Elf64_Xword),
124                ('sh_link', Elf64_Word),
125                ('sh_info', Elf64_Word),
126                ('sh_addralign', Elf64_Xword),
127                ('sh_entsize', Elf64_Xword)]
128
129
130class Elf32_Dyn(CStructure):
131    """ELF 32-bit dynamic section entry."""
132    class _Elf32_Dyn__d_un(CUnion):
133        _fields_ = [('d_val', Elf32_Word),
134                    ('d_ptr', Elf32_Addr)]
135    _fields_ = [('d_tag', Elf32_Sword),
136                ('d_un', _Elf32_Dyn__d_un)]
137
138
139class Elf64_Dyn(CStructure):
140    """ELF 64-bit dynamic section entry."""
141    class _Elf64_Dyn__d_un(CUnion):
142        _fields_ = [('d_val', Elf64_Xword),
143                    ('d_ptr', Elf64_Addr)]
144    _fields_ = [('d_tag', Elf64_Sxword),
145                ('d_un', _Elf64_Dyn__d_un)]
146
147
148class _Sym(CStructure):
149    """ELF symbol table entry base class."""
150
151    def GetBinding(self):
152        """Returns the symbol binding."""
153        return self.st_info >> 4
154
155    def GetType(self):
156        """Returns the symbol type."""
157        return self.st_info & 0xf
158
159    def SetBinding(self, binding):
160        """Sets the symbol binding.
161
162        Args:
163            binding: An integer specifying the new binding.
164        """
165        self.SetSymbolAndType(binding, self.GetType())
166
167    def SetType(self, type_):
168        """Sets the symbol type.
169
170        Args:
171            type_: An integer specifying the new type.
172        """
173        self.SetSymbolAndType(self.GetBinding(), type_)
174
175    def SetBindingAndType(self, binding, type_):
176        """Sets the symbol binding and type.
177
178        Args:
179            binding: An integer specifying the new binding.
180            type_: An integer specifying the new type.
181        """
182        self.st_info = (binding << 4) | (type_ & 0xf)
183
184
185class Elf32_Sym(_Sym):
186    """ELF 32-bit symbol table entry."""
187    _fields_ = [('st_name', Elf32_Word),
188                ('st_value', Elf32_Addr),
189                ('st_size', Elf32_Word),
190                ('st_info', ctypes.c_uint8),
191                ('st_other', ctypes.c_uint8),
192                ('st_shndx', Elf32_Half)]
193
194
195class Elf64_Sym(_Sym):
196    """ELF 64-bit symbol table entry."""
197    _fields_ = [('st_name', Elf64_Word),
198                ('st_info', ctypes.c_uint8),
199                ('st_other', ctypes.c_uint8),
200                ('st_shndx', Elf64_Half),
201                ('st_value', Elf64_Addr),
202                ('st_size', Elf64_Xword)]
203
204
205class _32_Rel(CStructure):
206    """ELF 32-bit relocation table entry base class."""
207
208    def GetSymbol(self):
209        """Returns the symbol table index with respect to the relocation.
210
211        Symbol table index with respect to which the relocation must be made.
212        """
213        return self.r_info >> 8
214
215    def GetType(self):
216        """Returns the relocation type."""
217        return self.r_info & 0xff
218
219    def SetSymbol(self, symndx):
220        """Sets the relocation's symbol table index.
221
222        Args:
223            symndx: An integer specifying the new symbol table index.
224        """
225        self.SetSymbolAndType(symndx, self.GetType())
226
227    def SetType(self, type_):
228        """Sets the relocation type.
229
230        Args:
231            type_: An integer specifying the new relocation type.
232        """
233        self.SetSymbolAndType(self.GetSymbol(), type_)
234
235    def SetSymbolAndType(self, symndx, type_):
236        """Sets the relocation's symbol table index and type.
237
238        Args:
239            symndx: An integer specifying the new symbol table index.
240            type_: An integer specifying the new relocation type.
241        """
242        self.r_info = (symndx << 8) | (type_ & 0xff)
243
244
245class Elf32_Rel(_32_Rel):
246    """ELF 32-bit relocation table entry."""
247    _fields_ = [('r_offset', Elf32_Addr),
248                ('r_info', Elf32_Word)]
249
250
251class Elf32_Rela(_32_Rel):
252    """ELF 32-bit relocation table entry with explicit addend."""
253    _fields_ = [('r_offset', Elf32_Addr),
254                ('r_info', Elf32_Word),
255                ('r_addend', Elf32_Sword)]
256
257
258class _64_Rel(CStructure):
259    """ELF 64-bit relocation table entry base class."""
260
261    def GetSymbol(self):
262        """Returns the symbol table index with respect to the relocation.
263
264        Symbol table index with respect to which the relocation must be made.
265        """
266        return self.r_info >> 32
267
268    def GetType(self):
269        """Returns the relocation type."""
270        return self.r_info & 0xffffffff
271
272    def SetSymbol(self, symndx):
273        """Sets the relocation's symbol table index.
274
275        Args:
276            symndx: An integer specifying the new symbol table index.
277        """
278        self.SetSymbolAndType(symndx, self.GetType())
279
280    def SetType(self, type_):
281        """Sets the relocation type.
282
283        Args:
284            type_: An integer specifying the new relocation type.
285        """
286        self.SetSymbolAndType(self.GetSymbol(), type_)
287
288    def SetSymbolAndType(self, symndx, type_):
289        """Sets the relocation's symbol table index and type.
290
291        Args:
292            symndx: An integer specifying the new symbol table index.
293            type_: An integer specifying the new relocation type.
294        """
295        self.r_info = (symndx << 32) | (type_ & 0xffffffff)
296
297
298class Elf64_Rel(_64_Rel):
299    """ELF 64-bit relocation table entry."""
300    _fields_ = [('r_offset', Elf64_Addr),
301                ('r_info', Elf64_Xword)]
302
303
304class Elf64_Rela(_64_Rel):
305    """ELF 64-bit relocation table entry with explicit addend."""
306    _fields_ = [('r_offset', Elf64_Addr),
307                ('r_info', Elf64_Xword),
308                ('r_addend', Elf64_Sxword)]
309
310
311class Elf32_Phdr(CStructure):
312    """ELF 32-bit program header."""
313    _fields_ = [('p_type', Elf32_Word),
314                ('p_offset', Elf32_Off),
315                ('p_vaddr', Elf32_Addr),
316                ('p_paddr', Elf32_Addr),
317                ('p_filesz', Elf32_Word),
318                ('p_memsz', Elf32_Word),
319                ('p_flags', Elf32_Word),
320                ('p_align', Elf32_Word)]
321
322
323class Elf64_Phdr(CStructure):
324    """ELF 64-bit program header."""
325    _fields_ = [('p_type', Elf64_Word),
326                ('p_flags', Elf64_Word),
327                ('p_offset', Elf64_Off),
328                ('p_vaddr', Elf64_Addr),
329                ('p_paddr', Elf64_Addr),
330                ('p_filesz', Elf64_Xword),
331                ('p_memsz', Elf64_Xword),
332                ('p_align', Elf64_Xword)]
333
334
335class Elf32_Nhdr(CStructure):
336    """ELF 32-bit note header."""
337    _fields_ = [('n_namesz', Elf32_Word),
338                ('n_descsz', Elf32_Word),
339                ('n_type', Elf32_Word)]
340
341
342class Elf64_Nhdr(CStructure):
343    """ELF 64-bit note header."""
344    _fields_ = [('n_namesz', Elf64_Word),
345                ('n_descsz', Elf64_Word),
346                ('n_type', Elf64_Word)]
347