1use crate::bit_misc::BitExtraction;
2use crate::elf::AllowedRange;
3use crate::elf::RelocationKind;
4use crate::elf::RelocationKindInfo;
5use crate::elf::RelocationSize;
6use crate::elf::RiscVInstruction;
7use crate::relaxation::RelocationModifier;
8use crate::utils::and_from_slice;
9use crate::utils::or_from_slice;
10use crate::utils::u32_from_slice;
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub enum RelaxationKind {
14 NoOp,
16
17 ReplaceWithNop,
19}
20
21impl RelaxationKind {
22 pub fn apply(self, section_bytes: &mut [u8], offset_in_section: &mut u64, _addend: &mut i64) {
23 let offset = *offset_in_section as usize;
24 match self {
25 RelaxationKind::NoOp => {}
26 RelaxationKind::ReplaceWithNop => {
27 section_bytes[offset..offset + 4].copy_from_slice(&[
28 0x01, 0x0, 0x01, 0x0, ]);
31 }
32 }
33 }
34
35 #[must_use]
36 pub fn next_modifier(&self) -> RelocationModifier {
37 RelocationModifier::Normal
38 }
39}
40
41#[must_use]
42pub const fn relocation_type_from_raw(r_type: u32) -> Option<RelocationKindInfo> {
43 let (kind, size, mask, range, alignment) = match r_type {
46 object::elf::R_RISCV_NONE => (
47 RelocationKind::None,
48 RelocationSize::ByteSize(0),
49 None,
50 AllowedRange::no_check(),
51 1,
52 ),
53 object::elf::R_RISCV_32 => (
54 RelocationKind::Absolute,
55 RelocationSize::ByteSize(4),
56 None,
57 AllowedRange::new(-(2i64.pow(31)), 2i64.pow(32)),
58 1,
59 ),
60 object::elf::R_RISCV_64 => (
61 RelocationKind::Absolute,
62 RelocationSize::ByteSize(4),
63 None,
64 AllowedRange::no_check(),
65 1,
66 ),
67 object::elf::R_RISCV_BRANCH => (
68 RelocationKind::Relative,
69 RelocationSize::bit_mask_riscv(0, 32, RiscVInstruction::BType),
70 None,
71 AllowedRange::new(-(2i64.pow(12)), 2i64.pow(13) - 2),
72 1,
73 ),
74 object::elf::R_RISCV_JAL => (
75 RelocationKind::Relative,
76 RelocationSize::bit_mask_riscv(0, 32, RiscVInstruction::JType),
77 None,
78 AllowedRange::new(-(2i64.pow(20)), 2i64.pow(20) - 2),
79 1,
80 ),
81 object::elf::R_RISCV_CALL | object::elf::R_RISCV_CALL_PLT => (
82 RelocationKind::PltRelative,
83 RelocationSize::bit_mask_riscv(0, 64, RiscVInstruction::UiType),
84 None,
85 AllowedRange::new(-(2i64.pow(31)), 2i64.pow(32)),
86 1,
87 ),
88 object::elf::R_RISCV_GOT_HI20 => (
89 RelocationKind::GotRelative,
90 RelocationSize::bit_mask_riscv(0, 32, RiscVInstruction::UType),
91 None,
92 AllowedRange::new(-(2i64.pow(31)), 2i64.pow(32)),
93 1,
94 ),
95 object::elf::R_RISCV_TLS_GOT_HI20 => (
96 RelocationKind::GotTpOff,
97 RelocationSize::bit_mask_riscv(0, 32, RiscVInstruction::UType),
98 None,
99 AllowedRange::new(-(2i64.pow(31)), 2i64.pow(32)),
100 1,
101 ),
102 object::elf::R_RISCV_TLS_GD_HI20 => (
103 RelocationKind::TlsGd,
104 RelocationSize::bit_mask_riscv(0, 32, RiscVInstruction::UType),
105 None,
106 AllowedRange::new(-(2i64.pow(31)), 2i64.pow(32)),
107 1,
108 ),
109 object::elf::R_RISCV_PCREL_HI20 => (
110 RelocationKind::Relative,
111 RelocationSize::bit_mask_riscv(0, 32, RiscVInstruction::UType),
112 None,
113 AllowedRange::new(-(2i64.pow(31)), 2i64.pow(32)),
114 1,
115 ),
116 object::elf::R_RISCV_PCREL_LO12_I => (
117 RelocationKind::RelativeRiscVLow12,
118 RelocationSize::bit_mask_riscv(0, 32, RiscVInstruction::IType),
119 None,
120 AllowedRange::new(-(2i64.pow(31)), 2i64.pow(32)),
121 1,
122 ),
123 object::elf::R_RISCV_PCREL_LO12_S => (
124 RelocationKind::RelativeRiscVLow12,
125 RelocationSize::bit_mask_riscv(0, 32, RiscVInstruction::SType),
126 None,
127 AllowedRange::new(-(2i64.pow(31)), 2i64.pow(32)),
128 1,
129 ),
130 object::elf::R_RISCV_HI20 => (
131 RelocationKind::Absolute,
132 RelocationSize::bit_mask_riscv(0, 32, RiscVInstruction::UType),
133 None,
134 AllowedRange::new(-(2i64.pow(31)), 2i64.pow(32)),
135 1,
136 ),
137 object::elf::R_RISCV_LO12_I => (
138 RelocationKind::Absolute,
139 RelocationSize::bit_mask_riscv(0, 32, RiscVInstruction::IType),
140 None,
141 AllowedRange::new(-(2i64.pow(31)), 2i64.pow(32)),
142 1,
143 ),
144 object::elf::R_RISCV_LO12_S => (
145 RelocationKind::Absolute,
146 RelocationSize::bit_mask_riscv(0, 32, RiscVInstruction::SType),
147 None,
148 AllowedRange::new(-(2i64.pow(31)), 2i64.pow(32)),
149 1,
150 ),
151 object::elf::R_RISCV_TPREL_HI20 => (
152 RelocationKind::TpOff,
153 RelocationSize::bit_mask_riscv(0, 32, RiscVInstruction::UType),
154 None,
155 AllowedRange::new(-(2i64.pow(31)), 2i64.pow(32)),
156 1,
157 ),
158 object::elf::R_RISCV_TPREL_LO12_I => (
159 RelocationKind::TpOff,
160 RelocationSize::bit_mask_riscv(0, 32, RiscVInstruction::IType),
161 None,
162 AllowedRange::new(-(2i64.pow(31)), 2i64.pow(32)),
163 1,
164 ),
165 object::elf::R_RISCV_TPREL_LO12_S => (
166 RelocationKind::TpOff,
167 RelocationSize::bit_mask_riscv(0, 32, RiscVInstruction::SType),
168 None,
169 AllowedRange::new(-(2i64.pow(31)), 2i64.pow(32)),
170 1,
171 ),
172 object::elf::R_RISCV_TPREL_ADD => (
173 RelocationKind::None,
174 RelocationSize::ByteSize(0),
175 None,
176 AllowedRange::no_check(),
177 1,
178 ),
179 object::elf::R_RISCV_ADD8 => (
180 RelocationKind::AbsoluteAddition,
181 RelocationSize::ByteSize(1),
182 None,
183 AllowedRange::no_check(),
184 1,
185 ),
186 object::elf::R_RISCV_ADD16 => (
187 RelocationKind::AbsoluteAddition,
188 RelocationSize::ByteSize(2),
189 None,
190 AllowedRange::no_check(),
191 1,
192 ),
193 object::elf::R_RISCV_ADD32 => (
194 RelocationKind::AbsoluteAddition,
195 RelocationSize::ByteSize(4),
196 None,
197 AllowedRange::no_check(),
198 1,
199 ),
200 object::elf::R_RISCV_ADD64 => (
201 RelocationKind::AbsoluteAddition,
202 RelocationSize::ByteSize(8),
203 None,
204 AllowedRange::no_check(),
205 1,
206 ),
207 object::elf::R_RISCV_SUB8 => (
208 RelocationKind::AbsoluteSubtraction,
209 RelocationSize::ByteSize(1),
210 None,
211 AllowedRange::no_check(),
212 1,
213 ),
214 object::elf::R_RISCV_SUB16 => (
215 RelocationKind::AbsoluteSubtraction,
216 RelocationSize::ByteSize(2),
217 None,
218 AllowedRange::no_check(),
219 1,
220 ),
221 object::elf::R_RISCV_SUB32 => (
222 RelocationKind::AbsoluteSubtraction,
223 RelocationSize::ByteSize(4),
224 None,
225 AllowedRange::no_check(),
226 1,
227 ),
228 object::elf::R_RISCV_SUB64 => (
229 RelocationKind::AbsoluteSubtraction,
230 RelocationSize::ByteSize(8),
231 None,
232 AllowedRange::no_check(),
233 1,
234 ),
235 object::elf::R_RISCV_GOT32_PCREL => (
236 RelocationKind::GotRelative,
237 RelocationSize::ByteSize(4),
238 None,
239 AllowedRange::new(-(2i64.pow(31)), 2i64.pow(32)),
240 1,
241 ),
242 object::elf::R_RISCV_ALIGN => (
243 RelocationKind::Alignment,
244 RelocationSize::ByteSize(0),
245 None,
246 AllowedRange::no_check(),
247 1,
248 ),
249 object::elf::R_RISCV_RVC_BRANCH => (
250 RelocationKind::Relative,
251 RelocationSize::bit_mask_riscv(0, 16, RiscVInstruction::CbType),
252 None,
253 AllowedRange::new(-(2i64.pow(8)), 2i64.pow(9) - 2),
254 1,
255 ),
256 object::elf::R_RISCV_RVC_JUMP => (
257 RelocationKind::Relative,
258 RelocationSize::bit_mask_riscv(0, 16, RiscVInstruction::CjType),
259 None,
260 AllowedRange::new(-(2i64.pow(11)), 2i64.pow(12) - 2),
261 1,
262 ),
263 object::elf::R_RISCV_RELAX => (
264 RelocationKind::None,
265 RelocationSize::ByteSize(0),
266 None,
267 AllowedRange::no_check(),
268 1,
269 ),
270 object::elf::R_RISCV_SUB6 => (
271 RelocationKind::AbsoluteSubtractionWord6,
272 RelocationSize::ByteSize(1),
273 None,
274 AllowedRange::no_check(),
275 1,
276 ),
277 object::elf::R_RISCV_SET6 => (
278 RelocationKind::AbsoluteSetWord6,
279 RelocationSize::ByteSize(1),
280 None,
281 AllowedRange::no_check(),
282 1,
283 ),
284 object::elf::R_RISCV_SET8 => (
285 RelocationKind::AbsoluteSet,
286 RelocationSize::ByteSize(1),
287 None,
288 AllowedRange::no_check(),
289 1,
290 ),
291 object::elf::R_RISCV_SET16 => (
292 RelocationKind::AbsoluteSet,
293 RelocationSize::ByteSize(2),
294 None,
295 AllowedRange::no_check(),
296 1,
297 ),
298 object::elf::R_RISCV_SET32 => (
299 RelocationKind::AbsoluteSet,
300 RelocationSize::ByteSize(4),
301 None,
302 AllowedRange::no_check(),
303 1,
304 ),
305 object::elf::R_RISCV_32_PCREL => (
306 RelocationKind::Relative,
307 RelocationSize::ByteSize(4),
308 None,
309 AllowedRange::new(-(2i64.pow(31)), 2i64.pow(32)),
310 1,
311 ),
312 object::elf::R_RISCV_PLT32 => (
313 RelocationKind::PltRelative,
314 RelocationSize::ByteSize(4),
315 None,
316 AllowedRange::new(-(2i64.pow(31)), 2i64.pow(32)),
317 1,
318 ),
319 object::elf::R_RISCV_SET_ULEB128 => (
322 RelocationKind::Relative,
323 RelocationSize::ByteSize(0),
324 None,
325 AllowedRange::no_check(),
326 1,
327 ),
328 object::elf::R_RISCV_SUB_ULEB128 => (
329 RelocationKind::PairSubtractionULEB128(object::elf::R_RISCV_SET_ULEB128),
330 RelocationSize::ByteSize(8),
331 None,
332 AllowedRange::no_check(),
333 1,
334 ),
335 object::elf::R_RISCV_TLSDESC_HI20 => return None,
337 object::elf::R_RISCV_TLSDESC_LOAD_LO12 => return None,
338 object::elf::R_RISCV_TLSDESC_ADD_LO12 => return None,
339 object::elf::R_RISCV_TLSDESC_CALL => return None,
340 _ => return None,
341 };
342
343 Some(RelocationKindInfo {
344 kind,
345 size,
346 mask,
347 range,
348 alignment,
349 bias: 0,
350 })
351}
352
353const UTYPE_IMMEDIATE_MASK: u32 = 0b0000_0000_0000_0000_0000_1111_1111_1111;
354const ITYPE_IMMEDIATE_MASK: u32 = 0b0000_0000_0000_1111_1111_1111_1111_1111;
355const STYPE_IMMEDIATE_MASK: u32 = 0b0000_0001_1111_1111_1111_0000_0111_1111;
356const BTYPE_IMMEDIATE_MASK: u32 = 0b0000_0001_1111_1111_1111_0000_0111_1111;
357const JTYPE_IMMEDIATE_MASK: u32 = 0b0000_0000_0000_0000_0000_1111_1111_1111;
358
359const CBTYPE_IMMEDIATE_MASK: u16 = 0b1110_0011_1000_0011;
360const CJTYPE_IMMEDIATE_MASK: u16 = 0b1110_0000_0000_0011;
361
362impl RiscVInstruction {
363 pub fn write_to_value(self, extracted_value: u64, _negative: bool, dest: &mut [u8]) {
371 match self {
372 RiscVInstruction::UiType => {
373 RiscVInstruction::UType.write_to_value(extracted_value, _negative, &mut dest[..4]);
374 RiscVInstruction::IType.write_to_value(extracted_value, _negative, &mut dest[4..]);
375 }
376 RiscVInstruction::UType => {
377 let mask = (extracted_value.wrapping_add(0x800).extract_bits(12..32) as u32) << 12;
382 and_from_slice(dest, UTYPE_IMMEDIATE_MASK.to_le_bytes().as_slice());
383 or_from_slice(dest, &mask.to_le_bytes());
384 }
385 RiscVInstruction::IType => {
386 let mask = extracted_value << 20;
387 and_from_slice(dest, ITYPE_IMMEDIATE_MASK.to_le_bytes().as_slice());
388 or_from_slice(dest, &(mask as u32).to_le_bytes());
389 }
390 RiscVInstruction::SType => {
391 let mut mask = extracted_value.extract_bits(0..5) << 7;
392 mask |= extracted_value.extract_bits(5..12) << 25;
393 and_from_slice(dest, STYPE_IMMEDIATE_MASK.to_le_bytes().as_slice());
394 or_from_slice(dest, &(mask as u32).to_le_bytes());
395 }
396 RiscVInstruction::BType => {
397 let mut mask = extracted_value.extract_bit(11) << 7;
398 mask |= extracted_value.extract_bits(1..5) << 8;
399 mask |= extracted_value.extract_bits(5..11) << 25;
400 mask |= extracted_value.extract_bit(12) << 31;
401 and_from_slice(dest, BTYPE_IMMEDIATE_MASK.to_le_bytes().as_slice());
402 or_from_slice(dest, &(mask as u32).to_le_bytes());
403 }
404 RiscVInstruction::JType => {
405 let mut mask = extracted_value.extract_bits(12..20) << 12;
406 mask |= extracted_value.extract_bit(11) << 20;
407 mask |= extracted_value.extract_bits(1..11) << 21;
408 mask |= extracted_value.extract_bit(20) << 31;
409 and_from_slice(dest, JTYPE_IMMEDIATE_MASK.to_le_bytes().as_slice());
410 or_from_slice(dest, &(mask as u32).to_le_bytes());
411 }
412 RiscVInstruction::CbType => {
413 let mut mask = extracted_value.extract_bit(5) << 2;
414 mask |= extracted_value.extract_bits(1..3) << 3;
415 mask |= extracted_value.extract_bits(6..8) << 5;
416 mask |= extracted_value.extract_bits(3..5) << 10;
418 mask |= extracted_value.extract_bit(8) << 12;
419 and_from_slice(dest, CBTYPE_IMMEDIATE_MASK.to_le_bytes().as_slice());
421 or_from_slice(dest, &mask.to_le_bytes()[..2]);
422 }
423 RiscVInstruction::CjType => {
424 let mut mask = extracted_value.extract_bit(5) << 2;
425 mask |= extracted_value.extract_bits(1..4) << 3;
426 mask |= extracted_value.extract_bit(7) << 6;
427 mask |= extracted_value.extract_bit(6) << 7;
428 mask |= extracted_value.extract_bit(10) << 8;
429 mask |= extracted_value.extract_bits(8..10) << 9;
430 mask |= extracted_value.extract_bit(4) << 11;
431 mask |= extracted_value.extract_bit(11) << 12;
432 and_from_slice(dest, CJTYPE_IMMEDIATE_MASK.to_le_bytes().as_slice());
434 or_from_slice(dest, &mask.to_le_bytes()[..2]);
435 }
436 };
437 }
438
439 #[must_use]
442 pub fn read_value(self, bytes: &[u8]) -> (u64, bool) {
443 match self {
444 RiscVInstruction::UiType => {
445 let (hi, _) = RiscVInstruction::UType.read_value(&bytes[..4]);
446 let (lo, _) = RiscVInstruction::IType.read_value(&bytes[4..]);
447 (hi << 12 | lo, false)
448 }
449 RiscVInstruction::UType => {
450 let value = u32_from_slice(bytes);
451 let imm = (value >> 12) & 0xfffff;
452 let adjusted = ((imm as i32) << 12) >> 12;
453 ((adjusted as u64).wrapping_sub(0x800), false)
454 }
455 RiscVInstruction::IType => {
456 let value = u32_from_slice(bytes);
457 let imm = (value >> 20) & 0xfff;
458 let sign_extended = ((imm as i32) << 20) >> 20;
459 (sign_extended as u64, sign_extended < 0)
460 }
461 RiscVInstruction::SType => {
462 let value = u32_from_slice(bytes);
463 let imm_low = (value >> 7) & 0x1f;
464 let imm_high = (value >> 25) & 0x7f;
465 let imm = (imm_high << 5) | imm_low;
466 let sign_extended = ((imm as i32) << 20) >> 20;
467 (sign_extended as u64, sign_extended < 0)
468 }
469 RiscVInstruction::BType => {
470 let value = u32_from_slice(bytes);
471 let imm11 = (value >> 7) & 0x1;
472 let imm1_4 = (value >> 8) & 0xf;
473 let imm5_10 = (value >> 25) & 0x3f;
474 let imm12 = (value >> 31) & 0x1;
475
476 let imm = (imm12 << 12) | (imm11 << 11) | (imm5_10 << 5) | (imm1_4 << 1);
477 let sign_extended = ((imm as i32) << 19) >> 19;
478 (sign_extended as u64, sign_extended < 0)
479 }
480 RiscVInstruction::JType => {
481 let value = u32_from_slice(bytes);
482 let imm12_19 = (value >> 12) & 0xff;
483 let imm11 = (value >> 20) & 0x1;
484 let imm1_10 = (value >> 21) & 0x3ff;
485 let imm20 = (value >> 31) & 0x1;
486
487 let imm = (imm20 << 20) | (imm12_19 << 12) | (imm11 << 11) | (imm1_10 << 1);
488 let sign_extended = ((imm as i32) << 11) >> 11;
489 (sign_extended as u64, sign_extended < 0)
490 }
491 RiscVInstruction::CbType => {
492 let value = u16::from_le_bytes([bytes[0], bytes[1]]);
493 let imm5 = (value >> 2) & 0x1;
494 let imm1_2 = (value >> 3) & 0x3;
495 let imm6_7 = (value >> 5) & 0x3;
496 let imm3_4 = (value >> 10) & 0x3;
497 let imm8 = (value >> 12) & 0x1;
498
499 let imm = (imm8 << 8) | (imm6_7 << 6) | (imm5 << 5) | (imm3_4 << 3) | (imm1_2 << 1);
500 let sign_extended = (i32::from(imm) << 23) >> 23;
501 (sign_extended as u64, sign_extended < 0)
502 }
503 RiscVInstruction::CjType => {
504 let value = u16::from_le_bytes([bytes[0], bytes[1]]);
505 let imm5 = (value >> 2) & 0x1;
506 let imm1_3 = (value >> 3) & 0x7;
507 let imm7 = (value >> 6) & 0x1;
508 let imm6 = (value >> 7) & 0x1;
509 let imm10 = (value >> 8) & 0x1;
510 let imm8_9 = (value >> 9) & 0x3;
511 let imm4 = (value >> 11) & 0x1;
512 let imm11 = (value >> 12) & 0x1;
513
514 let imm = (imm11 << 11)
515 | (imm10 << 10)
516 | (imm8_9 << 8)
517 | (imm7 << 7)
518 | (imm6 << 6)
519 | (imm5 << 5)
520 | (imm4 << 4)
521 | (imm1_3 << 1);
522 let sign_extended = (i32::from(imm) << 20) >> 20;
523 (sign_extended as u64, sign_extended < 0)
524 }
525 }
526 }
527}
528
529#[test]
530fn test_riscv_insn_immediate_mask() {
531 for (mask, insn) in &[
532 (UTYPE_IMMEDIATE_MASK, RiscVInstruction::UType),
533 (ITYPE_IMMEDIATE_MASK, RiscVInstruction::IType),
534 (STYPE_IMMEDIATE_MASK, RiscVInstruction::SType),
535 (BTYPE_IMMEDIATE_MASK, RiscVInstruction::BType),
536 (JTYPE_IMMEDIATE_MASK, RiscVInstruction::JType),
537 ] {
538 let mut dest = [0u8; 4];
539 let value = if matches!(insn, RiscVInstruction::UType) {
540 u64::MAX.wrapping_sub(0x800)
541 } else {
542 u64::MAX
543 };
544 insn.write_to_value(value, false, &mut dest);
545 assert_eq!(!mask, u32::from_le_bytes(dest));
546 }
547}
548
549#[test]
550fn test_riscv_insn_rvcimmediate_mask() {
551 for (mask, insn) in &[
552 (CBTYPE_IMMEDIATE_MASK, RiscVInstruction::CbType),
553 (CJTYPE_IMMEDIATE_MASK, RiscVInstruction::CjType),
554 ] {
555 let mut dest = [0u8; 2];
556 insn.write_to_value(u64::from(u16::MAX), false, &mut dest);
557 assert_eq!(!mask, u16::from_le_bytes(dest));
558 }
559}