Merge branch 'main' of git.mineau.eu:histausse/androscalpel
This commit is contained in:
commit
1845c9baa8
5 changed files with 78 additions and 155 deletions
|
|
@ -852,19 +852,20 @@ impl Apk {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert an instruction format to an instruction.
|
/// Convert an instruction format to an instruction.
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
fn instruction_format_to_instruction<F>(
|
fn instruction_format_to_instruction<F>(
|
||||||
format: &InsFormat,
|
format: &InsFormat,
|
||||||
addr: usize,
|
addr: usize,
|
||||||
insns_ref: &HashMap<usize, &InsFormat>,
|
insns_ref: &HashMap<usize, &InsFormat>,
|
||||||
dex: &DexFileReader,
|
dex: &DexFileReader,
|
||||||
label_ins: &mut F,
|
label_ins: &mut F,
|
||||||
) -> Result<Option<(instructions::Instruction, HashMap<usize, String>)>>
|
) -> Result<Option<(instructions::Instruction, HashMap<usize, Vec<String>>)>>
|
||||||
where
|
where
|
||||||
F: FnMut(&instructions::Instruction, usize) -> Option<String>,
|
F: FnMut(&instructions::Instruction, usize) -> Option<String>,
|
||||||
{
|
{
|
||||||
use crate::instructions::*;
|
use crate::instructions::*;
|
||||||
use InsFormat::*;
|
use InsFormat::*;
|
||||||
let mut labels = HashMap::new();
|
let mut labels = HashMap::<_, Vec<_>>::new();
|
||||||
let ins = match format.clone() {
|
let ins = match format.clone() {
|
||||||
Format10X { op: 0x00 } => Instruction::Nop {},
|
Format10X { op: 0x00 } => Instruction::Nop {},
|
||||||
Format12X { op: 0x01, va, vb } => Instruction::Move {
|
Format12X { op: 0x01, va, vb } => Instruction::Move {
|
||||||
|
|
@ -1037,12 +1038,7 @@ impl Apk {
|
||||||
addr - (-(a as i64) as usize)
|
addr - (-(a as i64) as usize)
|
||||||
};
|
};
|
||||||
let label = format!("label_{dest_addr:08X}");
|
let label = format!("label_{dest_addr:08X}");
|
||||||
if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
|
labels.entry(dest_addr).or_default().push(label.clone());
|
||||||
if old_label != label {
|
|
||||||
// TODO: internal error, panic?
|
|
||||||
bail!("There is already a label at 0x{dest_addr:08X} with an invalid name");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Instruction::Goto { label }
|
Instruction::Goto { label }
|
||||||
}
|
}
|
||||||
Format20T { op: 0x29, a } => {
|
Format20T { op: 0x29, a } => {
|
||||||
|
|
@ -1055,12 +1051,7 @@ impl Apk {
|
||||||
addr - (-(a as i64) as usize)
|
addr - (-(a as i64) as usize)
|
||||||
};
|
};
|
||||||
let label = format!("label_{dest_addr:08X}");
|
let label = format!("label_{dest_addr:08X}");
|
||||||
if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
|
labels.entry(dest_addr).or_default().push(label.clone());
|
||||||
if old_label != label {
|
|
||||||
// TODO: internal error, panic?
|
|
||||||
bail!("There is already a label at 0x{dest_addr:08X} with an invalid name");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Instruction::Goto { label }
|
Instruction::Goto { label }
|
||||||
}
|
}
|
||||||
Format30T { op: 0x2a, a } => {
|
Format30T { op: 0x2a, a } => {
|
||||||
|
|
@ -1073,12 +1064,7 @@ impl Apk {
|
||||||
addr - (-(a as i64) as usize)
|
addr - (-(a as i64) as usize)
|
||||||
};
|
};
|
||||||
let label = format!("label_{dest_addr:08X}");
|
let label = format!("label_{dest_addr:08X}");
|
||||||
if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
|
labels.entry(dest_addr).or_default().push(label.clone());
|
||||||
if old_label != label {
|
|
||||||
// TODO: internal error, panic?
|
|
||||||
bail!("There is already a label at 0x{dest_addr:08X} with an invalid name");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Instruction::Goto { label }
|
Instruction::Goto { label }
|
||||||
}
|
}
|
||||||
Format31T { op: 0x2b, va, b } => {
|
Format31T { op: 0x2b, va, b } => {
|
||||||
|
|
@ -1110,15 +1096,7 @@ impl Apk {
|
||||||
addr - (-(target as i64) as usize)
|
addr - (-(target as i64) as usize)
|
||||||
};
|
};
|
||||||
let label = format!("label_{dest_addr:08X}");
|
let label = format!("label_{dest_addr:08X}");
|
||||||
if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
|
labels.entry(dest_addr).or_default().push(label.clone());
|
||||||
if old_label != label {
|
|
||||||
// TODO: internal error, panic?
|
|
||||||
bail!(
|
|
||||||
"There is already a label at 0x{dest_addr:08X} with \
|
|
||||||
an invalid name"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
branches.insert(key, label);
|
branches.insert(key, label);
|
||||||
key += 1;
|
key += 1;
|
||||||
}
|
}
|
||||||
|
|
@ -1164,15 +1142,7 @@ impl Apk {
|
||||||
addr - (-target as usize)
|
addr - (-target as usize)
|
||||||
};
|
};
|
||||||
let label = format!("label_{dest_addr:08X}");
|
let label = format!("label_{dest_addr:08X}");
|
||||||
if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
|
labels.entry(dest_addr).or_default().push(label.clone());
|
||||||
if old_label != label {
|
|
||||||
// TODO: internal error, panic?
|
|
||||||
bail!(
|
|
||||||
"There is already a label at 0x{dest_addr:08X} with \
|
|
||||||
an invalid name"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
branches.insert(key, label);
|
branches.insert(key, label);
|
||||||
}
|
}
|
||||||
Instruction::Switch { reg: va, branches }
|
Instruction::Switch { reg: va, branches }
|
||||||
|
|
@ -1257,12 +1227,7 @@ impl Apk {
|
||||||
addr - (-(c as i64)) as usize
|
addr - (-(c as i64)) as usize
|
||||||
};
|
};
|
||||||
let label = format!("label_{dest_addr:08X}");
|
let label = format!("label_{dest_addr:08X}");
|
||||||
if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
|
labels.entry(dest_addr).or_default().push(label.clone());
|
||||||
if old_label != label {
|
|
||||||
// TODO: internal error, panic?
|
|
||||||
bail!("There is already a label at 0x{dest_addr:08X} with an invalid name");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Instruction::IfEq {
|
Instruction::IfEq {
|
||||||
a: va,
|
a: va,
|
||||||
b: vb,
|
b: vb,
|
||||||
|
|
@ -1287,12 +1252,7 @@ impl Apk {
|
||||||
addr - (-(c as i64)) as usize
|
addr - (-(c as i64)) as usize
|
||||||
};
|
};
|
||||||
let label = format!("label_{dest_addr:08X}");
|
let label = format!("label_{dest_addr:08X}");
|
||||||
if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
|
labels.entry(dest_addr).or_default().push(label.clone());
|
||||||
if old_label != label {
|
|
||||||
// TODO: internal error, panic?
|
|
||||||
bail!("There is already a label at 0x{dest_addr:08X} with an invalid name");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Instruction::IfNe {
|
Instruction::IfNe {
|
||||||
a: va,
|
a: va,
|
||||||
b: vb,
|
b: vb,
|
||||||
|
|
@ -1317,12 +1277,7 @@ impl Apk {
|
||||||
addr - (-(c as i64)) as usize
|
addr - (-(c as i64)) as usize
|
||||||
};
|
};
|
||||||
let label = format!("label_{dest_addr:08X}");
|
let label = format!("label_{dest_addr:08X}");
|
||||||
if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
|
labels.entry(dest_addr).or_default().push(label.clone());
|
||||||
if old_label != label {
|
|
||||||
// TODO: internal error, panic?
|
|
||||||
bail!("There is already a label at 0x{dest_addr:08X} with an invalid name");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Instruction::IfLt {
|
Instruction::IfLt {
|
||||||
a: va,
|
a: va,
|
||||||
b: vb,
|
b: vb,
|
||||||
|
|
@ -1347,12 +1302,7 @@ impl Apk {
|
||||||
addr - (-(c as i64)) as usize
|
addr - (-(c as i64)) as usize
|
||||||
};
|
};
|
||||||
let label = format!("label_{dest_addr:08X}");
|
let label = format!("label_{dest_addr:08X}");
|
||||||
if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
|
labels.entry(dest_addr).or_default().push(label.clone());
|
||||||
if old_label != label {
|
|
||||||
// TODO: internal error, panic?
|
|
||||||
bail!("There is already a label at 0x{dest_addr:08X} with an invalid name");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Instruction::IfGe {
|
Instruction::IfGe {
|
||||||
a: va,
|
a: va,
|
||||||
b: vb,
|
b: vb,
|
||||||
|
|
@ -1377,12 +1327,7 @@ impl Apk {
|
||||||
addr - (-(c as i64)) as usize
|
addr - (-(c as i64)) as usize
|
||||||
};
|
};
|
||||||
let label = format!("label_{dest_addr:08X}");
|
let label = format!("label_{dest_addr:08X}");
|
||||||
if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
|
labels.entry(dest_addr).or_default().push(label.clone());
|
||||||
if old_label != label {
|
|
||||||
// TODO: internal error, panic?
|
|
||||||
bail!("There is already a label at 0x{dest_addr:08X} with an invalid name");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Instruction::IfGt {
|
Instruction::IfGt {
|
||||||
a: va,
|
a: va,
|
||||||
b: vb,
|
b: vb,
|
||||||
|
|
@ -1407,12 +1352,7 @@ impl Apk {
|
||||||
addr - (-(c as i64)) as usize
|
addr - (-(c as i64)) as usize
|
||||||
};
|
};
|
||||||
let label = format!("label_{dest_addr:08X}");
|
let label = format!("label_{dest_addr:08X}");
|
||||||
if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
|
labels.entry(dest_addr).or_default().push(label.clone());
|
||||||
if old_label != label {
|
|
||||||
// TODO: internal error, panic?
|
|
||||||
bail!("There is already a label at 0x{dest_addr:08X} with an invalid name");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Instruction::IfLe {
|
Instruction::IfLe {
|
||||||
a: va,
|
a: va,
|
||||||
b: vb,
|
b: vb,
|
||||||
|
|
@ -1432,12 +1372,7 @@ impl Apk {
|
||||||
addr - (-(b as i64)) as usize
|
addr - (-(b as i64)) as usize
|
||||||
};
|
};
|
||||||
let label = format!("label_{dest_addr:08X}");
|
let label = format!("label_{dest_addr:08X}");
|
||||||
if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
|
labels.entry(dest_addr).or_default().push(label.clone());
|
||||||
if old_label != label {
|
|
||||||
// TODO: internal error, panic?
|
|
||||||
bail!("There is already a label at 0x{dest_addr:08X} with an invalid name");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Instruction::IfEqZ { a: va, label }
|
Instruction::IfEqZ { a: va, label }
|
||||||
}
|
}
|
||||||
Format21T { op: 0x39, va, b } => {
|
Format21T { op: 0x39, va, b } => {
|
||||||
|
|
@ -1453,12 +1388,7 @@ impl Apk {
|
||||||
addr - (-(b as i64)) as usize
|
addr - (-(b as i64)) as usize
|
||||||
};
|
};
|
||||||
let label = format!("label_{dest_addr:08X}");
|
let label = format!("label_{dest_addr:08X}");
|
||||||
if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
|
labels.entry(dest_addr).or_default().push(label.clone());
|
||||||
if old_label != label {
|
|
||||||
// TODO: internal error, panic?
|
|
||||||
bail!("There is already a label at 0x{dest_addr:08X} with an invalid name");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Instruction::IfNeZ { a: va, label }
|
Instruction::IfNeZ { a: va, label }
|
||||||
}
|
}
|
||||||
Format21T { op: 0x3a, va, b } => {
|
Format21T { op: 0x3a, va, b } => {
|
||||||
|
|
@ -1474,12 +1404,7 @@ impl Apk {
|
||||||
addr - (-(b as i64)) as usize
|
addr - (-(b as i64)) as usize
|
||||||
};
|
};
|
||||||
let label = format!("label_{dest_addr:08X}");
|
let label = format!("label_{dest_addr:08X}");
|
||||||
if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
|
labels.entry(dest_addr).or_default().push(label.clone());
|
||||||
if old_label != label {
|
|
||||||
// TODO: internal error, panic?
|
|
||||||
bail!("There is already a label at 0x{dest_addr:08X} with an invalid name");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Instruction::IfLtZ { a: va, label }
|
Instruction::IfLtZ { a: va, label }
|
||||||
}
|
}
|
||||||
Format21T { op: 0x3b, va, b } => {
|
Format21T { op: 0x3b, va, b } => {
|
||||||
|
|
@ -1495,12 +1420,7 @@ impl Apk {
|
||||||
addr - (-(b as i64)) as usize
|
addr - (-(b as i64)) as usize
|
||||||
};
|
};
|
||||||
let label = format!("label_{dest_addr:08X}");
|
let label = format!("label_{dest_addr:08X}");
|
||||||
if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
|
labels.entry(dest_addr).or_default().push(label.clone());
|
||||||
if old_label != label {
|
|
||||||
// TODO: internal error, panic?
|
|
||||||
bail!("There is already a label at 0x{dest_addr:08X} with an invalid name");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Instruction::IfGeZ { a: va, label }
|
Instruction::IfGeZ { a: va, label }
|
||||||
}
|
}
|
||||||
Format21T { op: 0x3c, va, b } => {
|
Format21T { op: 0x3c, va, b } => {
|
||||||
|
|
@ -1516,12 +1436,7 @@ impl Apk {
|
||||||
addr - (-(b as i64)) as usize
|
addr - (-(b as i64)) as usize
|
||||||
};
|
};
|
||||||
let label = format!("label_{dest_addr:08X}");
|
let label = format!("label_{dest_addr:08X}");
|
||||||
if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
|
labels.entry(dest_addr).or_default().push(label.clone());
|
||||||
if old_label != label {
|
|
||||||
// TODO: internal error, panic?
|
|
||||||
bail!("There is already a label at 0x{dest_addr:08X} with an invalid name");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Instruction::IfGtZ { a: va, label }
|
Instruction::IfGtZ { a: va, label }
|
||||||
}
|
}
|
||||||
Format21T { op: 0x3d, va, b } => {
|
Format21T { op: 0x3d, va, b } => {
|
||||||
|
|
@ -1537,12 +1452,7 @@ impl Apk {
|
||||||
addr - (-(b as i64)) as usize
|
addr - (-(b as i64)) as usize
|
||||||
};
|
};
|
||||||
let label = format!("label_{dest_addr:08X}");
|
let label = format!("label_{dest_addr:08X}");
|
||||||
if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
|
labels.entry(dest_addr).or_default().push(label.clone());
|
||||||
if old_label != label {
|
|
||||||
// TODO: internal error, panic?
|
|
||||||
bail!("There is already a label at 0x{dest_addr:08X} with an invalid name");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Instruction::IfLeZ { a: va, label }
|
Instruction::IfLeZ { a: va, label }
|
||||||
}
|
}
|
||||||
Format23X {
|
Format23X {
|
||||||
|
|
@ -2666,7 +2576,7 @@ impl Apk {
|
||||||
.with_context(|| anyhow!("Invalid instruction {ins:?} found at {addr}: {format:?}"))?;
|
.with_context(|| anyhow!("Invalid instruction {ins:?} found at {addr}: {format:?}"))?;
|
||||||
if let Some(label) = label_ins(&ins, addr) {
|
if let Some(label) = label_ins(&ins, addr) {
|
||||||
//let label = format!("label_{addr:08X}");
|
//let label = format!("label_{addr:08X}");
|
||||||
labels.insert(addr, label);
|
labels.entry(addr).or_default().push(label);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Some((ins, labels)))
|
Ok(Some((ins, labels)))
|
||||||
|
|
@ -2705,7 +2615,7 @@ impl Apk {
|
||||||
} else {
|
} else {
|
||||||
(DebugInfo::EndOfData, None)
|
(DebugInfo::EndOfData, None)
|
||||||
};
|
};
|
||||||
let mut labels: HashMap<usize, String> = HashMap::new();
|
let mut labels: HashMap<usize, Vec<String>> = HashMap::new();
|
||||||
let mut tries = HashMap::new();
|
let mut tries = HashMap::new();
|
||||||
for TryItem {
|
for TryItem {
|
||||||
start_addr,
|
start_addr,
|
||||||
|
|
@ -2725,12 +2635,7 @@ impl Apk {
|
||||||
.get_handler_at_offset(handler_off)?;
|
.get_handler_at_offset(handler_off)?;
|
||||||
let default_handler = if let Some(Uleb128(addr)) = *catch_all_addr {
|
let default_handler = if let Some(Uleb128(addr)) = *catch_all_addr {
|
||||||
let label = format!("label_{addr:08X}");
|
let label = format!("label_{addr:08X}");
|
||||||
if let Some(label_) = labels.insert(addr as usize, label.clone()) {
|
labels.entry(addr as usize).or_default().push(label.clone());
|
||||||
if label_ != label {
|
|
||||||
// TODO: that's an internal error
|
|
||||||
bail!("Label collision at 0x{addr:08X}: {label_} and {label}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(label)
|
Some(label)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
@ -2742,22 +2647,15 @@ impl Apk {
|
||||||
} in handlers.iter().cloned()
|
} in handlers.iter().cloned()
|
||||||
{
|
{
|
||||||
let label = format!("label_{addr:08X}");
|
let label = format!("label_{addr:08X}");
|
||||||
if let Some(label_) = labels.insert(addr as usize, label.clone()) {
|
labels.entry(addr as usize).or_default().push(label.clone());
|
||||||
if label_ != label {
|
|
||||||
// TODO: that's an internal error
|
|
||||||
bail!("Label collision at 0x{addr:08X}: {label_} and {label}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
handlers_.push((Self::get_id_type_from_idx(type_idx as usize, dex)?, label))
|
handlers_.push((Self::get_id_type_from_idx(type_idx as usize, dex)?, label))
|
||||||
}
|
}
|
||||||
let dest_addr = start_addr + insn_count as u32;
|
let dest_addr = start_addr + insn_count as u32;
|
||||||
let end_label = format!("label_{dest_addr:08X}");
|
let end_label = format!("label_{dest_addr:08X}");
|
||||||
if let Some(label_) = labels.insert(dest_addr as usize, end_label.clone()) {
|
labels
|
||||||
if label_ != end_label {
|
.entry(dest_addr as usize)
|
||||||
// TODO: that's an internal error
|
.or_default()
|
||||||
bail!("Label collision at 0x{dest_addr:08X}: {label_} and {end_label}");
|
.push(end_label.clone());
|
||||||
}
|
|
||||||
}
|
|
||||||
let try_ = Instruction::Try {
|
let try_ = Instruction::Try {
|
||||||
end_label,
|
end_label,
|
||||||
handlers: handlers_,
|
handlers: handlers_,
|
||||||
|
|
@ -2789,15 +2687,9 @@ impl Apk {
|
||||||
)? {
|
)? {
|
||||||
instructions.push((addr, ins));
|
instructions.push((addr, ins));
|
||||||
addr += ins_f.size() / 2;
|
addr += ins_f.size() / 2;
|
||||||
for (key, val) in &ins_labels {
|
for (addr, mut label_l) in ins_labels.into_iter() {
|
||||||
if let Some(val_) = ins_labels.get(key) {
|
labels.entry(addr).or_default().append(&mut label_l);
|
||||||
if val_ != val {
|
|
||||||
// TODO: internal error, panic?
|
|
||||||
bail!("Label collision at 0x{key:08X}: {val_} and {val}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
labels.extend(ins_labels);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut insns = vec![];
|
let mut insns = vec![];
|
||||||
|
|
@ -2852,8 +2744,10 @@ impl Apk {
|
||||||
if let Some(try_) = tries.remove(&addr) {
|
if let Some(try_) = tries.remove(&addr) {
|
||||||
insns.push(try_);
|
insns.push(try_);
|
||||||
}
|
}
|
||||||
if let Some(label) = labels.remove(&addr) {
|
if let Some(label_l) = labels.remove(&addr) {
|
||||||
insns.push(Instruction::Label { name: label });
|
for label in label_l.into_iter() {
|
||||||
|
insns.push(Instruction::Label { name: label });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
insns.push(ins);
|
insns.push(ins);
|
||||||
}
|
}
|
||||||
|
|
@ -2862,8 +2756,10 @@ impl Apk {
|
||||||
if let Some(try_) = tries.remove(&addr) {
|
if let Some(try_) = tries.remove(&addr) {
|
||||||
insns.push(try_);
|
insns.push(try_);
|
||||||
}
|
}
|
||||||
if let Some(label) = labels.remove(&addr) {
|
if let Some(label_l) = labels.remove(&addr) {
|
||||||
insns.push(Instruction::Label { name: label });
|
for label in label_l.into_iter() {
|
||||||
|
insns.push(Instruction::Label { name: label });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if !labels.is_empty() {
|
if !labels.is_empty() {
|
||||||
bail!("Could not put all label as instructions (label out of insns?)");
|
bail!("Could not put all label as instructions (label out of insns?)");
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,12 @@ pub struct MethodCFG<'a> {
|
||||||
pub nodes: Vec<MethodCFGNode<'a>>,
|
pub nodes: Vec<MethodCFGNode<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Method {
|
||||||
|
pub fn get_cfg(&self) -> Result<MethodCFG> {
|
||||||
|
MethodCFG::new(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> MethodCFG<'a> {
|
impl<'a> MethodCFG<'a> {
|
||||||
pub fn new(method: &'a Method) -> Result<Self> {
|
pub fn new(method: &'a Method) -> Result<Self> {
|
||||||
let insns: &'a [Instruction] = if let Some(code) = method.code.as_ref() {
|
let insns: &'a [Instruction] = if let Some(code) = method.code.as_ref() {
|
||||||
|
|
@ -153,7 +159,6 @@ impl<'a> MethodCFG<'a> {
|
||||||
last_labels.push(name.clone());
|
last_labels.push(name.clone());
|
||||||
} else {
|
} else {
|
||||||
nodes_next_label.push(vec![]);
|
nodes_next_label.push(vec![]);
|
||||||
last_labels.push(name.clone());
|
|
||||||
nodes.push(MethodCFGNode {
|
nodes.push(MethodCFGNode {
|
||||||
code_block: &insns[start_last_block..i],
|
code_block: &insns[start_last_block..i],
|
||||||
labels: last_labels,
|
labels: last_labels,
|
||||||
|
|
@ -161,7 +166,7 @@ impl<'a> MethodCFG<'a> {
|
||||||
prev_nodes: vec![],
|
prev_nodes: vec![],
|
||||||
});
|
});
|
||||||
start_last_block = i;
|
start_last_block = i;
|
||||||
last_labels = vec![];
|
last_labels = vec![name.clone()];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Instruction::ReturnVoid {}
|
Instruction::ReturnVoid {}
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,10 @@ impl MethodCFG<'_> {
|
||||||
}
|
}
|
||||||
// Initialize the entry block from function signature:
|
// Initialize the entry block from function signature:
|
||||||
let mut i = (code.registers_size - code.ins_size) as usize;
|
let mut i = (code.registers_size - code.ins_size) as usize;
|
||||||
|
if !self.method.is_static {
|
||||||
|
end_block_reg_tys[0][i] = RegType::Object; // 'this'
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
for arg in &self.method.descriptor.proto.get_parameters() {
|
for arg in &self.method.descriptor.proto.get_parameters() {
|
||||||
if arg.is_class() || arg.is_array() {
|
if arg.is_class() || arg.is_array() {
|
||||||
end_block_reg_tys[0][i] = RegType::Object;
|
end_block_reg_tys[0][i] = RegType::Object;
|
||||||
|
|
@ -69,11 +73,11 @@ impl MethodCFG<'_> {
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut changed = true;
|
let mut changed = true;
|
||||||
while changed {
|
while changed {
|
||||||
let mut new_end_block_reg_tys = vec![];
|
// The first node is empty and depend on the function signature, it must not change
|
||||||
for node in &self.nodes {
|
let mut new_end_block_reg_tys = vec![end_block_reg_tys[0].clone()];
|
||||||
|
for node in self.nodes.iter().skip(1) {
|
||||||
new_end_block_reg_tys.push(transform_reg_ty(
|
new_end_block_reg_tys.push(transform_reg_ty(
|
||||||
&merge_input(node, nb_reg, &end_block_reg_tys),
|
&merge_input(node, nb_reg, &end_block_reg_tys),
|
||||||
node,
|
node,
|
||||||
|
|
@ -106,6 +110,7 @@ impl MethodCFG<'_> {
|
||||||
);
|
);
|
||||||
dot_string += " style=\"dashed\";\n";
|
dot_string += " style=\"dashed\";\n";
|
||||||
dot_string += " color=\"black\";\n";
|
dot_string += " color=\"black\";\n";
|
||||||
|
dot_string += " rankdir=\"TB\";\n";
|
||||||
dot_string += &format!(
|
dot_string += &format!(
|
||||||
" label=\"Register Types{}\";\n",
|
" label=\"Register Types{}\";\n",
|
||||||
self.method.descriptor.__str__()
|
self.method.descriptor.__str__()
|
||||||
|
|
|
||||||
|
|
@ -503,9 +503,14 @@ impl DexWriter {
|
||||||
// for context
|
// for context
|
||||||
}
|
}
|
||||||
Instruction::Goto { label } => {
|
Instruction::Goto { label } => {
|
||||||
let (min_addr, max_addr) = label_min_max_addrs
|
let (min_addr, max_addr) = label_min_max_addrs.get(label).ok_or(anyhow!(
|
||||||
.get(label)
|
"Label {label} not found in label estimation map but used in Goto instruction. Known labels are [{}].",
|
||||||
.ok_or(anyhow!("Label {label} not found in label estimation map"))?;
|
label_min_max_addrs
|
||||||
|
.keys()
|
||||||
|
.map(|string| string.as_str())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ")
|
||||||
|
))?;
|
||||||
let size = Instruction::goto_size_from_branch_offset_interval(
|
let size = Instruction::goto_size_from_branch_offset_interval(
|
||||||
addr, *min_addr, *max_addr,
|
addr, *min_addr, *max_addr,
|
||||||
)?;
|
)?;
|
||||||
|
|
@ -820,7 +825,7 @@ impl DexWriter {
|
||||||
format!(
|
format!(
|
||||||
"Failed to convert instruction {} (found in code of {}) to raw instruction",
|
"Failed to convert instruction {} (found in code of {}) to raw instruction",
|
||||||
ins.__repr__(),
|
ins.__repr__(),
|
||||||
method_id.__repr__()
|
method_id.__str__()
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
addr += ins.size() / 2;
|
addr += ins.size() / 2;
|
||||||
|
|
@ -948,7 +953,8 @@ impl DexWriter {
|
||||||
// No if let because ownership gunfooterie
|
// No if let because ownership gunfooterie
|
||||||
let code_off = if class.direct_methods.get(id).unwrap().code.is_some() {
|
let code_off = if class.direct_methods.get(id).unwrap().code.is_some() {
|
||||||
let code_off = self.section_manager.get_aligned_size(Section::CodeItem);
|
let code_off = self.section_manager.get_aligned_size(Section::CodeItem);
|
||||||
self.insert_code_item(id.clone(), true)?;
|
self.insert_code_item(id.clone(), true)
|
||||||
|
.with_context(|| format!("Failed to serialize code of {}", id.__str__()))?;
|
||||||
Uleb128(code_off + 1)
|
Uleb128(code_off + 1)
|
||||||
} else {
|
} else {
|
||||||
Uleb128(0)
|
Uleb128(0)
|
||||||
|
|
@ -983,7 +989,8 @@ impl DexWriter {
|
||||||
// No if let because ownership gunfooterie
|
// No if let because ownership gunfooterie
|
||||||
let code_off = if class.virtual_methods.get(id).unwrap().code.is_some() {
|
let code_off = if class.virtual_methods.get(id).unwrap().code.is_some() {
|
||||||
let code_off = self.section_manager.get_aligned_size(Section::CodeItem);
|
let code_off = self.section_manager.get_aligned_size(Section::CodeItem);
|
||||||
self.insert_code_item(id.clone(), false)?;
|
self.insert_code_item(id.clone(), false)
|
||||||
|
.with_context(|| format!("Failed to serialize code of {}", id.__str__()))?;
|
||||||
Uleb128(code_off + 1)
|
Uleb128(code_off + 1)
|
||||||
} else {
|
} else {
|
||||||
Uleb128(0)
|
Uleb128(0)
|
||||||
|
|
|
||||||
|
|
@ -1978,8 +1978,13 @@ macro_rules! sanity_check_22b_or_22s {
|
||||||
macro_rules! raw_ins_if {
|
macro_rules! raw_ins_if {
|
||||||
($ins_op:tt, $label_addrs:ident, $label:ident, $addr:ident, $r1:ident, $r2:ident) => {{
|
($ins_op:tt, $label_addrs:ident, $label:ident, $addr:ident, $r1:ident, $r2:ident) => {{
|
||||||
let label_addr = $label_addrs.get($label).ok_or(anyhow!(
|
let label_addr = $label_addrs.get($label).ok_or(anyhow!(
|
||||||
"Label {} not found in code, but found `if` with this label",
|
"Label {} not found in code, but found `if` with this label. Known labels are [{}].",
|
||||||
$label,
|
$label,
|
||||||
|
$label_addrs
|
||||||
|
.keys()
|
||||||
|
.map(|string| string.as_str())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ")
|
||||||
))?;
|
))?;
|
||||||
let branch_offset = *label_addr as i32 - $addr as i32;
|
let branch_offset = *label_addr as i32 - $addr as i32;
|
||||||
if branch_offset > i16::MAX as i32 || branch_offset < i16::MIN as i32 {
|
if branch_offset > i16::MAX as i32 || branch_offset < i16::MIN as i32 {
|
||||||
|
|
@ -1997,8 +2002,13 @@ macro_rules! raw_ins_if {
|
||||||
macro_rules! raw_ins_ifz {
|
macro_rules! raw_ins_ifz {
|
||||||
($ins_op:tt, $label_addrs:ident, $label:ident, $addr:ident, $r1:ident) => {{
|
($ins_op:tt, $label_addrs:ident, $label:ident, $addr:ident, $r1:ident) => {{
|
||||||
let label_addr = $label_addrs.get($label).ok_or(anyhow!(
|
let label_addr = $label_addrs.get($label).ok_or(anyhow!(
|
||||||
"Label {} not found in code, but found `if` with this label",
|
"Label {} not found in code, but found `if` with this label. Known labels are [{}].",
|
||||||
$label,
|
$label,
|
||||||
|
$label_addrs
|
||||||
|
.keys()
|
||||||
|
.map(|string| string.as_str())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ")
|
||||||
))?;
|
))?;
|
||||||
let branch_offset = *label_addr as i32 - $addr as i32;
|
let branch_offset = *label_addr as i32 - $addr as i32;
|
||||||
if branch_offset > i16::MAX as i32 || branch_offset < i16::MIN as i32 {
|
if branch_offset > i16::MAX as i32 || branch_offset < i16::MIN as i32 {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue