Skip to content

Commit 284913e

Browse files
committed
Added armv7-linux-gnueabihf support.
Some more stuff was pulled into arch-specific modules, since arm/x86 differ. Began work for making function abort code part of the function.
1 parent ce68f40 commit 284913e

13 files changed

Lines changed: 1197 additions & 60 deletions

File tree

src/code.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ impl std::ops::AddAssign for Relocatable {
6262
let lhs_len = self.data.len();
6363
self.data.to_mut().extend_from_slice(&rhs.data);
6464

65+
self.abs_symbols.extend(rhs.abs_symbols.into_iter().map(
66+
|(sym, val)| (sym, val)
67+
));
68+
6569
self.symbols.extend(rhs.symbols.into_iter().map(
6670
|(sym, loc)| (sym, loc + lhs_len)
6771
));

src/code/arch/arm.rs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
use crate::code::AssembleError;
2+
3+
4+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5+
pub(crate) enum RelocationKind {
6+
None = 0,
7+
Jump24 = 29,
8+
Movw,
9+
Movt,
10+
}
11+
12+
impl RelocationKind {
13+
/// Addend has already been applied to value
14+
pub(crate) fn apply_relative(self, data: &mut [u8], location: usize, value: usize) -> Result<(), AssembleError> {
15+
use RelocationKind::*;
16+
let value: isize = if location < value {
17+
(value - location).try_into().ok().ok_or(AssembleError::InvalidRelocation("Relative relocation difference too large"))?
18+
} else {
19+
-(location - value).try_into().ok().ok_or(AssembleError::InvalidRelocation("Relative relocation difference too large"))?
20+
};
21+
match self {
22+
None => Ok(()),
23+
Jump24 => {
24+
// Low 24 bits of (big-endian) word contain low 26 bits of pc-relative address (00 on the end) (sign-extended)
25+
let instruction: &mut [u8; 4] = data.get_mut(location..location+4)
26+
.ok_or(AssembleError::InvalidRelocation("Attempted to apply relocation past end of section"))?
27+
.try_into().unwrap();
28+
if value & 3 != 0{
29+
return Err(AssembleError::InvalidRelocation("Relative relocation cut off low bits"));
30+
}
31+
let actual_value = value >> 2;
32+
let actual_value: i32 = actual_value.try_into().ok().ok_or(AssembleError::InvalidRelocation("Relative relocation difference too large"))?;
33+
let bytes = i32::to_le_bytes(actual_value);
34+
if !(
35+
(bytes[3] == 0x00 && bytes[2] & 0x80 == 0x00) ||
36+
(bytes[3] == 0xFF && bytes[2] & 0x80 == 0x80)
37+
) {
38+
return Err(AssembleError::InvalidRelocation("Relative relocation difference too large"));
39+
}
40+
instruction[..3].copy_from_slice(&bytes[..3]);
41+
Ok(())
42+
},
43+
Movw | Movt => Err(AssembleError::InvalidRelocation("Cannot apply direct relocation for relative symbol")),
44+
}
45+
}
46+
pub(crate) fn apply_absolute(self, data: &mut [u8], location: usize, value: isize) -> Result<(), AssembleError> {
47+
use RelocationKind::*;
48+
match self {
49+
None => Ok(()),
50+
Jump24 => Err(AssembleError::InvalidRelocation("Cannot apply relative relocation for absolute symbol")),
51+
Movw => {
52+
// Low 16 bits of value encoded in bits 19-16 and 11-0 of the 4-byte big-endian instruction
53+
let instruction: &mut [u8; 4] = data.get_mut(location..location+4)
54+
.ok_or(AssembleError::InvalidRelocation("Attempted to apply relocation past end of section"))?
55+
.try_into().unwrap();
56+
let actual_value: i32 = value.try_into().ok().ok_or(AssembleError::InvalidRelocation("Relative relocation difference too large"))?;
57+
let low_half: u16 = actual_value as u32 as u16;
58+
let imm4: u8 = (low_half >> 12) as u8 & 0xF;
59+
let imm12: u16 = low_half & 0xFFF;
60+
let imm12_bytes = imm12.to_be_bytes();
61+
instruction[2] &= 0xF0;
62+
instruction[2] |= imm4;
63+
instruction[1] &= 0xF0;
64+
instruction[1] |= imm12_bytes[0];
65+
instruction[0] = imm12_bytes[1];
66+
Ok(())
67+
},
68+
Movt => {
69+
// Low 16 bits of value encoded in bits 19-16 and 11-0 of the 4-byte big-endian instruction
70+
let instruction: &mut [u8; 4] = data.get_mut(location..location+4)
71+
.ok_or(AssembleError::InvalidRelocation("Attempted to apply relocation past end of section"))?
72+
.try_into().unwrap();
73+
let actual_value: i32 = value.try_into().ok().ok_or(AssembleError::InvalidRelocation("Relative relocation difference too large"))?;
74+
let high_half: u16 = (actual_value as u32 >> 16) as u16;
75+
let imm4: u8 = (high_half >> 12) as u8 & 0xF;
76+
let imm12: u16 = high_half & 0xFFF;
77+
let imm12_bytes = imm12.to_be_bytes();
78+
instruction[2] &= 0xF0;
79+
instruction[2] |= imm4;
80+
instruction[1] &= 0xF0;
81+
instruction[1] |= imm12_bytes[0];
82+
instruction[0] = imm12_bytes[1];
83+
Ok(())
84+
},
85+
}
86+
}
87+
}

src/code/symbol.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::sync::atomic::AtomicUsize;
22

33
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
44
enum SymbolInner {
5+
Abort,
56
Local(usize),
67
Global(String),
78
}
@@ -21,12 +22,16 @@ impl Symbol {
2122
let idx = LOCAL_COUNTER.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
2223
Symbol { inner: SymbolInner::Local(idx) }
2324
}
25+
pub fn abort() -> Self {
26+
Symbol { inner: SymbolInner::Abort }
27+
}
2428
}
2529

2630
impl std::fmt::Debug for Symbol {
2731
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2832
use SymbolInner::*;
2933
match &self.inner {
34+
Abort => write!(f, "\".Labort\""),
3035
Local(idx) => write!(f, "\".L{}\"", idx),
3136
Global(sym) => write!(f, "{:?}", sym),
3237
}
@@ -37,6 +42,7 @@ impl std::fmt::Display for Symbol {
3742
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3843
use SymbolInner::*;
3944
match &self.inner {
45+
Abort => write!(f, ".Labort"),
4046
Local(idx) => write!(f, ".L{}", idx),
4147
Global(sym) => write!(f, "{}", sym),
4248
}

0 commit comments

Comments
 (0)