diff --git a/androscalpel/src/dex_fragment.rs b/androscalpel/src/dex_fragment.rs index e369844..606a58a 100644 --- a/androscalpel/src/dex_fragment.rs +++ b/androscalpel/src/dex_fragment.rs @@ -49,7 +49,7 @@ pub struct DexFragment { /// The encoded_array_items section. encoded_array_items: Vec, /// The annotations_directory_item. - annotations_directory_items: Option, + annotations_directory_item: Option, /// The annotation_set_item section. annotation_set_items: Vec, /// The annotation item section. @@ -128,7 +128,7 @@ impl DexFragment { encoded_array_items: vec![], method_handles: vec![], code_items: vec![], - annotations_directory_items: None, + annotations_directory_item: None, annotation_set_items: vec![], annotation_items: vec![], annotation_set_lists: vec![], @@ -365,7 +365,7 @@ impl DexFragment { }; self.section_manager .add_elt(FragSection::AnnotationsDirectoryItem, Some(item.size())); - self.annotations_directory_items = Some(item); + self.annotations_directory_item = Some(item); Ok(()) } @@ -1963,8 +1963,23 @@ impl DexFragment { self.link_id_class_data_and_gen_code(class, &field_reindex, &method_reindex, index)?; self.link_id_class_def(&string_reindex, &type_reindex); self.link_id_method_handle(&field_reindex, &method_reindex); - - // GEN CODE + self.link_id_annotation( + &string_reindex, + &type_reindex, + &field_reindex, + &method_reindex, + &proto_reindex, + nb_method_handle_before_fragment, + ); + self.link_id_encoded_array_item( + &string_reindex, + &type_reindex, + &field_reindex, + &method_reindex, + &proto_reindex, + nb_method_handle_before_fragment, + ); + self.link_id_annotation_dir(field_reindex, method_reindex) todo!() } @@ -1992,20 +2007,184 @@ impl DexFragment { } } - fn link_id_string_data(&mut self) { - todo!() + fn link_id_annotation( + &mut self, + string_reindex: &[u32], + type_reindex: &[u32], + field_reindex: &[u16], + method_reindex: &[u16], + proto_reindex: &[u32], + nb_method_handle_before_fragment: usize, + ) { + let mut annotation_item_relocation = if let FragLinkState::LinkedIdx { + annotation_item_relocation, + .. + } = self.link_state + { + annotation_item_relocation + } else { + panic!("link_id_annotation() should only be called by link_global_ids()"); + }; + // TODO: can we update the new value directly in the direstoryies/set? + let mut initial_offset = 0; + let mut new_offset = 0; + for item in self.annotation_items { + let old_size = item.size() as u32; + item.annotation.type_idx.0 = type_reindex[item.annotation.type_idx.0 as usize]; + for elt in item.annotation.elements { + elt.name_idx.0 = string_reindex[elt.name_idx.0 as usize]; + Self::link_id_encoded_value( + &mut elt.value, + string_reindex, + type_reindex, + field_reindex, + method_reindex, + proto_reindex, + nb_method_handle_before_fragment, + ) + } + let new_size = item.size() as u32; + annotation_item_relocation.insert(initial_offset, new_offset); + initial_offset += old_size; + new_offset += new_size; + } } - fn link_id_debug_info(&mut self) { - todo!() + + fn link_id_encoded_annotation( + annotation: &mut EncodedAnnotation, + string_reindex: &[u32], + type_reindex: &[u32], + field_reindex: &[u16], + method_reindex: &[u16], + proto_reindex: &[u32], + nb_method_handle_before_fragment: usize, + ) { + annotation.type_idx.0 = type_reindex[annotation.type_idx.0 as usize]; + for elt in annotation.elements { + elt.name_idx.0 = string_reindex[elt.name_idx.0 as usize]; + Self::link_id_encoded_value( + &mut elt.value, + string_reindex, + type_reindex, + field_reindex, + method_reindex, + proto_reindex, + nb_method_handle_before_fragment, + ) + } } - fn link_id_annotation(&mut self) { - todo!() + + fn link_id_encoded_value( + val: &mut EncodedValue, + string_reindex: &[u32], + type_reindex: &[u32], + field_reindex: &[u16], + method_reindex: &[u16], + proto_reindex: &[u32], + nb_method_handle_before_fragment: usize, + ) { + match val { + EncodedValue::MethodType(idx) => *idx = proto_reindex[*idx as usize], + EncodedValue::MethodHandle(idx) => *idx += nb_method_handle_before_fragment as u32, + EncodedValue::String(idx) => *idx = string_reindex[*idx as usize], + EncodedValue::Type(idx) => *idx = type_reindex[*idx as usize], + EncodedValue::Field(idx) => *idx = field_reindex[*idx as usize] as u32, + EncodedValue::Method(idx) => *idx = method_reindex[*idx as usize] as u32, + EncodedValue::Enum(idx) => *idx = field_reindex[*idx as usize] as u32, + EncodedValue::Array(arr) => Self::link_id_encoded_array( + &mut arr, + string_reindex, + type_reindex, + field_reindex, + method_reindex, + proto_reindex, + nb_method_handle_before_fragment, + ), + EncodedValue::Annotation(annotation) => Self::link_id_encoded_annotation( + &mut annotation, + string_reindex, + type_reindex, + field_reindex, + method_reindex, + proto_reindex, + nb_method_handle_before_fragment, + ), + _ => (), + } } - fn link_id_encoded_array(&mut self) { - todo!() + + fn link_id_encoded_array( + array: &mut EncodedArray, + string_reindex: &[u32], + type_reindex: &[u32], + field_reindex: &[u16], + method_reindex: &[u16], + proto_reindex: &[u32], + nb_method_handle_before_fragment: usize, + ) { + for val in &mut array.values { + Self::link_id_encoded_value( + val, + string_reindex, + type_reindex, + field_reindex, + method_reindex, + proto_reindex, + nb_method_handle_before_fragment, + ) + } } - fn link_id_annotation_dir(&mut self) { - todo!() + + fn link_id_encoded_array_item( + &mut self, + string_reindex: &[u32], + type_reindex: &[u32], + field_reindex: &[u16], + method_reindex: &[u16], + proto_reindex: &[u32], + nb_method_handle_before_fragment: usize, + ) { + let mut encoded_array_relocation = if let FragLinkState::LinkedIdx { + encoded_array_relocation, + .. + } = self.link_state + { + encoded_array_relocation + } else { + panic!("link_id_encoded_arrays() should only be called by link_global_ids()"); + }; + let mut initial_offset = 0; + let mut relocated_offset = 0; + for array in self.encoded_array_items { + let old_size = array.size() as u32; + Self::link_id_encoded_array( + &mut array.value, + string_reindex, + type_reindex, + field_reindex, + method_reindex, + proto_reindex, + nb_method_handle_before_fragment, + ); + let new_size = array.size() as u32; + encoded_array_relocation.insert(old_size, new_size); + initial_offset += old_size; + relocated_offset += new_size; + } + } + + fn link_id_annotation_dir(&mut self, field_reindex: &[u16], method_reindex: &[u16]) { + if let Some(dir) = self.annotations_directory_item { + for annot in dir.field_annotations { + annot.field_idx = field_reindex[annot.field_idx as usize] as u32; + } + for annot in dir.method_annotations { + annot.method_idx = method_reindex[annot.method_idx as usize] as u32; + } + for annot in dir.parameter_annotations { + annot.method_idx = method_reindex[annot.method_idx as usize] as u32; + } + } } /// Link ids in [`ClassDataItem`] *and* generate the [`CodeItem`]. @@ -2389,8 +2568,9 @@ enum FragLinkState { /// The new local addresses of the element whose size depend on the value /// of the index are stored here. LinkedIdx { - code_item_relocation: HashMap, - debug_info_item_relocation: HashMap, + // Not relocation: the code are entirely generated at link id time + //code_item_relocation: HashMap, + //debug_info_item_relocation: HashMap, annotation_item_relocation: HashMap, encoded_array_relocation: HashMap, // TODO only one? }, @@ -2401,8 +2581,8 @@ impl FragLinkState { match self { Self::Unlinked => { *self = Self::LinkedIdx { - code_item_relocation: HashMap::::new(), - debug_info_item_relocation: HashMap::::new(), + // code_item_relocation: HashMap::::new(), + // debug_info_item_relocation: HashMap::::new(), annotation_item_relocation: HashMap::::new(), encoded_array_relocation: HashMap::::new(), };