mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-22 07:57:39 +00:00
Move hexpatch to Rust
This commit is contained in:
parent
5805573625
commit
399b9e5eba
@ -111,7 +111,6 @@ LOCAL_STATIC_LIBRARIES := \
|
||||
LOCAL_SRC_FILES := \
|
||||
boot/main.cpp \
|
||||
boot/bootimg.cpp \
|
||||
boot/hexpatch.cpp \
|
||||
boot/compress.cpp \
|
||||
boot/format.cpp \
|
||||
boot/dtb.cpp \
|
||||
|
@ -58,7 +58,6 @@ bool frm_rf(int dirfd);
|
||||
|
||||
} // extern "C"
|
||||
|
||||
using rust::fd_path;
|
||||
int fd_pathat(int dirfd, const char *name, char *path, size_t size);
|
||||
void mv_path(const char *src, const char *dest);
|
||||
void mv_dir(int src, int dest);
|
||||
|
@ -6,3 +6,6 @@
|
||||
#include "../logging.hpp"
|
||||
#include "../missing.hpp"
|
||||
#include "../base-rs.hpp"
|
||||
|
||||
using rust::xpipe2;
|
||||
using rust::fd_path;
|
@ -26,6 +26,11 @@ pub mod ffi {
|
||||
Debug,
|
||||
}
|
||||
|
||||
unsafe extern "C++" {
|
||||
include!("misc.hpp");
|
||||
fn mut_u8_patch(buf: &mut [u8], from: &[u8], to: &[u8]) -> Vec<usize>;
|
||||
}
|
||||
|
||||
extern "Rust" {
|
||||
fn log_with_rs(level: LogLevel, msg: &[u8]);
|
||||
fn exit_on_error(b: bool);
|
||||
|
@ -32,8 +32,8 @@ void byte_data::swap(byte_data &o) {
|
||||
std::swap(_sz, o._sz);
|
||||
}
|
||||
|
||||
vector<size_t> byte_data::patch(byte_view from, byte_view to) {
|
||||
vector<size_t> v;
|
||||
rust::Vec<size_t> byte_data::patch(byte_view from, byte_view to) {
|
||||
rust::Vec<size_t> v;
|
||||
if (_buf == nullptr)
|
||||
return v;
|
||||
auto p = _buf;
|
||||
@ -50,6 +50,14 @@ vector<size_t> byte_data::patch(byte_view from, byte_view to) {
|
||||
return v;
|
||||
}
|
||||
|
||||
rust::Vec<size_t> mut_u8_patch(
|
||||
rust::Slice<uint8_t> buf,
|
||||
rust::Slice<const uint8_t> from,
|
||||
rust::Slice<const uint8_t> to) {
|
||||
byte_data data(buf);
|
||||
return data.patch(from, to);
|
||||
}
|
||||
|
||||
int fork_dont_care() {
|
||||
if (int pid = xfork()) {
|
||||
waitpid(pid, nullptr, 0);
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <string_view>
|
||||
#include <bitset>
|
||||
#include <random>
|
||||
#include <cxx.h>
|
||||
|
||||
#include "xwrap.hpp"
|
||||
|
||||
@ -195,7 +196,7 @@ struct byte_data : public byte_view {
|
||||
uint8_t *buf() { return _buf; }
|
||||
|
||||
void swap(byte_data &o);
|
||||
std::vector<size_t> patch(byte_view from, byte_view to);
|
||||
rust::Vec<size_t> patch(byte_view from, byte_view to);
|
||||
};
|
||||
|
||||
template<size_t N>
|
||||
@ -217,6 +218,11 @@ struct heap_data : public byte_data {
|
||||
friend byte_channel;
|
||||
};
|
||||
|
||||
rust::Vec<size_t> mut_u8_patch(
|
||||
rust::Slice<uint8_t> buf,
|
||||
rust::Slice<const uint8_t> from,
|
||||
rust::Slice<const uint8_t> to);
|
||||
|
||||
uint64_t parse_uint64_hex(std::string_view s);
|
||||
int parse_int(std::string_view s);
|
||||
|
||||
|
@ -9,6 +9,8 @@ use std::{fmt, io, slice, str};
|
||||
use libc::c_char;
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::ffi;
|
||||
|
||||
pub fn copy_str<T: AsRef<[u8]>>(dest: &mut [u8], src: T) -> usize {
|
||||
let src = src.as_ref();
|
||||
let len = min(src.len(), dest.len() - 1);
|
||||
@ -346,3 +348,13 @@ impl<T> LibcReturn for *mut T {
|
||||
self.is_null()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait MutBytesExt {
|
||||
fn patch(&mut self, from: &[u8], to: &[u8]) -> Vec<usize>;
|
||||
}
|
||||
|
||||
impl<T: AsMut<[u8]>> MutBytesExt for T {
|
||||
fn patch(&mut self, from: &[u8], to: &[u8]) -> Vec<usize> {
|
||||
ffi::mut_u8_patch(self.as_mut(), from, to)
|
||||
}
|
||||
}
|
||||
|
@ -5,10 +5,6 @@
|
||||
#include <poll.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "base-rs.hpp"
|
||||
|
||||
using rust::xpipe2;
|
||||
|
||||
extern "C" {
|
||||
|
||||
FILE *xfopen(const char *pathname, const char *mode);
|
||||
|
@ -1,28 +0,0 @@
|
||||
#include "magiskboot.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
static void hex2byte(string_view hex, uint8_t *buf) {
|
||||
char high, low;
|
||||
for (int i = 0, length = hex.length(); i < length; i += 2) {
|
||||
high = toupper(hex[i]) - '0';
|
||||
low = toupper(hex[i + 1]) - '0';
|
||||
buf[i / 2] = ((high > 9 ? high - 7 : high) << 4) + (low > 9 ? low - 7 : low);
|
||||
}
|
||||
}
|
||||
|
||||
int hexpatch(const char *file, string_view from, string_view to) {
|
||||
mmap_data m(file, true);
|
||||
|
||||
vector<uint8_t> pattern(from.length() / 2);
|
||||
vector<uint8_t> patch(to.length() / 2);
|
||||
|
||||
hex2byte(from, pattern.data());
|
||||
hex2byte(to, patch.data());
|
||||
|
||||
auto v = m.patch(pattern, patch);
|
||||
for (size_t off : v) {
|
||||
fprintf(stderr, "Patch @ %08zX [%s] -> [%s]\n", off, from.data(), to.data());
|
||||
}
|
||||
return v.empty() ? 1 : 0;
|
||||
}
|
@ -3,9 +3,11 @@
|
||||
|
||||
pub use base;
|
||||
use cpio::*;
|
||||
use patch::*;
|
||||
use payload::*;
|
||||
|
||||
mod cpio;
|
||||
mod patch;
|
||||
mod payload;
|
||||
// Suppress warnings in generated code
|
||||
#[allow(warnings)]
|
||||
@ -31,5 +33,6 @@ pub mod ffi {
|
||||
) -> bool;
|
||||
|
||||
unsafe fn cpio_commands(argc: i32, argv: *const *const c_char) -> bool;
|
||||
fn hexpatch(file: &[u8], from: &[u8], to: &[u8]) -> bool;
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,6 @@
|
||||
int unpack(const char *image, bool skip_decomp = false, bool hdr = false);
|
||||
void repack(const char *src_img, const char *out_img, bool skip_comp = false);
|
||||
int split_image_dtb(const char *filename);
|
||||
int hexpatch(const char *file, std::string_view from, std::string_view to);
|
||||
int dtb_commands(int argc, char *argv[]);
|
||||
|
||||
size_t patch_verity(rust::Slice<uint8_t> data);
|
||||
|
@ -200,7 +200,7 @@ int main(int argc, char *argv[]) {
|
||||
} else if (argc > 2 && str_starts(action, "compress")) {
|
||||
compress(action[8] == '=' ? &action[9] : "gzip", argv[2], argv[3]);
|
||||
} else if (argc > 4 && action == "hexpatch") {
|
||||
return hexpatch(argv[2], argv[3], argv[4]);
|
||||
return rust::hexpatch(byte_view(argv[2]), byte_view(argv[3]), byte_view(argv[4])) ? 0 : 1;
|
||||
} else if (argc > 2 && action == "cpio"sv) {
|
||||
if (!rust::cpio_commands(argc - 2, argv + 2))
|
||||
usage(argv[0]);
|
||||
|
37
native/src/boot/patch.rs
Normal file
37
native/src/boot/patch.rs
Normal file
@ -0,0 +1,37 @@
|
||||
use base::{MappedFile, MutBytesExt, ResultExt, Utf8CStr};
|
||||
|
||||
fn hex2byte(hex: &[u8]) -> Vec<u8> {
|
||||
let mut v = Vec::new();
|
||||
v.reserve(hex.len() / 2);
|
||||
for bytes in hex.chunks(2) {
|
||||
if bytes.len() != 2 {
|
||||
break;
|
||||
}
|
||||
let high = bytes[0].to_ascii_uppercase() - b'0';
|
||||
let low = bytes[1].to_ascii_uppercase() - b'0';
|
||||
let h = if high > 9 { high - 7 } else { high };
|
||||
let l = if low > 9 { low - 7 } else { low };
|
||||
v.push(h << 4 | l);
|
||||
}
|
||||
v
|
||||
}
|
||||
|
||||
pub fn hexpatch(file: &[u8], from: &[u8], to: &[u8]) -> bool {
|
||||
fn inner(file: &[u8], from: &[u8], to: &[u8]) -> anyhow::Result<bool> {
|
||||
let file = Utf8CStr::from_bytes(file)?;
|
||||
let from = Utf8CStr::from_bytes(from)?;
|
||||
let to = Utf8CStr::from_bytes(to)?;
|
||||
|
||||
let mut map = MappedFile::open_rw(file)?;
|
||||
let pattern = hex2byte(from.as_bytes());
|
||||
let patch = hex2byte(to.as_bytes());
|
||||
|
||||
let v = map.patch(pattern.as_slice(), patch.as_slice());
|
||||
for off in &v {
|
||||
eprintln!("Patch @ {:#010X} [{}] -> [{}]", off, from, to);
|
||||
}
|
||||
|
||||
Ok(!v.is_empty())
|
||||
}
|
||||
inner(file, from, to).log().unwrap_or(false)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user