11use crate :: impls:: server:: { ProgressMessage , ServerMessage } ;
22use crate :: server:: OpenFileError ;
3- use crate :: Accessor ;
3+ use crate :: { Accessor , ExportableSource } ;
44use java_asm:: dex:: { ClassDef , DexFile , DexFileAccessor } ;
5- use java_asm:: smali:: SmaliNode ;
5+ use java_asm:: smali:: { stb , SmaliNode , SmaliToken } ;
66use java_asm:: { DescriptorRef , StrRef } ;
77use log:: { error, warn} ;
88use std:: collections:: HashMap ;
@@ -13,6 +13,7 @@ use zip::ZipArchive;
1313
1414pub struct ApkAccessor {
1515 pub map : HashMap < DescriptorRef , ClassPosition > ,
16+ pub dex_sources : HashMap < StrRef , Arc < DexFileAccessor > > ,
1617}
1718
1819type ClassPosition = ( Arc < DexFileAccessor > , ClassDef ) ;
@@ -37,12 +38,18 @@ pub async fn read_apk(
3738
3839 // put dex files
3940 let dex_file_count = dex_files. len ( ) ;
40- let dex_files = dex_files. iter ( ) . map ( |name| {
41- let mut file = zip_archive. by_index ( * name) . map_err ( OpenFileError :: LoadZip ) ?;
41+ let mut dex_sources = HashMap :: new ( ) ;
42+ let dex_files = dex_files. iter ( ) . map ( |entry_index| {
43+ let mut file = zip_archive. by_index ( * entry_index) . map_err ( OpenFileError :: LoadZip ) ?;
44+ let file_name = StrRef :: from ( file. name ( ) ) ;
45+ let file_name_for_dex_sources = file_name. clone ( ) ;
4246 let mut bytes = Vec :: new ( ) ;
4347 file. read_to_end ( & mut bytes) . map_err ( OpenFileError :: Io ) ?;
4448 let dex_file = DexFile :: resolve_from_bytes ( & bytes) . map_err ( OpenFileError :: ResolveError ) ?;
45- Ok ( Arc :: new ( DexFileAccessor :: new ( dex_file, bytes) ) )
49+ let dex_file_accessor = Arc :: new ( DexFileAccessor :: new ( dex_file, bytes, file_name) ) ;
50+
51+ dex_sources. insert ( file_name_for_dex_sources, dex_file_accessor. clone ( ) ) ;
52+ Ok ( dex_file_accessor)
4653 } ) . map ( |res : Result < Arc < DexFileAccessor > , OpenFileError > | {
4754 match res {
4855 Ok ( dex_file) => Some ( dex_file) ,
@@ -73,7 +80,7 @@ pub async fn read_apk(
7380 } ;
7481 map. shrink_to_fit ( ) ;
7582 send_loaded ( & sender) . await ;
76- Ok ( ApkAccessor { map } )
83+ Ok ( ApkAccessor { map, dex_sources } )
7784}
7885
7986async fn send_progress (
@@ -118,10 +125,34 @@ impl Accessor for ApkAccessor {
118125 fn read_content ( & self , class_key : & str ) -> Option < SmaliNode > {
119126 let class_position = self . map . get ( class_key) ;
120127 if let Some ( ( accessor, class_def) ) = class_position {
121- accessor. get_class_smali ( * class_def) . ok ( )
128+ let dex_file_name = accessor. file_name . clone ( ) ;
129+ let smali_node = accessor. get_class_smali ( * class_def) . ok ( ) ;
130+ let Some ( smali_node) = smali_node else {
131+ warn ! ( "No class content found for: {}" , class_key) ;
132+ return None ;
133+ } ;
134+ let mut smali_node = smali_node;
135+ let source_tag_smali = stb ( ) . push ( SmaliToken :: SourceInfo ( dex_file_name) ) . s ( ) ;
136+ smali_node. children . insert ( 0 , source_tag_smali) ;
137+ Some ( smali_node)
122138 } else {
123139 warn ! ( "No class content found for: {}" , class_key) ;
124140 None
125141 }
126142 }
143+
144+ // source key is the dex file name.
145+ fn peek_source ( & self , source_key : & str ) -> Option < ExportableSource > {
146+ let dex_source = self . dex_sources . get ( source_key) ;
147+ let Some ( dex_source) = dex_source else {
148+ warn ! ( "No source found for: {source_key} when trying peek source." ) ;
149+ return None ;
150+ } ;
151+ let file_name = dex_source. file_name . clone ( ) ;
152+ let source = dex_source. bytes . clone ( ) ;
153+ Some ( ExportableSource {
154+ exportable_name : file_name,
155+ source,
156+ } )
157+ }
127158}
0 commit comments