How can I break on all symbolicated code in Xcode 4.6? - ios

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.

Related

Framework using library crash

I have 2 frameworks created by me that use (both of them) a library also created by me.
The first framework initialize the library and makes all its workflow. After finishing the first framework, the second one must start.
But when the second one is going to start, after initializing the library, the app using both frameworks crashes with a exc_bad_access error.
Apparently the library is created correctly, but if i comment the line of code to initialize the library in the second framework, the workflow continues (it crashes later because it has no library initialization).
Is there anything I'm doing wrong? Should I use two separate libraries instead?
EDIT:
Imagine the situation:
Framework A has this methods: start, stop. And while it works it delegate to the methods: infoFromA,frameworkAFinished.
Framework B has this methods: start, stop. And while it works it delegate to the methods: infoFromB,frameworkBFinished.
Both start methods initialize the static library mentioned (lets call it problematicLibrary).
Both frameworks present some views to make its functionality. So lets make an example of the app workflow.
At the app view viewWillAppear method, I start the Framework A just using:
[FrameworkA start]; , this will initialize the library and present a view. With this view (using my problematicLibrary) some info will be delegated to the infoFromA delegated method. And after all the info is delegated, it will delegate to frameworkAFinished.
When the FrameworkA has delegated to the frameworkAFinished I start the next Framework: [FrameworkB start]. As the other Framework, it will initialize the library and present a view. While debugging, all the initialization of the library is done (create the instances of the needed objects and a new instance of the library is created) and while its presenting the view it goes through the viewDidLoad method and then it throws an exc_bad_access error at the problematicLibrary initialization line (which has been done before and continued to present the view!!) without going into any other method from the view.
I have checked if the initialization is doing well, and all the variables were at null value before the initialization, and a new memory address is given to the library object.
This sounds strongly like a symbol conflict to me. I'm just surprised the linker didn't catch it, but I assume that's because you're using a static library in both your frameworks instead of simply yet another framework.
Generally speaking, I'd warn that "this is a bad idea™". What you're trying to introduce into your design is basically dependency management. Like a lot of blog articles and specifically this SO answer suggest, you should avoid packaging frameworks (and by extension libraries) into frameworks.
What most likely happens in your scenario is this (I admit I'm guessing a bit here): You linked the library into Framework A. Thus, the library becomes a fixed part of it. Its symbols are in it, even if you did not expose them to the app in any header files or the like. As long as you use only that, everything works smoothly. Then comes Framework B, of which the library is also a fixed part. Even though you can't see it from your app, the very same symbols are inside it. This, however, clashes with the symbols that were already loaded by Framework A, hence a crash (as said, this would usually be caught by the linker, but I guess you "tricked" it by building the frameworks beforehand and packaged the library in them). Maybe somebody else can explain this in more detail, but that quickly becomes besides the point as to how you would go for a solution. From how I see it, it just won't work this way.
So here's a suggestion for how you can solve your problem:
If you really, really need to split like this (two frameworks used in your app using the same dependency), I'd suggest removing the library from the frameworks (i.e. make them depend on it, but not package the actual .a file in them) and documenting that properly. Then add the library to your app project, just like you added the frameworks.
If you want to make this fancy and easily installable into other apps, I'd recommend setting up a private CocoaPods repository and turn your frameworks into private pods. You can then easily define the library (or rather "new Framework C") as a dependency for Framework A and Framework B. When you then pod install in your app, cocoapods figures out the dependency and adds Framework C automatically to your project. This scenario is exactly what cocoapods (or any dependency manager for that matter) was designed for. It automates and helps in the project setup, so that the final build (the app) doesn't have to figure out dynamically what it can and can't use. The end result is the same.
Trying to duplicate that "in code" quickly becomes messy. Frameworks trying to figure out things of the surrounding app/project that uses them (like "is my dependency so-and-so already linked? if not, can I load my own version of the library?") can lead to a lot of pain.
Okay, in response to your comment I'll try my hand at a more detailed How-To for the non-cocoapods setup. As a preface, though, let me say that that's kinda hard to do on top of my head, as I have no ready sample project to toy around with. Since this is one of those "set it up once and then forget aout it for a long time" I have to admit my recollection of these things is a bit fuzzy, so consider this as a sort of "rough direction". There might be things you need to configure differently than how I recall them. Other SO user are thus hereby invited to edit and correct my answer here, too. :)
First, I have to say I am not exactly sure whether you need to convert your static library into a framework or not for this, I think you don't so I'll go from here (I have never used a static library in that way).
That means you can leave the project that builds your library as is. On second thought, you probably have to do this to be able to link against the library without making it a part of the framework that uses it. I will still refer to this code as "library" in the below points, but assume that you're able to turn it into a dynamic framework as well.
The projects building Framework A and Framework B should be changed. I don't know how you have this set up (as one project with various targets, whether you have a "development application" as part of it to test the frameworks on themselves, etc.), but the important thing is that in the target that builds a framework, the library should be linked (i.e. in the "Link Binary With Libraries" build phase), but not copied (i.e. it must not be in the "Copy Bundle Ressources" build phase). It might be tricky to set up any development/test target you use to run, depending on how you did that so far. For example you might have to manually edit Library Search paths in your build settings to be able to properly compile the framework.
Lastly, you need to change your final app's project settings, obviously. The library that was originally part of Framework A and B now needs to be linked to from its project directly, and, obviously, it needs to be copied into the bundle as well. Note that any projects that include either of your frameworks (A or B or both) in the future must do so, otherwise they won't work, because these frameworks expect the library to be present (but no longer "bring it with them").
In spite of this long-ish text wall, it shouldn't be that complicated, I think, but you may still want to check out how cocoapods can support you with something like this, perhaps it's helpful in the future. The linked article expects basic knowledge on how to use a pod and write one, but the other guides on the site explain that pretty well. I am just saying this because in the end, when using cocoapods in a project to add multiple libraries/frameworks that introduce dependencies, it basically sets up your project in the way I described above. It uses some fancy shell scripts that ensure everything is copied to the correct folders and such, but overall speaking that's how it works: A pod's podspec tells cocoapods what additional pods to include in your app for it to work (a dependecy the pod expects to be there, but doesn't "bring in" by itself).
Check if they are both compiling for the same target.
Check if they have access to the same target membership.
Check build phases to see that they are both there.
I think because the first library is not 'well' referencing the second one.
Also i think that you can't import a framework inside another one.
To make things easier, you can merge the two frameworks on a single one.
Also you can add a callback (using protocols or closures) that informs for the end of the first workflow, and you use this callback to initialize the second framework. This way the initialization will not be made automatically.

What happens to Console.WriteLine calls in Xamarin.iOS release builds?

When developing iOS apps using XCode, you can use NSLog calls to write information to the console for debugging. In Xamarin.iOS, the same can be done with Console.WriteLine.
When running a release build of an app, without the debugger attached, these calls serve no purpose. So I've thought of excluding them with pre-processor directives:
#if DEBUG
Console.WriteLine("foo");
#endif
So that the calls don't even exist in the release build. I appreciate this may be micro-optimisation - but I'm curious if Xamairn already does this, making this unnecessary?
Console output is not removed in iOS release builds.
FYI: Xcode does not "automatically" remove NSLog or print from Obj-C/Swift "release" code either. (You typically define a single global preprocessor macro to remove them all, if desired...)
Your options are many... including:
DEBUG preprocessor as you show in your question.
Use System.Diagnostic.Debug.WriteLine:
Any calls to Debug.* will be removed by the compiler due to the [Conditional("DEBUG")] attribute being applied.
Create your own "Logger" class as a wrapper to the stdout writers and [Conditional("DEBUG")] it
Use Fody and re-weave the assemblies to remove/NOP/redirect the WriteLine
I do this to redirect the calls to in internal log and upon crash or user stat requests, forward this log to our crash reporting servers.
etc, .....
Ref: Xamarin's NSLogWriter Helper Class

Xcode - turn off debug

Is it possible to turn off debug mode for a specific .m file ?
Summary.
I am writting a framework which will be used in other projects, code contains #try #catch blocks, which handles some exceptions.
Problem.
If framework user turns on Xcode's "All exceptions" breakpoints, then LLDB periodically stops program (when exception is raised) in #try block.
What I want.
I want to mark my framework files "non sensitive" for lldb (ignore exception breakpoints).
Solutions that I have already tried.
I tryed python script which checks eax/r0 and ignores exception, also a variant with breakpoint condition, but all this solutions are not nice for thousand of newbie third party developers.
Is it possible to have some nice solution?
Thanks.
This previous answer demonstrates how you can create a conditional exception breakpoint for your project. It may be a lot of work to specifically exclude each one of your framework's classes.

Xcode doesn't hit breakpoint when debugging on device

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?

Access Violation unless I clean before recompile

I am receiving an access violation after I recompile a certain unit (MyClass) unless I do a clean. The error is clearly a call to a null object (Write of address 00000000), but when I try to step to it, the compiler won't allow me to step into the code where I think the error is occurring. (Inside a method on the same object. When i trace into the method, there error after hitting trace into but before going to the line of code.) This happens in a used unit of MyClass, rather than MyClass itself.
The weird thing is that if I do a clean (or build) and then recompile, the program runs fine. Any reason this would happen?
Update
The application uses several threads created via the AsyncCalls library. I use several TEvent and TMultiReadExclusiveWriteSynchronizer objects to keep processes ordered and resources protected. Does any special care need to be taken when creating or freeing such objects?
Please check the Output-Path in Project-Settings.
Set an Output-Path (e.g. ".\$(Config)\_dcu") for compiled Units and then check again.

Resources