tag:blogger.com,1999:blog-80939091395803258692024-03-08T05:12:13.923-08:00Yet Another Mac Dev Blogasr -source /childlike/wonder -target /world -noverify -nopromptBlake C.http://www.blogger.com/profile/08296013471634395562noreply@blogger.comBlogger44125tag:blogger.com,1999:blog-8093909139580325869.post-39149606798010233132008-10-14T21:11:00.000-07:002009-06-04T22:58:23.483-07:00ValgrindMany of us have wanted <a href="http://valgrind.org/">Valgrind</a> on OS X for a long time, and now <a href="http://www.sealiesoftware.com/valgrind/index.html">we finally have it</a>, thanks to Greg Parker. Valgrind provides some impressive <a href="http://en.wikipedia.org/wiki/Dynamic_program_analysis">dynamic analysis</a> that complements the <a href="http://en.wikipedia.org/wiki/Static_code_analysis">static analysis</a> we can get from <a href="http://clang.llvm.org/StaticAnalysis.html">clang's checker</a>. This <a href="http://dot.kde.org/2006/02/20/interview-valgrind-author-julian-seward">interview with the original author</a> has a good description of what it does and how it works.<br /><br />I've used Valgrind a bit, and it has earned its place in my toolbox. Here are some things I've learned.<br /><br />While the LLVM checker analyzes your source files and tries to check every possible code path, Valgrind analyzes your <i>built executable</i> and only checks the code path that you specify. LLVM's checker uses lexical analysis and hypothetical variable values to point out problems. Valgrind, on the other hand, translates your executable's machine code into an instrumented bytecode representation, and runs that code in a virtual machine. There are no hypothetical values, so the accuracy of the results is much higher, but the coverage is drastically reduced.<br /><br />Valgrind instruments ALL of the code that your executable executes, including libraries/frameworks/bundles that were linked against or dynamically loaded. This is possible because Valgrind's input is the machine code that you execute, not the source code that you compile. This provides tremendous opportunities for us to help improve the quality of the binaries we use, but do not own.<br /><br />With the previous two paragraphs in mind, it is important to note that the actual code path taken by an executable can differ from launch to launch, even when launched repeatedly with the same arguments. Maybe a system cache gets updated, or one of your linked frameworks decides to contact an update server, etc. When your code exercises different paths, different code paths get checked.<br /><br />Valgrind has a firm grip on your RAM. If you overflow or underflow a buffer on the heap, you'll hear about it. If you read from or write to freed memory, you'll hear about it. If you allocate with new and deallocate with delete[], you'll hear about it.<br /><br />Valgrind can catch some errors that clang's checker cannot, and vice versa. And there are other errors that both tools will catch. By using these two tools on all of our projects, we can improve our code as well as other people's code that we use at runtime.<br /><br />Hat's off to the devs who've worked on Valgrind and LLVM's checker. I wish we had these tools a long time ago.<br /><br />Update: <a href="http://blog.mozilla.com/nnethercote/2009/05/28/mac-os-x-now-supported-on-the-valgrind-trunk/">Branch merged to trunk</a>. Thanks to Dan for the heads-up in comments.Blake C.http://www.blogger.com/profile/08296013471634395562noreply@blogger.com8tag:blogger.com,1999:blog-8093909139580325869.post-18535320154830183702008-09-08T21:47:00.000-07:002008-09-08T22:06:06.208-07:00Fun With DigraphsChrist, I can't believe this compiles-<br /><pre class=".source_code">%:include <stdio.h><br />%:include <Cocoa/Cocoa.h><br /><br />int main()<br /><%<br /> NSString *message = @"Hello, world";<br /><br /> printf("%s\n", <:message UTF8String:>);<br /><br /> return 0;<br />%></pre><br />It's section 6.4.6 in <a href="http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf">the C spec</a>. Good stuff for playing jokes on coworkers, but please don't ship code like this.Blake C.http://www.blogger.com/profile/08296013471634395562noreply@blogger.com2tag:blogger.com,1999:blog-8093909139580325869.post-67029601440675689562008-08-26T21:23:00.000-07:002008-08-26T21:24:48.561-07:00Tapuless<a href="http://www.techcrunch.com/2008/08/26/tapulous-cofounder-mike-lee-ejected-from-company/">Jobs come and go</a>, as do the companies that provide them.<br /><br />Friends stick around, and solid engineering outlives the engineer.<br /><br />I'll give you one guess who I'm betting on.Blake C.http://www.blogger.com/profile/08296013471634395562noreply@blogger.com0tag:blogger.com,1999:blog-8093909139580325869.post-60300732116726024222008-06-15T11:05:00.000-07:002008-06-15T11:14:40.830-07:00For the RecordBrent Simmons DID NOT get arrested- he paid for that case of Bud.<br /><br />The World's Toughest Programmer and I DID steal a few Buds from Brent. We also WERE NOT arrested.<br /><br />There did seem to be MORE red lemur shirts than Apple Engineer shirts.<br /><br />Kevin Ballard DID shave his beard on a dare.<br /><br />I DID lose every game of pool I played last week.<br /><br />She was not a "14-year-old" friend- she was an old friend I hadn't seen since we were 14.<br /><br />Add your own records in comments if desired.Blake C.http://www.blogger.com/profile/08296013471634395562noreply@blogger.com5tag:blogger.com,1999:blog-8093909139580325869.post-30127310311137627852008-06-09T00:12:00.000-07:002008-06-09T00:13:52.991-07:00Where In SF Is Blake?Find me if you can :)Blake C.http://www.blogger.com/profile/08296013471634395562noreply@blogger.com0tag:blogger.com,1999:blog-8093909139580325869.post-33287099550550636662008-04-01T18:33:00.000-07:002008-04-01T18:37:48.289-07:00Resistance Is FutileI'm pleased to announce that I've accepted a job offer from Microsoft. I can't wait to shuffle off the coil of Objective-C and revel in the awesomeness that is C# and .NET.<br /><br />Also, you Mac developers were getting a little smug for my taste. See ya, suckers!Blake C.http://www.blogger.com/profile/08296013471634395562noreply@blogger.com6tag:blogger.com,1999:blog-8093909139580325869.post-17037980839299355982008-01-24T17:50:00.000-08:002008-01-24T17:53:16.450-08:0024 DaysI was <a href="http://yamacdev.blogspot.com/2007/01/year-of-hig.html">a little bit off</a>, but <a href="http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/XHIGIntro/chapter_1_section_1.html">here it is</a>.Blake C.http://www.blogger.com/profile/08296013471634395562noreply@blogger.com0tag:blogger.com,1999:blog-8093909139580325869.post-72144307890408598552008-01-10T14:30:00.000-08:002008-01-15T15:29:53.772-08:00I Did Not Know ThatXcode's Cocoa project templates have 2 occurrences of "#import <Cocoa/Cocoa.h>"- One in the prefix file and one in main.m. The behavior of #import means that only the first occurrence actually matters, but then why would I need the second one in main.m? It turns out that in a monochrome world, I don't. But if you're like me and you use syntax coloring at all, deleting the unnecessary #import in main.m(and any other source files) will leave you with not-so-pretty coloring of all the Cocoa bits.<br /><br />I'm guilty of deleting the unnecessary #import on general principle, and I'm guessing somebody else out there has done this as well.<br /><br />Update: I'm now unable to reproduce the syntax coloring problem by deleting the unnecessary #import. However, the problem did exist for myself and others, and was fixed by adding the #import back to a source file. I guess the advice here is: If you have coloring issues and the #import is missing, add it back.Blake C.http://www.blogger.com/profile/08296013471634395562noreply@blogger.com2tag:blogger.com,1999:blog-8093909139580325869.post-77340334508466025102007-11-05T18:42:00.000-08:002007-11-09T14:19:04.524-08:00The Leopard Ate My Codeor: How I Learned to Stop Worrying and Love the Leopard<br /><br />Since Tiger appeared, many people have been jumping through some interesting hoops to get the iTunes-style "inset" text appearance in metal windows. Some people draw the text twice, where the first drawing is a lighter color and offset down by one pixel. Others are now apparently resorting to image editing products to get a similar result. I've mentioned <a href="http://www.latenightsw.com/blog/?p=45">elsewhere</a> that drawing the text twice is not necessary, and now it gets even easier with Leopard.<br /><br />Update: Ken points out in a comment that drawing the text twice can have better results than using NSShadow on Tiger. It's still much easier on Leopard.<br /><br />Here's a simple way to do it on Tiger, using attributed strings and NSShadow:<br /><br /><pre class=".source_code">NSTextField* textField = something from IB;<br />NSShadow* textShadow = [[NSShadow alloc] init];<br /><br />[textShadow setShadowColor: [NSColor<br /> colorWithCalibratedRed: 1.0 green: 1.0 blue: 1.0 alpha: 0.5]];<br />[textShadow setShadowOffset: NSMakeSize(0.0, -1.0)];<br />[textShadow setShadowBlurRadius: 0.0];<br /><br />NSMutableAttributedString* newString =<br /> [[NSMutableAttributedString alloc] initWithAttributedString:<br /> [textField attributedStringValue]];<br /><br />[newString addAttribute: NSShadowAttributeName value: textShadow<br /> range: NSMakeRange(0, [newString length])];<br />[textField setAttributedStringValue: newString];<br />[newString release];</pre><br />Not too bad, although the color values, pixel offset, etc. are hardcoded. Now let's see how much code it takes to achieve a similar result in Leopard:<br /><br /><pre class=".source_code">[[textField cell] setBackgroundStyle: NSBackgroundStyleRaised];</pre><br />Nice.Blake C.http://www.blogger.com/profile/08296013471634395562noreply@blogger.com7tag:blogger.com,1999:blog-8093909139580325869.post-29042336997996518432007-09-05T20:55:00.000-07:002007-09-06T15:07:32.417-07:00Speaking of Backtraces<a href="http://bugzilla.gnome.org/show_bug.cgi?id=47237%30">Words escape me.</a>Blake C.http://www.blogger.com/profile/08296013471634395562noreply@blogger.com0tag:blogger.com,1999:blog-8093909139580325869.post-40406146582909926262007-09-04T21:10:00.000-07:002008-01-16T12:25:25.677-08:00The Case of the Missing Stack FramesOur friend <a href="http://boredzo.org/blog/">Peter Hosey</a> recently <a href="http://boredzo.org/blog/archives/2007-08-14/fixing-an-adium-bug-a-timeline">mentioned</a> a problem that frequently makes debugging crash reports harder than usual. The problem is that stack traces don't always display every stack frame in the call chain, which can make it difficult or impossible to determine the flow of control that led to the crash. Let's look at a demonstration of the problem, its causes, and its solutions.<br /><br />Update: I probably should have mentioned this before- optimizations make debugging hard. Debug builds should not use any optimizations at all, unless you enjoy headaches. With no optimizations in place, your debug builds will not suffer from missing stack frames. This post is intended to help developers who have received crash reports from users testing release builds, where optimizations have been made.<br /><br />Note: I'll be using only the x86 assembly in this post. If anyone is interested, let me know and I'll post the ppc equivalents in a followup post.<br /><br />A sample app:<br /><br /><pre class=".source_code">int func2(int x)<br />{<br /> return x - 1;<br />}<br /><br />int func1(int x)<br />{<br /> int result = func2(x);<br /> return result;<br />}<br /><br />int main(int argc, const char** argv)<br />{<br /> return func1(1);<br />}</pre><br /><br />Here's what that looks like when compiled with no optimizations(-O0):<br /><br /><pre class=".source_code">_func2:<br /> +0 00001f7e 55 pushl %ebp<br /> +1 00001f7f 89e5 movl %esp,%ebp<br /> +3 00001f81 83ec08 subl $0x08,%esp<br /> +6 00001f84 8b4508 movl 0x08(%ebp),%eax<br /> +9 00001f87 83e801 subl $0x01,%eax<br /> +12 00001f8a c9 leave<br /> +13 00001f8b c3 ret<br /><br />_func1:<br /> +0 00001f8c 55 pushl %ebp<br /> +1 00001f8d 89e5 movl %esp,%ebp<br /> +3 00001f8f 83ec18 subl $0x18,%esp<br /> +6 00001f92 8b4508 movl 0x08(%ebp),%eax<br /> +9 00001f95 890424 movl %eax,(%esp,1)<br /> +12 00001f98 e8e1ffffff calll _func2<br /> +17 00001f9d c9 leave<br /> +18 00001f9e c3 ret<br /><br />_main:<br /> +0 00001f9f 55 pushl %ebp<br /> +1 00001fa0 89e5 movl %esp,%ebp<br /> +3 00001fa2 83ec18 subl $0x18,%esp<br /> +6 00001fa5 c7042401000000 movl $0x00000001,(%esp,1)<br /> +13 00001fac e8dbffffff calll _func1<br /> +18 00001fb1 c9 leave<br /> +19 00001fb2 c3 ret</pre><br /><br />Standard stuff- main calls func1, func1 calls func2. Each function's prolog pushes the base pointer onto the stack, saves the previous stack pointer as the new base pointer, and updates the stack pointer as needed for that function. And each function's epilog uses the 'leave' instruction to copy the base pointer back to the stack pointer, and pop the the old base pointer back into %ebp before returning control to the calling function. Because these functions perform this standard housekeeping, gdb can provide us with an accurate backtrace if we ask for it:<br /><br /><pre class=".source_code">Breakpoint 1, 0x00001f84 in func2 ()<br />(gdb) bt<br />#0 0x00001f84 in func2 ()<br />#1 0x00001f9d in func1 ()<br />#2 0x00001fb1 in main ()</pre><br /><br />So far, so good. Now let's crank up the optimization level to -O2:<br /><br /><pre class=".source_code">_func2:<br /> +0 00001f8e 55 pushl %ebp<br /> +1 00001f8f 89e5 movl %esp,%ebp<br /> +3 00001f91 8b4508 movl 0x08(%ebp),%eax<br /> +6 00001f94 83e801 subl $0x01,%eax<br /> +9 00001f97 5d popl %ebp<br /> +10 00001f98 c3 ret<br /><br />_func1:<br /> +0 00001f99 55 pushl %ebp<br /> +1 00001f9a 89e5 movl %esp,%ebp<br /> +3 00001f9c 5d popl %ebp<br /> +4 00001f9d e9ecffffff jmpl 0x00001f8e<br /><br />_main:<br /> +0 00001fa2 55 pushl %ebp<br /> +1 00001fa3 89e5 movl %esp,%ebp<br /> +3 00001fa5 c7450801000000 movl $0x00000001,0x08(%ebp)<br /> +10 00001fac 5d popl %ebp<br /> +11 00001fad e9e7ffffff jmpl 0x00001f99</pre><br /><br />Now we have a problem.<br /><br />Each function still has the usual prolog, but the epilogs have changed. There are no 'leave' instructions, and there's only one 'ret' instruction, in func2. gdb is now unable to give us an accurate backtrace:<br /><br /><pre class=".source_code">Breakpoint 1, 0x00001f91 in func2 ()<br />(gdb) bt<br />#0 0x00001f91 in func2 ()<br />#1 0x00001f72 in _start ()<br />#2 0x00001e99 in start ()</pre><br /><br />The stack frames from main and func1 are no longer visible in the backtrace(_start calls main in every application, though gdb may sometimes exclude it from the backtrace).<br /><br />There are two differences that we should note:<br /><br />• The mechanism by which one function transfers control to another function has changed. Under -O2 optimization, 'calll' has been replaced with 'jmpl', which is sometimes referred to as a <a href="http://en.wikipedia.org/wiki/Tail_call">tail call optimization</a>.<br />• Each function now pops the stack into %ebp before transferring control to the called function. <br /><br />These differences have these results:<br /><br />• The return address is not updated across function calls, because 'calll' is not used(%eip is not pushed onto the stack).<br />• %ebp retains its original value across function calls, because the caller pops %ebp(after it pushes %ebp in its prolog) before transferring control to the called function.<br /><br />Because of these changes, gdb is unable to give us an accurate backtrace. The specific flag that causes this code generation is -foptimize-sibling-calls, which is included in -O2 and higher.<br /><br />Depending on our needs, there are two ways to disable this optimization.<br /><br />• The sledgehammer: -fno-optimize-sibling-calls will prevent gcc from generating the problem code across the entire executable.<br />• The scalpel: Inserting an extra line of code in a function will prevent gcc from generating the problem code on a per-function basis:<br /><br /><pre class=".source_code">int func1(int x)<br />{<br /> int result = func2(x);<br /> __asm__ volatile("");<br /> return result;<br />}</pre><br /><br />The asm directive tells gcc to insert whatever text we specify into the intermediate assembly file before it gets passed to the assembler. Luckily, gcc does not parse our string(s), so it has no idea what logic, if any, that we're adding. Since it appears to gcc that there is additional logic after the function call, the tail call optimization is no longer possible. <strike>The 'volatile' keyword prevents gcc from moving the asm directive from its current location in the function.</strike><br /><br />Update: The volatile keyword only prevents the compiler from moving the asm block relative to other asm blocks, not relative to other lines of C code. The above use of 'result' after the asm block is the more important detail of this code snippet. The volatile keyword is not in fact needed, and this hack is a bit more fragile than I originally thought.<br /><br />There is one other optimization that can result in missing stack frames: -fomit-frame-pointer. gcc's man page doesn't seem to explain which optimization levels can include this flag, but it's easy to disable it entirely with -fno-omit-frame-pointer. Another issue with -fomit-frame-pointer is that it only results in missing stack frames on some architectures. I'll leave it to the reader to explore that one.Blake C.http://www.blogger.com/profile/08296013471634395562noreply@blogger.com8tag:blogger.com,1999:blog-8093909139580325869.post-76712278505510940512007-08-24T14:47:00.000-07:002007-08-24T14:50:36.449-07:00So Long, ChicagoI enjoyed my summer in California so much that I've decided to stick around. While I won't shed a tear for the weather, I'll miss <a href="http://www.violasong.com/blog/">all</a> <a href="http://www.dribin.org/dave/blog/">my</a> <a href="http://rentzsch.com/">friends</a> at <a href="http://cawug.org/">CAWUG</a> and <a href="http://rentzsch.com/psig/">PSIG</a>, but I'll try to make up for it at the <a href="http://www.cocoaheads.org/us/SiliconValleyCalifornia/index.html">Silicon Valley CocoaHeads</a> meetings.<br /><br /><rant><br />If you're a Cocoa programmer and you don't attend these regular meetings in your area, you owe it to yourself to start attending now. They are a refreshing vacation from the bleak Windows landscape, and I'm living proof that they can be an excellent career move.<br /></rant><br /><br />Many thanks to Wolf, Bob Frank and everyone else for the memories. I'll try to drop in when I can...Blake C.http://www.blogger.com/profile/08296013471634395562noreply@blogger.com3tag:blogger.com,1999:blog-8093909139580325869.post-44132603093230384562007-06-30T02:31:00.000-07:002007-06-30T02:54:41.988-07:00Choices and Repercussions<a href="http://www.macworld.com/news/2007/06/29/iphone_crowds/index.php">People want better phones, apparently.</a><br /><br /><blockquote>Ryan Overdevest, a 22-year-old student on a summer internship at an equity research firm, was third in line at the AT&T Store. [...] “I’m here for my boss. He sent me here as soon as I got in.” Overdewest showed up for work at 6 a.m., and was in line by 6:30 Friday morning.</blockquote><br />Sucks for Ryan. As a summer intern, I slept way past 6 AM, did some work, had some fun, and then went to a local Apple store to witness the iMadness firsthand.<br /><br />This is why I didn't major in equity research.Blake C.http://www.blogger.com/profile/08296013471634395562noreply@blogger.com4tag:blogger.com,1999:blog-8093909139580325869.post-87477540581895420172007-06-26T22:29:00.000-07:002007-06-26T22:41:00.849-07:00Apologies, More Posts Soon...Forgive me, folks- there's barely enough time to keep up with the latest iPhone hype/bashing/speculation/foolishness, and I can't seem to get any posts together lately. Maybe next week.<br /><br />Meanwhile, let's all chip in and send Gruber some ink for his jackass stamp. He won't last the next 3 days without us...Blake C.http://www.blogger.com/profile/08296013471634395562noreply@blogger.com0tag:blogger.com,1999:blog-8093909139580325869.post-29418477664191191792007-06-09T22:53:00.000-07:002007-06-09T22:54:19.472-07:00Another True StoryMe: "blah blah Jonathan Schwartz blah."<br /><br />My Friend: "Who?"<br /><br />Me: "My Little Pony."<br /><br />My Friend: "Oh."Blake C.http://www.blogger.com/profile/08296013471634395562noreply@blogger.com0tag:blogger.com,1999:blog-8093909139580325869.post-56171376048099610282007-05-31T22:54:00.000-07:002007-05-31T23:53:05.151-07:00C is to Wolf as D is to Goat<a href="http://en.wikipedia.org/wiki/Z1_(computer)">Z1</a>, <a href="http://www.a2-web.com">A2</a>, <a href="http://www.b3toledo.com">B3</a>, <a href="http://www.rentzsch.com/c4/">C4</a>, <a href="http://d5.allthingsd.com/">D5</a>, <a href="http://www.motorola.com/motoinfo/product/details.jsp?globalObjectId=175">E6</a>, <a href="http://www.michaellarabel.com/?k=blog&i=35">F7</a>, <a href="http://www.g8reboot.net">G8</a>...Blake C.http://www.blogger.com/profile/08296013471634395562noreply@blogger.com1tag:blogger.com,1999:blog-8093909139580325869.post-81148866085758988152007-05-20T20:00:00.000-07:002007-05-25T01:04:39.816-07:00WWDC Anyone?I'm going this year, and I've been told there may be others in attendance as well. If you are one such other and you share my interest in beer and/or whiskey, gimme a shout here.<br /><br />Update: Either I will be alone at WWDC or I'm the only alcoholic who reads my blog.Blake C.http://www.blogger.com/profile/08296013471634395562noreply@blogger.com5tag:blogger.com,1999:blog-8093909139580325869.post-58590727758274987002007-05-09T23:13:00.000-07:002007-05-29T01:27:44.495-07:00Display Eater UpdateWe had some <a href="http://yamacdev.blogspot.com/2007/02/behind-curtain-with-display-eater.html">interesting</a> <a href="http://yamacdev.blogspot.com/2007/02/open-letter-regarding-display-eater.html">discussions</a> with Reza recently, and I thought I should check in with him. Let's see what he's up to:<br /><br /><a href="http://www.reversecode.com/">http://www.reversecode.com/</a><br /><br />It now redirects to <a href="http://sio.midco.net/haunted/">sio.midco.net</a>, and I find myself in the awkward position of introducing the blogosphere to <a href="http://sio.midco.net/haunted/LED%20PIX/">LED pron</a>. (I'm too scared to download the dmg.)<br /><br />Hopefully, Reza's site got hacked. I can't even imagine the alternatives.<br /><br />Reza, feel free to comment here and let us know what's going on.<br /><br />Update: The LED pron has been replaced by <a href="http://sio.midco.net/haunted/FINISHED_/FINISHED_/">weed pron</a> and the previous URL is 404. Still waiting for Reza to reply here...Blake C.http://www.blogger.com/profile/08296013471634395562noreply@blogger.com0tag:blogger.com,1999:blog-8093909139580325869.post-66126327458962326122007-04-23T21:03:00.000-07:002007-04-29T23:59:23.457-07:00Run, Forrest, Run!One day, for no paticalar reason, I started runnin. I ran all the way to the end of Chicago. And since I run that far, I kept on runnin, clear across the great state of Illinois. And you know what? I ran all the way to California, and got me a internship at some fruit companay.<br /><br />I sure hope Jennay can come visit me. I hear they have lotsa them special cigarrets she likes so much.<br /><br />Update: Ridiculous Fish <a href="http://ridiculousfish.com/blog/archives/2007/04/13/42/">beats me</a> at my own movie-referencing game, and 10 days earlier to boot. If my calculations are correct, this will inspire a wildly popular Forrest Gump/LOTR mashup that youtube will promptly delete.Blake C.http://www.blogger.com/profile/08296013471634395562noreply@blogger.com10tag:blogger.com,1999:blog-8093909139580325869.post-8501352982233048202007-04-18T22:50:00.000-07:002007-04-18T22:51:16.900-07:00C'mon In, The Water's Fine.A big warm welcome to <a href="http://www.codebeach.org/">CodeBeach</a>.<br /><br /><blockquote>The goal of this site is to create a central repository where Mac developers can share pieces of useful code (like custom controls, formatters, categories) which is easier to search/use than forums or mailing lists.</blockquote><br /><br />This is way overdue. An OS X opensource <i>public domain</i> repository of freely re-usable code, with no bullshit licenses to muck things up. These guys have the right idea, and I urge everyone to contribute what they can, if at all possible.<br /><br />Many thanx to <a href="http://www.briksoftware.com/blog/">briksoftware</a> for creating this.Blake C.http://www.blogger.com/profile/08296013471634395562noreply@blogger.com1tag:blogger.com,1999:blog-8093909139580325869.post-24161484057086746562007-03-28T21:13:00.000-07:002007-03-28T21:15:19.579-07:00How To Tell If You're A Mac GeekWhen a cute girl says she's interested in studying computer science, she goes from cute to pretty.<br /><br />When she whips out a MacBook Pro, she goes from pretty to beautiful.<br /><br />When she mentions that she's a certified Apple hardware tech, she goes from beautiful to fucking gorgeous.<br /><br />True story. Disturbing, but true.Blake C.http://www.blogger.com/profile/08296013471634395562noreply@blogger.com2tag:blogger.com,1999:blog-8093909139580325869.post-53847314054236523922007-03-23T00:54:00.000-07:002007-03-23T01:30:52.171-07:00The BOOLs, They Do NothingFrom <CarbonCore/MacTypes.h>:<br /><pre class=".source_code">// kInvalidID KernelID: NULL is for pointers as kInvalidID is for ID's<br /><br />#define kInvalidID 0</pre><br />So I should say-<br /><br /><pre class=".source_code">if (someID == kInvalidID)</pre><br />instead of-<br /><br /><pre class=".source_code">if (!someID) ?</pre><br />OK yea, I'll get right on that.<br /><br />Seriously, every time i start to think that NS X rocks, I find some lameass redefinition like this. Zero is zero- am I missing something? Is this really just a Carbon relic, as the filename implies? Is it going away soon?Blake C.http://www.blogger.com/profile/08296013471634395562noreply@blogger.com8tag:blogger.com,1999:blog-8093909139580325869.post-19746971483358430512007-03-13T21:13:00.000-07:002007-03-13T21:27:42.602-07:00Obfuscated MeSo I was over at <a href="http://theocacao.com">Scott Stevenson's internet</a> recently and was surprised to <a href="http://theocacao.com/document.page/437">see</a> not only my name, but an eerily spot-on description of me:<br /><br /><blockquote>Now Blake, on the other hand; he's a riddle wrapped in a mystery inside an enigma passed to an instance of NSInvocation.</blockquote><br /><br />The only thing Bagelturf missed was that I'm usually just invoked with performSelector: - I'm not very complicated. As for the riddle, it's just @encode().Blake C.http://www.blogger.com/profile/08296013471634395562noreply@blogger.com0tag:blogger.com,1999:blog-8093909139580325869.post-35657777478372920252007-03-08T22:25:00.000-08:002007-03-15T02:04:55.818-07:00A Tale of Two CPUs<b>Exploring and comparing "Accelerated Objective-C Dispatch" on PPC and x86</b><br /><br />Links to Darwin source in this post require an Apple ID. They're free, so get one.<br /><br />I learned about the Obj-C runtime pages last year, and was reminded by <a href="http://lists.apple.com/archives/xcode-users/2005/Sep/msg00439.html">this post</a> to one of Apple's mailing lists. Mr. Maebe did a great job of explaining things, but there's always more to the story.<br /><br /><b><u>Who 0xfffeff00 is</u></b><br /><br />Mr. Feffoo is a copy of the _objc_msgSend assembly routine defined in <a href="http://www.opensource.apple.com/darwinsource/10.4.8.ppc/objc4-267.1/runtime/Messengers.subproj/objc-msg-ppc.s">objc-msg-ppc.s</a>. As Mr. Maebe pointed out, the only documentation is the source code. The easiest way to find it is to <a href="http://www.google.com/search?hl=en&q=0xfffeff00&btnG=Google+Search">google 0xfffeff00</a>. Apple's policy of requiring a login to view their source code seems to keep google's spider at bay, but our old dead friend, DarwinSource, is still cached. The first found occurrence of 0xfffeff00 is in <a href="http://www.opensource.apple.com/darwinsource/10.4.8.ppc/objc4-267.1/runtime/objc-rtp.h">objc-rtp.h</a>.<br /><br /><side note><br />While we're looking at _objc_msgSend, I'd like to remind everyone who says "messaging nil objects returns nil" that our friend Peter Ammon <a href="http://ridiculousfish.com/blog/archives/2005/05/29/nil/">showed us</a> that this is not always the case. If your code makes that assumption, it wouldn't hurt to fix it now.<br /></side note><br /><br />Notice that this is the PPC version of Darwin. 0xfffeff00 is the value assigned to kRTAddress_objc_msgSend, but only for PPC. While this header file is very interesting, its associated <a href="http://www.opensource.apple.com/darwinsource/10.4.8.ppc/objc4-267.1/runtime/objc-rtp.m">source file</a> is the real fun:<br /><br /><pre class=".source_code">/*<br /> objc-rtp.m<br /> Copyright 2004, Apple Computer, Inc.<br /> Author: Jim Laskey<br /> <br /> Implementation of the "objc runtime pages", an fixed area <br /> in high memory that can be reached via an absolute branch.<br />*/</pre><br /><br />Hat's off to Mr. Laskey for this file. In my opinion, what happens herein is some of the most interesting code in Darwin. I'll leave it to the reader to enjoy the code that actually <i>copies the _objc_msgSend routine to high memory</i>. Code that treats code like the data it is always makes me smile.<br /><br /><b><u>PPC Limits Set</u></b><br /><br />The magic number here is 0xffff8000. Above this address lie the "comm pages", the documentation for which eludes me now(anyone?). The reason this address is important is that a PPC absolute conditional branch can reach any address at or above it, thereby allowing the OS or kernel to copy some commonly used functions to those virtual memory pages.<br /><br />In the <a href="http://www.freescale.com/files/product/doc/MPCFPE32B.pdf">Programming Environments Manual</a>, 'bc', 'bca', 'bcl', and 'bcla' instructions are defined as having a 14 bit address field concatenated with two low zero bits, so that the destination address is guaranteed to be a multiple of four. That means that this is effectively a 16 bit address field. While 'bc' and 'bcl' have their charms, we're more interested in the absolute variants.<br /><br />If we set the high bit, or sign bit, of the address field and clear the lower bits, the CPU's sign extension produces the number 0xffff8000. And if we use the absolute variants 'bca' and 'bcla', we can branch to that address directly(as opposed to our current address minus 0x8000).<br /><br /><b><u>PPC Limits Broken</u></b><br /><br />The comm pages are nice, but they're already used for standard ANSI and/or Unix C functions, not Apple's Obj-C stuff. So how does Apple implement similar behavior for common Obj-C runtime routines like _objc_msgSend?<br /><br />Simple- build more comm pages below the ones that already exist, and use a branch instruction with a broader range that can reach those addresses.<br /><br />Assuming you're viewing the conditional branch documentation in the PEM, scroll up a bit to the unconditional branch instructions, specifically 'ba' and 'bla'. Notice the 24 bits available in the destination address field. This field is also concatenated with 2 low zeroes, which effectively gives us 26 bits. (Sure, we could use 'bcctr' to get a full 32 bits, but that would require 2 extra instructions to load the address and would clobber the count register.)<br /><br />So, if we sacrifice the ability to branch conditionally, we gain 10 bits, or 1024 bytes of addressability*. If we use the unconditional branch instructions, we can branch to anywhere at or above 0xfe000000, which is well below the addresses of the routines defined in objc-rtp.m.<br /><br />Jackpot.<br /><br />The _objc_msgSend assembly routine is copied into high RAM at launch time, and PPC code that was compiled with Xcode's "Accelerated Objective-C Dispatch" option uses the high-RAM version of _objc_msgSend instead of the usual symbol stub.<br /><br /><b><u>Intel Wins For Once</u></b><br /><br />I don't like x86 assembly and machine code any more than the next guy, but here's something that doesn't suck about the Intel chips:<br /><br />Darwin x86 has no runtime pages, because it doesn't need them. Not being able to load a 32 bit number in a single instruction is a limitation of the PPC ISA that Intel doesn't share. <i>x86 Obj-C code is "accelerated" by design</i>, and the "Accelerated Objective-C Dispatch" option has no effect whatsoever. Since they don't need symbol stubs, they don't need the "accelerated" workaround.<br /><br />It's not inconceivable that the "Accelerated Objective-C Dispatch" option will only exist for as long as Apple supports PPC machines.<br /><br /><b><u>One More Thing™</u></b><br /><br />Though it's only loosely related to this article, it's interesting to note the following code from objc-rtp.m:<br /><br /><pre class=".source_code"><br /> // initialize code in ObjC runtime pages<br /> rtp_set_up_objc_msgSend(kRTAddress_objc_msgSend, kRTSize_objc_msgSend);<br /> <br /> rtp_set_up_other(kRTAddress_objc_assign_ivar, kRTSize_objc_assign_ivar,<br /> "objc_assign_ivar", objc_assign_ivar_gc, objc_assign_ivar_non_gc);<br /></pre><br /><br />An entire function to assign a value to an instance variable? And an optimized version at that? Hmm.<br /><br />While I currently have no NDA obligation with Apple, I've been told that the information at which this code hints is hush-hush for now. So, out of respect for The Masters, I will only direct the reader to Xcode's "Project Settings" window. Specifically, the description of the "-fobjc-gc" flag.<br /><br />For those who don't want to fish around for details, "gc" stands for "Great Code".<br /><br />Many thanks to Mr. Laskey, Mr. Ammon, and all of the Apple coders working on the Obj-C runtime. Our applications only execute correctly and easily because you have all applied an enormous effort in designing a crucial part of the OS X underbelly. We all appreciate your work.<br /><br />If any of you attend C4[1], the drinks are on me.<br /><br />* I meant to say 33,521,664 bytes, not 1024 bytes. Minor oversight, sorry about that.Blake C.http://www.blogger.com/profile/08296013471634395562noreply@blogger.com0tag:blogger.com,1999:blog-8093909139580325869.post-12140038368813760412007-03-05T23:28:00.000-08:002007-11-30T18:08:45.403-08:00Free Noob Lesson #2We've all done this-<br /><br /><pre class=".source_code">- (id)init<br />{<br /> if (!(self = [super init]))<br /> return nil;<br /><br /> // etc.<br />}</pre><br /><br />That obviously returns nil when [super init] fails.<br /><br />But what if you accidentally add(or forget to remove) an extra semicolon?<br /><br /><pre class=".source_code">- (id)init<br />{<br /> if (!(self = [super init]));<br /> return nil;<br /><br /> // etc.<br />}</pre><br /><br />GCC is perfectly happy with that, but your application is not. The above code reduces to this useless logic:<br /><br /><pre class=".source_code">- (id)init<br />{<br /> self = [super init];<br /><br /> return nil;<br />}</pre><br /><br />One might say that we could avoid this by returning self instead of nil, but then the code in 'etc.' would still never be executed, and the resulting bug would probably be much harder to locate.<br /><br />The only quick and easy protection that I can think of is sobriety, which is clearly out of the question. Any thoughts?Blake C.http://www.blogger.com/profile/08296013471634395562noreply@blogger.com6