Conversation
oleavr
left a comment
There was a problem hiding this comment.
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; | ||
| } |
There was a problem hiding this comment.
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.)
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Oh, I misread the code. I'll reimplement it with optionals.
|
Updated. Still there's a potential problem when neither of the 2 |
lib/class-factory.js
Outdated
| const thread = api['art::Thread::CurrentFromGdb'](); | ||
| const target = api['art::mirror::Object::Clone'](methodId, thread); | ||
| const target = api['art::mirror::Object::Clone'](methodId, thread); | ||
|
|
There was a problem hiding this comment.
Let's ditch this trailing whitespace and blank line.
lib/android.js
Outdated
| } | ||
| }, | ||
| optionals : ['_ZN3art6mirror6Object5CloneEPNS_6ThreadEm', | ||
| '_ZN3art6mirror6Object5CloneEPNS_6ThreadE'] |
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
Using a Set this becomes just:
if (optionals.has(name)) {| this["art::mirror::Object::Clone"] = function(thisptr, threadptr) { | ||
| return nativeFn(thisptr, threadptr, 0); | ||
| } | ||
| } |
There was a problem hiding this comment.
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 || []; |
There was a problem hiding this comment.
const optionals = api.optionals || new Set();There was a problem hiding this comment.
Or actually let's just make optionals a plain array, and do the Set wrapping here:
const optionals = new Set(api.optionals || []);|
Done. |
|
Thanks! Could you also revert the trailing whitespace (see comment) and tweak the style to follow semistandard? |
|
Done. |
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) { |
There was a problem hiding this comment.
- 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) { |
There was a problem hiding this comment.
- 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) | ||
| } |
There was a problem hiding this comment.
- Missing space after
function - Missing semicolon inside and outside the function
lib/android.js
Outdated
| } | ||
| } | ||
| }, | ||
| optionals : new Set([ |
There was a problem hiding this comment.
- 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(); |
There was a problem hiding this comment.
Let's do the Set() wrapping here.
|
Updated. |
oleavr
left a comment
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
Sorry, I missed this one:
thisptr => thisPtr
threadptr => threadPtr
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); |
There was a problem hiding this comment.
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);There was a problem hiding this comment.
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']); |
There was a problem hiding this comment.
Thanks! We'll also have to change the last argument here to 'pointer'.
|
Thanks! |
No description provided.