This commit is contained in:
Jean-Marie 'Histausse' Mineau 2024-07-16 00:42:49 +02:00
parent b72fd67b7d
commit cfbd3fb90b
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2
2 changed files with 617 additions and 632 deletions

View file

@ -438,18 +438,17 @@ impl DexWriter {
for ins in &code.insns { for ins in &code.insns {
match ins { match ins {
Instruction::Label(Label { name }) => { Instruction::Label { name } => {
label_min_max_addrs.insert(name.clone(), (min_addr, max_addr)); label_min_max_addrs.insert(name.clone(), (min_addr, max_addr));
min_addr += ins.min_ins_size() / 2; min_addr += ins.min_ins_size() / 2;
max_addr += ins.max_ins_size() / 2; max_addr += ins.max_ins_size() / 2;
} }
Instruction::ConstString(ins) => { Instruction::ConstString { .. } => {
let string_idx = self.strings.get(&ins.lit).ok_or(anyhow!( let size = ins
"String {} (found in code of {}) not found in dex builder", .get_raw_ins(Some(&self.strings))
ins.lit.__repr__(), .with_context(|| format!("In code of {}", method_id.__repr__()))?
method_id.__repr__() .size()
))?; / 2;
let size = ins.get_raw_ins(*string_idx).size() / 2;
min_addr += size; min_addr += size;
max_addr += size; max_addr += size;
} }
@ -465,23 +464,23 @@ impl DexWriter {
let mut goto_sizes = vec![]; let mut goto_sizes = vec![];
for ins in &code.insns { for ins in &code.insns {
match ins { match ins {
Instruction::Label(Label { name }) => { Instruction::Label { name } => {
label_addrs.insert(name.clone(), addr); label_addrs.insert(name.clone(), addr);
addr += ins.max_ins_size() / 2; addr += ins.max_ins_size() / 2;
} }
Instruction::ConstString(ins) => { Instruction::ConstString { .. } => {
let string_idx = self.strings.get(&ins.lit).ok_or(anyhow!( addr += ins.get_raw_ins(Some(&self.strings, None))?.size() / 2;
"String {} (found in code of {}) not found in dex builder", // should not fail after
ins.lit.__repr__(), // first loop, no need
method_id.__repr__() // for context
))?;
addr += ins.get_raw_ins(*string_idx).size() / 2;
} }
Instruction::Goto(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) .get(label)
.ok_or(anyhow!("Label {label} not found in label estimation map"))?; .ok_or(anyhow!("Label {label} not found in label estimation map"))?;
let size = Goto::size_from_branch_offset_interval(addr, *min_addr, *max_addr)?; let size = Instruction::goto_size_from_branch_offset_interval(
addr, *min_addr, *max_addr,
)?;
goto_sizes.push(size); goto_sizes.push(size);
addr += size / 2; addr += size / 2;
} }
@ -502,86 +501,20 @@ impl DexWriter {
addr = 0; addr = 0;
for ins in &code.insns { for ins in &code.insns {
match ins { match ins {
Instruction::ConstString(ins) => { Instruction::FillArrayData {
let string_idx = self.strings.get(&ins.lit).ok_or(anyhow!( data,
"String {} (found in code of {}) not found in dex builder", elt_width,
ins.lit.__repr__(), arr,
method_id.__repr__() } => {
))?;
let ins = ins.get_raw_ins(*string_idx);
addr += ins.size() / 2;
insns.push(ins);
}
Instruction::ConstClass(ins) => {
let class_idx = *self.type_ids.get(&ins.lit).ok_or(anyhow!(
"Class {} (type of class found in code of {}) not found in dex builder",
ins.lit.__repr__(),
method_id.__repr__()
))?;
let ins = ins.get_raw_ins(class_idx);
addr += ins.size() / 2;
insns.push(ins);
}
Instruction::CheckCast(ins) => {
let class_idx = *self.type_ids.get(&ins.lit).ok_or(anyhow!(
"Class {} (type of class found in code of {}) not found in dex builder",
ins.lit.__repr__(),
method_id.__repr__()
))?;
let ins = ins.get_raw_ins(class_idx);
addr += ins.size() / 2;
insns.push(ins);
}
Instruction::InstanceOf(ins) => {
let class_idx = *self.type_ids.get(&ins.lit).ok_or(anyhow!(
"Class {} (type of class found in code of {}) not found in dex builder",
ins.lit.__repr__(),
method_id.__repr__()
))?;
let ins = ins.get_raw_ins(class_idx);
addr += ins.size() / 2;
insns.push(ins);
}
Instruction::NewInstance(ins) => {
let class_idx = *self.type_ids.get(&ins.lit).ok_or(anyhow!(
"Class {} (type of class found in code of {}) not found in dex builder",
ins.lit.__repr__(),
method_id.__repr__()
))?;
let ins = ins.get_raw_ins(class_idx);
addr += ins.size() / 2;
insns.push(ins);
}
Instruction::NewArray(ins) => {
let class_idx = *self.type_ids.get(&ins.lit).ok_or(anyhow!(
"Type {} (type found in code of {}) not found in dex builder",
ins.lit.__repr__(),
method_id.__repr__()
))?;
let ins = ins.get_raw_ins(class_idx);
addr += ins.size() / 2;
insns.push(ins);
}
Instruction::FilledNewArray(ins) => {
let class_idx = *self.type_ids.get(&ins.type_).ok_or(anyhow!(
"Type {} (type found in code of {}) not found in dex builder",
ins.type_.__repr__(),
method_id.__repr__()
))?;
let ins = ins.get_raw_ins(class_idx);
addr += ins.size() / 2;
insns.push(ins);
}
Instruction::FillArrayData(ins) => {
let payload = InsFormat::FormatFillArrayDataPayload { let payload = InsFormat::FormatFillArrayDataPayload {
elt_width: ins.elt_width, elt_width: *elt_width,
data: ins.data.clone(), data: data.clone(),
}; };
if payload_addr % 2 != 0 { if payload_addr % 2 != 0 {
// https://cs.android.com/android/platform/superproject/main/+/main:art/runtime/verifier/method_verifier.cc;drc=e8c3e7be783937a340cd4f3280b69962d6f1ea0c;l=1347 // https://cs.android.com/android/platform/superproject/main/+/main:art/runtime/verifier/method_verifier.cc;drc=e8c3e7be783937a340cd4f3280b69962d6f1ea0c;l=1347
// The ART check if the array data table is 4 bytes aligned (= 2 ins alligned) // The ART check if the array data table is 4 bytes aligned (= 2 ins alligned)
// TODO: check how it is donne in android and other dex generation code. // TODO: check how it is donne in android and other dex generation code.
let nop = (Instruction::Nop {}).get_raw_ins()?; let nop = (Instruction::Nop {}).get_raw_ins(None, None)?;
payload_addr += nop.size() / 2; payload_addr += nop.size() / 2;
payloads.push(nop); payloads.push(nop);
} }
@ -1372,9 +1305,11 @@ impl DexWriter {
handler_off += catches.size(); handler_off += catches.size();
handlers.list.push(catches); handlers.list.push(catches);
} }
Instruction::Label(_) => (), Instruction::Label { .. } => (),
_ => { _ => {
let ins = ins.get_raw_ins().with_context(|| { let ins = ins
.get_raw_ins(Some(&self.strings), Some(&self.type_ids))
.with_context(|| {
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__(),
@ -1388,7 +1323,7 @@ impl DexWriter {
} }
if addr % 2 != 0 { if addr % 2 != 0 {
// make sure the payload section is 4 bytes aligned // make sure the payload section is 4 bytes aligned
let nop = (Instruction::Nop {}).get_raw_ins()?; let nop = (Instruction::Nop {}).get_raw_ins(None, None)?;
//addr += nop.size() / 2; //addr += nop.size() / 2;
insns.push(nop); insns.push(nop);
} }

File diff suppressed because it is too large Load diff