diff --git a/androscalpel/src/dex_fragment.rs b/androscalpel/src/dex_fragment.rs index a506221..e5ddb9f 100644 --- a/androscalpel/src/dex_fragment.rs +++ b/androscalpel/src/dex_fragment.rs @@ -156,15 +156,15 @@ impl DexFragment { 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__() + class.descriptor.__str__(), + class.__str__() ))? 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__() + sup.__str__(), + class.__str__() ))? as u32 } else { NO_INDEX.0 @@ -173,14 +173,14 @@ impl DexFragment { 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__() + file.__str__(), + class.__str__() ))? as u32 } else { NO_INDEX.0 }; frag.class_def.annotations_off = if class.has_annotations() { - // TODO: frag.insert_annotations(class)?; + frag.insert_annotations(class)?; 1 } else { 0 @@ -204,6 +204,181 @@ impl DexFragment { Ok(frag) } + /// Insert a class annotations (including field, methods and parameters annotations). + /// + /// # Note + /// + /// annotation_set_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_annotations(&mut self, class: &Class) -> Result<()> { + let class_annotations_off = if !class.annotations.is_empty() { + let class_annotations_off = self + .section_manager + .get_aligned_size(FragSection::AnnotationSetItem); + self.insert_class_annotation_set(class).with_context(|| { + format!( + "Failed to insert class annotation for class {}", + class.__str__() + ) + })?; + class_annotations_off + 1 + } else { + 0 + }; + + let mut field_ids = vec![]; + let (class, _) = self.class_defs.get(class_id).unwrap(); + field_ids.extend(class.static_fields.keys().cloned()); + field_ids.extend(class.instance_fields.keys().cloned()); + field_ids.sort(); + let mut field_annotations = vec![]; + for field_id in field_ids { + let (class, _) = self.class_defs.get(class_id).unwrap(); + let static_field = class.static_fields.get(&field_id); + let instance_field = class.instance_fields.get(&field_id); + let (is_static, field) = match (static_field, instance_field) { + (Some(field), None) => (true, field), + (None, Some(field)) => (false, field), + _ => bail!( + "Unexpected configuration: field {} is both a static and a instance field in {}", + field_id.__str__(), class_id.__str__()), + }; + if !field.annotations.is_empty() { + let annotations_off = self + .section_manager + .get_aligned_size(Section::AnnotationSetItem) + + 1; + self.insert_field_annotation_set(&field_id, is_static)?; + field_annotations.push(FieldAnnotation { + field_idx: *self.field_ids.get(&field_id).ok_or(anyhow!( + "Field {} in {} not found in dex builder", + field_id.__str__(), + class_id.__str__(), + ))? as u32, + annotations_off, // linked in link_annotations() + }); + } + } + + let mut method_ids = vec![]; + let (class, _) = self.class_defs.get(class_id).unwrap(); + method_ids.extend(class.direct_methods.keys().cloned()); + method_ids.extend(class.virtual_methods.keys().cloned()); + method_ids.sort(); + let mut method_annotations = vec![]; + for method_id in &method_ids { + let (class, _) = self.class_defs.get(class_id).unwrap(); + let direct_method = class.direct_methods.get(method_id); + let virtual_method = class.virtual_methods.get(method_id); + let (is_direct, method) = match (direct_method, virtual_method) { + (Some(method), None) => (true, method), + (None, Some(method)) => (false, method), + _ => bail!( + "Unexpected configuration: method {} is both a direct and a virtual method in {}", + method_id.__str__(), class_id.__str__()), + }; + if !method.annotations.is_empty() { + let annotations_off = self + .section_manager + .get_aligned_size(Section::AnnotationSetItem) + + 1; + self.insert_method_annotation_set(method_id, is_direct)?; + method_annotations.push(MethodAnnotation { + method_idx: *self.method_ids.get(method_id).ok_or(anyhow!( + "Method {} in {} not found in dex builder", + method_id.__str__(), + class_id.__str__(), + ))? as u32, + annotations_off, // linked in link_annotations() + }); + } + } + + let mut parameter_annotations = vec![]; + for method_id in method_ids { + let (class, _) = self.class_defs.get(class_id).unwrap(); + let direct_method = class.direct_methods.get(&method_id); + let virtual_method = class.virtual_methods.get(&method_id); + let (is_direct, method) = match (direct_method, virtual_method) { + (Some(method), None) => (true, method), + (None, Some(method)) => (false, method), + _ => bail!( + "Unexpected configuration: method {} is both a direct and a virtual method in {}", + method_id.__str__(), class_id.__str__()), + }; + if !method.parameters_annotations.is_empty() { + let annotations_off = self + .section_manager + .get_aligned_size(Section::AnnotationSetRefList) + + 1; + self.insert_parameters_annotation_set_list(&method_id, is_direct)?; + parameter_annotations.push(ParameterAnnotation { + method_idx: *self.method_ids.get(&method_id).ok_or(anyhow!( + "Method {} in {} not found in dex builder", + method_id.__str__(), + class_id.__str__(), + ))? as u32, + annotations_off, // linked in link_annotations() + }); + } + } + + let item = AnnotationsDirectoryItem { + class_annotations_off, // linked in link_annotations() + field_annotations, + method_annotations, + parameter_annotations, + }; + self.section_manager + .add_elt(FragSection::AnnotationsDirectoryItem, Some(item.size())); + self.annotations_directory_items.push(item); + Ok(()) + } + + /// Insert the annnotations set for a class. + fn insert_class_annotation_set(&mut self, class: &Class) -> Result<()> { + let mut annotations = class.annotations.clone(); + + let mut annotation_set = AnnotationSetItem { entries: vec![] }; + annotations.sort_by_key(|annot| annot.annotation.type_.clone()); + for annot in annotations { + annotation_set.entries.push(AnnotationOffItem { + annotation_off: self + .section_manager + .get_aligned_size(FragSection::AnnotationItem) + + 1, + }); + + let item = AnnotationItem { + visibility: match ( + annot.visibility_build, + annot.visibility_runtime, + annot.visibility_system, + ) { + (true, false, false) => AnnotationVisibility::Build, + (false, true, false) => AnnotationVisibility::Runtime, + (false, false, true) => AnnotationVisibility::System, + _ => bail!( + "Annotation need visibility set to one and only one of build, \ + runtime or system" + ), // TODO: check if this is true + }, + annotation: self.dex_annotation_to_encoded_annotation(annot.annotation)?, + }; + self.section_manager + .add_elt(FragSection::AnnotationItem, Some(item.size())); + self.annotation_items.push(item); + } + self.section_manager + .add_elt(FragSection::AnnotationSetItem, Some(annotation_set.size())); + self.annotation_set_items.push(annotation_set); + Ok(()) + } + /// Insert a code_item. /// /// # Warning @@ -250,8 +425,8 @@ impl DexFragment { Instruction::ConstString(ins) => { let string_idx = self.strings.get(&ins.lit).ok_or(anyhow!( "String {} (found in code of {}) not found in dex builder", - ins.lit.__repr__(), - method_id.__repr__() + ins.lit.__str__(), + method_id.__str__() ))?; let size = ins.get_raw_ins(*string_idx).size() / 2; min_addr += size; @@ -276,8 +451,8 @@ impl DexFragment { Instruction::ConstString(ins) => { let string_idx = self.strings.get(&ins.lit).ok_or(anyhow!( "String {} (found in code of {}) not found in dex builder", - ins.lit.__repr__(), - method_id.__repr__() + ins.lit.__str__(), + method_id.__str__() ))?; addr += ins.get_raw_ins(*string_idx).size() / 2; } @@ -309,8 +484,8 @@ impl DexFragment { Instruction::ConstString(ins) => { let string_idx = self.strings.get(&ins.lit).ok_or(anyhow!( "String {} (found in code of {}) not found in dex builder", - ins.lit.__repr__(), - method_id.__repr__() + ins.lit.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(*string_idx); addr += ins.size() / 2; @@ -319,8 +494,8 @@ impl DexFragment { 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__() + ins.lit.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(class_idx); addr += ins.size() / 2; @@ -329,8 +504,8 @@ impl DexFragment { 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__() + ins.lit.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(class_idx); addr += ins.size() / 2; @@ -339,8 +514,8 @@ impl DexFragment { 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__() + ins.lit.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(class_idx); addr += ins.size() / 2; @@ -349,8 +524,8 @@ impl DexFragment { 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__() + ins.lit.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(class_idx); addr += ins.size() / 2; @@ -359,8 +534,8 @@ impl DexFragment { 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__() + ins.lit.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(class_idx); addr += ins.size() / 2; @@ -369,8 +544,8 @@ impl DexFragment { 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__() + ins.type_.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(class_idx); addr += ins.size() / 2; @@ -402,7 +577,7 @@ impl DexFragment { let label_addr = label_addrs.get(&ins.label).ok_or(anyhow!( "Label {} not found in code of {}, but found goto with this label", ins.label, - method_id.__repr__() + method_id.__str__() ))?; let branch_offset = *label_addr as i32 - addr as i32; let ins = ins.get_raw_ins(branch_offset, goto_size); @@ -415,7 +590,7 @@ impl DexFragment { let label_addr = label_addrs.get(label).ok_or(anyhow!( "Label {} not found in code of {}, but found goto with this label", label, - method_id.__repr__() + method_id.__str__() ))?; let branch_offset = *label_addr as i32 - addr as i32; key_targets.push((*key, branch_offset)); @@ -424,7 +599,7 @@ impl DexFragment { let payload = if ins.is_packed() { let (first_key, _) = *key_targets.first().ok_or(anyhow!( "Found empty swith in code of {}", - method_id.__repr__() + method_id.__str__() ))?; let targets: Vec<_> = key_targets.into_iter().map(|(_, target)| target).collect(); @@ -451,13 +626,13 @@ impl DexFragment { let label_addr = label_addrs.get(&ins.label).ok_or(anyhow!( "Label {} not found in code of {}, but found if with this label", ins.label, - method_id.__repr__() + method_id.__str__() ))?; let branch_offset = *label_addr as i32 - addr as i32; if branch_offset > i16::MAX as i32 || branch_offset < i16::MIN as i32 { bail!( "Found an if that jump to far from the instruction in code of {}", - method_id.__repr__() + method_id.__str__() ); } let ins = ins.get_raw_ins(branch_offset as i16); @@ -468,13 +643,13 @@ impl DexFragment { let label_addr = label_addrs.get(&ins.label).ok_or(anyhow!( "Label {} not found in code of {}, but found if with this label", ins.label, - method_id.__repr__() + method_id.__str__() ))?; let branch_offset = *label_addr as i32 - addr as i32; if branch_offset > i16::MAX as i32 || branch_offset < i16::MIN as i32 { bail!( "Found an if that jump to far from the instruction in code of {}", - method_id.__repr__() + method_id.__str__() ); } let ins = ins.get_raw_ins(branch_offset as i16); @@ -485,13 +660,13 @@ impl DexFragment { let label_addr = label_addrs.get(&ins.label).ok_or(anyhow!( "Label {} not found in code of {}, but found if with this label", ins.label, - method_id.__repr__() + method_id.__str__() ))?; let branch_offset = *label_addr as i32 - addr as i32; if branch_offset > i16::MAX as i32 || branch_offset < i16::MIN as i32 { bail!( "Found an if that jump to far from the instruction in code of {}", - method_id.__repr__() + method_id.__str__() ); } let ins = ins.get_raw_ins(branch_offset as i16); @@ -502,13 +677,13 @@ impl DexFragment { let label_addr = label_addrs.get(&ins.label).ok_or(anyhow!( "Label {} not found in code of {}, but found if with this label", ins.label, - method_id.__repr__() + method_id.__str__() ))?; let branch_offset = *label_addr as i32 - addr as i32; if branch_offset > i16::MAX as i32 || branch_offset < i16::MIN as i32 { bail!( "Found an if that jump to far from the instruction in code of {}", - method_id.__repr__() + method_id.__str__() ); } let ins = ins.get_raw_ins(branch_offset as i16); @@ -519,13 +694,13 @@ impl DexFragment { let label_addr = label_addrs.get(&ins.label).ok_or(anyhow!( "Label {} not found in code of {}, but found if with this label", ins.label, - method_id.__repr__() + method_id.__str__() ))?; let branch_offset = *label_addr as i32 - addr as i32; if branch_offset > i16::MAX as i32 || branch_offset < i16::MIN as i32 { bail!( "Found an if that jump to far from the instruction in code of {}", - method_id.__repr__() + method_id.__str__() ); } let ins = ins.get_raw_ins(branch_offset as i16); @@ -536,13 +711,13 @@ impl DexFragment { let label_addr = label_addrs.get(&ins.label).ok_or(anyhow!( "Label {} not found in code of {}, but found if with this label", ins.label, - method_id.__repr__() + method_id.__str__() ))?; let branch_offset = *label_addr as i32 - addr as i32; if branch_offset > i16::MAX as i32 || branch_offset < i16::MIN as i32 { bail!( "Found an if that jump to far from the instruction in code of {}", - method_id.__repr__() + method_id.__str__() ); } let ins = ins.get_raw_ins(branch_offset as i16); @@ -553,13 +728,13 @@ impl DexFragment { let label_addr = label_addrs.get(&ins.label).ok_or(anyhow!( "Label {} not found in code of {}, but found if with this label", ins.label, - method_id.__repr__() + method_id.__str__() ))?; let branch_offset = *label_addr as i32 - addr as i32; if branch_offset > i16::MAX as i32 || branch_offset < i16::MIN as i32 { bail!( "Found an if that jump to far from the instruction in code of {}", - method_id.__repr__() + method_id.__str__() ); } let ins = ins.get_raw_ins(branch_offset as i16); @@ -570,13 +745,13 @@ impl DexFragment { let label_addr = label_addrs.get(&ins.label).ok_or(anyhow!( "Label {} not found in code of {}, but found if with this label", ins.label, - method_id.__repr__() + method_id.__str__() ))?; let branch_offset = *label_addr as i32 - addr as i32; if branch_offset > i16::MAX as i32 || branch_offset < i16::MIN as i32 { bail!( "Found an if that jump to far from the instruction in code of {}", - method_id.__repr__() + method_id.__str__() ); } let ins = ins.get_raw_ins(branch_offset as i16); @@ -587,13 +762,13 @@ impl DexFragment { let label_addr = label_addrs.get(&ins.label).ok_or(anyhow!( "Label {} not found in code of {}, but found if with this label", ins.label, - method_id.__repr__() + method_id.__str__() ))?; let branch_offset = *label_addr as i32 - addr as i32; if branch_offset > i16::MAX as i32 || branch_offset < i16::MIN as i32 { bail!( "Found an if that jump to far from the instruction in code of {}", - method_id.__repr__() + method_id.__str__() ); } let ins = ins.get_raw_ins(branch_offset as i16); @@ -604,13 +779,13 @@ impl DexFragment { let label_addr = label_addrs.get(&ins.label).ok_or(anyhow!( "Label {} not found in code of {}, but found if with this label", ins.label, - method_id.__repr__() + method_id.__str__() ))?; let branch_offset = *label_addr as i32 - addr as i32; if branch_offset > i16::MAX as i32 || branch_offset < i16::MIN as i32 { bail!( "Found an if that jump to far from the instruction in code of {}", - method_id.__repr__() + method_id.__str__() ); } let ins = ins.get_raw_ins(branch_offset as i16); @@ -621,13 +796,13 @@ impl DexFragment { let label_addr = label_addrs.get(&ins.label).ok_or(anyhow!( "Label {} not found in code of {}, but found if with this label", ins.label, - method_id.__repr__() + method_id.__str__() ))?; let branch_offset = *label_addr as i32 - addr as i32; if branch_offset > i16::MAX as i32 || branch_offset < i16::MIN as i32 { bail!( "Found an if that jump to far from the instruction in code of {}", - method_id.__repr__() + method_id.__str__() ); } let ins = ins.get_raw_ins(branch_offset as i16); @@ -638,13 +813,13 @@ impl DexFragment { let label_addr = label_addrs.get(&ins.label).ok_or(anyhow!( "Label {} not found in code of {}, but found if with this label", ins.label, - method_id.__repr__() + method_id.__str__() ))?; let branch_offset = *label_addr as i32 - addr as i32; if branch_offset > i16::MAX as i32 || branch_offset < i16::MIN as i32 { bail!( "Found an if that jump to far from the instruction in code of {}", - method_id.__repr__() + method_id.__str__() ); } let ins = ins.get_raw_ins(branch_offset as i16); @@ -655,9 +830,9 @@ impl DexFragment { let field = &ins.field; let field_idx = self.field_ids.get(field).ok_or(anyhow!( "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() + field.__str__(), + field.class_.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(*field_idx); addr += ins.size() / 2; @@ -667,9 +842,9 @@ impl DexFragment { let field = &ins.field; let field_idx = self.field_ids.get(field).ok_or(anyhow!( "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() + field.__str__(), + field.class_.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(*field_idx); addr += ins.size() / 2; @@ -679,9 +854,9 @@ impl DexFragment { let field = &ins.field; let field_idx = self.field_ids.get(field).ok_or(anyhow!( "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() + field.__str__(), + field.class_.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(*field_idx); addr += ins.size() / 2; @@ -691,9 +866,9 @@ impl DexFragment { let field = &ins.field; let field_idx = self.field_ids.get(field).ok_or(anyhow!( "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() + field.__str__(), + field.class_.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(*field_idx); addr += ins.size() / 2; @@ -703,9 +878,9 @@ impl DexFragment { let field = &ins.field; let field_idx = self.field_ids.get(field).ok_or(anyhow!( "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() + field.__str__(), + field.class_.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(*field_idx); addr += ins.size() / 2; @@ -715,9 +890,9 @@ impl DexFragment { let field = &ins.field; let field_idx = self.field_ids.get(field).ok_or(anyhow!( "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() + field.__str__(), + field.class_.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(*field_idx); addr += ins.size() / 2; @@ -727,9 +902,9 @@ impl DexFragment { let field = &ins.field; let field_idx = self.field_ids.get(field).ok_or(anyhow!( "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() + field.__str__(), + field.class_.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(*field_idx); addr += ins.size() / 2; @@ -739,9 +914,9 @@ impl DexFragment { let field = &ins.field; let field_idx = self.field_ids.get(field).ok_or(anyhow!( "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() + field.__str__(), + field.class_.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(*field_idx); addr += ins.size() / 2; @@ -751,9 +926,9 @@ impl DexFragment { let field = &ins.field; let field_idx = self.field_ids.get(field).ok_or(anyhow!( "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() + field.__str__(), + field.class_.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(*field_idx); addr += ins.size() / 2; @@ -763,9 +938,9 @@ impl DexFragment { let field = &ins.field; let field_idx = self.field_ids.get(field).ok_or(anyhow!( "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() + field.__str__(), + field.class_.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(*field_idx); addr += ins.size() / 2; @@ -775,9 +950,9 @@ impl DexFragment { let field = &ins.field; let field_idx = self.field_ids.get(field).ok_or(anyhow!( "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() + field.__str__(), + field.class_.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(*field_idx); addr += ins.size() / 2; @@ -787,9 +962,9 @@ impl DexFragment { let field = &ins.field; let field_idx = self.field_ids.get(field).ok_or(anyhow!( "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() + field.__str__(), + field.class_.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(*field_idx); addr += ins.size() / 2; @@ -799,9 +974,9 @@ impl DexFragment { let field = &ins.field; let field_idx = self.field_ids.get(field).ok_or(anyhow!( "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() + field.__str__(), + field.class_.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(*field_idx); addr += ins.size() / 2; @@ -811,9 +986,9 @@ impl DexFragment { let field = &ins.field; let field_idx = self.field_ids.get(field).ok_or(anyhow!( "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() + field.__str__(), + field.class_.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(*field_idx); addr += ins.size() / 2; @@ -823,9 +998,9 @@ impl DexFragment { let field = &ins.field; let field_idx = self.field_ids.get(field).ok_or(anyhow!( "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() + field.__str__(), + field.class_.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(*field_idx); addr += ins.size() / 2; @@ -835,9 +1010,9 @@ impl DexFragment { let field = &ins.field; let field_idx = self.field_ids.get(field).ok_or(anyhow!( "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() + field.__str__(), + field.class_.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(*field_idx); addr += ins.size() / 2; @@ -847,9 +1022,9 @@ impl DexFragment { let field = &ins.field; let field_idx = self.field_ids.get(field).ok_or(anyhow!( "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() + field.__str__(), + field.class_.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(*field_idx); addr += ins.size() / 2; @@ -859,9 +1034,9 @@ impl DexFragment { let field = &ins.field; let field_idx = self.field_ids.get(field).ok_or(anyhow!( "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() + field.__str__(), + field.class_.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(*field_idx); addr += ins.size() / 2; @@ -871,9 +1046,9 @@ impl DexFragment { let field = &ins.field; let field_idx = self.field_ids.get(field).ok_or(anyhow!( "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() + field.__str__(), + field.class_.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(*field_idx); addr += ins.size() / 2; @@ -883,9 +1058,9 @@ impl DexFragment { let field = &ins.field; let field_idx = self.field_ids.get(field).ok_or(anyhow!( "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() + field.__str__(), + field.class_.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(*field_idx); addr += ins.size() / 2; @@ -895,9 +1070,9 @@ impl DexFragment { let field = &ins.field; let field_idx = self.field_ids.get(field).ok_or(anyhow!( "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() + field.__str__(), + field.class_.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(*field_idx); addr += ins.size() / 2; @@ -907,9 +1082,9 @@ impl DexFragment { let field = &ins.field; let field_idx = self.field_ids.get(field).ok_or(anyhow!( "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() + field.__str__(), + field.class_.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(*field_idx); addr += ins.size() / 2; @@ -919,9 +1094,9 @@ impl DexFragment { let field = &ins.field; let field_idx = self.field_ids.get(field).ok_or(anyhow!( "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() + field.__str__(), + field.class_.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(*field_idx); addr += ins.size() / 2; @@ -931,9 +1106,9 @@ impl DexFragment { let field = &ins.field; let field_idx = self.field_ids.get(field).ok_or(anyhow!( "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() + field.__str__(), + field.class_.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(*field_idx); addr += ins.size() / 2; @@ -943,9 +1118,9 @@ impl DexFragment { let field = &ins.field; let field_idx = self.field_ids.get(field).ok_or(anyhow!( "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() + field.__str__(), + field.class_.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(*field_idx); addr += ins.size() / 2; @@ -955,9 +1130,9 @@ impl DexFragment { let field = &ins.field; let field_idx = self.field_ids.get(field).ok_or(anyhow!( "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() + field.__str__(), + field.class_.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(*field_idx); addr += ins.size() / 2; @@ -967,9 +1142,9 @@ impl DexFragment { let field = &ins.field; let field_idx = self.field_ids.get(field).ok_or(anyhow!( "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() + field.__str__(), + field.class_.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(*field_idx); addr += ins.size() / 2; @@ -979,9 +1154,9 @@ impl DexFragment { let field = &ins.field; let field_idx = self.field_ids.get(field).ok_or(anyhow!( "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() + field.__str__(), + field.class_.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(*field_idx); addr += ins.size() / 2; @@ -991,9 +1166,9 @@ impl DexFragment { 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__() + meth.__str__(), + meth.class_.__str__(), + method_id.__str__() ))?; debug_assert!( *meth_idx <= u16::MAX as usize, @@ -1008,9 +1183,9 @@ impl DexFragment { 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__() + meth.__str__(), + meth.class_.__str__(), + method_id.__str__() ))?; debug_assert!( *meth_idx <= u16::MAX as usize, @@ -1025,9 +1200,9 @@ impl DexFragment { 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__() + meth.__str__(), + meth.class_.__str__(), + method_id.__str__() ))?; debug_assert!( *meth_idx <= u16::MAX as usize, @@ -1042,9 +1217,9 @@ impl DexFragment { 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__() + meth.__str__(), + meth.class_.__str__(), + method_id.__str__() ))?; debug_assert!( *meth_idx <= u16::MAX as usize, @@ -1059,9 +1234,9 @@ impl DexFragment { 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__() + meth.__str__(), + meth.class_.__str__(), + method_id.__str__() ))?; debug_assert!( *meth_idx <= u16::MAX as usize, @@ -1076,14 +1251,14 @@ impl DexFragment { 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__() + meth.__str__(), + meth.class_.__str__(), + method_id.__str__() ))?; 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__() + ins.proto.__str__(), + method_id.__str__() ))?; debug_assert!( *meth_idx <= u16::MAX as usize, @@ -1116,8 +1291,8 @@ impl DexFragment { Instruction::ConstMethodType(ins) => { 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__() + ins.proto.__str__(), + method_id.__str__() ))?; let ins = ins.get_raw_ins(*proto_idx); addr += ins.size() / 2; @@ -1127,12 +1302,12 @@ impl DexFragment { 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", &try_.end_label, - method_id.__repr__() + method_id.__str__() ))?; if end_block_addr < addr { bail!( "Found end label of a try block before the try instruction in code of {}", - method_id.__repr__() + method_id.__str__() ) } let try_item = TryItem { @@ -1150,15 +1325,15 @@ impl DexFragment { let type_idx = Uleb128(*self.type_ids.get(ty).ok_or(anyhow!( "Could not found type {} captured by a try block in {}\ in the dex builder", - ty.__repr__(), - method_id.__repr__() + ty.__str__(), + method_id.__str__() ))? as u32); let addr = Uleb128(*label_addrs.get(label).ok_or(anyhow!( "Label {} not found in code of {}, but found try \ with this label as catch for type {}", &try_.end_label, - method_id.__repr__(), - ty.__repr__(), + method_id.__str__(), + ty.__str__(), ))? as u32); catches .handlers @@ -1169,7 +1344,7 @@ impl DexFragment { "Label {} not found in code of {}, but found try \ with this label as catch all", &try_.end_label, - method_id.__repr__() + method_id.__str__() ))?; catches.catch_all_addr = Some(Uleb128(catch_all_addr as u32)); } @@ -1181,8 +1356,8 @@ impl DexFragment { let ins = ins.get_raw_ins().with_context(|| { format!( "Failed to convert instruction {} (found in code of {}) to raw instruction", - ins.__repr__(), - method_id.__repr__() + ins.__str__(), + method_id.__str__() ) })?; addr += ins.size() / 2; @@ -1221,7 +1396,7 @@ impl DexFragment { .push(Uleb128p1(*self.strings.get(name).ok_or(anyhow!( "String {} (name of param of {}) not found", name.__str__(), - method_id.__repr__() + method_id.__str__() ))? as u32)); } else { item.parameter_names.push(NO_INDEX); @@ -1276,8 +1451,8 @@ impl DexFragment { for id in &static_fields { let idx = self.field_ids.get(id).ok_or(anyhow!( "Field {} (field of class {}) not found in dex builder", - id.__repr__(), - class.__repr__() + id.__str__(), + class.__str__() ))?; let field_idx_diff = Uleb128((idx - last_field_id) as u32); last_field_id = *idx; @@ -1294,8 +1469,8 @@ impl DexFragment { for id in &instance_fields { let idx = self.field_ids.get(id).ok_or(anyhow!( "Field {} (field of class {}) not found in dex builder", - id.__repr__(), - class.__repr__() + id.__str__(), + class.__str__() ))?; let field_idx_diff = Uleb128((idx - last_field_id) as u32); last_field_id = *idx; @@ -1320,8 +1495,8 @@ impl DexFragment { let (class, _) = self.class_defs.get(class_id).unwrap(); let idx = self.method_ids.get(id).ok_or(anyhow!( "Method {} (method of class {}) not found in dex builder", - id.__repr__(), - class.__repr__() + id.__str__(), + class.__str__() ))?; let method_idx_diff = Uleb128((idx - last_method_id) as u32); last_method_id = *idx; @@ -1350,8 +1525,8 @@ impl DexFragment { let (class, _) = self.class_defs.get(class_id).unwrap(); let idx = self.method_ids.get(id).ok_or(anyhow!( "Method {} (method of class {}) not found in dex builder", - id.__repr__(), - class.__repr__() + id.__str__(), + class.__str__() ))?; let method_idx_diff = Uleb128((idx - last_method_id) as u32); last_method_id = *idx; @@ -1387,66 +1562,75 @@ impl DexFragment { pub fn insert_method_handle(&mut self, handle: &MethodHandle) -> Result<()> { let (field_or_method_id, method_handle_type) = match handle { MethodHandle::StaticPut(StaticPut(field)) => ( - *self.field_ids.get(field).ok_or(anyhow!( - "Field {} not found in dex writer", - field.__repr__() - ))? as u16, + *self + .field_ids + .get(field) + .ok_or(anyhow!("Field {} not found in dex writer", field.__str__()))? + as u16, MethodHandleType::StaticPut, ), MethodHandle::StaticGet(StaticGet(field)) => ( - *self.field_ids.get(field).ok_or(anyhow!( - "Field {} not found in dex writer", - field.__repr__() - ))? as u16, + *self + .field_ids + .get(field) + .ok_or(anyhow!("Field {} not found in dex writer", field.__str__()))? + as u16, MethodHandleType::StaticGet, ), MethodHandle::InstancePut(InstancePut(field)) => ( - *self.field_ids.get(field).ok_or(anyhow!( - "Field {} not found in dex writer", - field.__repr__() - ))? as u16, + *self + .field_ids + .get(field) + .ok_or(anyhow!("Field {} not found in dex writer", field.__str__()))? + as u16, MethodHandleType::InstancePut, ), MethodHandle::InstanceGet(InstanceGet(field)) => ( - *self.field_ids.get(field).ok_or(anyhow!( - "Field {} not found in dex writer", - field.__repr__() - ))? as u16, + *self + .field_ids + .get(field) + .ok_or(anyhow!("Field {} not found in dex writer", field.__str__()))? + as u16, MethodHandleType::InstanceGet, ), MethodHandle::InvokeStatic(InvokeStatic(meth)) => ( - *self.method_ids.get(meth).ok_or(anyhow!( - "Method {} not found in dex writer", - meth.__repr__() - ))? as u16, + *self + .method_ids + .get(meth) + .ok_or(anyhow!("Method {} not found in dex writer", meth.__str__()))? + as u16, MethodHandleType::InvokeStatic, ), MethodHandle::InvokeInstance(InvokeInstance(meth)) => ( - *self.method_ids.get(meth).ok_or(anyhow!( - "Method {} not found in dex writer", - meth.__repr__() - ))? as u16, + *self + .method_ids + .get(meth) + .ok_or(anyhow!("Method {} not found in dex writer", meth.__str__()))? + as u16, MethodHandleType::InvokeInstance, ), MethodHandle::InvokeConstructor(InvokeConstructor(meth)) => ( - *self.method_ids.get(meth).ok_or(anyhow!( - "Method {} not found in dex writer", - meth.__repr__() - ))? as u16, + *self + .method_ids + .get(meth) + .ok_or(anyhow!("Method {} not found in dex writer", meth.__str__()))? + as u16, MethodHandleType::InvokeConstructor, ), MethodHandle::InvokeDirect(InvokeDirect(meth)) => ( - *self.method_ids.get(meth).ok_or(anyhow!( - "Method {} not found in dex writer", - meth.__repr__() - ))? as u16, + *self + .method_ids + .get(meth) + .ok_or(anyhow!("Method {} not found in dex writer", meth.__str__()))? + as u16, MethodHandleType::InvokeDirect, ), MethodHandle::InvokeInterface(InvokeInterface(meth)) => ( - *self.method_ids.get(meth).ok_or(anyhow!( - "Method {} not found in dex writer", - meth.__repr__() - ))? as u16, + *self + .method_ids + .get(meth) + .ok_or(anyhow!("Method {} not found in dex writer", meth.__str__()))? + as u16, MethodHandleType::InvokeInterface, ), }; @@ -1476,7 +1660,7 @@ impl DexFragment { DexValue::MethodType(val) => Ok(EncodedValue::MethodType( *self.proto_ids.get(val).ok_or(anyhow!( "Prototype {} not found in dex writer", - val.__repr__() + val.__str__() ))? as u32, )), DexValue::MethodHandle(val) => { @@ -1489,35 +1673,35 @@ impl DexFragment { *self .strings .get(val) - .ok_or(anyhow!("String {} not found in dex writer", val.__repr__()))? + .ok_or(anyhow!("String {} not found in dex writer", val.__str__()))? as u32, )), DexValue::Type(val) => Ok(EncodedValue::Type( *self .type_ids .get(val) - .ok_or(anyhow!("Type {} not found in dex writer", val.__repr__()))? + .ok_or(anyhow!("Type {} not found in dex writer", val.__str__()))? as u32, )), DexValue::Field(val) => Ok(EncodedValue::Field( *self .field_ids .get(val) - .ok_or(anyhow!("Field {} not found in dex writer", val.__repr__()))? + .ok_or(anyhow!("Field {} not found in dex writer", val.__str__()))? as u32, )), DexValue::Method(val) => Ok(EncodedValue::Method( *self .method_ids .get(val) - .ok_or(anyhow!("Method {} not found in dex writer", val.__repr__()))? + .ok_or(anyhow!("Method {} not found in dex writer", val.__str__()))? as u32, )), DexValue::Enum(IdEnum(val)) => Ok(EncodedValue::Enum( *self .field_ids .get(val) - .ok_or(anyhow!("Field {} not found in dex writer", val.__repr__()))? + .ok_or(anyhow!("Field {} not found in dex writer", val.__str__()))? as u32, )), DexValue::Array(DexArray(arr)) => { @@ -1592,9 +1776,9 @@ impl DexFragment { } else { array.push(field.descriptor.type_.get_default_value().ok_or(anyhow!( "The type {} (for field {} in class {}) does not have a default value", - field.descriptor.type_.__repr__(), - field.descriptor.__repr__(), - class_id.__repr__() + field.descriptor.type_.__str__(), + field.descriptor.__str__(), + class_id.__str__() ))?); } } @@ -1602,7 +1786,7 @@ impl DexFragment { .with_context(|| { format!( "Failed to serialize static values of class {}", - class_id.__repr__() + class_id.__str__() ) }) } @@ -1629,52 +1813,12 @@ impl DexFragment { Ok(EncodedAnnotation { type_idx: Uleb128(*self.type_ids.get(&type_).ok_or(anyhow!( "Annotation type {} not found in dex builder", - type_.__repr__(), + type_.__str__(), ))? as u32), elements: encoded_elements, }) } - /// Insert the annnotations set for a class. - fn insert_class_annotation_set(&mut self, class_id: &IdType) -> Result<()> { - let (class, _) = self.class_defs.get(class_id).unwrap(); - let mut annotations = class.annotations.clone(); - - let mut annotation_set = AnnotationSetItem { entries: vec![] }; - annotations.sort_by_key(|annot| annot.annotation.type_.clone()); - for annot in annotations { - annotation_set.entries.push(AnnotationOffItem { - annotation_off: self - .section_manager - .get_aligned_size(Section::AnnotationItem), - }); // linked in link_annotations() - - let item = AnnotationItem { - visibility: match ( - annot.visibility_build, - annot.visibility_runtime, - annot.visibility_system, - ) { - (true, false, false) => AnnotationVisibility::Build, - (false, true, false) => AnnotationVisibility::Runtime, - (false, false, true) => AnnotationVisibility::System, - _ => bail!( - "Annotation need visibility set to one and only one of build, \ - runtime or system" - ), // TODO: check if this is true - }, - annotation: self.dex_annotation_to_encoded_annotation(annot.annotation)?, - }; - self.section_manager - .add_elt(Section::AnnotationItem, Some(item.size())); - self.annotation_items.push(item); - } - self.section_manager - .add_elt(Section::AnnotationSetItem, Some(annotation_set.size())); - self.annotation_set_items.push(annotation_set); - Ok(()) - } - /// Insert the annnotations set for a class. fn insert_field_annotation_set( &mut self, @@ -1861,150 +2005,13 @@ impl DexFragment { Ok(()) } - /// Insert a class annotations (including field, methods and parameters annotations). - /// - /// # Note - /// - /// annotation_set_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_annotations(&mut self, class_id: &IdType) -> Result<()> { - let (class, _) = self.class_defs.get(class_id).unwrap(); - let class_annotations_off = if !class.annotations.is_empty() { - let class_annotations_off = self - .section_manager - .get_aligned_size(Section::AnnotationSetItem); - self.insert_class_annotation_set(class_id) - .with_context(|| { - format!( - "Failed to insert class annotation for class {}", - class_id.__repr__() - ) - })?; - class_annotations_off + 1 - } else { - 0 - }; - - let mut field_ids = vec![]; - let (class, _) = self.class_defs.get(class_id).unwrap(); - field_ids.extend(class.static_fields.keys().cloned()); - field_ids.extend(class.instance_fields.keys().cloned()); - field_ids.sort(); - let mut field_annotations = vec![]; - for field_id in field_ids { - let (class, _) = self.class_defs.get(class_id).unwrap(); - let static_field = class.static_fields.get(&field_id); - let instance_field = class.instance_fields.get(&field_id); - let (is_static, field) = match (static_field, instance_field) { - (Some(field), None) => (true, field), - (None, Some(field)) => (false, field), - _ => bail!( - "Unexpected configuration: field {} is both a static and a instance field in {}", - field_id.__repr__(), class_id.__repr__()), - }; - if !field.annotations.is_empty() { - let annotations_off = self - .section_manager - .get_aligned_size(Section::AnnotationSetItem) - + 1; - self.insert_field_annotation_set(&field_id, is_static)?; - field_annotations.push(FieldAnnotation { - field_idx: *self.field_ids.get(&field_id).ok_or(anyhow!( - "Field {} in {} not found in dex builder", - field_id.__repr__(), - class_id.__repr__(), - ))? as u32, - annotations_off, // linked in link_annotations() - }); - } - } - - let mut method_ids = vec![]; - let (class, _) = self.class_defs.get(class_id).unwrap(); - method_ids.extend(class.direct_methods.keys().cloned()); - method_ids.extend(class.virtual_methods.keys().cloned()); - method_ids.sort(); - let mut method_annotations = vec![]; - for method_id in &method_ids { - let (class, _) = self.class_defs.get(class_id).unwrap(); - let direct_method = class.direct_methods.get(method_id); - let virtual_method = class.virtual_methods.get(method_id); - let (is_direct, method) = match (direct_method, virtual_method) { - (Some(method), None) => (true, method), - (None, Some(method)) => (false, method), - _ => bail!( - "Unexpected configuration: method {} is both a direct and a virtual method in {}", - method_id.__repr__(), class_id.__repr__()), - }; - if !method.annotations.is_empty() { - let annotations_off = self - .section_manager - .get_aligned_size(Section::AnnotationSetItem) - + 1; - self.insert_method_annotation_set(method_id, is_direct)?; - method_annotations.push(MethodAnnotation { - method_idx: *self.method_ids.get(method_id).ok_or(anyhow!( - "Method {} in {} not found in dex builder", - method_id.__repr__(), - class_id.__repr__(), - ))? as u32, - annotations_off, // linked in link_annotations() - }); - } - } - - let mut parameter_annotations = vec![]; - for method_id in method_ids { - let (class, _) = self.class_defs.get(class_id).unwrap(); - let direct_method = class.direct_methods.get(&method_id); - let virtual_method = class.virtual_methods.get(&method_id); - let (is_direct, method) = match (direct_method, virtual_method) { - (Some(method), None) => (true, method), - (None, Some(method)) => (false, method), - _ => bail!( - "Unexpected configuration: method {} is both a direct and a virtual method in {}", - method_id.__repr__(), class_id.__repr__()), - }; - if !method.parameters_annotations.is_empty() { - let annotations_off = self - .section_manager - .get_aligned_size(Section::AnnotationSetRefList) - + 1; - self.insert_parameters_annotation_set_list(&method_id, is_direct)?; - parameter_annotations.push(ParameterAnnotation { - method_idx: *self.method_ids.get(&method_id).ok_or(anyhow!( - "Method {} in {} not found in dex builder", - method_id.__repr__(), - class_id.__repr__(), - ))? as u32, - annotations_off, // linked in link_annotations() - }); - } - } - - let item = AnnotationsDirectoryItem { - class_annotations_off, // linked in link_annotations() - field_annotations, - method_annotations, - parameter_annotations, - }; - self.section_manager - .add_elt(Section::AnnotationsDirectoryItem, Some(item.size())); - self.annotations_directory_items.push(item); - Ok(()) - } - fn gen_type_list_section(&mut self) -> Result<()> { debug!("Generate the type_list section"); // Collect all type lists for proto in self.proto_ids.keys() { if !proto.parameters.is_empty() { let type_list = self.gen_type_list(&proto.parameters).with_context(|| { - format!("Failed to generate param list for {}", proto.__repr__()) + format!("Failed to generate param list for {}", proto.__str__()) })?; self.type_lists_index.insert(type_list, 0); } @@ -2012,7 +2019,7 @@ impl DexFragment { for (class, _) in self.class_defs.values() { if !class.interfaces.is_empty() { let type_list = self.gen_type_list(&class.interfaces).with_context(|| { - format!("Failed to generate interface list for {}", class.__repr__()) + format!("Failed to generate interface list for {}", class.__str__()) })?; self.type_lists_index.insert(type_list, 0); } @@ -2177,7 +2184,7 @@ impl DexFragment { for (proto, idx) in &self.proto_ids { if !proto.parameters.is_empty() { let type_list = self.gen_type_list(&proto.parameters).with_context(|| { - format!("Failed to generate param list for {}", proto.__repr__()) + format!("Failed to generate param list for {}", proto.__str__()) })?; let offset = self.section_manager.get_offset(Section::TypeList) + self.type_lists_with_offset[*self.type_lists_index.get(&type_list).unwrap()] @@ -2227,7 +2234,7 @@ impl DexFragment { for (cls, idx) in self.class_defs.values() { if !cls.interfaces.is_empty() { let type_list = self.gen_type_list(&cls.interfaces).with_context(|| { - format!("Failed to generate interface list for {}", cls.__repr__()) + format!("Failed to generate interface list for {}", cls.__str__()) })?; let offset = self.section_manager.get_offset(Section::TypeList) + self.type_lists_with_offset[*self.type_lists_index.get(&type_list).unwrap()] @@ -2591,7 +2598,7 @@ impl DexFragment { type_list.list.push(TypeItem { type_idx: *self.type_ids.get(ty).ok_or(anyhow!( "Could not found type {} in dex builder", - ty.__repr__() + ty.__str__() ))? as u16, }); } diff --git a/androscalpel/src/dex_writer.rs b/androscalpel/src/dex_writer.rs index a54c3f9..f967970 100644 --- a/androscalpel/src/dex_writer.rs +++ b/androscalpel/src/dex_writer.rs @@ -2568,6 +2568,7 @@ impl DexWriter { for annotation_set in self.annotation_set_items.iter_mut() { for entry in annotation_set.entries.iter_mut() { entry.annotation_off += self.section_manager.get_offset(Section::AnnotationItem); + // -1 now when linking frag } } for list in self.annotation_set_lists.iter_mut() {