Skip to content

feat(cli): upload Mach-O executables as native debug symbols#72776

Merged
cat-ph merged 7 commits into
masterfrom
cat/cli-macho-symbol-upload
Jul 22, 2026
Merged

feat(cli): upload Mach-O executables as native debug symbols#72776
cat-ph merged 7 commits into
masterfrom
cat/cli-macho-symbol-upload

Conversation

@cat-ph

@cat-ph cat-ph commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Problem

symbol-sets upload accepts ELF files and Apple .dSYM bundles, but not standalone Mach-O executables. That leaves Go on macOS with no upload path at all: Go embeds DWARF directly in the executable and never produces a dSYM (dsymutil reports "no debug symbols in executable" because Go's linker emits no debug map). With the Go SDK now sending native frames and $debug_images on macOS (PostHog/posthog-go#260), those events can never be re-symbolicated server-side.

Changes

  • The directory scan accepts thin and universal (fat) Mach-O executables, dylibs, and debug companions alongside ELF. A fat binary yields one symbol set per architecture slice, carrying just that slice's bytes (the server resolves one thin binary per chunk id). fat64 (0xcafebabf) stays unsupported, matching the parser.
  • Mach-O chunk ids are the LC_UUID, uppercased to match the SDKs and dsym upload; packaging uses the AppleDsym container with the binary at dwarf in the ZIP, the layout the server already parses. Files inside .dSYM bundles stay owned by the dsym packaging path.
  • Go's default darwin build compresses the embedded DWARF (__zdebug sections), which symbolication can't read yet. Those binaries are classified separately and skipped with guidance to rebuild with -ldflags=-compressdwarf=false, rather than uploaded as a names-only set that would resolve worse than the SDK's own runtime symbolication. Mach-O files missing an LC_UUID also get their own guidance instead of the ELF build-id advice.
  • --include-source works unchanged (DWARF source-path extraction is format-agnostic); the native source filter also drops /go/pkg/mod/ now.
  • New shared fixtures: test_go_binary_macho.zst (uncompressed DWARF) and test_go_binary_macho_zdebug.zst (default build), generated by the existing build.sh.

How did you test this code?

New integration tests: thin Mach-O discovery and packaging (uppercase LC_UUID chunk id, AppleDsym container, Mach-O magic at dwarf), compressed-DWARF classification with a hard error when nothing else is uploadable, and a two-slice fat container asserting each slice uploads separately under its own UUID with its own bytes. Full CLI suite (149 tests) and cargo clippy --all-targets -- -D warnings pass locally. Also verified end-to-end against symbolic 12.17.2 that an uncompressed-DWARF Go darwin binary converts to a symcache with files, lines, and inline expansions, while the default compressed build yields symbol-table names only, which is what motivates the skip-with-guidance behavior.

Automatic notifications

  • Publish to changelog?
  • Alert Sales and Marketing teams?

Docs update

cli/README.md updated in this PR; a release changeset is included (minor). The posthog.com error tracking docs get the Go/macOS setup flags in a separate docs PR.

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Claude Code authored this after a tester hit the dSYM dead end with a Go macOS binary. I (Claude) verified the failure boundary first: Go's __DWARF segment is embedded in the executable, dsymutil can't consume it, and symbolic reads it fully only when built with -compressdwarf=false (the compressed default degrades to symbol-table-only). Review rounds tightened the initial version: fat64 magic removed since the parser doesn't support it, missing LC_UUID split out of the ELF build-id guidance, and the fat test extended to two slices with distinct UUIDs.

@cat-ph cat-ph self-assigned this Jul 21, 2026
@cat-ph
cat-ph marked this pull request as ready for review July 22, 2026 10:59
@cat-ph
cat-ph requested review from a team, ablaszkiewicz and hpouillot July 22, 2026 11:00
Comment thread cli/src/debug_symbols/mod.rs
Comment thread cli/src/debug_symbols/mod.rs
@veria-ai

veria-ai Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

PR overview

All previously flagged issues have been addressed. No open security concerns remain on this pull request.

Security review

No open security issues remain on this pull request.

Fixed/addressed: 1 · PR risk: 0/10

@greptile-apps

greptile-apps Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Comments Outside Diff (1)

  1. cli/src/debug_symbols/upload.rs, line 86 (link)

    P1 Matching dSYM Is Discarded

    When a directory contains a Mach-O executable and its matching .dSYM, both uploads have the same uppercase LC_UUID. The executable is added first, so the later first-wins deduplication drops the richer dSYM and can reduce source-line and inline-frame symbolication.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: cli/src/debug_symbols/upload.rs
    Line: 86
    
    Comment:
    **Matching dSYM Is Discarded**
    
    When a directory contains a Mach-O executable and its matching `.dSYM`, both uploads have the same uppercase `LC_UUID`. The executable is added first, so the later first-wins deduplication drops the richer dSYM and can reduce source-line and inline-frame symbolication.
    
    How can I resolve this? If you propose a fix, please make it concise.

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
cli/src/debug_symbols/upload.rs:86
**Matching dSYM Is Discarded**

When a directory contains a Mach-O executable and its matching `.dSYM`, both uploads have the same uppercase `LC_UUID`. The executable is added first, so the later first-wins deduplication drops the richer dSYM and can reduce source-line and inline-frame symbolication.

Reviews (1): Last reviewed commit: "test(cli): cover multi-slice fat Mach-O ..." | Re-trigger Greptile

@cat-ph
cat-ph force-pushed the cat/cli-macho-symbol-upload branch from 1bf9d6e to 347d9c7 Compare July 22, 2026 11:03

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1bf9d6e78d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread cli/src/debug_symbols/mod.rs
@hex-security-app

Copy link
Copy Markdown

Agreed that the original high severity wording overstated the practical threat model: exploitation requires an authenticated upload context plus the ability to place or replace an artifact in the scanned directory, and the resulting symbol set is scoped to that project.

I would still treat the path handling as a security boundary worth fixing centrally, since artifact write access does not necessarily imply read access to the uploader’s local/CI credentials (for example, a compromised build dependency or artifact step). The impact is arbitrary files readable by that upload process being bundled into the project’s symbol upload—not anonymous cross-project access. A shared fix across the existing source-bundling paths is the right approach.

@hpouillot hpouillot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

@cat-ph
cat-ph enabled auto-merge (squash) July 22, 2026 18:04
@cat-ph
cat-ph merged commit 845de8f into master Jul 22, 2026
193 checks passed
@cat-ph
cat-ph deleted the cat/cli-macho-symbol-upload branch July 22, 2026 18:12
inkeep Bot added a commit to PostHog/posthog.com that referenced this pull request Jul 22, 2026
…ostHog/posthog#72776 adds Mach-O executable support to\n`symbol-sets upload`, enabling Go on macOS to upload debug symbols\ndirectly (Go never produces dSYM bundles).\n\n- Update CalloutBox to remove 'symbol set uploads not available' note\n- Add optional step for building with uncompressed DWARF and uploading
inkeep Bot added a commit to PostHog/posthog.com that referenced this pull request Jul 22, 2026
Reflects PostHog/posthog#72776 which extends the CLI to accept
standalone Mach-O executables, dylibs, and debug companions alongside
ELF files and dSYM bundles. Universal (fat) binaries are automatically
split per architecture slice.
@deployment-status-posthog

deployment-status-posthog Bot commented Jul 22, 2026

Copy link
Copy Markdown

Deploy status

Environment Status Deployed At Workflow
dev ✅ Deployed 2026-07-22 19:44 UTC Run
prod-us ✅ Deployed 2026-07-22 19:59 UTC Run
prod-eu ✅ Deployed 2026-07-22 19:59 UTC Run

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants