Giter Club home page Giter Club logo

Comments (14)

steven-michaud avatar steven-michaud commented on May 12, 2024

I can reproduce your problem, even with a minimal hook library (one that cuts out most of the code from my hook library template, and contains just one hook, an interpose hook for NSPushAutoreleasePool()). I can't reproduce it with Apple's DYLD_INSERT_LIBRARIES (after slightly altering my minimal hook library to use that functionality). So I guess this must really be a bug in HookCase. But it will be difficult to figure out, and I probably won't be able to fix it anytime soon.

Fortunately there's an easy workaround -- use LogWithFormat() instead of NSLog().

You've already discovered another workaround, printf(). But NSLog() is much more powerful, and LogWithFormat() has all that power. I made LogWithFormat() emulate NSLog(), so it's very puzzling that LogWithFormat() doesn't trigger the bug. But it's also very fortunate.

Almost nothing now works with DYLD_INSERT_LIBRARIES. I ended up having to create a simple command line utility to test it with.

from hookcase.

steven-michaud avatar steven-michaud commented on May 12, 2024

testlib.mm.txt

Here's the minimal hook library that I tested with.

from hookcase.

steven-michaud avatar steven-michaud commented on May 12, 2024

There are also no problems just loading my minimal hook library into a simple command line utility using dlopen() -- NSLog() works without any problems. Though, of course, no hooks get loaded when you do this.

from hookcase.

steven-michaud avatar steven-michaud commented on May 12, 2024

Another workaround:

If you're using my hook library template, add a call to Initialize_CF_If_Needed() just before your call to NSLog(). Then it works fine.

So the reason NSLog() crashes is that the CoreFoundation framework hasn't yet been initialized. Initialize_CF_If_Needed() is called from loadHandler::loadHandler(). But apparently it hasn't yet been called when your insert_entry() runs.

from hookcase.

steven-michaud avatar steven-michaud commented on May 12, 2024

I'm going to close this. The timing of CoreFoundation framework initialization is complicated, but it isn't really a bug. You just need to know that it might be an issue.

from hookcase.

liuyi12138 avatar liuyi12138 commented on May 12, 2024

Another workaround:

If you're using my hook library template, add a call to Initialize_CF_If_Needed() just before your call to NSLog(). Then it works fine.

So the reason NSLog() crashes is that the CoreFoundation framework hasn't yet been initialized. Initialize_CF_If_Needed() is called from loadHandler::loadHandler(). But apparently it hasn't yet been called when your insert_entry() runs.

this way works, i think maybe HookCase insert earlier than use DYLD_INSERT_LIBRARIES cause that.
Anyway, it solved my problem, thanks.

from hookcase.

steven-michaud avatar steven-michaud commented on May 12, 2024

If anything, C++ initializers run a little later with HookCase than with DYLD_INSERT_LIBRARIES. But (to work properly) HookCase needs to interrupt the process whereby dyld initializes each executable after it loads, load its hooks, then allow dyld to resume afterwards. This has always been complicated, and has only gotten more so over time (with newer versions of macOS). I've done my best not to mess things up, and I've generally succeeded in this. But there has been some fallout -- for example the CoreFoundation framework doesn't get initialized until later than normal, or perhaps at all. I've worked around this with Initialize_CF_If_Needed().

On macOS 12 (Monterey) and up, I need to stop the hook library's C++ initializers running when they normally would, then run them explicitly later (after HookCase's hooks have been set). But just now, playing around with my minimal test library in lldb (using both HookCase and DYLD_INSERT_LIBRARIES), I noticed that there's a dyld4::RuntimeState::notifyObjCInit() method that doesn't run again when the C++ initializers are run explicitly. Maybe it would help if I ran that explicitly, too.

I'll try this out and see what happens. But I may find that it has other, undesirable side effects. In which case it will be best to keep things as they are, since there's already an easy workaround.

from hookcase.

liuyi12138 avatar liuyi12138 commented on May 12, 2024

Sorry, I'm afriad the workaround doesn‘t apply to every situation.
I use [NSBundle mainBundle] in constructor function, and it crash again.
I think maybe another framework doesn't get initialized. Is there a way to load all the framework I need ?

Termination Reason:    Namespace SIGNAL, Code 11 Segmentation fault: 11
Terminating Process:   exc handler [12427]

VM Region Info: 0x7ff7bf31bff8 is in 0x7ff7bbb1c000-0x7ff7bf31c000;  bytes after start: 58720248  bytes before end: 7
      REGION TYPE                    START - END         [ VSIZE] PRT/MAX SHRMOD  REGION DETAIL
      MALLOC_SMALL             7fd589800000-7fd58a000000 [ 8192K] rw-/rwx SM=PRV  
      GAP OF 0x2231b1c000 BYTES
--->  STACK GUARD              7ff7bbb1c000-7ff7bf31c000 [ 56.0M] ---/rwx SM=NUL  ... for thread 0
      Stack                    7ff7bf31c000-7ff7bfb1c000 [ 8192K] rw-/rwx SM=PRV  thread 0

Thread 0 Crashed::  Dispatch queue: com.apple.main-thread
0   Foundation                    	    0x7ff802a406db +[NSString stringWithFormat:] + 124
1   Foundation                    	    0x7ff80314e92c _NSRequestConcreteObject + 81
2   Foundation                    	    0x7ff8030796ed -[NSString initWithFormat:locale:arguments:] + 14
3   Foundation                    	    0x7ff802a406f8 +[NSString stringWithFormat:] + 153
4   Foundation                    	    0x7ff80314e92c _NSRequestConcreteObject + 81
5   Foundation                    	    0x7ff8030796ed -[NSString initWithFormat:locale:arguments:] + 14
6   Foundation                    	    0x7ff802a406f8 +[NSString stringWithFormat:] + 153
7   Foundation                    	    0x7ff80314e92c _NSRequestConcreteObject + 81

And when I only use NSLog to console a NSString, I find the result is not what i except like this:

2023-03-15 14:32:46.829 ls[12694:309501] <CFString 0x6000032a6840 [0x7ff844bd3f80]>{contents = "ls"}

I think it is casud by the same reason.

from hookcase.

steven-michaud avatar steven-michaud commented on May 12, 2024

I use [NSBundle mainBundle] in constructor function, and it crash again.

I'll try this and let you know my results. But yes, it does look like my initializer problem is deeper than it first appeared.

What version of macOS are you using? I've found that the original bug you reported doesn't happen on macOS 11 (BigSur) -- only on macOS 12 (Monterey) and (presumably) macOS 13 (Ventura). This fits with my hunch that there are some initializers that I'm not running explicitly, on macOS 12 and 13. I didn't need to do this on macOS 11 and earlier.

There are comments about "Objective-C +load methods" in Apple's dyld and libobjc.A.dylib source code. I suspect these are what I'm missing. I'll be working on this.

from hookcase.

steven-michaud avatar steven-michaud commented on May 12, 2024

I use [NSBundle mainBundle] in constructor function, and it crash again.

Yes, I crash if I put this in your constructor function (on macOS 12). I get the crash you reported if I first call Initialize_CF_If_Needed(). Otherwise I get the _malloc_zone_malloc stack exhaustion crash you originally reported.

I also see the following error in the console after I run ls (and get your _NSRequestConcreteObject crash). This tends to confirm that I'm missing some "Objective-C initializers".

2023-03-15 10:37:35.238 ls[1171:36162] -[__NSCFString _stringByResolvingSymlinksInPathUsingCache:]: unrecognized selector sent to instance 0x60000352c9a0

from hookcase.

steven-michaud avatar steven-michaud commented on May 12, 2024

I'm still working on this. It'll be a while before I finish. But in the meantime I've found another workaround:

Call [NSObject load] in your constructor function before you call anything else. That seems to work for both NSLog() and [NSBundle mainBundle].

As best I can tell the problem is that (as you suspected) I'm not calling (or triggering calls to) enough initializers. So far I've been doing it only for the hook library itself. I also need to do it (or arrange it to happen) for all its dependencies. Without intervention, Monterey's and Ventura's dyld ignores these, because they're all loaded "before" the main executable. That is if they're loaded via HC_INSERT_LIBRARY and not DYLD_INSERT_LIBRARIES.

from hookcase.

liuyi12138 avatar liuyi12138 commented on May 12, 2024

thanks, it works for me.

from hookcase.

steven-michaud avatar steven-michaud commented on May 12, 2024

I've just released HookCase 7.1.2, which should fix this problem. You should no longer need the [NSObject load] workaround.

from hookcase.

liuyi12138 avatar liuyi12138 commented on May 12, 2024

I've just released HookCase 7.1.2, which should fix this problem. You should no longer need the [NSObject load] workaround.

It's proven to work for me, thanks!

from hookcase.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.