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)>,
|
||||
/// The encoded_array_items section.
|
||||
encoded_array_items: Vec<EncodedArrayItem>,
|
||||
/// The annotations_directory_item section.
|
||||
annotations_directory_items: Vec<AnnotationsDirectoryItem>,
|
||||
/// The annotations_directory_item.
|
||||
annotations_directory_items: Option<AnnotationsDirectoryItem>,
|
||||
/// The annotation_set_item section.
|
||||
annotation_set_items: Vec<AnnotationSetItem>,
|
||||
/// The annotation item section.
|
||||
|
|
@ -68,6 +68,8 @@ pub struct DexFragment {
|
|||
code_items: Vec<CodeItem>,
|
||||
/// The debug info items section.
|
||||
debug_info_items: Vec<DebugInfoItem>,
|
||||
/// The list of interfaces of the class.
|
||||
interfaces: Vec<IdType>,
|
||||
}
|
||||
|
||||
impl DexFragment {
|
||||
|
|
@ -101,11 +103,12 @@ impl DexFragment {
|
|||
encoded_array_items: vec![],
|
||||
method_handles: vec![],
|
||||
code_items: vec![],
|
||||
annotations_directory_items: vec![],
|
||||
annotations_directory_items: None,
|
||||
annotation_set_items: vec![],
|
||||
annotation_items: vec![],
|
||||
annotation_set_lists: vec![],
|
||||
debug_info_items: vec![],
|
||||
interfaces: class.interfaces.clone(),
|
||||
};
|
||||
frag.strings = class.get_all_strings().into_iter().collect();
|
||||
frag.strings.sort();
|
||||
|
|
@ -150,6 +153,54 @@ impl DexFragment {
|
|||
|
||||
frag.section_manager
|
||||
.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)
|
||||
}
|
||||
|
||||
|
|
@ -1947,97 +1998,6 @@ impl DexFragment {
|
|||
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<()> {
|
||||
debug!("Generate the type_list section");
|
||||
// Collect all type lists
|
||||
|
|
@ -2781,7 +2741,9 @@ impl FragSectionManager {
|
|||
if !self.editable {
|
||||
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)
|
||||
{
|
||||
panic!("{section:#?} cannot contain more than one element in a dex fragment");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue