1use std::collections::HashMap;
6use std::fmt::{Debug, Display};
7use std::fs;
8use std::ops::{Deref, DerefMut, Range};
9use std::path::Path;
10use std::time::Duration;
11
12use anyhow::Result;
13use object::{Object, ObjectSymbol};
14
15use crate::io::jtag::{Jtag, RiscvCsr, RiscvGpr, RiscvReg};
16
17pub struct ElfSymbols {
18 symbols: HashMap<String, u32>,
19}
20
21pub struct ElfDebugger<'a> {
22 symbols: &'a ElfSymbols,
23 jtag: Box<dyn Jtag + 'a>,
24}
25
26impl<'a> Deref for ElfDebugger<'a> {
27 type Target = dyn Jtag + 'a;
28
29 #[inline]
30 fn deref(&self) -> &Self::Target {
31 &*self.jtag
32 }
33}
34
35impl<'a> DerefMut for ElfDebugger<'a> {
36 #[inline]
37 fn deref_mut(&mut self) -> &mut Self::Target {
38 &mut *self.jtag
39 }
40}
41
42#[derive(Clone)]
43pub enum SymbolicAddress {
44 Absolute(u32),
45 SymbolRelative(String, u32),
46}
47
48impl From<String> for SymbolicAddress {
49 #[inline]
50 fn from(s: String) -> Self {
51 Self::SymbolRelative(s, 0)
52 }
53}
54
55impl From<&str> for SymbolicAddress {
56 #[inline]
57 fn from(s: &str) -> Self {
58 Self::SymbolRelative(s.to_owned(), 0)
59 }
60}
61
62impl From<u32> for SymbolicAddress {
63 #[inline]
64 fn from(s: u32) -> Self {
65 Self::Absolute(s)
66 }
67}
68
69impl std::ops::Add<u32> for SymbolicAddress {
70 type Output = Self;
71
72 #[inline]
73 fn add(self, rhs: u32) -> Self::Output {
74 match self {
75 SymbolicAddress::Absolute(addr) => SymbolicAddress::Absolute(addr + rhs),
76 SymbolicAddress::SymbolRelative(symbol, offset) => {
77 SymbolicAddress::SymbolRelative(symbol, offset + rhs)
78 }
79 }
80 }
81}
82
83impl Debug for SymbolicAddress {
84 #[inline]
85 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86 Display::fmt(self, f)
87 }
88}
89
90impl Display for SymbolicAddress {
91 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
92 match self {
93 SymbolicAddress::Absolute(addr) => write!(f, "{addr:#x}"),
94 SymbolicAddress::SymbolRelative(symbol, offset) => {
95 if *offset == 0 {
96 write!(f, "{symbol}")
97 } else {
98 write!(f, "{symbol} + {offset:#x}")
99 }
100 }
101 }
102 }
103}
104
105#[derive(Clone)]
106pub struct ResolvedAddress {
107 pub address: SymbolicAddress,
108 pub resolution: u32,
109}
110
111impl Debug for ResolvedAddress {
112 #[inline]
113 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
114 Display::fmt(self, f)
115 }
116}
117
118impl Display for ResolvedAddress {
119 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
120 Display::fmt(&self.address, f)?;
121
122 if !matches!(self.address, SymbolicAddress::Absolute(_)) {
124 write!(f, " ({:#x})", self.resolution)?;
125 }
126
127 Ok(())
128 }
129}
130
131impl ElfSymbols {
132 pub fn load_elf(path: impl AsRef<Path>) -> Result<Self> {
133 let elf_binary = fs::read(path)?;
134 let elf_file = object::File::parse(&*elf_binary)?;
135 let mut symbols = HashMap::new();
136 for sym in elf_file.symbols() {
137 symbols.insert(sym.name()?.to_owned(), sym.address() as u32);
138 }
139 Ok(Self { symbols })
140 }
141
142 pub fn resolve(&self, address: impl Into<SymbolicAddress>) -> Result<ResolvedAddress> {
144 let address = address.into();
145 let resolution = match address {
146 SymbolicAddress::Absolute(addr) => addr,
147 SymbolicAddress::SymbolRelative(ref symbol, offset) => {
148 let Some(symbol_addr) = self.symbols.get(symbol).copied() else {
149 anyhow::bail!("Cannot resolve symbol {symbol}");
150 };
151 symbol_addr + offset
152 }
153 };
154 Ok(ResolvedAddress {
155 address,
156 resolution,
157 })
158 }
159
160 pub fn attach<'a>(&'a self, jtag: Box<dyn Jtag + 'a>) -> ElfDebugger<'a> {
162 ElfDebugger {
163 symbols: self,
164 jtag,
165 }
166 }
167}
168
169impl<'a> ElfDebugger<'a> {
170 pub fn disconnect(self) -> Result<()> {
171 self.jtag.disconnect()
172 }
173
174 pub fn resolve(&self, address: impl Into<SymbolicAddress>) -> Result<ResolvedAddress> {
175 self.symbols.resolve(address)
176 }
177
178 pub fn read_reg(&mut self, reg: impl Into<RiscvReg>) -> Result<u32> {
182 self.read_riscv_reg(®.into())
183 }
184
185 pub fn write_reg(&mut self, reg: impl Into<RiscvReg>, value: u32) -> Result<()> {
189 self.write_riscv_reg(®.into(), value)
190 }
191
192 pub fn read_u32(&mut self, addr: u32) -> Result<u32> {
196 let mut ret = [0];
197 self.read_memory32(addr, &mut ret)?;
198 Ok(ret[0])
199 }
200
201 pub fn write_u32(&mut self, addr: u32, value: u32) -> Result<()> {
205 self.write_memory32(addr, &[value])
206 }
207
208 pub fn get_pc(&mut self) -> Result<u32> {
210 self.read_riscv_reg(&RiscvReg::Csr(RiscvCsr::DPC))
211 }
212
213 pub fn set_pc(&mut self, address: impl Into<SymbolicAddress>) -> Result<()> {
215 let resolved = self.resolve(address)?;
216 log::info!("Set PC to {}", resolved);
217 self.write_reg(RiscvCsr::DPC, resolved.resolution)?;
218 Ok(())
219 }
220
221 pub fn set_breakpoint(&mut self, address: impl Into<SymbolicAddress>) -> Result<()> {
223 let resolved = self.resolve(address)?;
224 log::info!("Set breakpoint at {}", resolved);
225 self.jtag.set_breakpoint(resolved.resolution, true)?;
226 Ok(())
227 }
228
229 pub fn expect_pc(&mut self, address: impl Into<SymbolicAddress>) -> Result<()> {
231 let resolved = self.resolve(address)?;
232 let pc = self.get_pc()?;
233 log::info!("PC = {:#x}, expected PC = {}", pc, resolved);
234 if pc != resolved.resolution {
235 anyhow::bail!("unexpected PC");
236 }
237 Ok(())
238 }
239
240 pub fn expect_pc_range(&mut self, range: Range<impl Into<SymbolicAddress>>) -> Result<()> {
242 let start = self.resolve(range.start)?;
243 let end = self.resolve(range.end)?;
244 let pc = self.get_pc()?;
245 log::info!("PC = {:#x}, expected PC = {}..{}", pc, start, end,);
246 if !(start.resolution..end.resolution).contains(&pc) {
247 anyhow::bail!("unexpected PC");
248 }
249 Ok(())
250 }
251
252 pub fn run_until(
260 &mut self,
261 address: impl Into<SymbolicAddress>,
262 timeout: Duration,
263 ) -> Result<()> {
264 let resolved = self.resolve(address)?;
265 log::info!("Run until {}", resolved);
266 self.jtag.set_breakpoint(resolved.resolution, true)?;
267 self.jtag.resume()?;
268 self.jtag.wait_halt(timeout)?;
269 self.expect_pc(resolved.resolution)?;
270 self.jtag.remove_breakpoint(resolved.resolution)?;
271 Ok(())
272 }
273
274 pub fn finish(&mut self, timeout: Duration) -> Result<()> {
279 let ra = self.read_reg(RiscvGpr::RA)?;
280 self.run_until(ra, timeout)
281 }
282
283 pub fn call(
285 &mut self,
286 address: impl Into<SymbolicAddress>,
287 args: &[u32],
288 timeout: Duration,
289 ) -> Result<(u32, u32)> {
290 const REGS_TO_SAVE: &[RiscvGpr] = &[
293 RiscvGpr::RA,
294 RiscvGpr::SP,
295 RiscvGpr::T0,
296 RiscvGpr::T1,
297 RiscvGpr::T2,
298 RiscvGpr::A0,
299 RiscvGpr::A1,
300 RiscvGpr::A2,
301 RiscvGpr::A3,
302 RiscvGpr::A4,
303 RiscvGpr::A5,
304 RiscvGpr::A6,
305 RiscvGpr::A7,
306 RiscvGpr::T3,
307 RiscvGpr::T4,
308 RiscvGpr::T5,
309 RiscvGpr::T6,
310 ];
311 let mut saved = [0; REGS_TO_SAVE.len()];
312 for (idx, gpr) in REGS_TO_SAVE.iter().copied().enumerate() {
313 saved[idx] = self.read_reg(gpr)?;
314 }
315
316 if saved[1] % 16 != 0 {
319 self.write_reg(RiscvGpr::SP, saved[1] & !15)?;
320 }
321
322 const ARG_GPRS: &[RiscvGpr] = &[
324 RiscvGpr::A0,
325 RiscvGpr::A1,
326 RiscvGpr::A2,
327 RiscvGpr::A3,
328 RiscvGpr::A4,
329 RiscvGpr::A5,
330 RiscvGpr::A6,
331 ];
332 assert!(args.len() < ARG_GPRS.len());
333 for (gpr, arg) in ARG_GPRS.iter().copied().zip(args.iter().copied()) {
334 self.write_reg(gpr, arg)?;
335 }
336
337 let pc = self.get_pc()?;
342 self.write_reg(RiscvGpr::RA, pc)?;
343 self.set_pc(address)?;
344 self.run_until(pc, timeout)?;
345
346 let a0 = self.read_reg(RiscvGpr::A0)?;
348 let a1 = self.read_reg(RiscvGpr::A1)?;
349
350 for (idx, gpr) in REGS_TO_SAVE.iter().copied().enumerate() {
352 self.write_reg(gpr, saved[idx])?;
353 }
354
355 Ok((a0, a1))
356 }
357}