1 #-------------------------------------------------------------------------------
2 # elftools: elf/relocation.py
6 # Eli Bendersky (eliben@gmail.com)
7 # This code is in the public domain
8 #-------------------------------------------------------------------------------
9 from collections
import namedtuple
11 from ..common
.exceptions
import ELFRelocationError
12 from ..common
.utils
import elf_assert
, struct_parse
13 from .sections
import Section
15 ENUM_RELOC_TYPE_i386
, ENUM_RELOC_TYPE_x64
, ENUM_RELOC_TYPE_MIPS
,
16 ENUM_RELOC_TYPE_ARM
, ENUM_RELOC_TYPE_AARCH64
, ENUM_RELOC_TYPE_PPC64
,
17 ENUM_RELOC_TYPE_S390X
, ENUM_RELOC_TYPE_BPF
, ENUM_RELOC_TYPE_LOONGARCH
,
19 from ..construct
import Container
22 class Relocation(object):
23 """ Relocation object - representing a single relocation entry. Allows
24 dictionary-like access to the entry's fields.
26 Can be either a REL or RELA relocation.
28 def __init__(self
, entry
, elffile
):
30 self
.elffile
= elffile
33 """ Is this a RELA relocation? If not, it's REL.
35 return 'r_addend' in self
.entry
37 def __getitem__(self
, name
):
38 """ Dict-like access to entries
40 return self
.entry
[name
]
43 return '<Relocation (%s): %s>' % (
44 'RELA' if self
.is_RELA() else 'REL',
48 return self
.__repr
__()
51 class RelocationTable(object):
52 """ Shared functionality between relocation sections and relocation tables
55 def __init__(self
, elffile
, offset
, size
, is_rela
):
56 self
._stream
= elffile
.stream
57 self
._elffile
= elffile
58 self
._elfstructs
= elffile
.structs
61 self
._is
_rela
= is_rela
64 self
.entry_struct
= self
._elfstructs
.Elf_Rela
66 self
.entry_struct
= self
._elfstructs
.Elf_Rel
68 self
.entry_size
= self
.entry_struct
.sizeof()
71 """ Is this a RELA relocation section? If not, it's REL.
75 def num_relocations(self
):
76 """ Number of relocations in the section
78 return self
._size
// self
.entry_size
80 def get_relocation(self
, n
):
81 """ Get the relocation at index #n from the section (Relocation object)
83 entry_offset
= self
._offset
+ n
* self
.entry_size
87 stream_pos
=entry_offset
)
88 return Relocation(entry
, self
._elffile
)
90 def iter_relocations(self
):
91 """ Yield all the relocations in the section
93 for i
in range(self
.num_relocations()):
94 yield self
.get_relocation(i
)
97 class RelocationSection(Section
, RelocationTable
):
98 """ ELF relocation section. Serves as a collection of Relocation entries.
100 def __init__(self
, header
, name
, elffile
):
101 Section
.__init
__(self
, header
, name
, elffile
)
102 RelocationTable
.__init
__(self
, self
.elffile
,
103 self
['sh_offset'], self
['sh_size'], header
['sh_type'] == 'SHT_RELA')
105 elf_assert(header
['sh_type'] in ('SHT_REL', 'SHT_RELA'),
106 'Unknown relocation type section')
107 elf_assert(header
['sh_entsize'] == self
.entry_size
,
108 'Expected sh_entsize of %s section to be %s' % (
109 header
['sh_type'], self
.entry_size
))
112 class RelrRelocationTable(object):
113 """ RELR compressed relocation table. This stores relative relocations
114 in a compressed format. An entry with an even value serves as an
115 'anchor' that defines a base address. Following this entry are one or
116 more bitmaps for consecutive addresses after the anchor which determine
117 if the corresponding relocation exists (if the bit is 1) or if it is
118 skipped. Addends are stored at the respective addresses (as in REL
122 def __init__(self
, elffile
, offset
, size
, entrysize
):
123 self
._elffile
= elffile
124 self
._offset
= offset
126 self
._relr
_struct
= self
._elffile
.structs
.Elf_Relr
127 self
._entrysize
= self
._relr
_struct
.sizeof()
128 self
._cached
_relocations
= None
130 elf_assert(self
._entrysize
== entrysize
,
131 'Expected RELR entry size to be %s, got %s' % (
132 self
._entrysize
, entrysize
))
134 def iter_relocations(self
):
135 """ Yield all the relocations in the section
138 # If DT_RELRSZ is zero, offset is meaningless and could be None.
142 limit
= self
._offset
+ self
._size
144 # The addresses of relocations in a bitmap are calculated from a base
145 # value provided in an initial 'anchor' relocation.
148 entry
= struct_parse(self
._relr
_struct
,
149 self
._elffile
.stream
,
151 entry_offset
= entry
['r_offset']
152 if (entry_offset
& 1) == 0:
153 # We found an anchor, take the current value as the base address
154 # for the following bitmaps and move the 'where' pointer to the
155 # beginning of the first bitmap.
157 base
+= self
._entrysize
158 yield Relocation(entry
, self
._elffile
)
160 # We're processing a bitmap.
161 elf_assert(base
is not None, 'RELR bitmap without base address')
164 # Iterate over all bits except the least significant one.
165 entry_offset
= (entry_offset
>> 1)
166 if entry_offset
== 0:
168 # if the current LSB is set, we have a relocation at the
169 # corresponding address so generate a Relocation with the
171 if (entry_offset
& 1) != 0:
172 calc_offset
= base
+ i
* self
._entrysize
173 yield Relocation(Container(r_offset
= calc_offset
),
176 # Advance 'base' past the current bitmap (8 == CHAR_BIT). There
177 # are 63 (or 31 for 32-bit ELFs) entries in each bitmap, and
178 # every bit corresponds to an ELF_addr-sized relocation.
179 base
+= (8 * self
._entrysize
- 1) * self
._elffile
.structs
.Elf_addr('').sizeof()
180 # Advance to the next entry
181 relr
+= self
._entrysize
183 def num_relocations(self
):
184 """ Number of relocations in the section
186 if self
._cached
_relocations
is None:
187 self
._cached
_relocations
= list(self
.iter_relocations())
188 return len(self
._cached
_relocations
)
190 def get_relocation(self
, n
):
191 """ Get the relocation at index #n from the section (Relocation object)
193 if self
._cached
_relocations
is None:
194 self
._cached
_relocations
= list(self
.iter_relocations())
195 return self
._cached
_relocations
[n
]
198 class RelrRelocationSection(Section
, RelrRelocationTable
):
199 """ ELF RELR relocation section. Serves as a collection of RELR relocation entries.
201 def __init__(self
, header
, name
, elffile
):
202 Section
.__init
__(self
, header
, name
, elffile
)
203 RelrRelocationTable
.__init
__(self
, self
.elffile
,
204 self
['sh_offset'], self
['sh_size'], self
['sh_entsize'])
207 class RelocationHandler(object):
208 """ Handles the logic of relocations in ELF files.
210 def __init__(self
, elffile
):
211 self
.elffile
= elffile
213 def find_relocations_for_section(self
, section
):
214 """ Given a section, find the relocation section for it in the ELF
215 file. Return a RelocationSection object, or None if none was
218 reloc_section_names
= (
219 '.rel' + section
.name
,
220 '.rela' + section
.name
)
221 # Find the relocation section aimed at this one. Currently assume
222 # that either .rel or .rela section exists for this section, but
224 for relsection
in self
.elffile
.iter_sections():
225 if ( isinstance(relsection
, RelocationSection
) and
226 relsection
.name
in reloc_section_names
):
230 def apply_section_relocations(self
, stream
, reloc_section
):
231 """ Apply all relocations in reloc_section (a RelocationSection object)
232 to the given stream, that contains the data of the section that is
233 being relocated. The stream is modified as a result.
235 # The symbol table associated with this relocation section
236 symtab
= self
.elffile
.get_section(reloc_section
['sh_link'])
237 for reloc
in reloc_section
.iter_relocations():
238 self
._do
_apply
_relocation
(stream
, reloc
, symtab
)
240 def _do_apply_relocation(self
, stream
, reloc
, symtab
):
241 # Preparations for performing the relocation: obtain the value of
242 # the symbol mentioned in the relocation, as well as the relocation
243 # recipe which tells us how to actually perform it.
244 # All peppered with some sanity checking.
245 if reloc
['r_info_sym'] >= symtab
.num_symbols():
246 raise ELFRelocationError(
247 'Invalid symbol reference in relocation: index %s' % (
248 reloc
['r_info_sym']))
249 sym_value
= symtab
.get_symbol(reloc
['r_info_sym'])['st_value']
251 reloc_type
= reloc
['r_info_type']
254 if self
.elffile
.get_machine_arch() == 'x86':
256 raise ELFRelocationError(
257 'Unexpected RELA relocation for x86: %s' % reloc
)
258 recipe
= self
._RELOCATION
_RECIPES
_X
86.get(reloc_type
, None)
259 elif self
.elffile
.get_machine_arch() == 'x64':
260 if not reloc
.is_RELA():
261 raise ELFRelocationError(
262 'Unexpected REL relocation for x64: %s' % reloc
)
263 recipe
= self
._RELOCATION
_RECIPES
_X
64.get(reloc_type
, None)
264 elif self
.elffile
.get_machine_arch() == 'MIPS':
266 if reloc_type
== ENUM_RELOC_TYPE_MIPS
['R_MIPS_64']:
267 if reloc
['r_type2'] != 0 or reloc
['r_type3'] != 0 or reloc
['r_ssym'] != 0:
268 raise ELFRelocationError(
269 'Multiple relocations in R_MIPS_64 are not implemented: %s' % reloc
)
270 recipe
= self
._RELOCATION
_RECIPES
_MIPS
_RELA
.get(reloc_type
, None)
272 recipe
= self
._RELOCATION
_RECIPES
_MIPS
_REL
.get(reloc_type
, None)
273 elif self
.elffile
.get_machine_arch() == 'ARM':
275 raise ELFRelocationError(
276 'Unexpected RELA relocation for ARM: %s' % reloc
)
277 recipe
= self
._RELOCATION
_RECIPES
_ARM
.get(reloc_type
, None)
278 elif self
.elffile
.get_machine_arch() == 'AArch64':
279 recipe
= self
._RELOCATION
_RECIPES
_AARCH
64.get(reloc_type
, None)
280 elif self
.elffile
.get_machine_arch() == '64-bit PowerPC':
281 recipe
= self
._RELOCATION
_RECIPES
_PPC
64.get(reloc_type
, None)
282 elif self
.elffile
.get_machine_arch() == 'IBM S/390':
283 recipe
= self
._RELOCATION
_RECIPES
_S
390X
.get(reloc_type
, None)
284 elif self
.elffile
.get_machine_arch() == 'Linux BPF - in-kernel virtual machine':
285 recipe
= self
._RELOCATION
_RECIPES
_EBPF
.get(reloc_type
, None)
286 elif self
.elffile
.get_machine_arch() == 'LoongArch':
287 if not reloc
.is_RELA():
288 raise ELFRelocationError(
289 'Unexpected REL relocation for LoongArch: %s' % reloc
)
290 recipe
= self
._RELOCATION
_RECIPES
_LOONGARCH
.get(reloc_type
, None)
293 raise ELFRelocationError(
294 'Unsupported relocation type: %s' % reloc_type
)
296 # So now we have everything we need to actually perform the relocation.
299 # 0. Find out which struct we're going to be using to read this value
300 # from the stream and write it back.
301 if recipe
.bytesize
== 4:
302 value_struct
= self
.elffile
.structs
.Elf_word('')
303 elif recipe
.bytesize
== 8:
304 value_struct
= self
.elffile
.structs
.Elf_word64('')
305 elif recipe
.bytesize
== 1:
306 value_struct
= self
.elffile
.structs
.Elf_byte('')
307 elif recipe
.bytesize
== 2:
308 value_struct
= self
.elffile
.structs
.Elf_half('')
310 raise ELFRelocationError('Invalid bytesize %s for relocation' %
313 # 1. Read the value from the stream (with correct size and endianness)
314 original_value
= struct_parse(
317 stream_pos
=reloc
['r_offset'])
318 # 2. Apply the relocation to the value, acting according to the recipe
319 relocated_value
= recipe
.calc_func(
320 value
=original_value
,
322 offset
=reloc
['r_offset'],
323 addend
=reloc
['r_addend'] if recipe
.has_addend
else 0)
324 # 3. Write the relocated value back into the stream
325 stream
.seek(reloc
['r_offset'])
327 # Make sure the relocated value fits back by wrapping it around. This
328 # looks like a problem, but it seems to be the way this is done in
330 relocated_value
= relocated_value
% (2 ** (recipe
.bytesize
* 8))
331 value_struct
.build_stream(relocated_value
, stream
)
333 # Relocations are represented by "recipes". Each recipe specifies:
334 # bytesize: The number of bytes to read (and write back) to the section.
335 # This is the unit of data on which relocation is performed.
336 # has_addend: Does this relocation have an extra addend?
337 # calc_func: A function that performs the relocation on an extracted
338 # value, and returns the updated value.
340 _RELOCATION_RECIPE_TYPE
= namedtuple('_RELOCATION_RECIPE_TYPE',
341 'bytesize has_addend calc_func')
343 def _reloc_calc_identity(value
, sym_value
, offset
, addend
=0):
346 def _reloc_calc_sym_plus_value(value
, sym_value
, offset
, addend
=0):
347 return sym_value
+ value
+ addend
349 def _reloc_calc_sym_plus_value_pcrel(value
, sym_value
, offset
, addend
=0):
350 return sym_value
+ value
- offset
352 def _reloc_calc_sym_plus_addend(value
, sym_value
, offset
, addend
=0):
353 return sym_value
+ addend
355 def _reloc_calc_sym_plus_addend_pcrel(value
, sym_value
, offset
, addend
=0):
356 return sym_value
+ addend
- offset
358 def _reloc_calc_value_minus_sym_addend(value
, sym_value
, offset
, addend
=0):
359 return value
- sym_value
- addend
361 def _arm_reloc_calc_sym_plus_value_pcrel(value
, sym_value
, offset
, addend
=0):
362 return sym_value
// 4 + value
- offset
// 4
364 def _bpf_64_32_reloc_calc_sym_plus_addend(value
, sym_value
, offset
, addend
=0):
365 return (sym_value
+ addend
) // 8 - 1
367 _RELOCATION_RECIPES_ARM
= {
368 ENUM_RELOC_TYPE_ARM
['R_ARM_ABS32']: _RELOCATION_RECIPE_TYPE(
369 bytesize
=4, has_addend
=False,
370 calc_func
=_reloc_calc_sym_plus_value
),
371 ENUM_RELOC_TYPE_ARM
['R_ARM_CALL']: _RELOCATION_RECIPE_TYPE(
372 bytesize
=4, has_addend
=False,
373 calc_func
=_arm_reloc_calc_sym_plus_value_pcrel
),
376 _RELOCATION_RECIPES_AARCH64
= {
377 ENUM_RELOC_TYPE_AARCH64
['R_AARCH64_ABS64']: _RELOCATION_RECIPE_TYPE(
378 bytesize
=8, has_addend
=True, calc_func
=_reloc_calc_sym_plus_addend
),
379 ENUM_RELOC_TYPE_AARCH64
['R_AARCH64_ABS32']: _RELOCATION_RECIPE_TYPE(
380 bytesize
=4, has_addend
=True, calc_func
=_reloc_calc_sym_plus_addend
),
381 ENUM_RELOC_TYPE_AARCH64
['R_AARCH64_PREL32']: _RELOCATION_RECIPE_TYPE(
382 bytesize
=4, has_addend
=True,
383 calc_func
=_reloc_calc_sym_plus_addend_pcrel
),
386 # https://dmz-portal.mips.com/wiki/MIPS_relocation_types
387 _RELOCATION_RECIPES_MIPS_REL
= {
388 ENUM_RELOC_TYPE_MIPS
['R_MIPS_NONE']: _RELOCATION_RECIPE_TYPE(
389 bytesize
=4, has_addend
=False, calc_func
=_reloc_calc_identity
),
390 ENUM_RELOC_TYPE_MIPS
['R_MIPS_32']: _RELOCATION_RECIPE_TYPE(
391 bytesize
=4, has_addend
=False,
392 calc_func
=_reloc_calc_sym_plus_value
),
394 _RELOCATION_RECIPES_MIPS_RELA
= {
395 ENUM_RELOC_TYPE_MIPS
['R_MIPS_NONE']: _RELOCATION_RECIPE_TYPE(
396 bytesize
=4, has_addend
=True, calc_func
=_reloc_calc_identity
),
397 ENUM_RELOC_TYPE_MIPS
['R_MIPS_32']: _RELOCATION_RECIPE_TYPE(
398 bytesize
=4, has_addend
=True,
399 calc_func
=_reloc_calc_sym_plus_value
),
400 ENUM_RELOC_TYPE_MIPS
['R_MIPS_64']: _RELOCATION_RECIPE_TYPE(
401 bytesize
=8, has_addend
=True,
402 calc_func
=_reloc_calc_sym_plus_value
),
405 _RELOCATION_RECIPES_PPC64
= {
406 ENUM_RELOC_TYPE_PPC64
['R_PPC64_ADDR32']: _RELOCATION_RECIPE_TYPE(
407 bytesize
=4, has_addend
=True, calc_func
=_reloc_calc_sym_plus_addend
),
408 ENUM_RELOC_TYPE_PPC64
['R_PPC64_REL32']: _RELOCATION_RECIPE_TYPE(
409 bytesize
=4, has_addend
=True, calc_func
=_reloc_calc_sym_plus_addend_pcrel
),
410 ENUM_RELOC_TYPE_PPC64
['R_PPC64_ADDR64']: _RELOCATION_RECIPE_TYPE(
411 bytesize
=8, has_addend
=True, calc_func
=_reloc_calc_sym_plus_addend
),
414 _RELOCATION_RECIPES_X86
= {
415 ENUM_RELOC_TYPE_i386
['R_386_NONE']: _RELOCATION_RECIPE_TYPE(
416 bytesize
=4, has_addend
=False, calc_func
=_reloc_calc_identity
),
417 ENUM_RELOC_TYPE_i386
['R_386_32']: _RELOCATION_RECIPE_TYPE(
418 bytesize
=4, has_addend
=False,
419 calc_func
=_reloc_calc_sym_plus_value
),
420 ENUM_RELOC_TYPE_i386
['R_386_PC32']: _RELOCATION_RECIPE_TYPE(
421 bytesize
=4, has_addend
=False,
422 calc_func
=_reloc_calc_sym_plus_value_pcrel
),
425 _RELOCATION_RECIPES_X64
= {
426 ENUM_RELOC_TYPE_x64
['R_X86_64_NONE']: _RELOCATION_RECIPE_TYPE(
427 bytesize
=8, has_addend
=True, calc_func
=_reloc_calc_identity
),
428 ENUM_RELOC_TYPE_x64
['R_X86_64_64']: _RELOCATION_RECIPE_TYPE(
429 bytesize
=8, has_addend
=True, calc_func
=_reloc_calc_sym_plus_addend
),
430 ENUM_RELOC_TYPE_x64
['R_X86_64_PC32']: _RELOCATION_RECIPE_TYPE(
431 bytesize
=4, has_addend
=True,
432 calc_func
=_reloc_calc_sym_plus_addend_pcrel
),
433 ENUM_RELOC_TYPE_x64
['R_X86_64_32']: _RELOCATION_RECIPE_TYPE(
434 bytesize
=4, has_addend
=True, calc_func
=_reloc_calc_sym_plus_addend
),
435 ENUM_RELOC_TYPE_x64
['R_X86_64_32S']: _RELOCATION_RECIPE_TYPE(
436 bytesize
=4, has_addend
=True, calc_func
=_reloc_calc_sym_plus_addend
),
439 # https://www.kernel.org/doc/html/latest/bpf/llvm_reloc.html#different-relocation-types
440 _RELOCATION_RECIPES_EBPF
= {
441 ENUM_RELOC_TYPE_BPF
['R_BPF_NONE']: _RELOCATION_RECIPE_TYPE(
442 bytesize
=8, has_addend
=False, calc_func
=_reloc_calc_identity
),
443 ENUM_RELOC_TYPE_BPF
['R_BPF_64_64']: _RELOCATION_RECIPE_TYPE(
444 bytesize
=8, has_addend
=False, calc_func
=_reloc_calc_identity
),
445 ENUM_RELOC_TYPE_BPF
['R_BPF_64_32']: _RELOCATION_RECIPE_TYPE(
446 bytesize
=8, has_addend
=False, calc_func
=_bpf_64_32_reloc_calc_sym_plus_addend
),
447 ENUM_RELOC_TYPE_BPF
['R_BPF_64_NODYLD32']: _RELOCATION_RECIPE_TYPE(
448 bytesize
=4, has_addend
=False, calc_func
=_reloc_calc_identity
),
449 ENUM_RELOC_TYPE_BPF
['R_BPF_64_ABS64']: _RELOCATION_RECIPE_TYPE(
450 bytesize
=8, has_addend
=False, calc_func
=_reloc_calc_identity
),
451 ENUM_RELOC_TYPE_BPF
['R_BPF_64_ABS32']: _RELOCATION_RECIPE_TYPE(
452 bytesize
=4, has_addend
=False, calc_func
=_reloc_calc_identity
),
455 # https://github.com/loongson/la-abi-specs/blob/release/laelf.adoc
456 _RELOCATION_RECIPES_LOONGARCH
= {
457 ENUM_RELOC_TYPE_LOONGARCH
['R_LARCH_NONE']: _RELOCATION_RECIPE_TYPE(
458 bytesize
=4, has_addend
=False, calc_func
=_reloc_calc_identity
),
459 ENUM_RELOC_TYPE_LOONGARCH
['R_LARCH_32']: _RELOCATION_RECIPE_TYPE(
460 bytesize
=4, has_addend
=True,
461 calc_func
=_reloc_calc_sym_plus_addend
),
462 ENUM_RELOC_TYPE_LOONGARCH
['R_LARCH_64']: _RELOCATION_RECIPE_TYPE(
463 bytesize
=8, has_addend
=True,
464 calc_func
=_reloc_calc_sym_plus_addend
),
465 ENUM_RELOC_TYPE_LOONGARCH
['R_LARCH_ADD8']: _RELOCATION_RECIPE_TYPE(
466 bytesize
=1, has_addend
=True,
467 calc_func
=_reloc_calc_sym_plus_value
),
468 ENUM_RELOC_TYPE_LOONGARCH
['R_LARCH_SUB8']: _RELOCATION_RECIPE_TYPE(
469 bytesize
=1, has_addend
=True,
470 calc_func
=_reloc_calc_value_minus_sym_addend
),
471 ENUM_RELOC_TYPE_LOONGARCH
['R_LARCH_ADD16']: _RELOCATION_RECIPE_TYPE(
472 bytesize
=2, has_addend
=True,
473 calc_func
=_reloc_calc_sym_plus_value
),
474 ENUM_RELOC_TYPE_LOONGARCH
['R_LARCH_SUB16']: _RELOCATION_RECIPE_TYPE(
475 bytesize
=2, has_addend
=True,
476 calc_func
=_reloc_calc_value_minus_sym_addend
),
477 ENUM_RELOC_TYPE_LOONGARCH
['R_LARCH_ADD32']: _RELOCATION_RECIPE_TYPE(
478 bytesize
=4, has_addend
=True,
479 calc_func
=_reloc_calc_sym_plus_value
),
480 ENUM_RELOC_TYPE_LOONGARCH
['R_LARCH_SUB32']: _RELOCATION_RECIPE_TYPE(
481 bytesize
=4, has_addend
=True,
482 calc_func
=_reloc_calc_value_minus_sym_addend
),
483 ENUM_RELOC_TYPE_LOONGARCH
['R_LARCH_ADD64']: _RELOCATION_RECIPE_TYPE(
484 bytesize
=8, has_addend
=True,
485 calc_func
=_reloc_calc_sym_plus_value
),
486 ENUM_RELOC_TYPE_LOONGARCH
['R_LARCH_SUB64']: _RELOCATION_RECIPE_TYPE(
487 bytesize
=8, has_addend
=True,
488 calc_func
=_reloc_calc_value_minus_sym_addend
),
489 ENUM_RELOC_TYPE_LOONGARCH
['R_LARCH_32_PCREL']: _RELOCATION_RECIPE_TYPE(
490 bytesize
=4, has_addend
=True,
491 calc_func
=_reloc_calc_sym_plus_addend_pcrel
),
492 ENUM_RELOC_TYPE_LOONGARCH
['R_LARCH_64_PCREL']: _RELOCATION_RECIPE_TYPE(
493 bytesize
=8, has_addend
=True,
494 calc_func
=_reloc_calc_sym_plus_addend_pcrel
),
497 _RELOCATION_RECIPES_S390X
= {
498 ENUM_RELOC_TYPE_S390X
['R_390_32']: _RELOCATION_RECIPE_TYPE(
499 bytesize
=4, has_addend
=True, calc_func
=_reloc_calc_sym_plus_addend
),
500 ENUM_RELOC_TYPE_S390X
['R_390_PC32']: _RELOCATION_RECIPE_TYPE(
501 bytesize
=4, has_addend
=True, calc_func
=_reloc_calc_sym_plus_addend_pcrel
),
502 ENUM_RELOC_TYPE_S390X
['R_390_64']: _RELOCATION_RECIPE_TYPE(
503 bytesize
=8, has_addend
=True, calc_func
=_reloc_calc_sym_plus_addend
),