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