@@ -118,8 +118,24 @@ static BlobBuilder IntFieldSignature ()
118118 return signature ;
119119 }
120120
121+ static BlobHandle AddLegacyJniMethodSignature ( JniFixtureBuilder fixture , bool findClass )
122+ {
123+ var signature = new BlobBuilder ( ) ;
124+ new BlobEncoder ( signature ) . MethodSignature ( )
125+ . Parameters ( findClass ? 1 : 3 , out ReturnTypeEncoder returnType , out ParametersEncoder parameters ) ;
126+ returnType . Type ( ) . Int32 ( ) ;
127+ if ( findClass ) {
128+ parameters . AddParameter ( ) . Type ( ) . String ( ) ;
129+ } else {
130+ parameters . AddParameter ( ) . Type ( ) . Int32 ( ) ;
131+ parameters . AddParameter ( ) . Type ( ) . String ( ) ;
132+ parameters . AddParameter ( ) . Type ( ) . String ( ) ;
133+ }
134+ return fixture . Metadata . GetOrAddBlob ( signature ) ;
135+ }
136+
121137 [ Test ]
122- public void RewritesBareMemberAndDescriptorForAReferencedJniClass ( )
138+ public void DoesNotRewriteUnrelatedBareMemberAndDescriptorStrings ( )
123139 {
124140 var fixture = new JniFixtureBuilder ( ) ;
125141 UserStringHandle className = fixture . String ( "net/dot/android/ApplicationRegistration" ) ;
@@ -139,11 +155,147 @@ public void RewritesBareMemberAndDescriptorForAReferencedJniClass ()
139155 MetadataReader reader = peReader . GetMetadataReader ( ) ;
140156 CollectionAssert . AreEqual ( new [ ] {
141157 "c4" ,
142- "a " ,
158+ "Context " ,
143159 "Landroid/content/Context;" ,
144160 } , LoadedStrings ( peReader , reader , method ) . ConvertAll ( entry => entry . Value ) ) ;
145161 }
146162
163+ [ Test ]
164+ public void RewritesLegacyJniLookupsForTwoClassesAndBothMethodHandleKinds ( )
165+ {
166+ var fixture = new JniFixtureBuilder ( ) ;
167+ BlobHandle findClassSignature = AddLegacyJniMethodSignature ( fixture , findClass : true ) ;
168+ BlobHandle memberLookupSignature = AddLegacyJniMethodSignature ( fixture , findClass : false ) ;
169+
170+ int fieldStart = fixture . NextFieldRid ;
171+ int methodStart = fixture . NextMethodRid ;
172+ MethodDefinitionHandle findClassDefinition = fixture . Metadata . AddMethodDefinition (
173+ MethodAttributes . Public | MethodAttributes . Static | MethodAttributes . HideBySig ,
174+ MethodImplAttributes . Runtime ,
175+ fixture . Metadata . GetOrAddString ( "FindClass" ) ,
176+ findClassSignature ,
177+ 0 ,
178+ MetadataTokens . ParameterHandle ( fixture . Metadata . GetRowCount ( TableIndex . Param ) + 1 ) ) ;
179+ MethodDefinitionHandle getStaticFieldDefinition = fixture . Metadata . AddMethodDefinition (
180+ MethodAttributes . Public | MethodAttributes . Static | MethodAttributes . HideBySig ,
181+ MethodImplAttributes . Runtime ,
182+ fixture . Metadata . GetOrAddString ( "GetStaticFieldID" ) ,
183+ memberLookupSignature ,
184+ 0 ,
185+ MetadataTokens . ParameterHandle ( fixture . Metadata . GetRowCount ( TableIndex . Param ) + 1 ) ) ;
186+ fixture . AddType ( "Android.Runtime" , "JNIEnv" , fieldStart , methodStart ) ;
187+
188+ TypeReferenceHandle jniEnvironmentReference = fixture . Metadata . AddTypeReference (
189+ fixture . CoreLibraryReference ,
190+ fixture . Metadata . GetOrAddString ( "Android.Runtime" ) ,
191+ fixture . Metadata . GetOrAddString ( "JNIEnv" ) ) ;
192+ MemberReferenceHandle findClassReference = fixture . Metadata . AddMemberReference (
193+ jniEnvironmentReference ,
194+ fixture . Metadata . GetOrAddString ( "FindClass" ) ,
195+ findClassSignature ) ;
196+ MemberReferenceHandle getMethodReference = fixture . Metadata . AddMemberReference (
197+ jniEnvironmentReference ,
198+ fixture . Metadata . GetOrAddString ( "GetMethodID" ) ,
199+ memberLookupSignature ) ;
200+
201+ UserStringHandle firstClass = fixture . String ( "acme/one/First" ) ;
202+ UserStringHandle firstField = fixture . String ( "count" ) ;
203+ UserStringHandle firstDescriptor = fixture . String ( "I" ) ;
204+ UserStringHandle firstOtherField = fixture . String ( "enabled" ) ;
205+ UserStringHandle firstOtherDescriptor = fixture . String ( "Z" ) ;
206+ UserStringHandle secondClass = fixture . String ( "acme/two/Second" ) ;
207+ UserStringHandle secondMethod = fixture . String ( "run" ) ;
208+ UserStringHandle secondDescriptor = fixture . String ( "()V" ) ;
209+ UserStringHandle ambiguousField = fixture . String ( "state" ) ;
210+
211+ var localSignature = new BlobBuilder ( ) ;
212+ var localEncoder = new BlobEncoder ( localSignature ) . LocalVariableSignature ( 2 ) ;
213+ localEncoder . AddVariable ( ) . Type ( ) . Int32 ( ) ;
214+ localEncoder . AddVariable ( ) . Type ( ) . Int32 ( ) ;
215+ StandaloneSignatureHandle locals = fixture . Metadata . AddStandaloneSignature ( fixture . Metadata . GetOrAddBlob ( localSignature ) ) ;
216+ var controlFlow = new ControlFlowBuilder ( ) ;
217+
218+ fieldStart = fixture . NextFieldRid ;
219+ methodStart = fixture . NextMethodRid ;
220+ MethodDefinitionHandle method = fixture . AddVoidMethod ( "LookUpBoth" , fixture . EmitBody ( encoder => {
221+ LabelHandle ambiguousLookup = encoder . DefineLabel ( ) ;
222+
223+ encoder . LoadString ( firstClass ) ;
224+ encoder . OpCode ( ILOpCode . Call ) ;
225+ encoder . Token ( findClassDefinition ) ;
226+ encoder . StoreLocal ( 0 ) ;
227+ encoder . LoadLocal ( 0 ) ;
228+ encoder . LoadString ( firstField ) ;
229+ encoder . LoadString ( firstDescriptor ) ;
230+ encoder . OpCode ( ILOpCode . Call ) ;
231+ encoder . Token ( getStaticFieldDefinition ) ;
232+ encoder . OpCode ( ILOpCode . Pop ) ;
233+
234+ encoder . LoadLocal ( 0 ) ;
235+ encoder . LoadString ( firstOtherField ) ;
236+ encoder . LoadString ( firstOtherDescriptor ) ;
237+ encoder . OpCode ( ILOpCode . Call ) ;
238+ encoder . Token ( getStaticFieldDefinition ) ;
239+ encoder . OpCode ( ILOpCode . Pop ) ;
240+
241+ encoder . LoadString ( secondClass ) ;
242+ encoder . OpCode ( ILOpCode . Call ) ;
243+ encoder . Token ( findClassReference ) ;
244+ encoder . StoreLocal ( 1 ) ;
245+ encoder . LoadLocal ( 1 ) ;
246+ encoder . LoadString ( secondMethod ) ;
247+ encoder . LoadString ( secondDescriptor ) ;
248+ encoder . OpCode ( ILOpCode . Call ) ;
249+ encoder . Token ( getMethodReference ) ;
250+ encoder . OpCode ( ILOpCode . Pop ) ;
251+
252+ encoder . LoadString ( firstClass ) ;
253+ encoder . OpCode ( ILOpCode . Call ) ;
254+ encoder . Token ( findClassDefinition ) ;
255+ encoder . StoreLocal ( 0 ) ;
256+ encoder . Branch ( ILOpCode . Br_s , ambiguousLookup ) ;
257+ encoder . LoadString ( secondClass ) ;
258+ encoder . OpCode ( ILOpCode . Call ) ;
259+ encoder . Token ( findClassReference ) ;
260+ encoder . StoreLocal ( 0 ) ;
261+ encoder . MarkLabel ( ambiguousLookup ) ;
262+ encoder . LoadLocal ( 0 ) ;
263+ encoder . LoadString ( ambiguousField ) ;
264+ encoder . LoadString ( firstDescriptor ) ;
265+ encoder . OpCode ( ILOpCode . Call ) ;
266+ encoder . Token ( getStaticFieldDefinition ) ;
267+ encoder . OpCode ( ILOpCode . Pop ) ;
268+ encoder . OpCode ( ILOpCode . Ret ) ;
269+ } , locals , controlFlow ) ) ;
270+ fixture . AddType ( "Acme" , "LegacyLookups" , fieldStart , methodStart ) ;
271+
272+ JniRewriteResult result = Rewrite ( fixture . Serialize ( ) , Mapping (
273+ "acme.one.First -> a.b.F:\n " +
274+ " int count -> x\n " +
275+ " boolean enabled -> q\n " +
276+ " int state -> f\n " +
277+ "acme.two.Second -> a.b.S:\n " +
278+ " int state -> s\n " +
279+ " void run() -> y\n " ) ) ;
280+
281+ using var peReader = new PEReader ( ImmutableArray . Create ( result . Image ) ) ;
282+ MetadataReader reader = peReader . GetMetadataReader ( ) ;
283+ CollectionAssert . AreEqual ( new [ ] {
284+ "a/b/F" ,
285+ "x" ,
286+ "I" ,
287+ "q" ,
288+ "Z" ,
289+ "a/b/S" ,
290+ "y" ,
291+ "()V" ,
292+ "a/b/F" ,
293+ "a/b/S" ,
294+ "state" ,
295+ "I" ,
296+ } , ValuesOf ( LoadedStrings ( peReader , reader , method ) ) ) ;
297+ }
298+
147299 [ Test ]
148300 public void RewritesAttributesAndLoadedStrings ( )
149301 {
0 commit comments