WIP: gen class def in frag
This commit is contained in:
parent
71fc0d2398
commit
7e63a523d7
1 changed files with 57 additions and 95 deletions
|
|
@ -54,8 +54,8 @@ pub struct DexFragment {
|
||||||
type_lists_with_offset: Vec<(TypeList, u32)>,
|
type_lists_with_offset: Vec<(TypeList, u32)>,
|
||||||
/// The encoded_array_items section.
|
/// The encoded_array_items section.
|
||||||
encoded_array_items: Vec<EncodedArrayItem>,
|
encoded_array_items: Vec<EncodedArrayItem>,
|
||||||
/// The annotations_directory_item section.
|
/// The annotations_directory_item.
|
||||||
annotations_directory_items: Vec<AnnotationsDirectoryItem>,
|
annotations_directory_items: Option<AnnotationsDirectoryItem>,
|
||||||
/// The annotation_set_item section.
|
/// The annotation_set_item section.
|
||||||
annotation_set_items: Vec<AnnotationSetItem>,
|
annotation_set_items: Vec<AnnotationSetItem>,
|
||||||
/// The annotation item section.
|
/// The annotation item section.
|
||||||
|
|
@ -68,6 +68,8 @@ pub struct DexFragment {
|
||||||
code_items: Vec<CodeItem>,
|
code_items: Vec<CodeItem>,
|
||||||
/// The debug info items section.
|
/// The debug info items section.
|
||||||
debug_info_items: Vec<DebugInfoItem>,
|
debug_info_items: Vec<DebugInfoItem>,
|
||||||
|
/// The list of interfaces of the class.
|
||||||
|
interfaces: Vec<IdType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DexFragment {
|
impl DexFragment {
|
||||||
|
|
@ -101,11 +103,12 @@ impl DexFragment {
|
||||||
encoded_array_items: vec![],
|
encoded_array_items: vec![],
|
||||||
method_handles: vec![],
|
method_handles: vec![],
|
||||||
code_items: vec![],
|
code_items: vec![],
|
||||||
annotations_directory_items: vec![],
|
annotations_directory_items: None,
|
||||||
annotation_set_items: vec![],
|
annotation_set_items: vec![],
|
||||||
annotation_items: vec![],
|
annotation_items: vec![],
|
||||||
annotation_set_lists: vec![],
|
annotation_set_lists: vec![],
|
||||||
debug_info_items: vec![],
|
debug_info_items: vec![],
|
||||||
|
interfaces: class.interfaces.clone(),
|
||||||
};
|
};
|
||||||
frag.strings = class.get_all_strings().into_iter().collect();
|
frag.strings = class.get_all_strings().into_iter().collect();
|
||||||
frag.strings.sort();
|
frag.strings.sort();
|
||||||
|
|
@ -150,6 +153,54 @@ impl DexFragment {
|
||||||
|
|
||||||
frag.section_manager
|
frag.section_manager
|
||||||
.add_elt(FragSection::ClassDefItem, None);
|
.add_elt(FragSection::ClassDefItem, None);
|
||||||
|
|
||||||
|
frag.class_def.class_idx = *types_index.get(&class.descriptor).ok_or(anyhow!(
|
||||||
|
"Type {} (type of class {}) not found in type list",
|
||||||
|
class.descriptor.__repr__(),
|
||||||
|
class.__repr__()
|
||||||
|
))? as u32;
|
||||||
|
frag.class_def.access_flags = class.get_raw_access_flags();
|
||||||
|
frag.class_def.superclass_idx = if let Some(sup) = &class.superclass {
|
||||||
|
*types_index.get(sup).ok_or(anyhow!(
|
||||||
|
"Type {} (superclass of class {}) not found in dex builder",
|
||||||
|
sup.__repr__(),
|
||||||
|
class.__repr__()
|
||||||
|
))? as u32
|
||||||
|
} else {
|
||||||
|
NO_INDEX.0
|
||||||
|
};
|
||||||
|
frag.class_def.interfaces_off = 0; // set when linking
|
||||||
|
frag.class_def.source_file_idx = if let Some(file) = &class.source_file {
|
||||||
|
*strings_index.get(file).ok_or(anyhow!(
|
||||||
|
"String {} (source file of class {}) not found in dex builder",
|
||||||
|
file.__repr__(),
|
||||||
|
class.__repr__()
|
||||||
|
))? as u32
|
||||||
|
} else {
|
||||||
|
NO_INDEX.0
|
||||||
|
};
|
||||||
|
frag.class_def.annotations_off = if class.has_annotations() {
|
||||||
|
// TODO: frag.insert_annotations(class)?;
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
frag.class_def.class_data_off = if class.has_data_item() {
|
||||||
|
//TODO: frag.insert_class_data_item(class_id)?;
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
frag.class_def.static_values_off = if class.has_static_values_array() {
|
||||||
|
let static_values_off = frag
|
||||||
|
.section_manager
|
||||||
|
.get_aligned_size(FragSection::EncodedArrayItem);
|
||||||
|
// TODO: frag.insert_class_static_values(class)?;
|
||||||
|
static_values_off + 1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
Ok(frag)
|
Ok(frag)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1947,97 +1998,6 @@ impl DexFragment {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Insert a class_def_item in the class_defs section **and** the other struct that needs to be
|
|
||||||
/// generated on the fly.
|
|
||||||
///
|
|
||||||
/// # Warning
|
|
||||||
///
|
|
||||||
/// The class_defs section **MUST** be sorted by inheritance dependencies (parents classes and
|
|
||||||
/// interfaces must appear **before** child classes). Accordingly, this method must be invoked
|
|
||||||
/// in the right order.
|
|
||||||
///
|
|
||||||
/// # Note
|
|
||||||
///
|
|
||||||
/// annotations_directory_item, encoded_array_item and class_data_item objects are 4 bytes
|
|
||||||
/// aligns, so their offset cannot be odd.
|
|
||||||
///
|
|
||||||
/// To distinguish prelinked value (offset inside the code_item section) to actual values (offset
|
|
||||||
/// in the whole file or 0), their value is set to the actual value prelink value + 1. This allow
|
|
||||||
/// to distinguish the offset of the first item (equal to zero before linking) and the value
|
|
||||||
/// 0 used to indicate an abscence of item.
|
|
||||||
fn insert_class_def_item(&mut self, class_id: &IdType) -> Result<()> {
|
|
||||||
let idx = self.class_defs_list.len();
|
|
||||||
self.class_defs
|
|
||||||
.entry(class_id.clone())
|
|
||||||
.and_modify(|(_, i)| *i = idx);
|
|
||||||
let (class, _) = self.class_defs.get(class_id).unwrap();
|
|
||||||
let class_data_off = if class.has_data_item() {
|
|
||||||
let class_data_off = self
|
|
||||||
.section_manager
|
|
||||||
.get_aligned_size(Section::ClassDataItem);
|
|
||||||
self.insert_class_data_item(class_id)?;
|
|
||||||
class_data_off + 1
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
};
|
|
||||||
// & vs &mut cluster-f, this make rust drop the ref so self hold by `class` before
|
|
||||||
// mutating self with `insert_class_data_item`, and get a new ref afterward
|
|
||||||
let (class, _) = self.class_defs.get(class_id).unwrap();
|
|
||||||
let static_values_off = if class.has_static_values_array() {
|
|
||||||
let static_values_off = self
|
|
||||||
.section_manager
|
|
||||||
.get_aligned_size(Section::EncodedArrayItem);
|
|
||||||
self.insert_class_static_values(class_id)?;
|
|
||||||
static_values_off + 1
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
};
|
|
||||||
let (class, _) = self.class_defs.get(class_id).unwrap();
|
|
||||||
let annotations_off = if class.has_annotations() {
|
|
||||||
let annotations_off = self
|
|
||||||
.section_manager
|
|
||||||
.get_aligned_size(Section::AnnotationsDirectoryItem);
|
|
||||||
self.insert_annotations(class_id)?;
|
|
||||||
annotations_off + 1
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
};
|
|
||||||
let (class, _) = self.class_defs.get(class_id).unwrap();
|
|
||||||
self.class_defs_list.push(ClassDefItem {
|
|
||||||
class_idx: *self.type_ids.get(class_id).ok_or(anyhow!(
|
|
||||||
"Type {} (type of class {}) not found in dex builder",
|
|
||||||
class_id.__repr__(),
|
|
||||||
class.__repr__()
|
|
||||||
))? as u32,
|
|
||||||
access_flags: class.get_raw_access_flags(),
|
|
||||||
superclass_idx: if let Some(sup) = &class.superclass {
|
|
||||||
*self.type_ids.get(sup).ok_or(anyhow!(
|
|
||||||
"Type {} (superclass of class {}) not found in dex builder",
|
|
||||||
sup.__repr__(),
|
|
||||||
class.__repr__()
|
|
||||||
))? as u32
|
|
||||||
} else {
|
|
||||||
NO_INDEX.0
|
|
||||||
},
|
|
||||||
interfaces_off: 0,
|
|
||||||
source_file_idx: if let Some(file) = &class.source_file {
|
|
||||||
*self.strings.get(file).ok_or(anyhow!(
|
|
||||||
"String {} (source file of class {}) not found in dex builder",
|
|
||||||
file.__repr__(),
|
|
||||||
class.__repr__()
|
|
||||||
))? as u32
|
|
||||||
} else {
|
|
||||||
NO_INDEX.0
|
|
||||||
},
|
|
||||||
|
|
||||||
annotations_off, // need relinking once offset of class_def_item section is known
|
|
||||||
class_data_off, // need relinking once offset of class_data section is known
|
|
||||||
static_values_off, // need relinking once offset of encoded_array section is known
|
|
||||||
});
|
|
||||||
self.section_manager.add_elt(Section::ClassDefItem, None);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn gen_type_list_section(&mut self) -> Result<()> {
|
fn gen_type_list_section(&mut self) -> Result<()> {
|
||||||
debug!("Generate the type_list section");
|
debug!("Generate the type_list section");
|
||||||
// Collect all type lists
|
// Collect all type lists
|
||||||
|
|
@ -2781,7 +2741,9 @@ impl FragSectionManager {
|
||||||
if !self.editable {
|
if !self.editable {
|
||||||
panic!("Try to modify a section when the sections are set to read only");
|
panic!("Try to modify a section when the sections are set to read only");
|
||||||
}
|
}
|
||||||
if (section == FragSection::ClassDefItem || section == FragSection::ClassDataItem)
|
if (section == FragSection::ClassDefItem
|
||||||
|
|| section == FragSection::ClassDataItem
|
||||||
|
|| section == FragSection::AnnotationsDirectoryItem)
|
||||||
&& (self.nb_elt[section.get_index()] >= 1)
|
&& (self.nb_elt[section.get_index()] >= 1)
|
||||||
{
|
{
|
||||||
panic!("{section:#?} cannot contain more than one element in a dex fragment");
|
panic!("{section:#?} cannot contain more than one element in a dex fragment");
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue