Identifying the type of build (Build, Archive) at compile time in Xcode

Posted: June 23rd, 2016 | Author: | Filed under: iOS, macOS, Programming, Xcode | Tags: , , , , , | No Comments »

Let’s say you want to have a different behavior in your app depending on whether you build it in Xcode or you perform an Archive. And you want this behavior to be done at compile time. Note that the use of different configurations is not what is wanted.

Here is a solution using the ‘ACTION’ Xcode property build setting. This property is documented in the Xcode Build Setting Reference:


ACTION

The ‘ACTION’ environment variable has 2 interesting values:

  • build: when the app is built
  • install: when the app is archived

Here is what you can do to identify the type of build (Build, Archive) at compile time in Xcode:

  • In the ‘Preprocessor Macros’ (GCC_PREPROCESSOR_DEFINITIONS) in the Builds Settings of your project, add:
     XCODE_ACTION_${ACTION}=1
    
  • In your precompiled prefix header for example, you can now create a define IS_ARCHIVE_BUILD:
    #if XCODE_ACTION_install
    	#define IS_ARCHIVE_BUILD	1
    #else
    	#define IS_ARCHIVE_BUILD	0
    #endif
    

You can then use the define IS_ARCHIVE_BUILD to have a different behavior at compile time. This solution works fine with Xcode 7.3.1 as well as Xcode 8.0b1. It hasn’t been tested with other Xcode versions.


Detecting if an app runs in a 32-bit or 64-bit iOS Simulator

Posted: October 1st, 2013 | Author: | Filed under: iOS, Programming | Tags: , , , , | No Comments »

With Xcode 5, it is now possible to compile an application for armv7 and/or arm64.
You can compile an application as 32-bit and/or as 64-bit and you can run this application in a 32-bit or 64-bit iOS Simulator:

In fact there are 3 different cases:

  • 32-bit application running in a 32-bit iOS Simulator
  • 32-bit application running in a 64-bit iOS Simulator
  • 64-bit application running in a 64-bit iOS Simulator

It is possible to distinguish these 3 different cases but this is not as easy as I would expected.

The case of a 64-bit application running in a 64-bit iOS Simulator is simple to solve by just using the define __LP64__: A 64-bit application can only run in a 64-bit iOS Simulator.

Distinguishing the 2 other cases is more difficult and a runtime check is needed. Something to note is that the ‘iOS Simulator’ process is running as 64-bit even in the case of a 32-bit iOS Simulator.

I noticed however that a process called ‘SimulatorBridge’ is used:

  • When launching an 64-bit iOS Simulator, the process ‘SimulatorBridge’ runs as 64-bit
  • When launching an 32-bit iOS Simulator, the process ‘SimulatorBridge’ runs as 32-bit

Running a 32-bit iOS Simulator

Below is a function to know if the iOS Simulator is a 32-bit Simulator or a 64-bit Simulator. The function “is64bitSimulator()” returns true if the iOS Simulator is a 64-bit iOS Simulator:

#include <sys/sysctl.h>

#if TARGET_IPHONE_SIMULATOR

bool is64bitSimulator()
{
	bool is64bitSimulator = false;
	
	/* Setting up the mib (Management Information Base) which is an array of integers where each
	 * integer specifies how the data will be gathered.  Here we are setting the MIB
	 * block to lookup the information on all the BSD processes on the system.  Also note that
	 * every regular application has a recognized BSD process accociated with it.  We pass
	 * CTL_KERN, KERN_PROC, KERN_PROC_ALL to sysctl as the MIB to get back a BSD structure with
	 * all BSD process information for all processes in it (including BSD process names)
	 */
	int mib[6] = {0,0,0,0,0,0};
	mib[0] = CTL_KERN;
    mib[1] = KERN_PROC;
    mib[2] = KERN_PROC_ALL;
	
	long numberOfRunningProcesses = 0;
	struct kinfo_proc* BSDProcessInformationStructure = NULL;
	size_t sizeOfBufferRequired = 0;
	
	/* Here we have a loop set up where we keep calling sysctl until we finally get an unrecoverable error
	 * (and we return) or we finally get a succesful result.  Note with how dynamic the process list can
	 * be you can expect to have a failure here and there since the process list can change between
	 * getting the size of buffer required and the actually filling that buffer.
	 */
	BOOL successfullyGotProcessInformation = NO;
	int error = 0;
	
	while (successfullyGotProcessInformation == NO)
	{
		/* Now that we have the MIB for looking up process information we will pass it to sysctl to get the 
		 * information we want on BSD processes.  However, before we do this we must know the size of the buffer to 
		 * allocate to accomidate the return value.  We can get the size of the data to allocate also using the 
		 * sysctl command.  In this case we call sysctl with the proper arguments but specify no return buffer 
		 * specified (null buffer).  This is a special case which causes sysctl to return the size of buffer required.
		 *
		 * First Argument: The MIB which is really just an array of integers.  Each integer is a constant
		 *     representing what information to gather from the system.  Check out the man page to know what
		 *     constants sysctl will work with.  Here of course we pass our MIB block which was passed to us.
		 * Second Argument: The number of constants in the MIB (array of integers).  In this case there are three.
		 * Third Argument: The output buffer where the return value from sysctl will be stored.  In this case
		 *     we don't want anything return yet since we don't yet know the size of buffer needed.  Thus we will
		 *     pass null for the buffer to begin with.
		 * Forth Argument: The size of the output buffer required.  Since the buffer itself is null we can just
		 *     get the buffer size needed back from this call.
		 * Fifth Argument: The new value we want the system data to have.  Here we don't want to set any system
		 *     information we only want to gather it.  Thus, we pass null as the buffer so sysctl knows that 
		 *     we have no desire to set the value.
		 * Sixth Argument: The length of the buffer containing new information (argument five).  In this case
		 *     argument five was null since we didn't want to set the system value.  Thus, the size of the buffer
		 *     is zero or NULL.
		 * Return Value: a return value indicating success or failure.  Actually, sysctl will either return
		 *     zero on no error and -1 on error.  The errno UNIX variable will be set on error.
		 */ 
		error = sysctl(mib, 3, NULL, &sizeOfBufferRequired, NULL, 0);
		if (error) 
			return NULL;
		
		/* Now we successful obtained the size of the buffer required for the sysctl call.  This is stored in the 
		 * SizeOfBufferRequired variable.  We will malloc a buffer of that size to hold the sysctl result.
		 */
		BSDProcessInformationStructure = (struct kinfo_proc*) malloc(sizeOfBufferRequired);
		if (BSDProcessInformationStructure == NULL)
			return NULL;
		
		/* Now we have the buffer of the correct size to hold the result we can now call sysctl
		 * and get the process information.  
		 *
		 * First Argument: The MIB for gathering information on running BSD processes.  The MIB is really 
		 *     just an array of integers.  Each integer is a constant representing what information to 
		 *     gather from the system.  Check out the man page to know what constants sysctl will work with.  
		 * Second Argument: The number of constants in the MIB (array of integers).  In this case there are three.
		 * Third Argument: The output buffer where the return value from sysctl will be stored.  This is the buffer
		 *     which we allocated specifically for this purpose.  
		 * Forth Argument: The size of the output buffer (argument three).  In this case its the size of the 
		 *     buffer we already allocated.  
		 * Fifth Argument: The buffer containing the value to set the system value to.  In this case we don't
		 *     want to set any system information we only want to gather it.  Thus, we pass null as the buffer
		 *     so sysctl knows that we have no desire to set the value.
		 * Sixth Argument: The length of the buffer containing new information (argument five).  In this case
		 *     argument five was null since we didn't want to set the system value.  Thus, the size of the buffer
		 *     is zero or NULL.
		 * Return Value: a return value indicating success or failure.  Actually, sysctl will either return 
		 *     zero on no error and -1 on error.  The errno UNIX variable will be set on error.
		 */
		error = sysctl(mib, 3, BSDProcessInformationStructure, &sizeOfBufferRequired, NULL, 0);
		if (error == 0)
        {
			//Here we successfully got the process information.  Thus set the variable to end this sysctl calling loop
            successfullyGotProcessInformation = YES;
        }
        else 
        {
			/* failed getting process information we will try again next time around the loop.  Note this is caused
			 * by the fact the process list changed between getting the size of the buffer and actually filling
			 * the buffer (something which will happen from time to time since the process list is dynamic).
			 * Anyways, the attempted sysctl call failed.  We will now begin again by freeing up the allocated 
			 * buffer and starting again at the beginning of the loop.
			 */
            free(BSDProcessInformationStructure); 
        }
	} //end while loop
	
	
	/* Now that we have the BSD structure describing the running processes we will parse it for the desired
     * process name.  First we will the number of running processes.  We can determine
     * the number of processes running because there is a kinfo_proc structure for each process.
     */
	numberOfRunningProcesses = sizeOfBufferRequired / sizeof(struct kinfo_proc);
	for (int i = 0; i < numberOfRunningProcesses; i++)
    {
		//Getting name of process we are examining
        const char *name = BSDProcessInformationStructure[i].kp_proc.p_comm;
		
		if(strcmp(name, "SimulatorBridge") == 0)
		{
			int p_flag = BSDProcessInformationStructure[i].kp_proc.p_flag;
			is64bitSimulator = (p_flag & P_LP64) == P_LP64;
			break;
		}
    }
	
	free(BSDProcessInformationStructure);
	return is64bitSimulator;
}

#endif // TARGET_IPHONE_SIMULATOR


Using AddressSanitizer with Xcode 4.6.1

Posted: April 10th, 2013 | Author: | Filed under: Debugging, macOS, Programming | Tags: , , , , , | 3 Comments »

Clang 3.3 now supports AddressSanitizer. Here is the description from the Clang 3.3 documentation:

AddressSanitizer is a fast memory error detector. It consists of a compiler instrumentation module and a run-time library. The tool can detect the following types of bugs:

  • Out-of-bounds accesses to heap, stack and globals
  • Use-after-free
  • Use-after-return (to some extent)
  • Double-free, invalid free

Typical slowdown introduced by AddressSanitizer is 2x.

Using AddressSanitizer by manually compiling a file is well documented. On the other hand using Xcode 4.6.1 to build a complex project with AddressSanitizer enabled is not so easy. Following are the steps to build an Xcode project with AddressSanitizer.

Note that I used Xcode 4.6.1 when writing this article. Xcode 4.6.1 contains a Clang build based on LLVM 3.2. Most likely a future Xcode build will contain a Clang build based on LLVM 3.3 which would simplify the use of AddressSanitizer in Xcode.

1- Building Clang 3.3

Since Xcode 4.6.1 contains an old build of Clang, we need to get and build Clang trunk. This is fairly easy. Here is what I did:

– svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm
– cd llvm/tools
– svn co http://llvm.org/svn/llvm-project/cfe/trunk clang
– cd ../..
– cd llvm/projects
– svn co http://llvm.org/svn/llvm-project/compiler-rt/trunk compiler-rt
– cd ../..
– mkdir build
– cd build
– ../llvm/configure –enable-optimizations
– make -j `sysctl -n hw.logicalcpu`

2- Tell Xcode 4.6.1 to use Clang 3.3 we just compiled

The simplest solution I found is to add the following user define in the Xcode target:
CC = “PATH_TO/llvm/build/Debug+Asserts/bin/clang”;
You need to set PATH_TO to the folder where you compiled llvm.

3- Make sure the deployment target is set to 10.7 or higher.

I used the deployment target set to 10.7.

4- Add the C flag and linker flag -fsanitize=address

Add the C flag -fsanitize=address
Add the linker flag -fsanitize=address

5- Compile your project

Congratulations! You now have a build of your project with AddressSanitizer enabled.

6- Running the application

Xcode 4.6.1 fails to run this executable but you can run it from the Terminal and AddressSanitizer will detect possible memory errors.
If your application has a memory error, you will see an error message like:


Memory Error with AddressSanitizer

7- Symbolize the symbols

Currently AddressSanitizer does not symbolize its output.
You will need to manually symbolize the addresses. This can easily be done with atos (see man atos) and the dSYM file produced during the compilation (you might need to turn on “DWARF with dSYM File” in the Xcode target).

For example to symbolize the symbol 0x100001d86 in the AddressSanitizer message:

Alex:MyApplication alex$ atos -o build/Debug/MyApplication.app.dSYM/Contents/Resources/DWARF/MyApplication 0x100001d86
-[AppDelegate applicationDidFinishLaunching:] (in MyApplication) (AppDelegate.mm:23)

Useful references

Clang 3.3 documentation for AddressSanitizer: http://clang.llvm.org/docs/AddressSanitizer.html

AddressSanitizer HomePage: http://code.google.com/p/address-sanitizer/


Programmatically break into GDB

Posted: August 24th, 2008 | Author: | Filed under: Debugging | Tags: , , , | 4 Comments »

You may want to stop into the debugger if something bad happened while executing your program. The easier way to do that is to have a breakpoint always set and to run your program in the debugger.

But sometimes you want to break even if there are no breakpoint. For example you know that something is wrong now and your program will crash later.

The following BreakIntoGDB() function checks if the application runs with GDB attached. If you are running your application with the debugger attached, BreakIntoGDB calls the Debugger() function. If you are running without GDB attached, BreakIntoGDB opens a Terminal window and attaches your application to the debugger using an Applescript. In both cases, your program stops into GDB and your can examine what’s wrong.

//
//  DebuggingUtilities.h
//  BreakingIntoGDB
//
//  Created by Alexandre Colucci on 23/08/08.
//

#import <Foundation/Foundation.h>
#import <ApplicationServices/ApplicationServices.h>

#include <assert.h>
#include <stdbool.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/sysctl.h>
#include <sys/proc.h>

// From Technical Q&A QA1361
// Returns true if the current process
// is being debugged (either running
// under the debugger or has a debugger
// attached post facto).
static bool AmIBeingDebugged(void)
{
    int                 junk;
    int                 mib[4];
    struct kinfo_proc   info;
    size_t              size;
	
    // Initialize the flags so that,
    // if sysctl fails for some bizarre
    // reason, we get a predictable result.
	
    info.kp_proc.p_flag = 0;
	
    // Initialize mib, which tells sysctl the info
    // we want, in this case we're looking for
    // information about a specific process ID.
	
    mib[0] = CTL_KERN;
    mib[1] = KERN_PROC;
    mib[2] = KERN_PROC_PID;
    mib[3] = getpid();
	
    // Call sysctl.
	
    size = sizeof(info);
    junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);

    assert(junk == 0);
	
    // We're being debugged if the P_TRACED
    // flag is set.
	
    return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
}

static void BreakIntoGDB()
{
	if(AmIBeingDebugged())
	{
		// GDB is already attached to the application.
		// We simply break using the Debugger function.
		Debugger();
	}
	else
	{
		// GDB is not running. We open a
		// Terminal window and attach the
		// current application.
			
		ProcessSerialNumber psn = {0,kCurrentProcess};
		pid_t thePID;
		OSStatus err = GetProcessPID(&psn, &thePID);
		if(err == noErr)
		{
			NSString *scriptSource =
 [NSString stringWithFormat:@"tell application \"Terminal\" ndo script \"gdb attach \" & %d nend tell", thePID];

			NSAppleScript *appleScript = [[NSAppleScript alloc] initWithSource:scriptSource];
			if(appleScript != nil)
			{
				NSDictionary *errorDict;
				
				// Don't check the returned value
				[appleScript executeAndReturnError:&errorDict];
			}

			sleep(2);
		}
	}
}

To break into the debugger, you just have to call the BreakIntoGDB() function like in the following example.

-(IBAction)breakNow:(id)sender
{
	BreakIntoGDB();
}

Several other notes:


libMallocDebug

Posted: July 19th, 2008 | Author: | Filed under: Debugging | Tags: , , , | No Comments »

Here is a little description on how to use libMallocDebug for developers and QA people. It seems not many people know about it.
libMallocDebug is really useful in the case you have a crash sometimes when doing something but it is hard to reproduce.

What is libMallocDebug?

libMallocDebug is a debugging malloc library that can track down memory related bugs and can be turned on and off at runtime. If you use this library, it will replace the malloc functions with a debug version of these functions. It contains several interesting options but only 3 are really useful.

MallocGuardEdges: This option adds guard pages to detect buffer overflows. Buffer overflows are not easy to find because it might crash randomly depending on what you write and where.

MallocScribble: This option detects writes to a freed block by setting its contents to 0x55 when deallocated. This can detect bugs like double frees, or using freed memory. Dereferencing a pointer in cleared freed memory will cause the program to reference the memory at 0x55555555, which usually is unallocated and will cause an immediate crash if the pointer is dereferenced for reading or writing.

MallocPreScribble: This option detects reads of uninitialized memory (also known as uninitialized variables) by setting its contents to 0xAA when allocated. Reading an uninitialized pointer from that memory will cause the program to reference the memory at 0xAAAAAAAA, which is usually unallocated and will cause an immediate crash if the pointer is dereferenced for reading or writing.
Using libMallocDebug (without sources) for beta testers:

You can run any application with the libMallocDebug library. To do that, open a terminal window (bash) and type:

export DYLD_INSERT_LIBRARIES=/usr/lib/libMallocDebug.A.dylib
export MallocGuardEdges=YES
export MallocScribble=YES
export MallocPreScribble=YES
/Applications/MyAppDBG.app/Contents/MacOS/MyAppDBG

This will run MyApp using libMallocDebug. You will see in the Terminal window some printf made by libMallocDebug. To see if libMallocDebug is used, the first line should be:
“libMallocDebug[MyAppDBG-10714]: initializing libMallocDebug on thread 10b”. Here is an example:

Alex:~ leopard$ export DYLD_INSERT_LIBRARIES=/usr/lib/libMallocDebug.A.dylib
Alex:~ leopard$ export MallocGuardEdges=YES
Alex:~ leopard$ export MallocScribble=YES
Alex:~ leopard$ export MallocPreScribble=YES
Alex:~ leopard$ /Applications/MyAppDBG.app/Contents/MacOS/MyAppDBG 
libMallocDebug[MyAppDBG-4388]: initializing libMallocDebug on thread 10b
task_set_exception_ports (os/kern) invalid argument
libMallocDebug[MyAppDBG-4388]: target application recently wrote to freed malloc’d memory at: 0x32b03c0, suggesting it didn’t realize the memory had been freed

Using libMallocDebug (with sources) for developers:

Select the Executable in the Project and add the 4 environment variables as shown on the following picture:

Setting environment variables in Xcode.

This will help to reproduce crashes. You can also use gdb and libMallocDebug at the same time.

Limitations and issues:

  • This tool helps to find memory bugs but it might not find all of them. 
  • It checks memory at runtime and thus only detects bugs in the features you try.
  • This library affects performances. So don’t use it while doing performance comparisons.
  • For developers: don’t forget to uncheck the environment variables in the Executable once you are done.
  • For developers: You can use gdb and libmallocDebug at the same time to reproduce and debug issues. But there is a bug on Leopard with Intel machines (rdar://5611207). You can’t use gdb in Xcode and libMallocDebug at the same time. There are several workarounds: Boot on Tiger with your intel machine, use a PowerPC machine with Leopard, or use gdb from the command line on Leopard with an intel machine.

[Update]: Thomas Clement pointed out several things.

  • MallocGuardEdges, MallocScribble and MallocPreScribble are available in the default memory allocator as mentioned in Mac OS X Debugging Magic Tech Note. That means you can use them without having to use LibMallocDebug. Of course when you use LibMallocDebug I recommend you to always enable these environment variables to detect more possible issues.
  • The application MallocDebug (available in the CHUD tools) uses LibMallocDebug. If you don’t like to set environment variables, you can use that application which is really nice.
  • There is another allocation debugging library called libgmalloc which seems to be more aggressive than LibMallocDebug. This library can be enabled through Xcode with the menu item “Enable Guard Malloc” in the menu “Run”. You can get more information about this library in the man page (man libgmalloc).