Skip to content

Support for ART on Xposed#12

Merged
oleavr merged 10 commits intofrida:masterfrom
hedger:xposedsupport
Feb 3, 2017
Merged

Support for ART on Xposed#12
oleavr merged 10 commits intofrida:masterfrom
hedger:xposedsupport

Conversation

@hedger
Copy link
Contributor

@hedger hedger commented Feb 2, 2017

No description provided.

Copy link
Member

@oleavr oleavr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome! Let's see if we can use the optionals feature to simplify the logic a bit.

lib/android.js Outdated
return true;
}
return false;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be cleaner if we made use of the optionals support, by having two entries and adding both of them to optionals. We could then check if the regular one is missing, and plug in a shim function that just forwards to the Xposed one with the extra argument set to 0. (That way the implementation doesn't need to know about Xposed.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that passing an extra argument in case of basic ART will produce correct behavior on all platforms. It may break stack or overwrite register values.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant at the JS API level only, so class-factory.js doesn't need to know which of the two functions it's calling.

Copy link
Contributor Author

@hedger hedger Feb 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. Currently optionals doesn't have support for remaining counter, so in case if none of those exports could be found it'll still return a non-functional API object. And extending optionals to group and count exports by their name will result in similar, if not more, complex code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I misread the code. I'll reimplement it with optionals.

@hedger
Copy link
Contributor Author

hedger commented Feb 3, 2017

Updated. Still there's a potential problem when neither of the 2 ::Clone versions could be found, which is VERY unlikely.

Copy link
Member

@oleavr oleavr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome! Just a few nitpicks:

const thread = api['art::Thread::CurrentFromGdb']();
const target = api['art::mirror::Object::Clone'](methodId, thread);
const target = api['art::mirror::Object::Clone'](methodId, thread);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's ditch this trailing whitespace and blank line.

lib/android.js Outdated
}
},
optionals : ['_ZN3art6mirror6Object5CloneEPNS_6ThreadEm',
'_ZN3art6mirror6Object5CloneEPNS_6ThreadE']
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we're changing the data structure let's use a Set here instead:

    optionals: new Set([
      '_ZN3art6mirror6Object5CloneEPNS_6ThreadEm',
      '_ZN3art6mirror6Object5CloneEPNS_6ThreadE',
    ]);

lib/android.js Outdated
} else {
const optional = optionals[name];
if (optional) {
if (optionals.indexOf(name) > -1) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using a Set this becomes just:

          if (optionals.has(name)) {

this["art::mirror::Object::Clone"] = function(thisptr, threadptr) {
return nativeFn(thisptr, threadptr, 0);
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The style here should follow semistandard for consistency.

lib/android.js Outdated
const functions = api.functions || {};
const variables = api.variables || {};
const optionals = api.optionals || {};
const optionals = api.optionals || [];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

    const optionals = api.optionals || new Set();

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or actually let's just make optionals a plain array, and do the Set wrapping here:

    const optionals = new Set(api.optionals || []);

@hedger
Copy link
Contributor Author

hedger commented Feb 3, 2017

Done.

@oleavr
Copy link
Member

oleavr commented Feb 3, 2017

Thanks! Could you also revert the trailing whitespace (see comment) and tweak the style to follow semistandard?

@hedger
Copy link
Contributor Author

hedger commented Feb 3, 2017

Done.

Copy link
Member

@oleavr oleavr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Final batch :)

lib/android.js Outdated
'_ZN3art6Thread14CurrentFromGdbEv': ['art::Thread::CurrentFromGdb', 'pointer', []],
'_ZNK3art6Thread13DecodeJObjectEP8_jobject': ['art::Thread::DecodeJObject', 'pointer', ['pointer', 'pointer']],
'_ZN3art6mirror6Object5CloneEPNS_6ThreadE': ['art::mirror::Object::Clone', 'pointer', ['pointer', 'pointer']]
'_ZN3art6mirror6Object5CloneEPNS_6ThreadE' : function(address) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Extra space before :
  • Missing space after function

lib/android.js Outdated
'_ZN3art6mirror6Object5CloneEPNS_6ThreadE' : function(address) {
this["art::mirror::Object::Clone"] = new NativeFunction(address, 'pointer', ['pointer', 'pointer']);
},
'_ZN3art6mirror6Object5CloneEPNS_6ThreadEm' : function(address) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Extra space before :
  • Missing space after function

lib/android.js Outdated
const nativeFn = new NativeFunction(address, 'pointer', ['pointer', 'pointer', 'int']);
this["art::mirror::Object::Clone"] = function(thisptr, threadptr) {
return nativeFn(thisptr, threadptr, 0)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Missing space after function
  • Missing semicolon inside and outside the function

lib/android.js Outdated
}
}
},
optionals : new Set([
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Extra space before :
  • Let's use a plain array and do the Set() wrapping below (see earlier comment) – sorry for the back and forth

lib/android.js Outdated
const functions = api.functions || {};
const variables = api.variables || {};
const optionals = api.optionals || {};
const optionals = api.optionals || new Set();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's do the Set() wrapping here.

@hedger
Copy link
Contributor Author

hedger commented Feb 3, 2017

Updated.

Copy link
Member

@oleavr oleavr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suck at reading code when the style is just slightly off, so I missed this:

lib/android.js Outdated
'_ZN3art6mirror6Object5CloneEPNS_6ThreadEm': function (address) {
const nativeFn = new NativeFunction(address, 'pointer', ['pointer', 'pointer', 'int']);
this["art::mirror::Object::Clone"] = function (thisptr, threadptr) {
return nativeFn(thisptr, threadptr, 0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I missed this one:
thisptr => thisPtr
threadptr => threadPtr

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No problem, renamed.

lib/android.js Outdated
'_ZN3art6mirror6Object5CloneEPNS_6ThreadEm': function (address) {
const nativeFn = new NativeFunction(address, 'pointer', ['pointer', 'pointer', 'int']);
this["art::mirror::Object::Clone"] = function (thisPtr, threadPtr) {
return nativeFn(thisptr, threadptr, 0);
Copy link
Member

@oleavr oleavr Feb 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

^ these two guys also need to be renamed.

One more thing, I noticed Xposed uses size_t for the last argument – we don't have a type for that yet in the NativeFunction API, so the most correct thing would be pointer as it's the same size (and use the NULL short-hand). That will look pretty weird though, so maybe we can make that clearer by doing:

          const numTargetBytes = NULL;
          return nativeFn(thisPtr, threadPtr, numTargetBytes);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, my bad. NULL trick looks reasonable, added.

lib/android.js Outdated
this["art::mirror::Object::Clone"] = new NativeFunction(address, 'pointer', ['pointer', 'pointer']);
},
'_ZN3art6mirror6Object5CloneEPNS_6ThreadEm': function (address) {
const nativeFn = new NativeFunction(address, 'pointer', ['pointer', 'pointer', 'int']);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! We'll also have to change the last argument here to 'pointer'.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

@oleavr
Copy link
Member

oleavr commented Feb 3, 2017

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants