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 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}