-
Notifications
You must be signed in to change notification settings - Fork 367
Update darwin headers #452
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,23 +1,38 @@ | ||
| name: "Darwin XNU Mach-O headers" | ||
| description: | ||
| "A few header files from the Darwin XNU project. These define the Mach-O format." | ||
| "Header files from Apple's cctools and Darwin XNU projects." | ||
| "Mach-O file format definitions from the cctools project." | ||
| "Mach kernel type definitions from the XNU project." | ||
| "They only contain struct and constant definitions (no code)." | ||
|
|
||
| third_party { | ||
| url { | ||
| type: HOMEPAGE | ||
| value: "https://opensource.apple.com/source/xnu/" | ||
| type: GIT | ||
| value: "https://github.com/apple-oss-distributions/xnu" | ||
| } | ||
| version: "f6217f891ac0bb64f3d375211650a4c1ff8ca1ea" | ||
| last_upgrade_date { | ||
| year: 2025 | ||
| month: 11 | ||
| day: 13 | ||
| } | ||
| local_modifications: | ||
| "Mach kernel type headers (machine.h, vm_prot.h) from XNU osfmk/mach/" | ||
| "Added __has_include() guards and fallback typedefs for cross-platform compatibility." | ||
| } | ||
|
|
||
| third_party { | ||
| url { | ||
| type: GIT | ||
| value: "https://github.com/apple/darwin-xnu" | ||
| value: "https://github.com/apple-oss-distributions/cctools" | ||
| } | ||
| version: "0a798f6738bc1db01281fc08ae024145e84df927" | ||
| version: "920a2b45080fb9badf31bf675f03b19973f0dd4f" | ||
| last_upgrade_date { | ||
| year: 2017 | ||
| year: 2025 | ||
| month: 11 | ||
| day: 11 | ||
| day: 13 | ||
| } | ||
| local_modifications: | ||
| "Removed some includes and definitions not related to the Mach-O file format." | ||
| "Mach-O file format headers (fat.h, loader.h, nlist.h, reloc.h) from cctools include/mach-o/" | ||
| "Modified loader.h to use bundled vm_prot.h instead of system header for cross-platform compatibility." | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| # Darwin XNU and Mach-O Headers | ||
|
|
||
| This directory contains header files from Apple's open source XNU kernel and cctools projects. | ||
| These headers define the Mach-O binary format and related kernel types used by bloaty to parse Mach-O binaries. | ||
|
|
||
| ## Source Repositories | ||
|
|
||
| The headers are obtained from: | ||
|
|
||
| - **XNU (mach/ headers)**: https://github.com/apple-oss-distributions/xnu | ||
| - `mach/machine.h` - CPU type definitions | ||
| - `mach/vm_prot.h` - Virtual memory protection flags | ||
|
|
||
| - **cctools (mach-o/ headers)**: https://github.com/apple-oss-distributions/cctools | ||
| - `mach-o/fat.h` - Universal binary format | ||
| - `mach-o/loader.h` - Mach-O file structure | ||
| - `mach-o/nlist.h` - Symbol table format | ||
|
|
||
| The specific versions are documented in the `METADATA` file. | ||
|
|
||
| ## Local Modifications | ||
|
|
||
| To make these headers work cross-platform, we apply minimal local modifications: | ||
|
|
||
| 1. **Cross-platform includes**: Add `__has_include()` guards for system headers | ||
| 2. **Fallback definitions**: Provide fallback typedefs when system headers aren't available | ||
| 3. **Bundled headers**: Reference bundled copies instead of system headers | ||
|
|
||
| All local modifications are documented as patch files in the `patches/` directory. | ||
|
|
||
| ## Reproducibility | ||
|
|
||
| The header update process is fully reproducible using the provided Python scripts: | ||
|
|
||
| ### Updating Headers | ||
|
|
||
| To update to newer versions of the headers: | ||
|
|
||
| 1. Edit `METADATA` to specify new git commit hashes | ||
| 2. Run the update script: | ||
| ```bash | ||
| python3 update_headers.py | ||
| ``` | ||
|
|
||
| This will: | ||
| - Fetch the specified headers from GitHub | ||
| - Apply local modifications from `patches/` | ||
| - Install the modified headers | ||
|
|
||
| ### Regenerating Patches | ||
|
|
||
| If you need to add new local modifications: | ||
|
|
||
| 1. Manually edit the header files as needed | ||
| 2. Regenerate the patches: | ||
| ```bash | ||
| python3 generate_patches.py | ||
| ``` | ||
|
|
||
| This will: | ||
| - Fetch the original upstream headers | ||
| - Compare them to your modified versions | ||
| - Generate/update patch files in `patches/` | ||
|
|
||
| ### Dry Run | ||
|
|
||
| To see what would happen without making changes: | ||
|
|
||
| ```bash | ||
| python3 update_headers.py --dry-run | ||
| ``` | ||
|
|
||
| ## Patch Files | ||
|
|
||
| Current patches: | ||
|
|
||
| - **`mach_machine.h.patch`**: Adds `__has_include()` guards and fallback `integer_t` typedef for cross-platform compatibility | ||
| - **`mach-o_loader.h.patch`**: Changes `#include <mach/vm_prot.h>` to `#include "../mach/vm_prot.h"` to use bundled header |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,204 @@ | ||
| #!/usr/bin/env python3 | ||
| """ | ||
| Script to generate patch files documenting local modifications to headers. | ||
|
|
||
| This script should be run after manually editing headers to add cross-platform | ||
| compatibility fixes. It will generate patch files that can be applied by | ||
| update_headers.py. | ||
|
|
||
| Usage: python3 generate_patches.py | ||
|
|
||
| The script will: | ||
| 1. Fetch the original upstream headers | ||
| 2. Compare them to the current headers | ||
| 3. Generate patch files | ||
| """ | ||
|
|
||
| import os | ||
| import subprocess | ||
| import sys | ||
| from pathlib import Path | ||
| from update_headers import ( | ||
| MetadataParser, | ||
| fetch_file_from_github, | ||
| XNU_HEADERS, | ||
| CCTOOLS_HEADERS, | ||
| ) | ||
|
|
||
|
|
||
| def generate_patch(original_content: bytes, modified_file: Path, output_patch: Path) -> bool: | ||
| """ | ||
| Generate a patch file comparing original content to modified file. | ||
|
|
||
| Args: | ||
| original_content: Original file content from upstream | ||
| modified_file: Path to the modified file | ||
| output_patch: Path where patch should be written | ||
|
|
||
| Returns: | ||
| True if a patch was generated, False otherwise | ||
| """ | ||
| # Write original content to a temporary file | ||
| temp_original = modified_file.parent / (modified_file.name + ".orig") | ||
| with open(temp_original, 'wb') as f: | ||
| f.write(original_content) | ||
|
|
||
| try: | ||
| # Generate diff | ||
| result = subprocess.run( | ||
| ["diff", "-u", str(temp_original), str(modified_file)], | ||
| capture_output=True, | ||
| text=True | ||
| ) | ||
|
|
||
| if result.returncode == 0: | ||
| return False | ||
| elif result.returncode == 1: | ||
| # Files differ, generate new patch content | ||
| # Adjust paths in diff output to be relative to script directory | ||
| new_patch_content = result.stdout | ||
| new_patch_content = new_patch_content.replace( | ||
| str(temp_original), str(modified_file.name + ".orig") | ||
| ) | ||
| new_patch_content = new_patch_content.replace( | ||
| str(modified_file), str(modified_file.name) | ||
| ) | ||
|
|
||
| # Check if existing patch has the same content (ignoring timestamp lines) | ||
| if output_patch.exists(): | ||
| with open(output_patch, 'r') as f: | ||
| old_patch_content = f.read() | ||
|
|
||
| # Compare patches ignoring the first two lines (which contain timestamps) | ||
| old_lines = old_patch_content.split('\n')[2:] # Skip timestamp lines | ||
| new_lines = new_patch_content.split('\n')[2:] # Skip timestamp lines | ||
|
|
||
| if old_lines == new_lines: | ||
| # Patch content is identical, don't update | ||
| return False | ||
|
|
||
| with open(output_patch, 'w') as f: | ||
| f.write(new_patch_content) | ||
| return True | ||
| else: | ||
| raise RuntimeError(f"diff failed: {result.stderr}") | ||
|
|
||
| finally: | ||
| if temp_original.exists(): | ||
| temp_original.unlink() | ||
|
|
||
|
|
||
| def process_headers( | ||
| repo_name: str, | ||
| repo_url: str, | ||
| version: str, | ||
| headers: list, | ||
| script_dir: Path, | ||
| patch_dir: Path | ||
| ) -> list: | ||
| """ | ||
| Process headers from a repository and generate patches. | ||
|
|
||
| Args: | ||
| repo_name: Human-readable repository name (e.g., "XNU") | ||
| repo_url: Git repository URL | ||
| version: Git commit hash | ||
| headers: List of (source_path, dest_path) tuples | ||
| script_dir: Script directory Path | ||
| patch_dir: Patches directory Path | ||
|
|
||
| Returns: | ||
| List of patch filenames that were generated or unchanged | ||
|
|
||
| Raises: | ||
| Exception: If an error occurs processing a header | ||
| """ | ||
| patches_generated = [] | ||
| print(f"=== Processing {repo_name} headers ===") | ||
|
|
||
| for source_path, dest_path in headers: | ||
| print(f" Checking: {dest_path}") | ||
| modified_file = script_dir / dest_path | ||
|
|
||
| if not modified_file.exists(): | ||
| print(f" Warning: Modified file not found, skipping") | ||
| continue | ||
|
|
||
| original_content = fetch_file_from_github(repo_url, version, source_path) | ||
|
|
||
| patch_name = dest_path.replace("/", "_") + ".patch" | ||
| patch_file = patch_dir / patch_name | ||
|
|
||
| if generate_patch(original_content, modified_file, patch_file): | ||
| print(f" Generated patch: {patch_name}") | ||
| patches_generated.append(patch_name) | ||
| else: | ||
| if patch_file.exists(): | ||
| print(f" Patch unchanged: {patch_name}") | ||
| patches_generated.append(patch_name) | ||
| else: | ||
| print(f" No modifications detected") | ||
|
|
||
| print() | ||
| return patches_generated | ||
|
|
||
|
|
||
| def main(): | ||
| script_dir = Path(__file__).parent.resolve() | ||
| os.chdir(script_dir) | ||
|
|
||
| print("=== Darwin XNU/Mach-O Header Patch Generator ===") | ||
| print() | ||
|
|
||
| metadata_path = script_dir / "METADATA" | ||
| if not metadata_path.exists(): | ||
| print(f"Error: METADATA file not found at {metadata_path}") | ||
| return 1 | ||
|
|
||
| parser = MetadataParser(metadata_path) | ||
|
|
||
| try: | ||
| xnu_url, xnu_version = parser.get_repo_info("xnu") | ||
| cctools_url, cctools_version = parser.get_repo_info("cctools") | ||
| except ValueError as e: | ||
| print(f"Error parsing METADATA: {e}") | ||
| return 1 | ||
|
|
||
| print(f"XNU repository: {xnu_url}") | ||
| print(f"XNU version: {xnu_version}") | ||
| print(f"cctools repository: {cctools_url}") | ||
| print(f"cctools version: {cctools_version}") | ||
| print() | ||
|
|
||
| patch_dir = script_dir / "patches" | ||
| patch_dir.mkdir(exist_ok=True) | ||
| print(f"Patches will be written to: {patch_dir}") | ||
| print() | ||
|
|
||
| patches_generated = [] | ||
| try: | ||
| patches_generated.extend( | ||
| process_headers("XNU", xnu_url, xnu_version, XNU_HEADERS, script_dir, patch_dir) | ||
| ) | ||
| patches_generated.extend( | ||
| process_headers("cctools", cctools_url, cctools_version, CCTOOLS_HEADERS, script_dir, patch_dir) | ||
| ) | ||
| except Exception as e: | ||
| print(f"Error: {e}") | ||
| return 1 | ||
|
|
||
| print("=== Patch Generation Complete ===") | ||
| if patches_generated: | ||
| print(f"Generated {len(patches_generated)} patch file(s):") | ||
| for patch in patches_generated: | ||
| print(f" - {patch}") | ||
| print() | ||
| print("These patches will be automatically applied by update_headers.py") | ||
| else: | ||
| print("No patches generated - files are identical to upstream") | ||
|
|
||
| return 0 | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| sys.exit(main()) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.