mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-22 16:07: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 := \
|
LOCAL_SRC_FILES := \
|
||||||
boot/main.cpp \
|
boot/main.cpp \
|
||||||
boot/bootimg.cpp \
|
boot/bootimg.cpp \
|
||||||
boot/hexpatch.cpp \
|
|
||||||
boot/compress.cpp \
|
boot/compress.cpp \
|
||||||
boot/format.cpp \
|
boot/format.cpp \
|
||||||
boot/dtb.cpp \
|
boot/dtb.cpp \
|
||||||
|
@ -58,7 +58,6 @@ bool frm_rf(int dirfd);
|
|||||||
|
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
||||||
using rust::fd_path;
|
|
||||||
int fd_pathat(int dirfd, const char *name, char *path, size_t size);
|
int fd_pathat(int dirfd, const char *name, char *path, size_t size);
|
||||||
void mv_path(const char *src, const char *dest);
|
void mv_path(const char *src, const char *dest);
|
||||||
void mv_dir(int src, int dest);
|
void mv_dir(int src, int dest);
|
||||||
|
@ -6,3 +6,6 @@
|
|||||||
#include "../logging.hpp"
|
#include "../logging.hpp"
|
||||||
#include "../missing.hpp"
|
#include "../missing.hpp"
|
||||||
#include "../base-rs.hpp"
|
#include "../base-rs.hpp"
|
||||||
|
|
||||||
|
using rust::xpipe2;
|
||||||
|
using rust::fd_path;
|
@ -26,6 +26,11 @@ pub mod ffi {
|
|||||||
Debug,
|
Debug,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe extern "C++" {
|
||||||
|
include!("misc.hpp");
|
||||||
|
fn mut_u8_patch(buf: &mut [u8], from: &[u8], to: &[u8]) -> Vec<usize>;
|
||||||
|
}
|
||||||
|
|
||||||
extern "Rust" {
|
extern "Rust" {
|
||||||
fn log_with_rs(level: LogLevel, msg: &[u8]);
|
fn log_with_rs(level: LogLevel, msg: &[u8]);
|
||||||
fn exit_on_error(b: bool);
|
fn exit_on_error(b: bool);
|
||||||
|
@ -32,8 +32,8 @@ void byte_data::swap(byte_data &o) {
|
|||||||
std::swap(_sz, o._sz);
|
std::swap(_sz, o._sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<size_t> byte_data::patch(byte_view from, byte_view to) {
|
rust::Vec<size_t> byte_data::patch(byte_view from, byte_view to) {
|
||||||
vector<size_t> v;
|
rust::Vec<size_t> v;
|
||||||
if (_buf == nullptr)
|
if (_buf == nullptr)
|
||||||
return v;
|
return v;
|
||||||
auto p = _buf;
|
auto p = _buf;
|
||||||
@ -50,6 +50,14 @@ vector<size_t> byte_data::patch(byte_view from, byte_view to) {
|
|||||||
return v;
|
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() {
|
int fork_dont_care() {
|
||||||
if (int pid = xfork()) {
|
if (int pid = xfork()) {
|
||||||
waitpid(pid, nullptr, 0);
|
waitpid(pid, nullptr, 0);
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
#include <cxx.h>
|
||||||
|
|
||||||
#include "xwrap.hpp"
|
#include "xwrap.hpp"
|
||||||
|
|
||||||
@ -195,7 +196,7 @@ struct byte_data : public byte_view {
|
|||||||
uint8_t *buf() { return _buf; }
|
uint8_t *buf() { return _buf; }
|
||||||
|
|
||||||
void swap(byte_data &o);
|
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>
|
template<size_t N>
|
||||||
@ -217,6 +218,11 @@ struct heap_data : public byte_data {
|
|||||||
friend byte_channel;
|
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);
|
uint64_t parse_uint64_hex(std::string_view s);
|
||||||
int parse_int(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 libc::c_char;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
use crate::ffi;
|
||||||
|
|
||||||
pub fn copy_str<T: AsRef<[u8]>>(dest: &mut [u8], src: T) -> usize {
|
pub fn copy_str<T: AsRef<[u8]>>(dest: &mut [u8], src: T) -> usize {
|
||||||
let src = src.as_ref();
|
let src = src.as_ref();
|
||||||
let len = min(src.len(), dest.len() - 1);
|
let len = min(src.len(), dest.len() - 1);
|
||||||
@ -346,3 +348,13 @@ impl<T> LibcReturn for *mut T {
|
|||||||
self.is_null()
|
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 <poll.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
#include "base-rs.hpp"
|
|
||||||
|
|
||||||
using rust::xpipe2;
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
FILE *xfopen(const char *pathname, const char *mode);
|
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;
|
pub use base;
|
||||||
use cpio::*;
|
use cpio::*;
|
||||||
|
use patch::*;
|
||||||
use payload::*;
|
use payload::*;
|
||||||
|
|
||||||
mod cpio;
|
mod cpio;
|
||||||
|
mod patch;
|
||||||
mod payload;
|
mod payload;
|
||||||
// Suppress warnings in generated code
|
// Suppress warnings in generated code
|
||||||
#[allow(warnings)]
|
#[allow(warnings)]
|
||||||
@ -31,5 +33,6 @@ pub mod ffi {
|
|||||||
) -> bool;
|
) -> bool;
|
||||||
|
|
||||||
unsafe fn cpio_commands(argc: i32, argv: *const *const c_char) -> 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);
|
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);
|
void repack(const char *src_img, const char *out_img, bool skip_comp = false);
|
||||||
int split_image_dtb(const char *filename);
|
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[]);
|
int dtb_commands(int argc, char *argv[]);
|
||||||
|
|
||||||
size_t patch_verity(rust::Slice<uint8_t> data);
|
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")) {
|
} else if (argc > 2 && str_starts(action, "compress")) {
|
||||||
compress(action[8] == '=' ? &action[9] : "gzip", argv[2], argv[3]);
|
compress(action[8] == '=' ? &action[9] : "gzip", argv[2], argv[3]);
|
||||||
} else if (argc > 4 && action == "hexpatch") {
|
} 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) {
|
} else if (argc > 2 && action == "cpio"sv) {
|
||||||
if (!rust::cpio_commands(argc - 2, argv + 2))
|
if (!rust::cpio_commands(argc - 2, argv + 2))
|
||||||
usage(argv[0]);
|
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