arch_ops/
traits.rs

1use std::io::{Read, Write};
2
3#[derive(Clone, Debug, Hash, PartialEq, Eq)]
4pub enum Address {
5    Abs(u128),
6    Disp(i64),
7    Symbol { name: String, disp: i64 },
8    PltSym { name: String },
9}
10
11impl core::fmt::Display for Address {
12    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13        match self {
14            Self::Abs(n) => f.write_fmt(format_args!("{:#x}", n)),
15            Self::Disp(n) => f.write_fmt(format_args!("{:+}", n)),
16            Self::Symbol { name, disp: 0 } => f.write_str(name),
17            Self::Symbol { name, disp } => f.write_fmt(format_args!("{}{:+}", name, disp)),
18            Self::PltSym { name } => f.write_fmt(format_args!("{}@plt", name)),
19        }
20    }
21}
22
23pub trait InsnRead: Read {
24    fn read_addr(&mut self, size: usize, rel: bool) -> std::io::Result<Address>;
25    /// Reads a relocation
26    /// If `offset` is `None`, reads from the head of the stream. Otherwise, reads from the given offset from the head.
27    ///
28    /// If `offset` is not-None, the function may error if it is not between -size and size in bytes, rounded away from zero
29    fn read_reloc(
30        &mut self,
31        size: usize,
32        rel: bool,
33        offset: Option<isize>,
34    ) -> std::io::Result<Option<Address>>;
35}
36
37impl<R: InsnRead + ?Sized> InsnRead for &mut R {
38    fn read_addr(&mut self, size: usize, rel: bool) -> std::io::Result<Address> {
39        <R as InsnRead>::read_addr(self, size, rel)
40    }
41
42    fn read_reloc(
43        &mut self,
44        size: usize,
45        rel: bool,
46        offset: Option<isize>,
47    ) -> std::io::Result<Option<Address>> {
48        <R as InsnRead>::read_reloc(self, size, rel, offset)
49    }
50}
51
52impl<R: InsnRead + ?Sized> InsnRead for Box<R> {
53    fn read_addr(&mut self, size: usize, rel: bool) -> std::io::Result<Address> {
54        <R as InsnRead>::read_addr(self, size, rel)
55    }
56
57    fn read_reloc(
58        &mut self,
59        size: usize,
60        rel: bool,
61        offset: Option<isize>,
62    ) -> std::io::Result<Option<Address>> {
63        <R as InsnRead>::read_reloc(self, size, rel, offset)
64    }
65}
66
67pub fn default_write_zeroes<W: Write>(mut out: W, mut count: usize) -> std::io::Result<()> {
68    let val: [u8; 1024] = [0; 1024];
69    while count >= 1024 {
70        out.write_all(&val)?;
71        count -= 1024;
72    }
73    out.write_all(&val[..count])
74}
75
76pub trait InsnWrite: Write {
77    fn write_addr(&mut self, size: usize, addr: Address, rel: bool) -> std::io::Result<()>;
78    fn write_reloc(&mut self, reloc: Reloc) -> std::io::Result<()>;
79    fn offset(&self) -> usize;
80    fn write_zeroes(&mut self, count: usize) -> std::io::Result<()> {
81        default_write_zeroes(self, count)
82    }
83}
84
85impl<W: InsnWrite + ?Sized> InsnWrite for &mut W {
86    fn write_addr(&mut self, size: usize, addr: Address, rel: bool) -> std::io::Result<()> {
87        <W as InsnWrite>::write_addr(self, size, addr, rel)
88    }
89    fn offset(&self) -> usize {
90        <W as InsnWrite>::offset(self)
91    }
92
93    fn write_reloc(&mut self, reloc: Reloc) -> std::io::Result<()> {
94        <W as InsnWrite>::write_reloc(self, reloc)
95    }
96    fn write_zeroes(&mut self, count: usize) -> std::io::Result<()> {
97        <W as InsnWrite>::write_zeroes(self, count)
98    }
99}
100
101impl<W: InsnWrite + ?Sized> InsnWrite for Box<W> {
102    fn write_addr(&mut self, size: usize, addr: Address, rel: bool) -> std::io::Result<()> {
103        <W as InsnWrite>::write_addr(self, size, addr, rel)
104    }
105    fn offset(&self) -> usize {
106        <W as InsnWrite>::offset(self)
107    }
108
109    fn write_reloc(&mut self, reloc: Reloc) -> std::io::Result<()> {
110        <W as InsnWrite>::write_reloc(self, reloc)
111    }
112    fn write_zeroes(&mut self, count: usize) -> std::io::Result<()> {
113        <W as InsnWrite>::write_zeroes(self, count)
114    }
115}
116
117#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
118pub enum RelocCode {
119    None,
120    Abs { addr_width: usize },
121    BaseRel { addr_width: usize },
122    Rel { addr_width: usize },
123    AbsShifted { addr_width: usize, shift: usize },
124    RelShifted { addr_width: usize, shift: usize },
125    Got { addr_width: usize },
126    RelGot { addr_wdith: usize },
127    Plt { addr_width: usize },
128    RelPlt { addr_width: usize },
129    DynSymEntry { width: usize },
130    W65Direct,
131    W65RelaxJsl,
132    W65RelaxJml,
133    W65RelaxBrl,
134    W65RelaxDirect,
135    W65RelaxAbs,
136    W65RelaxJmp,
137    CleverShort,
138    CleverShortPcrel,
139}
140
141#[derive(Clone, Debug, Hash, PartialEq, Eq)]
142pub struct Reloc {
143    pub code: RelocCode,
144    pub symbol: String,
145    pub addend: Option<i64>,
146    pub offset: u64,
147}