DavidGoldman / InspectiveC

objc_msgSend hook for debugging/inspection purposes.
GNU General Public License v3.0
715 stars 108 forks source link

Feature request: logging caller image name #7

Closed mbazaliy closed 9 years ago

mbazaliy commented 9 years ago

It could be really great to know who is calling particular objc_msgSend. Could you add a caller image name to logfile ?

Something like:

 void *addr = __builtin_return_address(0);
 Dl_info info;
 dladdr(addr, &info);
 NSString *callerName = [NSString stringWithUTF8String: info.dli_sname]; // thats bad and just an example
DavidGoldman commented 9 years ago

This can easily be added to preObjc_msgSend since the lr argument is the return address.

However, how would the image name fit in with the current logging format?

mbazaliy commented 9 years ago

Where should I add that code to not corrupt a stack ? I see a + 208 const for arm64 for example.

What if

|Foundation| -|NSPlaceholderString@<0x12f60c520> initWithFormat:| @"/var/mobile/Library/Preferences/%@"
DavidGoldman commented 9 years ago

On stack corruption: 208 is the offset from the regstate to the top of the stack when objcmsgSend was called (where arguments may be ). Notice 208 == sizeof(struct RegState). As long as you don't mess with the regstate struct you'll be fine.

Not sure if I'm a fan of that - won't it mess up the indentation?

mbazaliy commented 9 years ago

I've add this code to preObjc_msgSend

  Dl_info info;
    if(dladdr((void*)lr, &info) != 0 ) {
        fprintf(cs->file, "|%s| ", strrchr(info.dli_fname, '/')+1);
    }

and now its looks like this:

|libinspectivec.dylib|     +|NSArray allocWithZone:| NULL
|CoreFoundation|       +|NSArray self|
|CoreFoundation|       +|__NSPlaceholderArray immutablePlaceholder|
|CoreFoundation|   -|__NSArrayM@<0x17004e7f0> count|
|CoreFoundation|   -|__NSPlaceholderArray@<0x17400be90> initWithArray:range:copyItems:| <__NSArrayM@0x17004e7f0> {0, 1} false

but sometimes it show stuff like this:

Foundation|           +|NSPathStore2 pathStoreWithCharacters:length:| 0x16fd6aea8 94
|Foundation|             +|NSPathStore2 self|
|Foundation|             -|NSPathStore2@<0x174192a30> autorelease|
|Foundation| |libobjc.A.dylib|       +|__NSCFArray initialize|     -- here the problem
      -|__NSCFArray@<0x17006e1c0> mutableCopy| --- and here
|libinspectivec.dylib|         -|__NSCFArray@<0x17006e1c0> mutableCopyWithZone:| NULL

Any ideas why it could happen ?

DavidGoldman commented 9 years ago

Ah, it shouldn't be added to preObjc_msgSend. The problem is that when logging happens, [obj class] is called to make sure the class is initialized, which can lead to a [ initialize] call.

mbazaliy commented 9 years ago

Hm, what is a good place to put it instead of preObjc_msgSend ?

DavidGoldman commented 9 years ago

I would modify onWatchHit and onNestedCall to pass curRecord.lr to logWatchedHit and logObjectAndArgs, which they can use for dladdr.

mbazaliy commented 9 years ago

Thanks for update, just implemented it. Sometimes I see stuff like this:

|libinspectivec.dylib| -|UIStatusBarDataNetworkItemView@<0x13de16c70> _resizeWithOldSuperviewSize:| {0, 20} 

or this

|BaseBoard| -|FBSDisplay@<0x1740589f0> isKindOfClass:| [FBSDisplay class]
|libobjc.A.dylib| -|FBSDisplay@<0x1740589f0> class|  -- ?
|FrontBoardServices| -|FBSDisplay@<0x1740589f0> caDisplay|

Looks like some image names were resolved incorrectly. Other problem - performance is not good with image name logging.

DavidGoldman commented 9 years ago

I'm not sure how good dladdr is, but what you're seeing may be due to tail call optimizations.

You could also try caching the result from dladdr - that may improve performance.

mbazaliy commented 9 years ago

I think I can close this now, thanks for your help.

DavidGoldman commented 9 years ago

No problem.