1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
//! Typed reads of the data at an address: fixed-width integers, pointers, and strings.
//!
//! These interpret the analyzed image (the raw [`bytes`](Database::bytes)) as values, in the
//! database's byte order. Each read is `None` when the covered bytes are not fully mapped, so a
//! read off the end of a segment fails rather than quietly returning zero. They pair with the
//! data [`xrefs_to`](Database::xrefs_to): follow a data xref to an address, then read what
//! lives there.
use crate::Database;
use crate::address::Address;
use crate::bitness::Bitness;
impl Database {
/// Read the unsigned byte at `address`, or `None` if it is not mapped.
#[must_use]
#[doc(alias("get_byte"))]
pub fn read_u8(&self, address: Address) -> Option<u8> {
self.get_u8(address)
}
/// Read a 16-bit unsigned value at `address` (database byte order), or `None` if the two
/// covered bytes are not fully mapped.
#[must_use]
#[doc(alias("get_word"))]
pub fn read_u16(&self, address: Address) -> Option<u16> {
self.get_u16(address)
}
/// Read a 32-bit unsigned value at `address` (database byte order), or `None` if the four
/// covered bytes are not fully mapped.
#[must_use]
#[doc(alias("get_dword"))]
pub fn read_u32(&self, address: Address) -> Option<u32> {
self.get_u32(address)
}
/// Read a 64-bit unsigned value at `address` (database byte order), or `None` if the eight
/// covered bytes are not fully mapped.
#[must_use]
#[doc(alias("get_qword"))]
pub fn read_u64(&self, address: Address) -> Option<u64> {
self.get_u64(address)
}
/// Read a pointer at `address` as an [`Address`].
///
/// The pointer is the width of the database's address size (4 bytes for a 32-bit image, 8
/// for 64-bit). `None` if the database reports no recognized [`Bitness`], the bytes are
/// unmapped, or the stored value is the `BADADDR` sentinel.
#[must_use]
pub fn read_pointer(&self, address: Address) -> Option<Address> {
let raw = match self.bitness()? {
Bitness::Bits64 => self.read_u64(address)?,
Bitness::Bits32 => u64::from(self.read_u32(address)?),
Bitness::Bits16 => u64::from(self.read_u16(address)?),
};
Address::try_new(raw)
}
/// Read the C string (1-byte units, NUL-terminated) at `address`, decoded as UTF-8, or
/// `None` if `address` holds no string.
///
/// The length is auto-detected up to the terminator, and undecodable bytes become the
/// Unicode replacement character (U+FFFD). For wide strings and a whole-database sweep, use
/// [`strings`](Database::strings) instead.
#[must_use]
#[doc(alias("get_strlit_contents"))]
pub fn read_string(&self, address: Address) -> Option<String> {
self.get_strlit(address, 0)
}
}