atom_macho/load_command/
unix_thread.rs

1use crate::io::{Endian, ReadExt as _, WriteExt as _};
2use std::io::{Read, Write};
3
4/*
5 * Thread commands contain machine-specific data structures suitable for
6 * use in the thread state primitives.  The machine specific data structures
7 * follow the struct thread_command as follows.
8 * Each flavor of machine specific data structure is preceded by an uint32_t
9 * constant for the flavor of that data structure, an uint32_t that is the
10 * count of uint32_t's of the size of the state data structure and then
11 * the state data structure follows.  This triple may be repeated for many
12 * flavors.  The constants for the flavors, counts and state data structure
13 * definitions are expected to be in the header file <machine/thread_status.h>.
14 * These machine specific data structures sizes must be multiples of
15 * 4 bytes.  The cmdsize reflects the total size of the thread_command
16 * and all of the sizes of the constants for the flavors, counts and state
17 * data structures.
18 *
19 * For executable objects that are unix processes there will be one
20 * thread_command (cmd == LC_UNIXTHREAD) created for it by the link-editor.
21 * This is the same as a LC_THREAD, except that a stack is automatically
22 * created (based on the shell's limit for the stack size).  Command arguments
23 * and environment variables are copied onto that stack.
24 */
25#[derive(Debug, Clone, PartialEq, Eq)]
26pub struct UnixThreadCommand {
27    pub cmd: u32,
28    pub cmdsize: u32,
29    pub flavor: Flavor,
30    /// size of the thread state data, in number of 32-bit integers. The thread state data
31    /// structure must be fully padded to 32-bit alignment.
32    pub count: u32,
33    pub state: ThreadState,
34}
35
36impl UnixThreadCommand {
37    pub const TYPE: u32 = 0x5;
38
39    pub fn read_from_in<R: Read>(read: &mut R, endian: Endian) -> Self {
40        let cmd = read.read_u32_in(endian);
41        let cmdsize = read.read_u32_in(endian);
42        let flavor = Flavor::read_from_in(read, endian);
43        let count = read.read_u32_in(endian);
44
45        let state = match flavor {
46            Flavor::ThreadStateX86_64 => {
47                let state = StateX86_64::read_from_in(read, endian);
48                ThreadState::X86_64(state)
49            }
50            Flavor::Unknown(_) => {
51                let mut state = Vec::with_capacity(count as usize * 4);
52                state.resize(count as usize * 4, 0);
53                read.read_exact(&mut state).unwrap();
54                ThreadState::Unknown(state)
55            }
56        };
57
58        UnixThreadCommand {
59            cmd,
60            cmdsize,
61            flavor,
62            count,
63            state,
64        }
65    }
66
67    pub fn write_into<W: Write>(&self, write: &mut W) {
68        write.write_u32_native(self.cmd);
69        write.write_u32_native(self.cmdsize);
70        self.flavor.write_into(write);
71        write.write_u32_native(self.count);
72
73        match &self.state {
74            ThreadState::X86_64(state) => state.write_into(write),
75            ThreadState::Unknown(state) => write.write_all(&state).unwrap(),
76        }
77    }
78}
79
80#[derive(Debug, Clone, PartialEq, Eq)]
81pub enum Flavor {
82    ThreadStateX86_64,
83    Unknown(u32),
84}
85
86impl Flavor {
87    pub fn read_from_in<R: Read>(read: &mut R, endian: Endian) -> Self {
88        match read.read_u32_in(endian) {
89            4 => Flavor::ThreadStateX86_64,
90            n => Flavor::Unknown(n),
91        }
92    }
93
94    pub fn write_into<W: Write>(&self, write: &mut W) {
95        match self {
96            Flavor::ThreadStateX86_64 => write.write_u32_native(4),
97            Flavor::Unknown(n) => write.write_u32_native(*n),
98        }
99    }
100}
101
102#[derive(Debug, Clone, PartialEq, Eq)]
103pub enum ThreadState {
104    X86_64(StateX86_64),
105    Unknown(Vec<u8>),
106}
107
108#[derive(Debug, Clone, PartialEq, Eq)]
109pub struct StateX86_64 {
110    pub __rax: u64,
111    pub __rbx: u64,
112    pub __rcx: u64,
113    pub __rdx: u64,
114    pub __rdi: u64,
115    pub __rsi: u64,
116    pub __rbp: u64,
117    pub __rsp: u64,
118    pub __r8: u64,
119    pub __r9: u64,
120    pub __r10: u64,
121    pub __r11: u64,
122    pub __r12: u64,
123    pub __r13: u64,
124    pub __r14: u64,
125    pub __r15: u64,
126    pub __rip: u64,
127    pub __rflags: u64,
128    pub __cs: u64,
129    pub __fs: u64,
130    pub __gs: u64,
131}
132
133impl StateX86_64 {
134    pub fn read_from_in<R: Read>(read: &mut R, endian: Endian) -> Self {
135        StateX86_64 {
136            __rax: read.read_u64_in(endian),
137            __rbx: read.read_u64_in(endian),
138            __rcx: read.read_u64_in(endian),
139            __rdx: read.read_u64_in(endian),
140            __rdi: read.read_u64_in(endian),
141            __rsi: read.read_u64_in(endian),
142            __rbp: read.read_u64_in(endian),
143            __rsp: read.read_u64_in(endian),
144            __r8: read.read_u64_in(endian),
145            __r9: read.read_u64_in(endian),
146            __r10: read.read_u64_in(endian),
147            __r11: read.read_u64_in(endian),
148            __r12: read.read_u64_in(endian),
149            __r13: read.read_u64_in(endian),
150            __r14: read.read_u64_in(endian),
151            __r15: read.read_u64_in(endian),
152            __rip: read.read_u64_in(endian),
153            __rflags: read.read_u64_in(endian),
154            __cs: read.read_u64_in(endian),
155            __fs: read.read_u64_in(endian),
156            __gs: read.read_u64_in(endian),
157        }
158    }
159
160    pub fn write_into<W: Write>(&self, write: &mut W) {
161        write.write_u64_native(self.__rax);
162        write.write_u64_native(self.__rbx);
163        write.write_u64_native(self.__rcx);
164        write.write_u64_native(self.__rdx);
165        write.write_u64_native(self.__rdi);
166        write.write_u64_native(self.__rsi);
167        write.write_u64_native(self.__rbp);
168        write.write_u64_native(self.__rsp);
169        write.write_u64_native(self.__r8);
170        write.write_u64_native(self.__r9);
171        write.write_u64_native(self.__r10);
172        write.write_u64_native(self.__r11);
173        write.write_u64_native(self.__r12);
174        write.write_u64_native(self.__r13);
175        write.write_u64_native(self.__r14);
176        write.write_u64_native(self.__r15);
177        write.write_u64_native(self.__rip);
178        write.write_u64_native(self.__rflags);
179        write.write_u64_native(self.__cs);
180        write.write_u64_native(self.__fs);
181        write.write_u64_native(self.__gs);
182    }
183}