从零开始的 Rust 学习笔记(19) —— Rewrite insert_dylib in Rust
最近鹹魚了蠻長一段時間,發現大約有一個多月沒有寫這個系列了,今天繼續學習 Rust 好啦!雖然有在看「The Rust Programming Language」,但是還是得寫寫的~想了一會兒之後,決定把在「另一种方法获取 macOS 网易云音乐的正在播放」裡用過的 insert_dylib
用 Rust 重寫一下(^O^)/
insert_dylib
本身來說並不複雜,但因為不像 C/C++/Objective-C 裡那樣可以直接 #import <mach-o/loader.h>
等,於是 MachO 的一些 struct 就需要自己在 Rust 中重寫一遍~
當然,實際上也可以用 Rust 寫個 Parser,然後去 parse 這些 header 文件,並且自動生成 Rust 的 struct。可是我太懶了,留到下次試試看好啦(咕咕咕) 這次的就放在 GitHub 上了,insert_dylib_rs
不過需要注意的就是有個 BigEndian 和 LittleEndian 的問題,不同的 MachO 使用的可能不一樣,因此就增加了一個 swap_bytes!
的 macro 和一個 FixMachOStructEndian
的 trait
從 src/macho/macho.rs
裡隨機選一個 struct 出來展示的話,大約就是如下這樣子
use super::prelude::*; macro_rules! swap_bytes { ($self:ident, $field_name:ident) => { $self.$field_name = $self.$field_name.swap_bytes(); }; } pub trait FixMachOStructEndian { fn fix_endian(&mut self); } #[derive(Debug)] pub struct SymtabCommand { pub cmd: u32, pub cmdsize: u32, pub symoff: u32, pub nsyms: u32, pub stroff: u32, pub strsize: u32, } impl SymtabCommand { pub fn from(buffer: [u8; 24], is_little_endian: bool) -> SymtabCommand { let sc_buffer: [u32; 6] = unsafe { std::mem::transmute_copy::<[u8; 24], [u32; 6]>(&buffer) }; let mut symtab_command = SymtabCommand { cmd: sc_buffer[0], cmdsize: sc_buffer[1], symoff: sc_buffer[2], nsyms: sc_buffer[3], stroff: sc_buffer[4], strsize: sc_buffer[5], }; if is_little_endian { symtab_command.fix_endian(); } symtab_command } pub fn to_u8(&self) -> [u8; 24] { let mut data: [u32; 6] = [0u32; 6]; data[0] = self.cmd; data[1] = self.cmdsize; data[2] = self.symoff; data[3] = self.nsyms; data[4] = self.stroff; data[5] = self.strsize; unsafe { std::mem::transmute_copy::<[u32; 6], [u8; 24]>(&data) } } } impl FixMachOStructEndian for SymtabCommand { fn fix_endian(&mut self) { swap_bytes!(self, cmd); swap_bytes!(self, cmdsize); swap_bytes!(self, symoff); swap_bytes!(self, nsyms); swap_bytes!(self, stroff); swap_bytes!(self, strsize); } }Continue reading 从零开始的 Rust 学习笔记(19) —— Rewrite insert_dylib in Rust