Skip to content

Commit 88bd2e3

Browse files
committed
Move registers out of HubrisArchive
1 parent d213698 commit 88bd2e3

4 files changed

Lines changed: 76 additions & 68 deletions

File tree

humility-cli/src/lib.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -285,10 +285,7 @@ impl Cli {
285285
validate: Option<HubrisValidate>,
286286
) -> Result<Box<dyn Core>> {
287287
let mut core = if let Some(dump) = &self.dump {
288-
let Some(hubris) = hubris else {
289-
bail!("cannot load dump without archive");
290-
};
291-
humility::core::attach_dump(dump, hubris)?
288+
humility::core::attach_dump(dump)?
292289
} else if let Some(ip) = &self.ip {
293290
let Some(hubris) = hubris else {
294291
bail!("cannot connect over the network without archive");
@@ -335,9 +332,9 @@ impl Cli {
335332
/// Attaches to a dump
336333
///
337334
/// Reads from the `--dump` argument to pick a target file
338-
pub fn attach_dump(&self, hubris: &HubrisArchive) -> Result<Box<dyn Core>> {
335+
pub fn attach_dump(&self) -> Result<Box<dyn Core>> {
339336
let core = if let Some(dump) = &self.dump {
340-
humility::core::attach_dump(dump, hubris)?
337+
humility::core::attach_dump(dump)?
341338
} else {
342339
bail!("must be run against a dump");
343340
};

humility-core/src/core.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,8 @@ pub enum NetAgent {
129129
Hiffy,
130130
}
131131

132-
pub fn attach_dump(
133-
dump: &str,
134-
hubris: &HubrisArchive,
135-
) -> Result<Box<dyn Core>> {
136-
let core = DumpCore::new(dump, hubris)?;
132+
pub fn attach_dump(dump: &str) -> Result<Box<dyn Core>> {
133+
let core = DumpCore::new(dump)?;
137134
crate::msg!("attached to dump");
138135
Ok(Box::new(core))
139136
}

humility-core/src/dump.rs

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
44

55
use crate::core::Core;
6-
use crate::hubris::HubrisArchive;
7-
use anyhow::{Result, anyhow, bail};
6+
use crate::hubris::OXIDE_NT_HUBRIS_REGISTERS;
7+
use anyhow::{Context, Result, anyhow, bail};
88
use goblin::elf::Elf;
99
use humility_arch_arm::ARMRegister;
10+
use num_traits::FromPrimitive;
1011
use std::collections::{BTreeMap, HashMap};
1112
use std::fs::File;
1213
use std::io::Read;
@@ -15,11 +16,11 @@ use std::path::Path;
1516
pub struct DumpCore {
1617
contents: Vec<u8>,
1718
regions: BTreeMap<u32, (u32, usize)>,
18-
registers: HashMap<ARMRegister, u32>,
19+
registers: Option<HashMap<ARMRegister, u32>>,
1920
}
2021

2122
impl DumpCore {
22-
pub(crate) fn new(dump: &str, hubris: &HubrisArchive) -> Result<DumpCore> {
23+
pub(crate) fn new(dump: &str) -> Result<DumpCore> {
2324
let mut file = File::open(dump)?;
2425
let mut regions = BTreeMap::new();
2526

@@ -41,7 +42,23 @@ impl DumpCore {
4142
);
4243
}
4344

44-
Ok(Self { contents, regions, registers: hubris.dump_registers() })
45+
let mut registers = None;
46+
if let Some(notes) = elf.iter_note_headers(&contents) {
47+
for note in notes {
48+
let note = note.context("failed to parse note")?;
49+
if note.n_type == OXIDE_NT_HUBRIS_REGISTERS {
50+
if registers.is_some() {
51+
bail!(
52+
"multiple copies of OXIDE_NT_HUBRIS_REGISTERS \
53+
found in dump"
54+
);
55+
}
56+
registers = Some(load_registers(note.desc)?);
57+
}
58+
}
59+
}
60+
61+
Ok(Self { contents, regions, registers })
4562
}
4663

4764
fn check_offset(&self, addr: u32, rsize: usize, offs: usize) -> Result<()> {
@@ -67,6 +84,38 @@ impl DumpCore {
6784
}
6885
}
6986

87+
fn load_registers(r: &[u8]) -> Result<HashMap<ARMRegister, u32>> {
88+
if !r.len().is_multiple_of(8) {
89+
bail!("bad length {} in registers note", r.len());
90+
}
91+
let mut registers = HashMap::new();
92+
for (i, chunk) in r.chunks_exact(8).enumerate() {
93+
let (id, val) = chunk.split_at(4);
94+
// We unwrap here because it can only fail if the length is wrong,
95+
// but we've explicitly broken a chunk of 8 into two chunks of 4,
96+
// so a failure here would mean this code has been changed.
97+
let id = u32::from_le_bytes(id.try_into().unwrap());
98+
let val = u32::from_le_bytes(val.try_into().unwrap());
99+
100+
let reg = match ARMRegister::from_u32(id) {
101+
Some(r) => r,
102+
None => {
103+
// This can totally happen if we encounter a future coredump
104+
// where we decided to store, say, additional MSRs or a
105+
// floating point register. Since this version of Humility
106+
// doesn't understand them, we'll just skip it.
107+
continue;
108+
}
109+
};
110+
111+
if registers.insert(reg, val).is_some() {
112+
bail!("duplicate register {} ({}) at offset {}", reg, id, i * 8);
113+
}
114+
}
115+
116+
Ok(registers)
117+
}
118+
70119
#[rustfmt::skip::macros(bail)]
71120
impl Core for DumpCore {
72121
fn info(&self) -> (String, Option<String>) {
@@ -114,10 +163,15 @@ impl Core for DumpCore {
114163
}
115164

116165
fn read_reg(&mut self, reg: ARMRegister) -> Result<u32> {
117-
if let Some(val) = self.registers.get(&reg) {
118-
Ok(*val)
119-
} else {
120-
bail!("register {} not found in dump", reg);
166+
match &self.registers {
167+
Some(regs) => {
168+
if let Some(val) = regs.get(&reg) {
169+
Ok(*val)
170+
} else {
171+
bail!("register {} not found in dump", reg);
172+
}
173+
}
174+
None => bail!("dump does not include register info"),
121175
}
122176
}
123177

humility-core/src/hubris.rs

Lines changed: 8 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ use rustc_demangle::demangle;
3333
use scroll::{IOwrite, Pwrite};
3434
use zerocopy::{FromBytes, IntoBytes};
3535

36-
const OXIDE_NT_NAME: &str = "Oxide Computer Company";
37-
const OXIDE_NT_BASE: u32 = 0x1de << 20;
38-
const OXIDE_NT_HUBRIS_ARCHIVE: u32 = OXIDE_NT_BASE + 1;
39-
const OXIDE_NT_HUBRIS_REGISTERS: u32 = OXIDE_NT_BASE + 2;
40-
const OXIDE_NT_HUBRIS_TASK: u32 = OXIDE_NT_BASE + 3;
36+
pub const OXIDE_NT_NAME: &str = "Oxide Computer Company";
37+
pub const OXIDE_NT_BASE: u32 = 0x1de << 20;
38+
pub const OXIDE_NT_HUBRIS_ARCHIVE: u32 = OXIDE_NT_BASE + 1;
39+
pub const OXIDE_NT_HUBRIS_REGISTERS: u32 = OXIDE_NT_BASE + 2;
40+
pub const OXIDE_NT_HUBRIS_TASK: u32 = OXIDE_NT_BASE + 3;
4141

4242
const MAX_HUBRIS_VERSION: u32 = 11;
4343

@@ -715,9 +715,6 @@ pub struct HubrisArchive {
715715
// Manual stack pushes before a syscall
716716
syscall_pushes: HashMap<u32, Option<Vec<ARMRegister>>>,
717717

718-
// Current registers (if a dump)
719-
registers: HashMap<ARMRegister, u32>,
720-
721718
// Modules: text address to module
722719
modules: BTreeMap<u32, HubrisModule>,
723720

@@ -810,7 +807,6 @@ impl HubrisArchive {
810807
task_dump: None,
811808
instrs: HashMap::new(),
812809
syscall_pushes: HashMap::new(),
813-
registers: HashMap::new(),
814810
modules: BTreeMap::new(),
815811
tasks: HashMap::new(),
816812
frames: HashMap::new(),
@@ -1658,38 +1654,6 @@ impl HubrisArchive {
16581654
flash.chip
16591655
}
16601656

1661-
fn load_registers(&mut self, r: &[u8]) -> Result<()> {
1662-
if !r.len().is_multiple_of(8) {
1663-
bail!("bad length {} in registers note", r.len());
1664-
}
1665-
1666-
for (i, chunk) in r.chunks_exact(8).enumerate() {
1667-
let (id, val) = chunk.split_at(4);
1668-
// We unwrap here because it can only fail if the length is wrong,
1669-
// but we've explicitly broken a chunk of 8 into two chunks of 4,
1670-
// so a failure here would mean this code has been changed.
1671-
let id = u32::from_le_bytes(id.try_into().unwrap());
1672-
let val = u32::from_le_bytes(val.try_into().unwrap());
1673-
1674-
let reg = match ARMRegister::from_u32(id) {
1675-
Some(r) => r,
1676-
None => {
1677-
// This can totally happen if we encounter a future coredump
1678-
// where we decided to store, say, additional MSRs or a
1679-
// floating point register. Since this version of Humility
1680-
// doesn't understand them, we'll just skip it.
1681-
continue;
1682-
}
1683-
};
1684-
1685-
if self.registers.insert(reg, val).is_some() {
1686-
bail!("duplicate register {} ({}) at offset {}", reg, id, i * 8);
1687-
}
1688-
}
1689-
1690-
Ok(())
1691-
}
1692-
16931657
/// Destroys the `HubrisArchive`, returning the raw archive data
16941658
pub fn take_raw_archive(self) -> Vec<u8> {
16951659
self.archive
@@ -1724,9 +1688,6 @@ impl HubrisArchive {
17241688

17251689
self.archive = note.desc.to_vec();
17261690
}
1727-
OXIDE_NT_HUBRIS_REGISTERS => {
1728-
self.load_registers(note.desc)?;
1729-
}
17301691
OXIDE_NT_HUBRIS_TASK => {
17311692
match DumpTask::read_from_prefix(note.desc) {
17321693
Ok((task, _)) => {
@@ -1740,6 +1701,9 @@ impl HubrisArchive {
17401701
}
17411702
}
17421703
}
1704+
OXIDE_NT_HUBRIS_REGISTERS => {
1705+
// unused when building the archive, but valid
1706+
}
17431707
_ => {
17441708
bail!("unrecognized note 0x{:x}", note.n_type);
17451709
}
@@ -2726,10 +2690,6 @@ impl HubrisArchive {
27262690
Ok(regions)
27272691
}
27282692

2729-
pub fn dump_registers(&self) -> HashMap<ARMRegister, u32> {
2730-
self.registers.clone()
2731-
}
2732-
27332693
pub fn registers(
27342694
&self,
27352695
core: &mut dyn crate::core::Core,

0 commit comments

Comments
 (0)