WIP
This commit is contained in:
parent
920cc181dc
commit
69e7476904
2 changed files with 1732 additions and 713 deletions
|
|
@ -445,7 +445,18 @@ impl DexWriter {
|
||||||
}
|
}
|
||||||
Instruction::ConstString { .. } => {
|
Instruction::ConstString { .. } => {
|
||||||
let size = ins
|
let size = ins
|
||||||
.get_raw_ins(Some(&self.strings), None, None, None, None, None)
|
.get_raw_ins(
|
||||||
|
Some(&self.strings),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
)
|
||||||
.with_context(|| format!("In code of {}", method_id.__repr__()))?
|
.with_context(|| format!("In code of {}", method_id.__repr__()))?
|
||||||
.size()
|
.size()
|
||||||
/ 2;
|
/ 2;
|
||||||
|
|
@ -470,7 +481,18 @@ impl DexWriter {
|
||||||
}
|
}
|
||||||
Instruction::ConstString { .. } => {
|
Instruction::ConstString { .. } => {
|
||||||
addr += ins
|
addr += ins
|
||||||
.get_raw_ins(Some(&self.strings), None, None, None, None, None)?
|
.get_raw_ins(
|
||||||
|
Some(&self.strings),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
)?
|
||||||
.size()
|
.size()
|
||||||
/ 2;
|
/ 2;
|
||||||
// should not fail after
|
// should not fail after
|
||||||
|
|
@ -492,7 +514,7 @@ impl DexWriter {
|
||||||
}
|
}
|
||||||
// Serialize instructions
|
// Serialize instructions
|
||||||
let mut tries = vec![];
|
let mut tries = vec![];
|
||||||
let mut handlers = EncodedCatchHandlerList { list: vec![] };
|
let mut encoded_handlers = EncodedCatchHandlerList { list: vec![] };
|
||||||
let mut handler_off = 0;
|
let mut handler_off = 0;
|
||||||
let mut insns = vec![];
|
let mut insns = vec![];
|
||||||
let mut payloads = vec![];
|
let mut payloads = vec![];
|
||||||
|
|
@ -517,15 +539,27 @@ impl DexWriter {
|
||||||
// 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 {})
|
let nop = (Instruction::Nop {}).get_raw_ins(
|
||||||
.get_raw_ins(None, None, None, None, None, None)?;
|
None, None, None, None, None, None, None, None, None, None,
|
||||||
|
)?;
|
||||||
payload_addr += nop.size() / 2;
|
payload_addr += nop.size() / 2;
|
||||||
payloads.push(nop);
|
payloads.push(nop);
|
||||||
}
|
}
|
||||||
let data_offset = payload_addr as i32 - addr as i32;
|
let data_offset = payload_addr as i32 - addr as i32;
|
||||||
payload_addr += payload.size() / 2;
|
payload_addr += payload.size() / 2;
|
||||||
payloads.push(payload);
|
payloads.push(payload);
|
||||||
let ins = ins.get_raw_ins(None, None, None, None, None, Some(data_offset))?;
|
let ins = ins.get_raw_ins(
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
Some(data_offset),
|
||||||
|
)?;
|
||||||
addr += ins.size() / 2;
|
addr += ins.size() / 2;
|
||||||
insns.push(ins);
|
insns.push(ins);
|
||||||
}
|
}
|
||||||
|
|
@ -533,6 +567,10 @@ impl DexWriter {
|
||||||
let goto_size = goto_sizes[goto_idx];
|
let goto_size = goto_sizes[goto_idx];
|
||||||
goto_idx += 1;
|
goto_idx += 1;
|
||||||
let ins = ins.get_raw_ins(
|
let ins = ins.get_raw_ins(
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
|
@ -570,158 +608,74 @@ impl DexWriter {
|
||||||
// https://cs.android.com/android/platform/superproject/main/+/main:art/runtime/verifier/method_verifier.cc;drc=e8c3e7be783937a340cd4f3280b69962d6f1ea0c;l=1464
|
// https://cs.android.com/android/platform/superproject/main/+/main:art/runtime/verifier/method_verifier.cc;drc=e8c3e7be783937a340cd4f3280b69962d6f1ea0c;l=1464
|
||||||
// The ART check if the switch table is 4 bytes aligned (= 2 ins alligned)
|
// The ART check if the switch 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 {})
|
let nop = (Instruction::Nop {}).get_raw_ins(
|
||||||
.get_raw_ins(None, None, None, None, None, None)?;
|
None, None, None, None, None, None, None, None, None, None,
|
||||||
|
)?;
|
||||||
payload_addr += nop.size() / 2;
|
payload_addr += nop.size() / 2;
|
||||||
payloads.push(nop);
|
payloads.push(nop);
|
||||||
}
|
}
|
||||||
let data_offset = payload_addr as i32 - addr as i32;
|
let data_offset = payload_addr as i32 - addr as i32;
|
||||||
payload_addr += payload.size() / 2;
|
payload_addr += payload.size() / 2;
|
||||||
payloads.push(payload);
|
payloads.push(payload);
|
||||||
let ins = ins.get_raw_ins(None, None, None, None, None, Some(data_offset))?;
|
let ins = ins.get_raw_ins(
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
Some(data_offset),
|
||||||
|
)?;
|
||||||
addr += ins.size() / 2;
|
addr += ins.size() / 2;
|
||||||
insns.push(ins);
|
insns.push(ins);
|
||||||
}
|
}
|
||||||
Instruction::InvokeVirtual(ins) => {
|
Instruction::InvokeCustom { call_site, .. } => {
|
||||||
let meth = &ins.method;
|
|
||||||
let meth_idx = self.method_ids.get(meth).ok_or(anyhow!(
|
|
||||||
"Method {} (method of class {}, found in code of {}) not found in dex builder",
|
|
||||||
meth.__repr__(),
|
|
||||||
meth.class_.__repr__(),
|
|
||||||
method_id.__repr__()
|
|
||||||
))?;
|
|
||||||
debug_assert!(
|
|
||||||
*meth_idx <= u16::MAX as usize,
|
|
||||||
"methode id too big for invoke instruction"
|
|
||||||
);
|
|
||||||
let meth_idx = *meth_idx as u16;
|
|
||||||
let ins = ins.get_raw_ins(meth_idx);
|
|
||||||
addr += ins.size() / 2;
|
|
||||||
insns.push(ins);
|
|
||||||
}
|
|
||||||
Instruction::InvokeSuper(ins) => {
|
|
||||||
let meth = &ins.method;
|
|
||||||
let meth_idx = self.method_ids.get(meth).ok_or(anyhow!(
|
|
||||||
"Method {} (method of class {}, found in code of {}) not found in dex builder",
|
|
||||||
meth.__repr__(),
|
|
||||||
meth.class_.__repr__(),
|
|
||||||
method_id.__repr__()
|
|
||||||
))?;
|
|
||||||
debug_assert!(
|
|
||||||
*meth_idx <= u16::MAX as usize,
|
|
||||||
"methode id too big for invoke instruction"
|
|
||||||
);
|
|
||||||
let meth_idx = *meth_idx as u16;
|
|
||||||
let ins = ins.get_raw_ins(meth_idx);
|
|
||||||
addr += ins.size() / 2;
|
|
||||||
insns.push(ins);
|
|
||||||
}
|
|
||||||
Instruction::InvokeDirect(ins) => {
|
|
||||||
let meth = &ins.method;
|
|
||||||
let meth_idx = self.method_ids.get(meth).ok_or(anyhow!(
|
|
||||||
"Method {} (method of class {}, found in code of {}) not found in dex builder",
|
|
||||||
meth.__repr__(),
|
|
||||||
meth.class_.__repr__(),
|
|
||||||
method_id.__repr__()
|
|
||||||
))?;
|
|
||||||
debug_assert!(
|
|
||||||
*meth_idx <= u16::MAX as usize,
|
|
||||||
"methode id too big for invoke instruction"
|
|
||||||
);
|
|
||||||
let meth_idx = *meth_idx as u16;
|
|
||||||
let ins = ins.get_raw_ins(meth_idx);
|
|
||||||
addr += ins.size() / 2;
|
|
||||||
insns.push(ins);
|
|
||||||
}
|
|
||||||
Instruction::InvokeStatic(ins) => {
|
|
||||||
let meth = &ins.method;
|
|
||||||
let meth_idx = self.method_ids.get(meth).ok_or(anyhow!(
|
|
||||||
"Method {} (method of class {}, found in code of {}) not found in dex builder",
|
|
||||||
meth.__repr__(),
|
|
||||||
meth.class_.__repr__(),
|
|
||||||
method_id.__repr__()
|
|
||||||
))?;
|
|
||||||
debug_assert!(
|
|
||||||
*meth_idx <= u16::MAX as usize,
|
|
||||||
"methode id too big for invoke instruction"
|
|
||||||
);
|
|
||||||
let meth_idx = *meth_idx as u16;
|
|
||||||
let ins = ins.get_raw_ins(meth_idx);
|
|
||||||
addr += ins.size() / 2;
|
|
||||||
insns.push(ins);
|
|
||||||
}
|
|
||||||
Instruction::InvokeInterface(ins) => {
|
|
||||||
let meth = &ins.method;
|
|
||||||
let meth_idx = self.method_ids.get(meth).ok_or(anyhow!(
|
|
||||||
"Method {} (method of class {}, found in code of {}) not found in dex builder",
|
|
||||||
meth.__repr__(),
|
|
||||||
meth.class_.__repr__(),
|
|
||||||
method_id.__repr__()
|
|
||||||
))?;
|
|
||||||
debug_assert!(
|
|
||||||
*meth_idx <= u16::MAX as usize,
|
|
||||||
"methode id too big for invoke instruction"
|
|
||||||
);
|
|
||||||
let meth_idx = *meth_idx as u16;
|
|
||||||
let ins = ins.get_raw_ins(meth_idx);
|
|
||||||
addr += ins.size() / 2;
|
|
||||||
insns.push(ins);
|
|
||||||
}
|
|
||||||
Instruction::InvokePolymorphic(ins) => {
|
|
||||||
let meth = &ins.method;
|
|
||||||
let meth_idx = self.method_ids.get(meth).ok_or(anyhow!(
|
|
||||||
"Method {} (method of class {}, found in code of {}) not found in dex builder",
|
|
||||||
meth.__repr__(),
|
|
||||||
meth.class_.__repr__(),
|
|
||||||
method_id.__repr__()
|
|
||||||
))?;
|
|
||||||
let proto_idx = self.proto_ids.get(&ins.proto).ok_or(anyhow!(
|
|
||||||
"Prototype {} (found in code of {}) not found in dex builder",
|
|
||||||
ins.proto.__repr__(),
|
|
||||||
method_id.__repr__()
|
|
||||||
))?;
|
|
||||||
debug_assert!(
|
|
||||||
*meth_idx <= u16::MAX as usize,
|
|
||||||
"methode id too big for invoke instruction"
|
|
||||||
);
|
|
||||||
debug_assert!(
|
|
||||||
*proto_idx <= u16::MAX as usize,
|
|
||||||
"proto id too big for invoke instruction"
|
|
||||||
);
|
|
||||||
let meth_idx = *meth_idx as u16;
|
|
||||||
let proto_idx = *proto_idx as u16;
|
|
||||||
let ins = ins.get_raw_ins(meth_idx, proto_idx);
|
|
||||||
addr += ins.size() / 2;
|
|
||||||
insns.push(ins);
|
|
||||||
}
|
|
||||||
Instruction::InvokeCustom(ins) => {
|
|
||||||
let call_site_idx = self.call_site_ids.len();
|
let call_site_idx = self.call_site_ids.len();
|
||||||
self.insert_call_site_item(&ins.call_site)?;
|
self.insert_call_site_item(&call_site)?;
|
||||||
let ins = ins.get_raw_ins(call_site_idx);
|
let ins = ins.get_raw_ins(
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
Some(call_site_idx),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
)?;
|
||||||
addr += ins.size() / 2;
|
addr += ins.size() / 2;
|
||||||
insns.push(ins);
|
insns.push(ins);
|
||||||
}
|
}
|
||||||
Instruction::ConstMethodHandle(ins) => {
|
Instruction::ConstMethodHandle { handle, .. } => {
|
||||||
let method_handle_idx = self.method_handles.len();
|
let method_handle_idx = self.method_handles.len();
|
||||||
self.insert_method_handle(&ins.handle)?;
|
self.insert_method_handle(&handle)?;
|
||||||
let ins = ins.get_raw_ins(method_handle_idx);
|
let ins = ins.get_raw_ins(
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
Some(method_handle_idx),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
)?;
|
||||||
addr += ins.size() / 2;
|
addr += ins.size() / 2;
|
||||||
insns.push(ins);
|
insns.push(ins);
|
||||||
}
|
}
|
||||||
Instruction::ConstMethodType(ins) => {
|
Instruction::Try {
|
||||||
let proto_idx = self.proto_ids.get(&ins.proto).ok_or(anyhow!(
|
end_label,
|
||||||
"Prototype {} (found in code of {}) not found in dex builder",
|
handlers,
|
||||||
ins.proto.__repr__(),
|
default_handler,
|
||||||
method_id.__repr__()
|
} => {
|
||||||
))?;
|
let end_block_addr = *label_addrs.get(end_label).ok_or(anyhow!(
|
||||||
let ins = ins.get_raw_ins(*proto_idx);
|
|
||||||
addr += ins.size() / 2;
|
|
||||||
insns.push(ins);
|
|
||||||
}
|
|
||||||
Instruction::Try(try_) => {
|
|
||||||
let end_block_addr = *label_addrs.get(&try_.end_label).ok_or(anyhow!(
|
|
||||||
"Label {} not found in code of {}, but found try with this label",
|
"Label {} not found in code of {}, but found try with this label",
|
||||||
&try_.end_label,
|
end_label,
|
||||||
method_id.__repr__()
|
method_id.__repr__()
|
||||||
))?;
|
))?;
|
||||||
if end_block_addr < addr {
|
if end_block_addr < addr {
|
||||||
|
|
@ -741,7 +695,7 @@ impl DexWriter {
|
||||||
handlers: vec![],
|
handlers: vec![],
|
||||||
catch_all_addr: None,
|
catch_all_addr: None,
|
||||||
};
|
};
|
||||||
for (ty, label) in &try_.handlers {
|
for (ty, label) in handlers {
|
||||||
let type_idx = Uleb128(*self.type_ids.get(ty).ok_or(anyhow!(
|
let type_idx = Uleb128(*self.type_ids.get(ty).ok_or(anyhow!(
|
||||||
"Could not found type {} captured by a try block in {}\
|
"Could not found type {} captured by a try block in {}\
|
||||||
in the dex builder",
|
in the dex builder",
|
||||||
|
|
@ -751,7 +705,7 @@ impl DexWriter {
|
||||||
let addr = Uleb128(*label_addrs.get(label).ok_or(anyhow!(
|
let addr = Uleb128(*label_addrs.get(label).ok_or(anyhow!(
|
||||||
"Label {} not found in code of {}, but found try \
|
"Label {} not found in code of {}, but found try \
|
||||||
with this label as catch for type {}",
|
with this label as catch for type {}",
|
||||||
&try_.end_label,
|
end_label,
|
||||||
method_id.__repr__(),
|
method_id.__repr__(),
|
||||||
ty.__repr__(),
|
ty.__repr__(),
|
||||||
))? as u32);
|
))? as u32);
|
||||||
|
|
@ -759,17 +713,17 @@ impl DexWriter {
|
||||||
.handlers
|
.handlers
|
||||||
.push(EncodedTypeAddrPair { type_idx, addr });
|
.push(EncodedTypeAddrPair { type_idx, addr });
|
||||||
}
|
}
|
||||||
if let Some(ref label) = try_.default_handler {
|
if let Some(ref label) = default_handler {
|
||||||
let catch_all_addr = *label_addrs.get(label).ok_or(anyhow!(
|
let catch_all_addr = *label_addrs.get(label).ok_or(anyhow!(
|
||||||
"Label {} not found in code of {}, but found try \
|
"Label {} not found in code of {}, but found try \
|
||||||
with this label as catch all",
|
with this label as catch all",
|
||||||
&try_.end_label,
|
end_label,
|
||||||
method_id.__repr__()
|
method_id.__repr__()
|
||||||
))?;
|
))?;
|
||||||
catches.catch_all_addr = Some(Uleb128(catch_all_addr as u32));
|
catches.catch_all_addr = Some(Uleb128(catch_all_addr as u32));
|
||||||
}
|
}
|
||||||
handler_off += catches.size();
|
handler_off += catches.size();
|
||||||
handlers.list.push(catches);
|
encoded_handlers.list.push(catches);
|
||||||
}
|
}
|
||||||
Instruction::Label { .. } => (),
|
Instruction::Label { .. } => (),
|
||||||
_ => {
|
_ => {
|
||||||
|
|
@ -778,6 +732,10 @@ impl DexWriter {
|
||||||
Some(&self.strings),
|
Some(&self.strings),
|
||||||
Some(&self.type_ids),
|
Some(&self.type_ids),
|
||||||
Some(&self.field_ids),
|
Some(&self.field_ids),
|
||||||
|
Some(&self.method_ids),
|
||||||
|
Some(&self.proto_ids),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
Some((addr, &label_addrs)),
|
Some((addr, &label_addrs)),
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
|
@ -796,14 +754,15 @@ 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(None, None, None, None, None, None)?;
|
let nop = (Instruction::Nop {})
|
||||||
|
.get_raw_ins(None, None, None, None, None, None, None, None, None, None)?;
|
||||||
//addr += nop.size() / 2;
|
//addr += nop.size() / 2;
|
||||||
insns.push(nop);
|
insns.push(nop);
|
||||||
}
|
}
|
||||||
insns.extend(payloads);
|
insns.extend(payloads);
|
||||||
|
|
||||||
for try_ in &mut tries {
|
for try_ in &mut tries {
|
||||||
try_.handler_off += handlers.size_field().size() as u16;
|
try_.handler_off += encoded_handlers.size_field().size() as u16;
|
||||||
}
|
}
|
||||||
|
|
||||||
let debug_info_off = if code.debug_info.1.is_empty() && code.parameter_names.is_none() {
|
let debug_info_off = if code.debug_info.1.is_empty() && code.parameter_names.is_none() {
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue