Experimental dev diary for tracking interesting things

February 2026

Binary Spelunking 101: nm, otool, strings

Some tools for peeking inside compiled binaries. Let’s compile a simple Swift file:

class UserAuthenticator {
    private let apiKey = "sk_live_abc123secret"
    private let apiEndpoint = "https://api.myapp.com/v1/auth"

    func authenticate(username: String, password: String) -> Bool {
        return user == "admin" && pass == "supersecret123"
    }
}

class PaymentProcessor {
    let merchantId = "merchant_prod_xyz789"
    func processPayment(amount: Double) -> Bool { ... }
}

strings - extract readable text:

$ strings BinaryDemo | grep -iE "(secret|http|merchant|admin)"
sk_live_abc123secret
https://api.myapp.com/v1/auth
admin
supersecret123
merchant_prod_xyz789

nm - list symbols (functions, classes, globals):

$ nm BinaryDemo | grep Payment | head -5
00000001000013ec t _$s10BinaryDemo16PaymentProcessorC07processC06amountSbSd_tF
00000001000013b8 t _$s10BinaryDemo16PaymentProcessorC10merchantIdSSvg
...

$ nm BinaryDemo | xcrun swift-demangle | grep Payment | head -3
00000001000013ec t BinaryDemo.PaymentProcessor.processPayment(amount: Swift.Double) -> Swift.Bool
00000001000013b8 t BinaryDemo.PaymentProcessor.merchantId.getter : Swift.String

otool -L - linked libraries:

$ otool -L BinaryDemo
BinaryDemo:
  /usr/lib/libSystem.B.dylib (...)
  /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (...)
  /usr/lib/swift/libswiftCore.dylib (...)

Note: This binary was compiled with plain swiftc - no symbol stripping, obfuscation, or App Store encryption (FairPlay).

January 2026

#require in Swift Testing

The #require macro in Swift Testing safely unwraps optionals and throws if nil, stopping the test immediately. It replaces the old XCTUnwrap pattern.

Before (XCTest):

func testUserName() throws {
    let user = try XCTUnwrap(fetchUser())
    XCTAssertEqual(user.name, "John")
}

After (Swift Testing):

@Test func userName() throws {
    let user = try #require(fetchUser())
    #expect(user.name == "John")
}

It also works with boolean conditions - the test fails if the condition is false:

@Test func adminAccess() throws {
    let user = try #require(fetchUser())
    try #require(user.isAdmin)  // Fails test if not admin
    // Continue with admin-only tests...
}

The key difference from #expect: #require stops execution on failure, while #expect records the failure but continues. Use #require when subsequent code depends on the condition being true.

Tart: macOS VMs like containers

Tart from Cirrus Labs uses Apple’s Virtualization.framework to run macOS/Linux VMs on Apple Silicon. The killer feature: it distributes VM images via OCI registries, so you can pull/push them like Docker images.

tart clone ghcr.io/cirruslabs/macos-sequoia-xcode:latest my-vm
tart run my-vm

Combine with Packer to automate image creation - install Xcode, dependencies, snapshot, and push to your registry:

tart push my-vm ghcr.io/myorg/macos-ci:v1

OCI is only the distribution format - it’s not containerizing macOS (that would violate licensing). It just chunks the disk image into layers for efficient transfer and versioning. Great for CI runners.

Swift ownership: borrowing, consuming, inout

Swift 5.9 introduced ownership modifiers for non-copyable types (~Copyable). Here’s the difference:

struct DBConnection: ~Copyable {
    mutating func open() { /* ... */ }
    mutating func close() { /* ... */ }
    func query(_ sql: String) { /* ... */ }
}

borrowing - read-only access, caller keeps ownership:

func inspect(_ connection: borrowing DBConnection) {
    connection.query("SELECT 1")  // OK - read only
    // connection.open()          // Error - can't mutate
}

consuming - takes ownership, caller loses the value:

func runAndClose(_ connection: consuming DBConnection) {
    connection.open()
    connection.close()
    // connection is destroyed here
}

runAndClose(db)
// db.query("...")  // Error - db was consumed

inout - mutable borrow, caller keeps ownership:

func reopen(_ connection: inout DBConnection) {
    connection.open()  // OK - can mutate
}
// db still usable after call

Useful for modeling resources like DB connections, file handles, or locks where you want compile-time guarantees against use-after-close bugs.

rss facebook twitter github youtube mail spotify lastfm instagram linkedin google google-plus pinterest medium vimeo stackoverflow reddit quora