1use log::info;
12
13use crate::dex::reader::DexReader;
14use crate::dex::header::DexHeader;
15use crate::dex::strings::DexStrings;
16use crate::dex::types::DexTypes;
17use crate::dex::protos::DexProtos;
18use crate::dex::fields::DexFields;
19use crate::dex::methods::DexMethods;
20use crate::dex::classes::{ DexClasses, ClassDefItem, EncodedMethod };
21
22#[derive(Debug)]
24pub struct DexFile {
25 pub header: DexHeader,
27 pub strings: DexStrings,
29 pub types: DexTypes,
31 pub protos: DexProtos,
33 pub fields: DexFields,
35 pub methods: DexMethods,
37 pub classes: DexClasses,
39}
40
41impl DexFile {
42 pub fn build(mut dex_reader: DexReader) -> Self {
44 let dex_header = DexHeader::new(&mut dex_reader).unwrap();
45
46 let strings_list = DexStrings::build(&mut dex_reader,
47 dex_header.string_ids_off,
48 dex_header.string_ids_size);
49
50 let type_ids_list = DexTypes::build(&mut dex_reader,
51 dex_header.type_ids_off,
52 dex_header.type_ids_size,
53 &strings_list);
54
55 let proto_ids_list = DexProtos::build(&mut dex_reader,
56 dex_header.proto_ids_off,
57 dex_header.proto_ids_size,
58 &type_ids_list);
59
60 let field_ids_list = DexFields::build(&mut dex_reader,
61 dex_header.fields_ids_off,
62 dex_header.fields_ids_size,
63 &type_ids_list,
64 &strings_list);
65
66 let method_ids_list = DexMethods::build(&mut dex_reader,
67 dex_header.method_ids_off,
68 dex_header.method_ids_size,
69 &type_ids_list,
70 &proto_ids_list,
71 &strings_list);
72
73 let class_defs_list = DexClasses::build(&mut dex_reader,
74 dex_header.class_defs_off,
75 dex_header.class_defs_size,
76 &field_ids_list,
77 &type_ids_list,
78 &strings_list,
79 &method_ids_list);
80
81 DexFile {
82 header: dex_header,
83 strings: strings_list,
84 types: type_ids_list,
85 protos: proto_ids_list,
86 fields: field_ids_list,
87 methods: method_ids_list,
88 classes: class_defs_list,
89 }
90 }
91
92 pub fn merge(readers: Vec<DexReader>) -> Self {
96 let mut strings_list = Vec::new();
97 let mut type_ids_list = Vec::new();
98 let mut proto_ids_list = Vec::new();
99 let mut field_ids_list = Vec::new();
100 let mut method_ids_list = Vec::new();
101 let mut class_defs_list = Vec::new();
102
103 info!("start merging DEX files");
104 for reader in readers.into_iter() {
105 let current_dex_file = DexFile::build(reader);
106
107 info!(" merging strings");
108 for string in current_dex_file.strings.strings.into_iter() {
109 strings_list.push(string);
110 }
111
112 info!(" merging types");
113 for type_id in current_dex_file.types.items.into_iter() {
114 type_ids_list.push(type_id);
115 }
116
117 info!(" merging protos");
118 for proto_id in current_dex_file.protos.items.into_iter() {
119 proto_ids_list.push(proto_id);
120 }
121
122 info!(" merging fields");
123 for field_id in current_dex_file.fields.items.into_iter() {
124 field_ids_list.push(field_id);
125 }
126
127 info!(" merging methods");
128 for method_id in current_dex_file.methods.items.into_iter() {
129 method_ids_list.push(method_id);
130 }
131
132 info!(" merging classes");
133 for class_def_id in current_dex_file.classes.items.into_iter() {
134 class_defs_list.push(class_def_id);
135 }
136 }
137
138 info!("removing strings duplicates and storing strings");
139 strings_list.dedup();
140 strings_list.sort();
141 info!("removing strings duplicates and storing types");
142 type_ids_list.dedup();
143 type_ids_list.sort();
144 info!("removing strings duplicates and storing protos");
145 proto_ids_list.dedup();
146 proto_ids_list.sort();
147 info!("removing strings duplicates and storing fields");
148 field_ids_list.dedup();
149 field_ids_list.sort();
150 info!("removing strings duplicates and storing methods");
151 method_ids_list.dedup();
152 method_ids_list.sort();
153 info!("done merging");
157
158 let header = DexHeader {
159 version: [0x00; 3],
160 checksum: 0x0,
161 signature: [0x00; 20],
162 file_size: 0x00,
163 header_size: 0x00,
164 endian_tag: 0x00,
165 link_size: 0x00,
166 link_off: 0x00,
167 map_off: 0x00,
168 string_ids_size: strings_list.len() as u32,
169 string_ids_off: 0x00,
170 type_ids_size: type_ids_list.len() as u32,
171 type_ids_off: 0x00,
172 proto_ids_size: proto_ids_list.len() as u32,
173 proto_ids_off: 0x00,
174 fields_ids_size: field_ids_list.len() as u32,
175 fields_ids_off: 0x00,
176 method_ids_size: method_ids_list.len() as u32,
177 method_ids_off: 0x00,
178 class_defs_size: class_defs_list.len() as u32,
179 class_defs_off: 0x00,
180 data_size: 0x00,
181 data_off: 0x00
182 };
183
184 DexFile {
185 header: header,
186 strings: DexStrings { strings: strings_list },
187 types: DexTypes { items: type_ids_list },
188 protos: DexProtos { items: proto_ids_list },
189 fields: DexFields { items: field_ids_list },
190 methods: DexMethods { items: method_ids_list },
191 classes: DexClasses { items: class_defs_list },
192 }
193 }
194
195 pub fn get_classes_names(&self) -> Vec<&String> {
197 let mut class_names = Vec::new();
198
199 for class in &self.classes.items {
200 class_names.push(class.get_class_name());
201 }
202
203 class_names
204 }
205
206 pub fn get_class_def(&self, class_name: &String) -> Option<&ClassDefItem> {
208 self.classes.get_class_def(class_name)
209 }
210
211 pub fn get_methods_for_class(&self, class_name: &String) -> Vec<&EncodedMethod> {
213 if let Some(class_def) = self.get_class_def(class_name) {
214 return class_def.get_methods();
215 }
216 Vec::new()
217 }
218}