1use crate::bit_misc::BitExtraction;
2use crate::elf::AArch64Instruction;
3use crate::elf::AllowedRange;
4use crate::elf::PAGE_MASK_4KB;
5use crate::elf::PageMask;
6use crate::elf::RelocationKind;
7use crate::elf::RelocationKindInfo;
8use crate::elf::RelocationSize;
9use crate::elf::Sign;
10use crate::relaxation::RelocationModifier;
11use crate::utils::and_from_slice;
12use crate::utils::or_from_slice;
13use crate::utils::u32_from_slice;
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum RelaxationKind {
17 NoOp,
19
20 ReplaceWithNop,
22
23 MovzX0Lsl16,
25
26 MovkX0,
28
29 MovzXnLsl16,
31
32 MovkXn,
34
35 AdrpToAdr,
37
38 AdrpX0,
40
41 LdrX0,
43
44 AddToAdr,
46 LdrToAdr,
47}
48
49impl RelaxationKind {
50 pub fn apply(self, section_bytes: &mut [u8], offset_in_section: &mut u64, _addend: &mut i64) {
51 let offset = *offset_in_section as usize;
52 match self {
53 RelaxationKind::NoOp => {}
54 RelaxationKind::ReplaceWithNop => {
55 section_bytes[offset..offset + 4].copy_from_slice(&[
56 0x1f, 0x20, 0x03, 0xd5, ]);
58 }
59 RelaxationKind::MovzX0Lsl16 => {
60 section_bytes[offset..offset + 4].copy_from_slice(&[
61 0x0, 0x0, 0xa0, 0xd2, ]);
63 }
64 RelaxationKind::MovkX0 => {
65 section_bytes[offset..offset + 4].copy_from_slice(&[
66 0x0, 0x0, 0x80, 0xf2, ]);
68 }
69 RelaxationKind::MovzXnLsl16 => {
70 let reg = u64::from(u32_from_slice(§ion_bytes[offset..offset + 4]))
71 .extract_bit_range(0..5) as u8;
72 section_bytes[offset..offset + 4].copy_from_slice(&[
73 reg, 0x0, 0xa0, 0xd2, ]);
75 }
76 RelaxationKind::MovkXn => {
77 let raw = u64::from(u32_from_slice(§ion_bytes[offset..offset + 4]));
78 let dst_reg = raw.extract_bit_range(0..5) as u8;
79 let src_reg = raw.extract_bit_range(5..10) as u8;
80 debug_assert_eq!(
81 src_reg, dst_reg,
82 "Source and destination registers must be equal"
83 );
84 section_bytes[offset..offset + 4].copy_from_slice(&[
85 dst_reg, 0x0, 0x80, 0xf2, ]);
87 }
88 RelaxationKind::AdrpToAdr => {
89 section_bytes[offset + 3] &= !0x80;
91 }
92 RelaxationKind::AddToAdr => {
93 section_bytes[offset + 3] &= !0x89;
94 }
95 RelaxationKind::LdrToAdr => {
96 section_bytes[offset + 3] &= !0x89;
97 }
98 RelaxationKind::AdrpX0 => {
99 section_bytes[offset..offset + 4].copy_from_slice(&[
100 0x0, 0x0, 0x0, 0x90, ]);
102 }
103 RelaxationKind::LdrX0 => {
104 section_bytes[offset..offset + 4].copy_from_slice(&[
105 0x0, 0x0, 0x40, 0xf9, ]);
107 }
108 }
109 }
110
111 #[must_use]
112 pub fn next_modifier(&self) -> RelocationModifier {
113 RelocationModifier::Normal
114 }
115}
116
117#[must_use]
118pub const fn relocation_type_from_raw(r_type: u32) -> Option<RelocationKindInfo> {
119 let (kind, size, mask, range, alignment) = match r_type {
120 object::elf::R_AARCH64_NONE => (
122 RelocationKind::None,
123 RelocationSize::ByteSize(0),
124 None,
125 AllowedRange::no_check(),
126 1,
127 ),
128
129 object::elf::R_AARCH64_ABS64 => (
132 RelocationKind::Absolute,
133 RelocationSize::ByteSize(8),
134 None,
135 AllowedRange::no_check(),
136 1,
137 ),
138 object::elf::R_AARCH64_ABS32 => (
139 RelocationKind::Absolute,
140 RelocationSize::ByteSize(4),
141 None,
142 AllowedRange::new(-(2i64.pow(31)), 2i64.pow(32)),
144 1,
145 ),
146 object::elf::R_AARCH64_ABS16 => (
147 RelocationKind::Absolute,
148 RelocationSize::ByteSize(2),
149 None,
150 AllowedRange::new(-(2i64.pow(15)), 2i64.pow(16)),
152 1,
153 ),
154 object::elf::R_AARCH64_PREL64 => (
155 RelocationKind::Relative,
156 RelocationSize::ByteSize(8),
157 None,
158 AllowedRange::no_check(),
159 1,
160 ),
161 object::elf::R_AARCH64_PREL32 => (
162 RelocationKind::Relative,
163 RelocationSize::ByteSize(4),
164 None,
165 AllowedRange::new(-(2i64.pow(31)), 2i64.pow(32)),
167 1,
168 ),
169 object::elf::R_AARCH64_PREL16 => (
170 RelocationKind::Relative,
171 RelocationSize::ByteSize(2),
172 None,
173 AllowedRange::new(-(2i64.pow(15)), 2i64.pow(16)),
175 1,
176 ),
177 object::elf::R_AARCH64_PLT32 => (
178 RelocationKind::PltRelative,
179 RelocationSize::ByteSize(4),
180 None,
181 AllowedRange::from_bit_size(32, Sign::Signed),
183 1,
184 ),
185
186 object::elf::R_AARCH64_MOVW_UABS_G0 => (
190 RelocationKind::Absolute,
191 RelocationSize::bit_mask_aarch64(0, 16, AArch64Instruction::Movkz),
192 None,
193 AllowedRange::from_bit_size(16, Sign::Unsigned),
194 1,
195 ),
196 object::elf::R_AARCH64_MOVW_UABS_G0_NC => (
197 RelocationKind::Absolute,
198 RelocationSize::bit_mask_aarch64(0, 16, AArch64Instruction::Movkz),
199 None,
200 AllowedRange::no_check(),
201 1,
202 ),
203 object::elf::R_AARCH64_MOVW_UABS_G1 => (
204 RelocationKind::Absolute,
205 RelocationSize::bit_mask_aarch64(16, 32, AArch64Instruction::Movkz),
206 None,
207 AllowedRange::from_bit_size(32, Sign::Unsigned),
208 1,
209 ),
210 object::elf::R_AARCH64_MOVW_UABS_G1_NC => (
211 RelocationKind::Absolute,
212 RelocationSize::bit_mask_aarch64(16, 32, AArch64Instruction::Movkz),
213 None,
214 AllowedRange::no_check(),
215 1,
216 ),
217 object::elf::R_AARCH64_MOVW_UABS_G2 => (
218 RelocationKind::Absolute,
219 RelocationSize::bit_mask_aarch64(32, 48, AArch64Instruction::Movkz),
220 None,
221 AllowedRange::from_bit_size(48, Sign::Unsigned),
222 1,
223 ),
224 object::elf::R_AARCH64_MOVW_UABS_G2_NC => (
225 RelocationKind::Absolute,
226 RelocationSize::bit_mask_aarch64(32, 48, AArch64Instruction::Movkz),
227 None,
228 AllowedRange::no_check(),
229 1,
230 ),
231 object::elf::R_AARCH64_MOVW_UABS_G3 => (
232 RelocationKind::Absolute,
233 RelocationSize::bit_mask_aarch64(48, 64, AArch64Instruction::Movkz),
234 None,
235 AllowedRange::no_check(),
236 1,
237 ),
238 object::elf::R_AARCH64_MOVW_SABS_G0 => (
240 RelocationKind::Absolute,
241 RelocationSize::bit_mask_aarch64(0, 16, AArch64Instruction::Movnz),
242 None,
243 AllowedRange::from_bit_size(17, Sign::Signed),
244 1,
245 ),
246 object::elf::R_AARCH64_MOVW_SABS_G1 => (
247 RelocationKind::Absolute,
248 RelocationSize::bit_mask_aarch64(16, 32, AArch64Instruction::Movnz),
249 None,
250 AllowedRange::from_bit_size(33, Sign::Signed),
251 1,
252 ),
253 object::elf::R_AARCH64_MOVW_SABS_G2 => (
254 RelocationKind::Absolute,
255 RelocationSize::bit_mask_aarch64(32, 48, AArch64Instruction::Movnz),
256 None,
257 AllowedRange::from_bit_size(49, Sign::Signed),
258 1,
259 ),
260 object::elf::R_AARCH64_LD_PREL_LO19 => (
262 RelocationKind::Relative,
263 RelocationSize::bit_mask_aarch64(2, 21, AArch64Instruction::Ldr),
264 None,
265 AllowedRange::from_bit_size(21, Sign::Signed),
266 4,
267 ),
268 object::elf::R_AARCH64_ADR_PREL_LO21 => (
269 RelocationKind::Relative,
270 RelocationSize::bit_mask_aarch64(0, 21, AArch64Instruction::Adr),
271 None,
272 AllowedRange::from_bit_size(21, Sign::Signed),
273 1,
274 ),
275 object::elf::R_AARCH64_ADR_PREL_PG_HI21 => (
276 RelocationKind::Relative,
277 RelocationSize::bit_mask_aarch64(12, 33, AArch64Instruction::Adr),
278 Some(PageMask::SymbolPlusAddendAndPosition(PAGE_MASK_4KB)),
279 AllowedRange::from_bit_size(33, Sign::Signed),
280 1,
281 ),
282 object::elf::R_AARCH64_ADR_PREL_PG_HI21_NC => (
283 RelocationKind::Relative,
284 RelocationSize::bit_mask_aarch64(12, 33, AArch64Instruction::Adr),
285 Some(PageMask::SymbolPlusAddendAndPosition(PAGE_MASK_4KB)),
286 AllowedRange::no_check(),
287 1,
288 ),
289 object::elf::R_AARCH64_ADD_ABS_LO12_NC => (
290 RelocationKind::AbsoluteLowPart,
291 RelocationSize::bit_mask_aarch64(0, 12, AArch64Instruction::Add),
292 None,
293 AllowedRange::no_check(),
294 1,
295 ),
296 object::elf::R_AARCH64_LDST8_ABS_LO12_NC => (
297 RelocationKind::AbsoluteLowPart,
298 RelocationSize::bit_mask_aarch64(0, 12, AArch64Instruction::LdSt),
299 None,
300 AllowedRange::no_check(),
301 1,
302 ),
303 object::elf::R_AARCH64_LDST16_ABS_LO12_NC => (
304 RelocationKind::AbsoluteLowPart,
305 RelocationSize::bit_mask_aarch64(1, 12, AArch64Instruction::LdSt),
306 None,
307 AllowedRange::no_check(),
308 2,
309 ),
310 object::elf::R_AARCH64_LDST32_ABS_LO12_NC => (
311 RelocationKind::AbsoluteLowPart,
312 RelocationSize::bit_mask_aarch64(2, 12, AArch64Instruction::LdSt),
313 None,
314 AllowedRange::no_check(),
315 4,
316 ),
317 object::elf::R_AARCH64_LDST64_ABS_LO12_NC => (
318 RelocationKind::AbsoluteLowPart,
319 RelocationSize::bit_mask_aarch64(3, 12, AArch64Instruction::LdSt),
320 None,
321 AllowedRange::no_check(),
322 8,
323 ),
324 object::elf::R_AARCH64_LDST128_ABS_LO12_NC => (
325 RelocationKind::AbsoluteLowPart,
326 RelocationSize::bit_mask_aarch64(4, 12, AArch64Instruction::LdSt),
327 None,
328 AllowedRange::no_check(),
329 16,
330 ),
331
332 object::elf::R_AARCH64_TSTBR14 => (
334 RelocationKind::Relative,
335 RelocationSize::bit_mask_aarch64(2, 16, AArch64Instruction::TstBr),
336 None,
337 AllowedRange::from_bit_size(16, Sign::Signed),
338 4,
339 ),
340 object::elf::R_AARCH64_CONDBR19 => (
341 RelocationKind::Relative,
342 RelocationSize::bit_mask_aarch64(2, 21, AArch64Instruction::Bcond),
343 None,
344 AllowedRange::from_bit_size(21, Sign::Signed),
345 4,
346 ),
347 object::elf::R_AARCH64_JUMP26 => (
348 RelocationKind::PltRelative,
349 RelocationSize::bit_mask_aarch64(2, 28, AArch64Instruction::JumpCall),
350 None,
351 AllowedRange::from_bit_size(28, Sign::Signed),
352 4,
353 ),
354 object::elf::R_AARCH64_CALL26 => (
355 RelocationKind::PltRelative,
356 RelocationSize::bit_mask_aarch64(2, 28, AArch64Instruction::JumpCall),
357 None,
358 AllowedRange::from_bit_size(28, Sign::Signed),
359 4,
360 ),
361
362 object::elf::R_AARCH64_MOVW_PREL_G0 => (
364 RelocationKind::Relative,
365 RelocationSize::bit_mask_aarch64(0, 16, AArch64Instruction::Movnz),
366 None,
367 AllowedRange::no_check(),
368 1,
369 ),
370 object::elf::R_AARCH64_MOVW_PREL_G0_NC => (
371 RelocationKind::Relative,
372 RelocationSize::bit_mask_aarch64(0, 16, AArch64Instruction::Movkz),
373 None,
374 AllowedRange::no_check(),
375 1,
376 ),
377 object::elf::R_AARCH64_MOVW_PREL_G1 => (
378 RelocationKind::Relative,
379 RelocationSize::bit_mask_aarch64(16, 32, AArch64Instruction::Movnz),
380 None,
381 AllowedRange::no_check(),
382 1,
383 ),
384 object::elf::R_AARCH64_MOVW_PREL_G1_NC => (
385 RelocationKind::Relative,
386 RelocationSize::bit_mask_aarch64(16, 32, AArch64Instruction::Movkz),
387 None,
388 AllowedRange::no_check(),
389 1,
390 ),
391 object::elf::R_AARCH64_MOVW_PREL_G2 => (
392 RelocationKind::Relative,
393 RelocationSize::bit_mask_aarch64(32, 48, AArch64Instruction::Movnz),
394 None,
395 AllowedRange::no_check(),
396 1,
397 ),
398 object::elf::R_AARCH64_MOVW_PREL_G2_NC => (
399 RelocationKind::Relative,
400 RelocationSize::bit_mask_aarch64(32, 48, AArch64Instruction::Movkz),
401 None,
402 AllowedRange::no_check(),
403 1,
404 ),
405 object::elf::R_AARCH64_MOVW_PREL_G3 => (
406 RelocationKind::Relative,
407 RelocationSize::bit_mask_aarch64(48, 64, AArch64Instruction::Movnz),
408 None,
409 AllowedRange::no_check(),
410 1,
411 ),
412
413 object::elf::R_AARCH64_MOVW_GOTOFF_G0 => (
415 RelocationKind::GotRelGotBase,
416 RelocationSize::bit_mask_aarch64(0, 16, AArch64Instruction::Movnz),
417 None,
418 AllowedRange::no_check(),
419 1,
420 ),
421 object::elf::R_AARCH64_MOVW_GOTOFF_G0_NC => (
422 RelocationKind::GotRelGotBase,
423 RelocationSize::bit_mask_aarch64(0, 16, AArch64Instruction::Movkz),
424 None,
425 AllowedRange::no_check(),
426 1,
427 ),
428 object::elf::R_AARCH64_MOVW_GOTOFF_G1 => (
429 RelocationKind::GotRelGotBase,
430 RelocationSize::bit_mask_aarch64(16, 32, AArch64Instruction::Movnz),
431 None,
432 AllowedRange::no_check(),
433 1,
434 ),
435 object::elf::R_AARCH64_MOVW_GOTOFF_G1_NC => (
436 RelocationKind::GotRelGotBase,
437 RelocationSize::bit_mask_aarch64(16, 32, AArch64Instruction::Movkz),
438 None,
439 AllowedRange::no_check(),
440 1,
441 ),
442 object::elf::R_AARCH64_MOVW_GOTOFF_G2 => (
443 RelocationKind::GotRelGotBase,
444 RelocationSize::bit_mask_aarch64(32, 48, AArch64Instruction::Movnz),
445 None,
446 AllowedRange::no_check(),
447 1,
448 ),
449 object::elf::R_AARCH64_MOVW_GOTOFF_G2_NC => (
450 RelocationKind::GotRelGotBase,
451 RelocationSize::bit_mask_aarch64(32, 48, AArch64Instruction::Movkz),
452 None,
453 AllowedRange::no_check(),
454 1,
455 ),
456 object::elf::R_AARCH64_MOVW_GOTOFF_G3 => (
457 RelocationKind::GotRelGotBase,
458 RelocationSize::bit_mask_aarch64(48, 64, AArch64Instruction::Movnz),
459 None,
460 AllowedRange::no_check(),
461 1,
462 ),
463
464 object::elf::R_AARCH64_GOTREL64 => (
466 RelocationKind::SymRelGotBase,
467 RelocationSize::ByteSize(4),
468 None,
469 AllowedRange::no_check(),
470 1,
471 ),
472 object::elf::R_AARCH64_GOTREL32 => (
473 RelocationKind::SymRelGotBase,
474 RelocationSize::ByteSize(8),
475 None,
476 AllowedRange::from_bit_size(32, Sign::Signed),
477 1,
478 ),
479 object::elf::R_AARCH64_GOTPCREL32 => (
480 RelocationKind::GotRelative,
481 RelocationSize::ByteSize(4),
482 None,
483 AllowedRange::from_bit_size(32, Sign::Signed),
484 1,
485 ),
486 object::elf::R_AARCH64_GOT_LD_PREL19 => (
487 RelocationKind::GotRelative,
488 RelocationSize::bit_mask_aarch64(2, 21, AArch64Instruction::LdSt),
489 None,
490 AllowedRange::from_bit_size(21, Sign::Signed),
491 4,
492 ),
493 object::elf::R_AARCH64_LD64_GOTOFF_LO15 => (
494 RelocationKind::GotRelGotBase,
495 RelocationSize::bit_mask_aarch64(3, 15, AArch64Instruction::LdSt),
496 None,
497 AllowedRange::from_bit_size(15, Sign::Unsigned),
498 8,
499 ),
500 object::elf::R_AARCH64_ADR_GOT_PAGE => (
501 RelocationKind::GotRelative,
502 RelocationSize::bit_mask_aarch64(12, 33, AArch64Instruction::Adr),
503 Some(PageMask::GotEntryAndPosition(PAGE_MASK_4KB)),
504 AllowedRange::from_bit_size(33, Sign::Signed),
505 1,
506 ),
507 object::elf::R_AARCH64_LD64_GOT_LO12_NC => (
508 RelocationKind::Got,
509 RelocationSize::bit_mask_aarch64(3, 12, AArch64Instruction::LdSt),
510 None,
511 AllowedRange::no_check(),
512 8,
513 ),
514 object::elf::R_AARCH64_LD64_GOTPAGE_LO15 => (
515 RelocationKind::GotRelGotBase,
516 RelocationSize::bit_mask_aarch64(3, 15, AArch64Instruction::LdSt),
517 Some(PageMask::GotBase(PAGE_MASK_4KB)),
518 AllowedRange::from_bit_size(15, Sign::Unsigned),
519 8,
520 ),
521
522 object::elf::R_AARCH64_TLSGD_ADR_PREL21 => (
524 RelocationKind::TlsGd,
525 RelocationSize::bit_mask_aarch64(0, 21, AArch64Instruction::Adr),
526 None,
527 AllowedRange::from_bit_size(21, Sign::Signed),
528 1,
529 ),
530 object::elf::R_AARCH64_TLSGD_ADR_PAGE21 => (
531 RelocationKind::TlsGd,
532 RelocationSize::bit_mask_aarch64(12, 33, AArch64Instruction::Adr),
533 Some(PageMask::GotEntryAndPosition(PAGE_MASK_4KB)),
534 AllowedRange::from_bit_size(33, Sign::Signed),
535 1,
536 ),
537 object::elf::R_AARCH64_TLSGD_ADD_LO12_NC => (
538 RelocationKind::TlsGdGot,
539 RelocationSize::bit_mask_aarch64(0, 12, AArch64Instruction::Add),
540 None,
541 AllowedRange::no_check(),
542 1,
543 ),
544 object::elf::R_AARCH64_TLSGD_MOVW_G1 => (
545 RelocationKind::TlsGdGotBase,
546 RelocationSize::bit_mask_aarch64(16, 33, AArch64Instruction::Movnz),
547 None,
548 AllowedRange::no_check(),
549 1,
550 ),
551 object::elf::R_AARCH64_TLSGD_MOVW_G0_NC => (
552 RelocationKind::TlsGdGotBase,
553 RelocationSize::bit_mask_aarch64(0, 16, AArch64Instruction::Movkz),
554 None,
555 AllowedRange::no_check(),
556 1,
557 ),
558
559 object::elf::R_AARCH64_TLSLD_ADR_PREL21 => (
561 RelocationKind::TlsLd,
562 RelocationSize::bit_mask_aarch64(0, 21, AArch64Instruction::Adr),
563 None,
564 AllowedRange::from_bit_size(21, Sign::Signed),
565 1,
566 ),
567 object::elf::R_AARCH64_TLSLD_ADR_PAGE21 => (
568 RelocationKind::TlsLd,
569 RelocationSize::bit_mask_aarch64(12, 33, AArch64Instruction::Adr),
570 Some(PageMask::GotEntryAndPosition(PAGE_MASK_4KB)),
571 AllowedRange::from_bit_size(33, Sign::Signed),
572 1,
573 ),
574 object::elf::R_AARCH64_TLSLD_ADD_LO12_NC => (
575 RelocationKind::TlsLdGot,
576 RelocationSize::bit_mask_aarch64(0, 12, AArch64Instruction::Add),
577 None,
578 AllowedRange::no_check(),
579 1,
580 ),
581 object::elf::R_AARCH64_TLSLD_MOVW_G1 => (
582 RelocationKind::TlsLdGotBase,
583 RelocationSize::bit_mask_aarch64(16, 32, AArch64Instruction::Movnz),
584 None,
585 AllowedRange::no_check(),
586 1,
587 ),
588 object::elf::R_AARCH64_TLSLD_MOVW_G0_NC => (
589 RelocationKind::TlsLdGotBase,
590 RelocationSize::bit_mask_aarch64(0, 16, AArch64Instruction::Movkz),
591 None,
592 AllowedRange::no_check(),
593 1,
594 ),
595 object::elf::R_AARCH64_TLSLD_LD_PREL19 => (
596 RelocationKind::TlsLd,
597 RelocationSize::bit_mask_aarch64(0, 21, AArch64Instruction::Ldr),
598 None,
599 AllowedRange::from_bit_size(21, Sign::Signed),
600 1,
601 ),
602 object::elf::R_AARCH64_TLSLD_MOVW_DTPREL_G2 => (
603 RelocationKind::DtpOff,
604 RelocationSize::bit_mask_aarch64(32, 48, AArch64Instruction::Movnz),
605 None,
606 AllowedRange::no_check(),
607 1,
608 ),
609 object::elf::R_AARCH64_TLSLD_MOVW_DTPREL_G1 => (
610 RelocationKind::DtpOff,
611 RelocationSize::bit_mask_aarch64(16, 32, AArch64Instruction::Movnz),
612 None,
613 AllowedRange::no_check(),
614 1,
615 ),
616 object::elf::R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC => (
617 RelocationKind::DtpOff,
618 RelocationSize::bit_mask_aarch64(16, 32, AArch64Instruction::Movkz),
619 None,
620 AllowedRange::no_check(),
621 1,
622 ),
623 object::elf::R_AARCH64_TLSLD_MOVW_DTPREL_G0 => (
624 RelocationKind::DtpOff,
625 RelocationSize::bit_mask_aarch64(0, 16, AArch64Instruction::Movnz),
626 None,
627 AllowedRange::no_check(),
628 1,
629 ),
630 object::elf::R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC => (
631 RelocationKind::DtpOff,
632 RelocationSize::bit_mask_aarch64(0, 16, AArch64Instruction::Movkz),
633 None,
634 AllowedRange::no_check(),
635 1,
636 ),
637 object::elf::R_AARCH64_TLSLD_ADD_DTPREL_HI12 => (
638 RelocationKind::DtpOff,
639 RelocationSize::bit_mask_aarch64(12, 24, AArch64Instruction::Add),
640 None,
641 AllowedRange::from_bit_size(24, Sign::Unsigned),
642 1,
643 ),
644 object::elf::R_AARCH64_TLSLD_ADD_DTPREL_LO12 => (
645 RelocationKind::DtpOff,
646 RelocationSize::bit_mask_aarch64(0, 12, AArch64Instruction::Add),
647 None,
648 AllowedRange::from_bit_size(12, Sign::Unsigned),
649 1,
650 ),
651 object::elf::R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC => (
652 RelocationKind::DtpOff,
653 RelocationSize::bit_mask_aarch64(0, 12, AArch64Instruction::Add),
654 None,
655 AllowedRange::no_check(),
656 1,
657 ),
658 object::elf::R_AARCH64_TLSLD_LDST8_DTPREL_LO12 => (
659 RelocationKind::DtpOff,
660 RelocationSize::bit_mask_aarch64(0, 12, AArch64Instruction::LdSt),
661 None,
662 AllowedRange::from_bit_size(12, Sign::Unsigned),
663 1,
664 ),
665 object::elf::R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC => (
666 RelocationKind::DtpOff,
667 RelocationSize::bit_mask_aarch64(0, 12, AArch64Instruction::LdSt),
668 None,
669 AllowedRange::no_check(),
670 1,
671 ),
672 object::elf::R_AARCH64_TLSLD_LDST16_DTPREL_LO12 => (
673 RelocationKind::DtpOff,
674 RelocationSize::bit_mask_aarch64(1, 12, AArch64Instruction::LdSt),
675 None,
676 AllowedRange::from_bit_size(12, Sign::Unsigned),
677 2,
678 ),
679 object::elf::R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC => (
680 RelocationKind::DtpOff,
681 RelocationSize::bit_mask_aarch64(1, 12, AArch64Instruction::LdSt),
682 None,
683 AllowedRange::no_check(),
684 2,
685 ),
686 object::elf::R_AARCH64_TLSLD_LDST32_DTPREL_LO12 => (
687 RelocationKind::DtpOff,
688 RelocationSize::bit_mask_aarch64(2, 12, AArch64Instruction::LdSt),
689 None,
690 AllowedRange::from_bit_size(12, Sign::Unsigned),
691 4,
692 ),
693 object::elf::R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC => (
694 RelocationKind::DtpOff,
695 RelocationSize::bit_mask_aarch64(2, 12, AArch64Instruction::LdSt),
696 None,
697 AllowedRange::no_check(),
698 4,
699 ),
700 object::elf::R_AARCH64_TLSLD_LDST64_DTPREL_LO12 => (
701 RelocationKind::DtpOff,
702 RelocationSize::bit_mask_aarch64(3, 12, AArch64Instruction::LdSt),
703 None,
704 AllowedRange::from_bit_size(12, Sign::Unsigned),
705 8,
706 ),
707 object::elf::R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC => (
708 RelocationKind::DtpOff,
709 RelocationSize::bit_mask_aarch64(3, 12, AArch64Instruction::LdSt),
710 None,
711 AllowedRange::no_check(),
712 8,
713 ),
714 object::elf::R_AARCH64_TLSLD_LDST128_DTPREL_LO12 => (
715 RelocationKind::DtpOff,
716 RelocationSize::bit_mask_aarch64(4, 12, AArch64Instruction::LdSt),
717 None,
718 AllowedRange::from_bit_size(12, Sign::Unsigned),
719 16,
720 ),
721
722 object::elf::R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC => (
723 RelocationKind::DtpOff,
724 RelocationSize::bit_mask_aarch64(4, 12, AArch64Instruction::LdSt),
725 None,
726 AllowedRange::no_check(),
727 16,
728 ),
729
730 object::elf::R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 => (
732 RelocationKind::GotTpOffGotBase,
733 RelocationSize::bit_mask_aarch64(16, 32, AArch64Instruction::Movnz),
734 None,
735 AllowedRange::no_check(),
736 1,
737 ),
738 object::elf::R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC => (
739 RelocationKind::GotTpOffGotBase,
740 RelocationSize::bit_mask_aarch64(0, 16, AArch64Instruction::Movkz),
741 None,
742 AllowedRange::no_check(),
743 1,
744 ),
745 object::elf::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 => (
746 RelocationKind::GotTpOff,
747 RelocationSize::bit_mask_aarch64(12, 33, AArch64Instruction::Adr),
748 Some(PageMask::GotEntryAndPosition(PAGE_MASK_4KB)),
749 AllowedRange::from_bit_size(33, Sign::Signed),
750 1,
751 ),
752 object::elf::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC => (
753 RelocationKind::GotTpOffGot,
754 RelocationSize::bit_mask_aarch64(3, 12, AArch64Instruction::LdrRegister),
755 None,
756 AllowedRange::no_check(),
757 8,
758 ),
759 object::elf::R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 => (
760 RelocationKind::GotTpOff,
761 RelocationSize::bit_mask_aarch64(2, 21, AArch64Instruction::Ldr),
762 None,
763 AllowedRange::from_bit_size(21, Sign::Signed),
764 4,
765 ),
766
767 object::elf::R_AARCH64_TLSLE_MOVW_TPREL_G2 => (
769 RelocationKind::TpOff,
770 RelocationSize::bit_mask_aarch64(32, 48, AArch64Instruction::Movnz),
771 None,
772 AllowedRange::no_check(),
773 1,
774 ),
775 object::elf::R_AARCH64_TLSLE_MOVW_TPREL_G1 => (
776 RelocationKind::TpOff,
777 RelocationSize::bit_mask_aarch64(16, 32, AArch64Instruction::Movnz),
778 None,
779 AllowedRange::no_check(),
780 1,
781 ),
782 object::elf::R_AARCH64_TLSLE_MOVW_TPREL_G1_NC => (
783 RelocationKind::TpOff,
784 RelocationSize::bit_mask_aarch64(16, 32, AArch64Instruction::Movkz),
785 None,
786 AllowedRange::no_check(),
787 1,
788 ),
789 object::elf::R_AARCH64_TLSLE_MOVW_TPREL_G0 => (
790 RelocationKind::TpOff,
791 RelocationSize::bit_mask_aarch64(0, 16, AArch64Instruction::Movnz),
792 None,
793 AllowedRange::no_check(),
794 1,
795 ),
796 object::elf::R_AARCH64_TLSLE_MOVW_TPREL_G0_NC => (
797 RelocationKind::TpOff,
798 RelocationSize::bit_mask_aarch64(0, 16, AArch64Instruction::Movkz),
799 None,
800 AllowedRange::no_check(),
801 1,
802 ),
803 object::elf::R_AARCH64_TLSLE_ADD_TPREL_HI12 => (
804 RelocationKind::TpOff,
805 RelocationSize::bit_mask_aarch64(12, 24, AArch64Instruction::Add),
806 None,
807 AllowedRange::from_bit_size(24, Sign::Unsigned),
808 1,
809 ),
810 object::elf::R_AARCH64_TLSLE_ADD_TPREL_LO12 => (
811 RelocationKind::TpOff,
812 RelocationSize::bit_mask_aarch64(0, 12, AArch64Instruction::Add),
813 None,
814 AllowedRange::from_bit_size(12, Sign::Unsigned),
815 1,
816 ),
817 object::elf::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC => (
818 RelocationKind::TpOff,
819 RelocationSize::bit_mask_aarch64(0, 12, AArch64Instruction::Add),
820 None,
821 AllowedRange::no_check(),
822 1,
823 ),
824 object::elf::R_AARCH64_TLSLE_LDST8_TPREL_LO12 => (
825 RelocationKind::TpOff,
826 RelocationSize::bit_mask_aarch64(0, 12, AArch64Instruction::LdSt),
827 None,
828 AllowedRange::from_bit_size(12, Sign::Unsigned),
829 1,
830 ),
831 object::elf::R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC => (
832 RelocationKind::TpOff,
833 RelocationSize::bit_mask_aarch64(0, 12, AArch64Instruction::LdSt),
834 None,
835 AllowedRange::no_check(),
836 1,
837 ),
838 object::elf::R_AARCH64_TLSLE_LDST16_TPREL_LO12 => (
839 RelocationKind::TpOff,
840 RelocationSize::bit_mask_aarch64(1, 12, AArch64Instruction::LdSt),
841 None,
842 AllowedRange::from_bit_size(12, Sign::Unsigned),
843 2,
844 ),
845
846 object::elf::R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC => (
847 RelocationKind::TpOff,
848 RelocationSize::bit_mask_aarch64(1, 12, AArch64Instruction::LdSt),
849 None,
850 AllowedRange::no_check(),
851 2,
852 ),
853 object::elf::R_AARCH64_TLSLE_LDST32_TPREL_LO12 => (
854 RelocationKind::TpOff,
855 RelocationSize::bit_mask_aarch64(2, 12, AArch64Instruction::LdSt),
856 None,
857 AllowedRange::from_bit_size(12, Sign::Unsigned),
858 4,
859 ),
860
861 object::elf::R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC => (
862 RelocationKind::TpOff,
863 RelocationSize::bit_mask_aarch64(2, 12, AArch64Instruction::LdSt),
864 None,
865 AllowedRange::no_check(),
866 4,
867 ),
868 object::elf::R_AARCH64_TLSLE_LDST64_TPREL_LO12 => (
869 RelocationKind::TpOff,
870 RelocationSize::bit_mask_aarch64(3, 12, AArch64Instruction::LdSt),
871 None,
872 AllowedRange::from_bit_size(12, Sign::Unsigned),
873 8,
874 ),
875 object::elf::R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC => (
876 RelocationKind::TpOff,
877 RelocationSize::bit_mask_aarch64(3, 12, AArch64Instruction::LdSt),
878 None,
879 AllowedRange::no_check(),
880 8,
881 ),
882 object::elf::R_AARCH64_TLSLE_LDST128_TPREL_LO12 => (
883 RelocationKind::TpOff,
884 RelocationSize::bit_mask_aarch64(4, 12, AArch64Instruction::LdSt),
885 None,
886 AllowedRange::from_bit_size(12, Sign::Unsigned),
887 16,
888 ),
889
890 object::elf::R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC => (
891 RelocationKind::TpOff,
892 RelocationSize::bit_mask_aarch64(4, 12, AArch64Instruction::LdSt),
893 None,
894 AllowedRange::no_check(),
895 16,
896 ),
897
898 object::elf::R_AARCH64_TLSDESC_LD_PREL19 => (
900 RelocationKind::TlsDesc,
901 RelocationSize::bit_mask_aarch64(2, 21, AArch64Instruction::Ldr),
902 None,
903 AllowedRange::from_bit_size(21, Sign::Signed),
904 4,
905 ),
906 object::elf::R_AARCH64_TLSDESC_ADR_PREL21 => (
907 RelocationKind::TlsDesc,
908 RelocationSize::bit_mask_aarch64(0, 21, AArch64Instruction::Adr),
909 None,
910 AllowedRange::from_bit_size(21, Sign::Signed),
911 1,
912 ),
913 object::elf::R_AARCH64_TLSDESC_ADR_PAGE21 => (
914 RelocationKind::TlsDesc,
915 RelocationSize::bit_mask_aarch64(12, 33, AArch64Instruction::Adr),
916 Some(PageMask::GotEntryAndPosition(PAGE_MASK_4KB)),
917 AllowedRange::from_bit_size(33, Sign::Signed),
918 1,
919 ),
920
921 object::elf::R_AARCH64_TLSDESC_LD64_LO12 => (
922 RelocationKind::TlsDescGot,
923 RelocationSize::bit_mask_aarch64(3, 12, AArch64Instruction::LdrRegister),
924 None,
925 AllowedRange::no_check(),
926 8,
927 ),
928 object::elf::R_AARCH64_TLSDESC_ADD_LO12 => (
929 RelocationKind::TlsDescGot,
930 RelocationSize::bit_mask_aarch64(0, 12, AArch64Instruction::Add),
931 None,
932 AllowedRange::no_check(),
933 1,
934 ),
935 object::elf::R_AARCH64_TLSDESC_OFF_G1 => (
936 RelocationKind::TlsDescGotBase,
937 RelocationSize::bit_mask_aarch64(16, 32, AArch64Instruction::Movnz),
938 None,
939 AllowedRange::from_bit_size(33, Sign::Signed),
940 1,
941 ),
942 object::elf::R_AARCH64_TLSDESC_OFF_G0_NC => (
943 RelocationKind::TlsDescGotBase,
944 RelocationSize::bit_mask_aarch64(0, 16, AArch64Instruction::Movkz),
945 None,
946 AllowedRange::no_check(),
947 1,
948 ),
949
950 object::elf::R_AARCH64_TLSDESC_CALL => (
952 RelocationKind::TlsDescCall,
953 RelocationSize::ByteSize(0),
954 None,
955 AllowedRange::no_check(),
956 1,
957 ),
958
959 _ => return None,
960 };
961
962 Some(RelocationKindInfo {
963 kind,
964 size,
965 mask,
966 range,
967 alignment,
968 bias: 0,
969 thunkable: matches!(
970 r_type,
971 object::elf::R_AARCH64_CALL26 | object::elf::R_AARCH64_JUMP26
972 ),
973 })
974}
975
976impl AArch64Instruction {
977 pub fn write_to_value(self, extracted_value: u64, negative: bool, dest: &mut [u8]) {
981 let mut mask;
982 match self {
983 AArch64Instruction::Adr => {
985 mask = ((extracted_value.extract_bit_range(0..2) as u32) << 29)
986 | ((extracted_value.extract_bit_range(2..32) as u32) << 5);
987 }
988 AArch64Instruction::Movkz => {
990 mask = (extracted_value as u32) << 5;
991 }
992 AArch64Instruction::Movnz => {
994 and_from_slice(dest, &0x0060_001F_u32.to_le_bytes());
996 let mut value = extracted_value as i64;
997 mask = 0u32;
998 if negative {
999 value = !value;
1000 mask |= 0x9280_0000;
1002 } else {
1003 mask |= 0xd280_0000;
1005 }
1006 mask |= ((value as u64).extract_bit_range(0..16) as u32) << 5;
1007 }
1008 AArch64Instruction::Ldr => {
1010 mask = (extracted_value as u32) << 5;
1011 }
1012 AArch64Instruction::LdrRegister => {
1013 mask = (extracted_value as u32) << 10;
1014 }
1015 AArch64Instruction::Add => {
1017 mask = (extracted_value as u32) << 10;
1018 }
1019 AArch64Instruction::LdSt => {
1021 mask = (extracted_value as u32) << 10;
1022 }
1023 AArch64Instruction::TstBr => {
1025 mask = (extracted_value as u32) << 5;
1026 }
1027 AArch64Instruction::Bcond => {
1029 mask = (extracted_value as u32) << 5;
1030 }
1031 AArch64Instruction::JumpCall => {
1033 mask = extracted_value as u32;
1034 }
1035 AArch64Instruction::MachOLow12 => {
1036 let insn = u32_from_slice(&dest[0..4]);
1040 let mut scale = 0;
1041 if (insn & 0x3b00_0000) == 0x3900_0000 {
1042 scale = insn >> 30;
1044 if scale == 0 && (insn & 0x0480_0000) == 0x0480_0000 {
1045 scale = 4;
1047 }
1048 }
1049 mask = (extracted_value as u32) >> scale;
1050 }
1051 }
1052 or_from_slice(dest, &mask.to_le_bytes());
1054 }
1055
1056 #[must_use]
1059 pub fn read_value(self, bytes: &[u8]) -> (u64, bool) {
1060 let mut negative = false;
1061 let value = u64::from(u32_from_slice(bytes));
1062 let extracted_value = match self {
1063 AArch64Instruction::Adr => {
1065 (value >> 29).low_bits(2) | (((value >> 5).low_bits_signed(19)) << 2)
1066 }
1067 AArch64Instruction::Movkz => (value >> 5).low_bits_signed(16),
1069 AArch64Instruction::Movnz => {
1071 negative = (value & (1 << 30)) == 0;
1072 let v = (value >> 5).low_bits(16);
1073 if negative { !v } else { v }
1074 }
1075 AArch64Instruction::Ldr => (value >> 5).low_bits_signed(19),
1077 AArch64Instruction::LdrRegister => (value >> 10).low_bits(12),
1079 AArch64Instruction::Add => (value >> 10).low_bits(12),
1081 AArch64Instruction::LdSt => (value >> 10).low_bits_signed(12),
1083 AArch64Instruction::TstBr => (value >> 5).low_bits_signed(14),
1085 AArch64Instruction::Bcond => (value >> 5).low_bits_signed(19),
1087 AArch64Instruction::JumpCall => value.low_bits_signed(26),
1089 AArch64Instruction::MachOLow12 => todo!(),
1090 };
1091
1092 (extracted_value, negative)
1093 }
1094}