diff --git a/androscalpel/src/dex_fragment.rs b/androscalpel/src/dex_fragment.rs index 4a0b0a9..ae29e17 100644 --- a/androscalpel/src/dex_fragment.rs +++ b/androscalpel/src/dex_fragment.rs @@ -1991,7 +1991,7 @@ impl DexFragment { } else { bail!("Fragment cannot be linked without the frag index (see DexFragment::frag_index doc)") }; - self.link_state.start_linking_idx()?; + self.link_state = self.link_state.start_linking_idx()?; let string_reindex = Vec::with_capacity(self.strings.len()); // TODO: considering we have the map, this can be simplified a lot let mut global_idx = 0; @@ -2419,6 +2419,11 @@ impl DexFragment { pub fn get_interfaces(&self) -> &Vec { &self.interfaces } + + pub fn link_offsets_but_class_data(&mut self, offsets: &SectionOffsets) -> Result<()> { + self.link_state = self.link_state.start_linking_offset()?; + Ok(()) + } } #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -2627,25 +2632,51 @@ enum FragLinkState { //code_item_relocation: HashMap, //debug_info_item_relocation: HashMap, annotation_item_relocation: HashMap, - encoded_array_relocation: HashMap, // TODO only one? + encoded_array_relocation: HashMap, + }, + /// The index used in the fragment are linked and offset are in the process of beeing linked. + LinkingOffset { + // 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, }, } impl FragLinkState { - fn start_linking_idx(&mut self) -> Result<()> { + fn start_linking_idx(self) -> Result { match self { Self::Unlinked => { - *self = Self::LinkedIdx { + Ok(Self::LinkedIdx { // code_item_relocation: HashMap::::new(), // debug_info_item_relocation: HashMap::::new(), annotation_item_relocation: HashMap::::new(), encoded_array_relocation: HashMap::::new(), - }; - Ok(()) + }) } _ => { bail!("Cannot link the idx in a fragment that is already linked"); } } } + + fn start_linking_offset(self) -> Result { + match self { + Self::LinkedIdx { + annotation_item_relocation, + encoded_array_relocation, + } => { + Ok(Self::LinkingOffset { + // code_item_relocation: HashMap::::new(), + // debug_info_item_relocation: HashMap::::new(), + annotation_item_relocation, + encoded_array_relocation, + }) + } + _ => { + bail!("Cannot link the offsets in a fragment that have already linked offset of not linked ids"); + } + } + } } diff --git a/androscalpel/src/dex_writer.rs b/androscalpel/src/dex_writer.rs index 862a8eb..fbae656 100644 --- a/androscalpel/src/dex_writer.rs +++ b/androscalpel/src/dex_writer.rs @@ -167,6 +167,8 @@ impl<'a> DexWriter<'a> { // collect section offsets // The type are quite uggly but I'm behind on time let mut fragment_section_manager = FragSectionManager::default(); + // DexFragment and the merged fragment section managers of the previous fragments + // (excluding the current fragment) let fragments_in_file: Vec<(FragSectionManager, DexFragment)> = fragments_in_file .into_iter() .map(|fragment| { @@ -228,8 +230,8 @@ impl<'a> DexWriter<'a> { Ok(ty_list) }) .collect::>()?; + section_manager.add_elt(Section::MapList, Some(4)); - let offsets = section_manager.get_offsets(); let map_item_size = 12; /* = MapItem { type_: MapItemType::HeaderItem, unused: 0, @@ -237,6 +239,15 @@ impl<'a> DexWriter<'a> { offset: 0, } .size(); */ + for section in Section::VARIANT_LIST { + if !section.is_data() && section_manager.get_nb_elt(*section) != 0 { + section_manager.incr_section_size(Section::MapList, map_item_size); + } + } + let offsets = section_manager.get_offsets(); + // Sections are computed (except for class_data_item sizes, but those are at the end of the + // file so it does not affect the map_list) + let mut map_list = MapList::default(); for section in Section::VARIANT_LIST { if !section.is_data() && section_manager.get_nb_elt(*section) != 0 { @@ -250,9 +261,18 @@ impl<'a> DexWriter<'a> { } } - // TODO: link en correct data section + // link everything but class_def_item.class_data_off and collect the offsets of the + // sections of the fragments + let fragments_in_file: Vec<(SectionOffsets, DexFragment)> = fragments_in_file + .into_iter() + .map(|(frag_section_manager, fragment)| { + let fragment_offsets = offsets.get_fragment_offset(&frag_section_manager); + fragment.link_offsets_but_class_data(&fragment_offsets); + todo!() + }) + .collect(); - // TODO: link everything else + // TODO: class_def_item.class_data_off // TODO: serialize @@ -324,7 +344,7 @@ impl<'a> DexIndex<'a> { } #[derive(Debug, Clone, Copy, PartialEq, Eq)] -enum Section { +pub(crate) enum Section { HeaderItem, StringIdItem, TypeIdItem, @@ -662,7 +682,7 @@ impl SectionManager { } #[derive(Debug, Default, Clone)] -struct SectionOffsets { +pub(crate) struct SectionOffsets { offsets: [u32; SectionManager::NB_SECTION], }