I'm trying to debug a certain method, but my breakpoints in that method never get hit when I'm debugging on a device, but they do get hit when I am debugging with the iOS simulator. The method is part of a library that my app calls, and I feel like that may be a factor. I developed both the app and the library, and I have both the app and the library open in the same Workspace when I'm debugging.
I put one breakpoint in on the line in my app's code that calls the library method, then a second breakpoint on the first line of the library. When I test with the simulator, both are hit. When I test on a device, only the first one is hit, and the second one gets skipped over (the code for the library method still appears to run).
Is there anything special I need to do to be able to step into a library call when I'm debugging on a device that I don't need to do when debugging on the simulator? Or is it impossible to debug inside a library?
I'm sorry if this is a little unclear - I'm trying to describe what I'm doing as well as I can, but it's pretty strange behavior that I haven't seen before, so it's a little hard to describe. If you need anymore information or anything is unclear, please let me know.
EDIT 1: I noticed something that's a little different, not sure if it's connected or not: I don't have a .h file containing the methods in my library. Actually, there is only 1 method in it (which I'll callmyMethod) that will be called from outside the library (then that method calls the other methods in the library as it needs them). Furthermore, I'm using the TARGET_IPHONE_SIMULATOR pre-processor trigger to make the call in a slightly different manner depending on if it's running on a device or on the simulator. To make the call into the library, on a button click method in my app I just have
#if TARGET_IPHONE_SIMULATOR
extern void myMethod();
myMethod();
#else
extern void myMethod(const char diretory[], int directoryLength);
const char *dir = [[documents path] UTF8String];
myMethod(dir, [[documents path] length]);
#endif
I have matching #if blocks in the method in my library to declare it as needed, and to use dir when it is passed in. This seems to execute just fine. I can tell the code in my library is being called and doing something, it's just not doing what I want it to. Thus the attempts to put in a breakpoint, and the reason for this whole question.
EDIT 2: My library actually contains plain C code, not Objective-C. I put some printf lines into the library code, and its not being displayed. I'm curious if somehow my app is calling a previous version of my library, instead of calling the one that's open in my workspace. That would be consistent with the "it's just not doing what I want it to" part of my last edit. Would it be possible that the device is trying to run an old version of the library it has saved somehow? I thought that completely removing the app from the device before installing the new version of my app would prevent that, but perhaps I'm mistaken?
Related
This looked promising but doesn't seem like a duplicate question as it addresses issues in Swift.
I am finalising an existing Objective C project but NSLog disappeared when I updated to Xcode 9. So I'm looking for some setting in Xcode that lets me continue using NSLog to fine tune the project.
Basic debugging using logging for Swift and Objective-C apps appears to have changed in Xcode 9 as NSLog messages no longer appear in the Debug area. The window where DEBUG=1 is set no longer looks like Figure 2 The DEBUG preprocessor macro setting in an Xcode project.
As an example, I want to display this string message in the Debug area using Xcode9.
NSString *outputData = #"This should show in Debug area";
NSLog( #"text: %#", outputData );
I studied the latest documentation here or here but so far that has not helped. It may also be worth noting that previously the Debug area would open automatically when I ran the project. Since installing Xcode9 it no longer does that.
Hopefully the extra information provided in the edits below will suggest to someone where I have yet to look. Thanks.
EDIT 1
In the Console area - i.e. the bottom right part of the Debug area - I had All Output selected. So I tried using Debugger output and Target output but there was still no log.
I added these statements in the Prefix.pch file
#ifndef DEBUG
#define NSLog(...) /* suppress NSLog when in release mode
#endif
When I ran the code the following appeared in the Issue Navigator.
Unused variable 'outputData'
EDIT 2
There seems to be a different place to set DEBUG=1 in Xcode9 (see below).
I inserted a DEBUG macro into the .pch file using the examples suggested in several SO posts here, here, here (all quite old) and even here (making sure to change MyLog back to NSLog). And in each case I was able to report the same issue in the Issue navigator but never in the Debug console. A similar problem (with Xcode5) was solved here by copying over the files into a new project but I want to avoid this.
My app which was almost finished has so far not had to deal with any of the complex issues that unified logging seeks to address. But I watched the 2016 WWDC video on unified logging and read through its slide show files searching for an example of how to use the appropriate API to do something as basic - print NSLog live to the console area - the way I did before installing Xcode9. This may be the wrong approach. But I can’t think of a better way to proceed.
EDIT 3
It's worth noting that when I created a new Objective C project using Xcode9 and ran the above code, the string message appeared in the Console area.
In other words, using Xcode9 the new logging API does work with NSLog, but only for a new project and not for one created using an earlier version of Xcode.
Enable DEBUG preprocessor macro
Rather than writing your debug statement into code, you might try dropping in a breakpoint, right clicking on it, and selecting "Edit Breakpoint". You should see this menu:
From there, you'll click "Edit Breakpoint" and you're presented with this:
From there, you can click "Action" and you'll see this menu:
You can enter print messages (ex: myMethodCalled) or variable values (myIntValue = #myIntValue#), or you can type debugger commands to execute at that spot in the code (ex: po dump(myArray)).
The downside of this approach is the breakpoints aren't always "sticky" to the line of code you originally drop it in on.
Try this. Navigate to:
Product -> Scheme -> Edit Scheme -> Run -> Arguments -> Environment Variables
in Xcode.
Add OS_ACTIVITY_MODE and set the value to disable or leave it empty.
Make sure it is checked!
Hope this helps
A Debug log was enabled in the Console area of Xcode9 after replacing these definitions in the preCompile header
#ifndef DEBUG
#define NSLog(...) /* suppress NSLog when in release mode */
#endif
with the following
#ifdef __DEBUG__
#define NSLog(...) /* suppress NSLog when in release mode */
#endif
Environment Variables for Arguments were set according to the answer above with an additional setting for Options. Someone more familiar with the unified logging API might explain the particular options but I'm satisfied I have a working solution.
Arguments
Options
I've been searching for 2 days to prevent my app from jailbreak device, and I got it, the problem is I still can hook my class use theOS and override the jailbreak check function.
Do you have any proven Idea maybe , framework , library or something else ?
You can use dyld for that.
_dyld_image_count returns a number of dynamic libraries loaded into your application address space. Then you can iterate over them using _dyld_get_image_name checking dynamic library path. That way you can determine whether CydiaSubstrate library or any dynamic library with unknown path been loaded into your application.
Of course with jailbreak even those functions can be hooked and I don't think you can do much about it. Arxan claims it can do something with it but even if it detects something you can always hook any function it uses for detection. CydiaSubstrate tweaks are always one step ahead because they're loaded before main is called. Thus it can hook everything it wants in constructor and you can't do anything about it.
Without jailbreak only way to load malicious library is to modify and resign your app so that it links against the library. Without jailbreak you can't hook C functions so _dyld_get_image_name will be able to detect that library.
I've created a small static library for Mac OS and iOS, and it's working very nicely thank you. However, during testing, there were times when my code bugged out and it hit a breakpoint that I keep set on 'All Exceptions' in case of just such an eventuality. I'm not worried about the bug itself - all the ones I know of are fixed - I'm more worried that Xcode took me straight to the code that crashed - inside my library's code, thus revealing the inner workings of my library's .m file.
Naturally I don't want this to happen in the wild, or people would be able to rip my code directly. How do I prevent Xcode from displaying the internals of my static library, even when an exception occurs within it?
-Ash
This appears to be an example of Xcode being a little too clever for its own good. It was actually detecting that I had the code for this library on my computer and fetching it directly from the folder, not reading it from within the library at all! I renamed the folder containing my library's source code and project file temporarily and, lo and behold, the library code is no longer displayed when a crash occurs!
Freaky.
I'm untangling spaghetti code and as an exercise I'm walking through the application from its launch, breaking on applicationDidFinishLaunching and stepping over and into.
When this first method returns I then break into assembly. Knowing when to step over and when to step into is a real pain. I want the debugger to pause on all the symbolicated code (i.e. code I can see in Xcode – maybe this is called 'user' code? Basically, non framework/library code.), but I don't care about Apple's internal methods.
I'm looking for the practical equivalent of setting a breakpoint on the first line (or every line) of every method and function that I (or my predecessor) has written.
Is there some LLDB voodoo that will do this?
There's a simple way of setting breakpoints on all of your modules' functions, excluding those of any other shared library (Apple frameworks), assuming your product/module is called 'MyApp' that would be:
breakpoint set -s MyApp -r .
However, this will include any library you have statically linked to, which probably means any library you've brought in since dynamic linking isn't allowed in the App Store.
If you tend to prefix your classes, you could narrow down the results by only breaking on functions that are part of classes with that prefix. Assuming your prefix is 'MA' you can do something like:
breakpoint set -s MyApp -r ^[^A-Za-z]*MA
which should cover the majority of your code.
I am creating an iphone test using c++,and I want to use nslog( the only way to show debug information?) whenever I want to include nslog function my cpp has to change to mm right? is it the only way to do it? because I don't want to change back to cpp when I move to other platform.
thanks for help
Since NSLog only exists on Objective-C platforms, why not create your own LogMessage() method taking standard C++ arguments in a single .mm file that calls NSLog and call that from C++ files named as usual. That way you'll not need to rename every single file that needs to log to .mm
On other platforms, just include another implementation of LogMessage() since there's no NSLog to call there anyway.