NSURLConnection & Using HEAD Method

| | Comments (0) | TrackBacks (0)

If you want to use the HEAD method with NSURLConnection, it’s simple, you use -[NSMutableURLRequest setHTTPMethod:].

However, you need to be careful with redirects. Redirections will revert to using the GET method which usually isn’t what you want, so you need something like:

- (NSURLRequest *)connection:(NSURLConnection *)connection
             willSendRequest:(NSURLRequest *)request
            redirectResponse:(NSURLResponse *)redirectResponse
{
    if ([[request HTTPMethod] isEqualTo:@"HEAD"])
        return request;

    NSMutableURLRequest *newRequest = [request mutableCopy];
    [newRequest setHTTPMethod:@"HEAD"];

    return [newRequest autorelease];
}

I suspect that this bug report is invalid: http://openradar.appspot.com/7019347.

x86_64 Assembler

| | Comments (0) | TrackBacks (0)

I’m OK at deciphering PowerPC assembler and i386 assembler but now it’s all x86_64. If you’re having a look at the internals of AppKit in x86_64, you need to print out page 21 of this: http://www.x86-64.org/documentation/abi.pdf and stick it on your wall next to your C operator precedence table.

Now wherever you see objc_msgSend (or something similar), the selector gets passed in $rsi. To find out what it is, type:

p (char *)sel_getName($rsi)

x86_64 comes with instruction pointer relative addressing so you might notice that gdb helpfully displays what the target address is wherever it’s used. So if you’re looking at some assembler that looks like this:

0x00007fff811f33fc <-[NSTableView reloadData]+115>: mov -0x10f16b8b(%rip),%rsi # 0x7fff702dc878
0x00007fff811f3403 <-[NSTableView reloadData]+122>: mov %rbx,%rdi
0x00007fff811f3406 <-[NSTableView reloadData]+125>: callq 0x7fff8184278e <dyld_stub_objc_msgSend>

You can figure out what the call is by typing:

p (char *)sel_getName(*(void **)0x7fff702dc878)

And you’ll see something like:

$2 = 0x7fff8187bb68 "_endMyEditing"

Attempt to Pop an Unknown Autorelease Pool

| | Comments (0) | TrackBacks (0)

If you see:

*** attempt to pop an unknown autorelease pool (0x12345678)

You can debug it by setting a breakpoint in the _CFAutoreleasePoolPop function. To find out exactly where, disassemble the _CFAutoreleasePoolPop function, and look for the first call to CFLog. On the i386 architecture it’s at _CFAutoreleasePoolPop+84.

_Block_dump

| | Comments (0) | TrackBacks (0)

If you’re playing with blocks you can get debug information by using:

char *_Block_dump (block_t block);

It’s not in any public header so you’ll have to declare it yourself. It returns a debug string you can log and will give you the retain count of the block, whether it’s a global, stack or heap block and other information.

Hacking

| | Comments (0) | TrackBacks (0)

In my last entry I mentioned the private API _LSSetStrongBindingForRef that Launch Services has to set the application that launches a particular file. I thought it might be interesting to post how I figured it out.

Firstly, I reasoned that Launch Services would probably have a private API that Finder uses to set it. I could have gone through all the symbols that Launch Services exports, including the private ones looking for likely candidates. To do that, you use the nm tool:

nm /System/Library/Frameworks/CoreServices.framework/ \
Versions/A/Frameworks/LaunchServices.framework/LaunchServices

That will spew out a load of information. Any symbols that are tagged U, are undefined which mean they're come from somewhere else--another framework or library. We're interested in symbols that are tagged T since they're symbols that are exported by that framework. Symbols that have a lower case t, are local to the module and aren't exported. Binaries that are stripped shouldn't have any symbols with a lower case codes. Remember that all C symbols will have an underscore at the beginning that you won't see in your code. C++ symbols are a different story that I won't go into here.

OK, so that's one way I could have figured it, but I got bored looking through them all, so...

Since I knew that Finder was able to set the binding, I figured I could just see what Finder does, but how to do that? What I did was attach the debugger (gdb) to Finder and set some breakpoints. To attach the debugger to Finder:

gdb /System/Library/CoreServices/Finder.app/Contents/MacOS/Finder
attach Finder<TAB>

Apple's version of gdb supports tab completion for the attach command so when you press the tab command you should find it fills in the process id of Finder.

Now what to set the breakpoints on? Well, I first tried setting the breakpoint on write--obviously setting the binding is going to involve writing to the disk at some point (I already knew that the binding was set as part of the usro resource in the resource fork) so my idea was that I'd set a breakpoint on write and then set a binding in Finder and see what we got. There aren't actually that many primitives for writing to the disk; all the Cocoa and Carbon frameworks eventually call BSD primitives to do what they want so you usually just need to set breakpoints on write/pwrite. For example, you'll probably find -[NSData writeToFile:atomically:] calls a CoreFoundation function which then calls one of the BSD write functions.

To set a breakpoint:

b write

Now on my system it sets breakpoints in two places, on write and write$NOCANCEL. That's fine so I just continued. Type c to continue.

OK, those of you playing along at home will find that whilst it might stop in a few places whilst you're trying to set the binding (e.g. when an open panel appears), it doesn't stop after you've actually set the binding. By the way, to continue after hitting a breakpoint, type c.

So then I set a breakpoint on pwrite, and this time, just after setting the binding, the debugger stops. What now? Well, we want a backtrace. To get that, type bt and this is what we get:

#0 0x00007fff82b8b03c in pwrite ()
#1 0x00007fff821b6b1a in BasicWrite ()
#2 0x00007fff821b6a49 in PBWriteForkSync ()
#3 0x00007fff821b69d6 in FSWriteFork ()
#4 0x00007fff822281c0 in WriteData ()
#5 0x00007fff822282d3 in WrResource ()
#6 0x00007fff821ca33a in UpdateTheFile ()
#7 0x00007fff821ca035 in UpdateResFileCommon ()
#8 0x00007fff8213a028 in _LSSetStrongBindingForRef ()

It goes on but I stopped at _LSSetStrongBindingForRef. As you can see, there are a bunch of Carbon functions before we get to the pwrite call.

To get the prototype for the function I searched Google and found someone had already done it for me. ;-)

I should note that you'll probably want to detach from Finder: type detach, and then Finder will continue running. If you don't, you'll probably end up killing Finder which isn't actually such a big deal as it'll just be restarted for you.

Anyway, every programmer should get seriously familiar with gdb. In this case, I've used it to discover a private API which I personally wouldn't use and don't recommend others using either, but I have used similar techniques before to debug problems I've had with some of Apple's frameworks, not to mention my own code. I've mentioned the nm command which is useful, but there's also otool which will dump things like what libraries a binary is linked to; there's the awesome class-dump tool; there's fs_usage for monitoring what accesses the disk and lsof for tracking down open files, and then there's dtrace and probably many more that I've forgotten.

There’s some press about suggesting that Creator Codes are replaced by Uniform Type Identifiers (UTI) which is rubbish.

They’re not.

Uniform Type Identifiers are just a type. To be able to work out the type of something you have to look at some metadata which for the vast majority of things isn’t a UTI. For most files on your Mac, it will be the extension of the file that determines what type of file it is. About the only place that you’ll see a UTI is within the property list of an application where it says what types it supports.

As far as I know, there is no direct replacement for creator codes. There is no other metadata that you can put on the file that tells the system what application created it, and even if there was, UTIs would have little to do with it since UTIs represent types, not applications.

There is metadata on a file that is used to say what application should open the file (on a per file basis). This is stored within the resource fork of the file in a usro resource. This simply stores the path of the application (no UTI is involved) that should open a file and yes, this could be used to replace creator codes—I don’t know if there’s an API for setting them, I haven’t checked. Launch Services has a private API that you could use to set the binding:

extern OSStatus _LSSetStrongBindingForRef(const FSRef *inItemRef,
                                          FSRef *inAppRefOrNil);

I don’t know why Apple have got rid of creator codes but it is a shame they haven’t replaced them with something. Perhaps they haven’t had time to figure out what to replace them with. Thinking about it, what you probably want is to store the bundle ID of the application that created the file in some metadata somewhere (as an extended attribute or within the resource fork). I haven’t thought it through, but there might also be security issues with creator codes—malicious programs could set them behind your back and cause bad stuff to happen.

AppleGlot on Snow Leopard

| | Comments (0) | TrackBacks (0)

To get AppleGlot to work properly on Snow Leopard, apply this patch to /Developer/Applications/AppleGlot/AppleGlot.app/Contents/Frameworks /AppleGlot.framework/Resources/ibtoolWrapper.

(It’s broken because ibtool runs as a 64-bit app. and can’t load AppleGlot’s plugin which is 32-bit).

Here’s how to get hexdump to give you a suitable output for embedding in a C file:

hexdump -e "8/1 \"0x%02x, \" \"\n\"" <file>

(This post is for my benefit as much as anyone else.)

Kernel Log Buffer Size

| | Comments (0) | TrackBacks (0)

I’ve been working on some kernel code recently. The default log buffer size is only 4 KB so it doesn’t take much before you lose messages (not that I recommend you use logging for debugging purposes, but there are some times when it’s necessary). Anyway to increase it, you need to set the msgbuf boot argument. For example, in Terminal type this:

sudo nvram boot-args=msgbuf=65536

C++ Operator Overloading

| | Comments (0) | TrackBacks (0)

I came across this code recently:

level = kIOStorageAccessNone;
while ( ( object = objects->getNextObject( ) ) )
{
    if ( object != client )
    {
        level += _openClients->getObject( ( OSSymbol * ) object );
    }
}

Basically, it’s going through a list of clients that it services and works out what the aggregate access level is for all the clients. Here are the possible access levels:

enum
{
    kIOStorageAccessNone          = 0x00,
    kIOStorageAccessReader        = 0x01,
    kIOStorageAccessReaderWriter  = 0x03,
    kIOStorageAccessSharedLock    = 0x04,
    kIOStorageAccessExclusiveLock = 0x08
};

Now, from looking at this code, it looks wrong because of the use of the +=. Surely |= is more appropriate. It’s obvious to me now, but it took me some time before I found the bit where they’d overridden the += operator:

inline void operator+=( IOStorageAccess access )
{
    _access = ( ( _access - 1 ) >> 1 ) & 7;
    _access = gIOMediaAccessTable[ ( ( access - 1 ) >> 1 ) & 7 ][ _access ];
    _access = ( ( _access & 7 ) << 1 ) + 1;
}

Anyway, this, in my opinion, is a classic example of an abuse of C++ operator overloading. The rule when writing code should be to make it as readable and as obvious as possible first before you start trying to be clever. If the code had been something like this:

    clientLevel = _openClients->getObject( ( OSSymbol * ) object )->unsigned32BitValue( );
    level = aggregateLevel( level, clientLevel );

it wouldn’t have cost me any time as it would have been clear what was going on.

It’s for similar reasons that I always put brackets round expressions that combine && and || clauses: not everybody knows the order of precedence of these two and it’s easy to forget; adding brackets means you don’t need to remember.

For example, I would always do:

    if ((a && b) || (c && d))

rather than

    if (a && b || c && d)

I know it’s tempting to use that clever bit of the language that you just learnt about but in doing so you might make it harder for the person that follows you. The general rule should be: unless it is a common idiom, make it clear what’s going on and if a better known alternative exists, use that instead.