#[cfg(feature = "pyo3")]
use pyo3::prelude::*;
use super::{RelocReferencedSym, RelocationInfo};
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[non_exhaustive]
#[allow(non_camel_case_types)]
#[cfg_attr(feature = "pyo3", pyclass(module = "spimdisasm", eq))]
pub enum RelocationType {
R_MIPS_NONE = 0,
R_MIPS_16 = 1,
R_MIPS_32 = 2,
R_MIPS_REL32 = 3,
R_MIPS_26 = 4,
R_MIPS_HI16 = 5,
R_MIPS_LO16 = 6,
R_MIPS_GPREL16 = 7,
R_MIPS_LITERAL = 8,
R_MIPS_GOT16 = 9,
R_MIPS_PC16 = 10,
R_MIPS_CALL16 = 11,
R_MIPS_GPREL32 = 12,
R_MIPS_GOT_HI16 = 22,
R_MIPS_GOT_LO16 = 23,
R_MIPS_CALL_HI16 = 30,
R_MIPS_CALL_LO16 = 31,
R_CUSTOM_CONSTANT_HI = -1,
R_CUSTOM_CONSTANT_LO = -2,
}
impl RelocationType {
#[must_use]
pub const fn name(&self) -> &'static str {
match *self {
RelocationType::R_MIPS_NONE => "R_MIPS_NONE",
RelocationType::R_MIPS_16 => "R_MIPS_16",
RelocationType::R_MIPS_32 => "R_MIPS_32",
RelocationType::R_MIPS_REL32 => "R_MIPS_REL32",
RelocationType::R_MIPS_26 => "R_MIPS_26",
RelocationType::R_MIPS_HI16 => "R_MIPS_HI16",
RelocationType::R_MIPS_LO16 => "R_MIPS_LO16",
RelocationType::R_MIPS_GPREL16 => "R_MIPS_GPREL16",
RelocationType::R_MIPS_LITERAL => "R_MIPS_LITERAL",
RelocationType::R_MIPS_GOT16 => "R_MIPS_GOT16",
RelocationType::R_MIPS_PC16 => "R_MIPS_PC16",
RelocationType::R_MIPS_CALL16 => "R_MIPS_CALL16",
RelocationType::R_MIPS_GPREL32 => "R_MIPS_GPREL32",
RelocationType::R_MIPS_GOT_HI16 => "R_MIPS_GOT_HI16",
RelocationType::R_MIPS_GOT_LO16 => "R_MIPS_GOT_LO16",
RelocationType::R_MIPS_CALL_HI16 => "R_MIPS_CALL_HI16",
RelocationType::R_MIPS_CALL_LO16 => "R_MIPS_CALL_LO16",
RelocationType::R_CUSTOM_CONSTANT_HI => "R_CUSTOM_CONSTANT_HI",
RelocationType::R_CUSTOM_CONSTANT_LO => "R_CUSTOM_CONSTANT_LO",
}
}
#[must_use]
pub fn from_name(name: &str) -> Option<Self> {
match name {
"R_MIPS_NONE" => Some(RelocationType::R_MIPS_NONE),
"R_MIPS_16" => Some(RelocationType::R_MIPS_16),
"R_MIPS_32" => Some(RelocationType::R_MIPS_32),
"R_MIPS_REL32" => Some(RelocationType::R_MIPS_REL32),
"R_MIPS_26" => Some(RelocationType::R_MIPS_26),
"R_MIPS_HI16" => Some(RelocationType::R_MIPS_HI16),
"R_MIPS_LO16" => Some(RelocationType::R_MIPS_LO16),
"R_MIPS_GPREL16" => Some(RelocationType::R_MIPS_GPREL16),
"R_MIPS_LITERAL" => Some(RelocationType::R_MIPS_LITERAL),
"R_MIPS_GOT16" => Some(RelocationType::R_MIPS_GOT16),
"R_MIPS_PC16" => Some(RelocationType::R_MIPS_PC16),
"R_MIPS_CALL16" => Some(RelocationType::R_MIPS_CALL16),
"R_MIPS_GPREL32" => Some(RelocationType::R_MIPS_GPREL32),
"R_MIPS_GOT_HI16" => Some(RelocationType::R_MIPS_GOT_HI16),
"R_MIPS_GOT_LO16" => Some(RelocationType::R_MIPS_GOT_LO16),
"R_MIPS_CALL_HI16" => Some(RelocationType::R_MIPS_CALL_HI16),
"R_MIPS_CALL_LO16" => Some(RelocationType::R_MIPS_CALL_LO16),
"R_CUSTOM_CONSTANT_HI" => Some(RelocationType::R_CUSTOM_CONSTANT_HI),
"R_CUSTOM_CONSTANT_LO" => Some(RelocationType::R_CUSTOM_CONSTANT_LO),
_ => None,
}
}
#[must_use]
pub const fn is_none(&self) -> bool {
matches!(self, RelocationType::R_MIPS_NONE)
}
#[must_use]
pub(crate) fn uses_parenthesis(&self) -> bool {
match *self {
RelocationType::R_MIPS_NONE => false,
RelocationType::R_MIPS_16 => false,
RelocationType::R_MIPS_32 => false,
RelocationType::R_MIPS_REL32 => false,
RelocationType::R_MIPS_26 => false,
RelocationType::R_MIPS_HI16 => true,
RelocationType::R_MIPS_LO16 => true,
RelocationType::R_MIPS_GPREL16 => true,
RelocationType::R_MIPS_LITERAL => false,
RelocationType::R_MIPS_GOT16 => true,
RelocationType::R_MIPS_PC16 => false,
RelocationType::R_MIPS_CALL16 => true,
RelocationType::R_MIPS_GPREL32 => false,
RelocationType::R_MIPS_GOT_HI16 => true,
RelocationType::R_MIPS_GOT_LO16 => true,
RelocationType::R_MIPS_CALL_HI16 => true,
RelocationType::R_MIPS_CALL_LO16 => true,
RelocationType::R_CUSTOM_CONSTANT_HI => true,
RelocationType::R_CUSTOM_CONSTANT_LO => true,
}
}
#[must_use]
pub fn allow_addends_on_ref(&self) -> bool {
!matches!(
self,
RelocationType::R_MIPS_26
| RelocationType::R_MIPS_PC16
| RelocationType::R_MIPS_CALL16
| RelocationType::R_MIPS_CALL_HI16
| RelocationType::R_MIPS_CALL_LO16
)
}
#[must_use]
pub(crate) fn valid_for_function(&self) -> bool {
match *self {
RelocationType::R_MIPS_NONE => true,
RelocationType::R_MIPS_16 => true, RelocationType::R_MIPS_32 => false,
RelocationType::R_MIPS_REL32 => false, RelocationType::R_MIPS_26 => true,
RelocationType::R_MIPS_HI16 => true,
RelocationType::R_MIPS_LO16 => true,
RelocationType::R_MIPS_GPREL16 => true,
RelocationType::R_MIPS_LITERAL => true, RelocationType::R_MIPS_GOT16 => true,
RelocationType::R_MIPS_PC16 => true,
RelocationType::R_MIPS_CALL16 => true,
RelocationType::R_MIPS_GPREL32 => false,
RelocationType::R_MIPS_GOT_HI16 => true,
RelocationType::R_MIPS_GOT_LO16 => true,
RelocationType::R_MIPS_CALL_HI16 => true,
RelocationType::R_MIPS_CALL_LO16 => true,
RelocationType::R_CUSTOM_CONSTANT_HI => true,
RelocationType::R_CUSTOM_CONSTANT_LO => true,
}
}
#[must_use]
pub(crate) fn valid_for_data_sym(&self) -> bool {
match *self {
RelocationType::R_MIPS_NONE => true,
RelocationType::R_MIPS_16 => true, RelocationType::R_MIPS_32 => true,
RelocationType::R_MIPS_REL32 => true, RelocationType::R_MIPS_26 => false,
RelocationType::R_MIPS_HI16 => false,
RelocationType::R_MIPS_LO16 => false,
RelocationType::R_MIPS_GPREL16 => false,
RelocationType::R_MIPS_LITERAL => true, RelocationType::R_MIPS_GOT16 => false,
RelocationType::R_MIPS_PC16 => false,
RelocationType::R_MIPS_CALL16 => false,
RelocationType::R_MIPS_GPREL32 => true,
RelocationType::R_MIPS_GOT_HI16 => false,
RelocationType::R_MIPS_GOT_LO16 => false,
RelocationType::R_MIPS_CALL_HI16 => false,
RelocationType::R_MIPS_CALL_LO16 => false,
RelocationType::R_CUSTOM_CONSTANT_HI => false,
RelocationType::R_CUSTOM_CONSTANT_LO => false,
}
}
#[must_use]
pub fn new_reloc_info(self, referenced_sym: RelocReferencedSym) -> RelocationInfo {
RelocationInfo::new(self, referenced_sym)
}
}
#[cfg(feature = "pyo3")]
pub(crate) mod python_bindings {
use super::*;
#[pymethods]
impl RelocationType {
#[pyo3(name = "from_name")]
#[staticmethod]
pub fn py_from_name(name: &str) -> Option<Self> {
Self::from_name(name)
}
}
}