From 6f6ff60161adf39435a3c76a96211e528d0fb03a Mon Sep 17 00:00:00 2001 From: Ryan Mansfield Date: Mon, 3 Nov 2025 19:05:34 -0500 Subject: [PATCH 1/2] Update darwin XNU and Mach-O headers Updates third_party/darwin_xnu_macho headers to latest versions from Apple open source repositories: - mach-o headers from cctools (include/mach-o/) - mach headers from XNU (osfmk/mach/) Fixes #438 --- third_party/darwin_xnu_macho/METADATA | 31 +- third_party/darwin_xnu_macho/mach-o/fat.h | 36 +- third_party/darwin_xnu_macho/mach-o/loader.h | 221 +++++++-- third_party/darwin_xnu_macho/mach-o/nlist.h | 8 +- third_party/darwin_xnu_macho/mach/machine.h | 451 ++++++++++++------- third_party/darwin_xnu_macho/mach/vm_prot.h | 109 +++-- 6 files changed, 613 insertions(+), 243 deletions(-) diff --git a/third_party/darwin_xnu_macho/METADATA b/third_party/darwin_xnu_macho/METADATA index 22f9ce49..32fc93ed 100644 --- a/third_party/darwin_xnu_macho/METADATA +++ b/third_party/darwin_xnu_macho/METADATA @@ -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." } diff --git a/third_party/darwin_xnu_macho/mach-o/fat.h b/third_party/darwin_xnu_macho/mach-o/fat.h index 79ad1b7c..03fca164 100644 --- a/third_party/darwin_xnu_macho/mach-o/fat.h +++ b/third_party/darwin_xnu_macho/mach-o/fat.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2016 Apple, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -42,22 +42,48 @@ * and contains the constants for the possible values of these types. */ #include -#include "third_party/darwin_xnu_macho/mach/machine.h" + +#if __has_include() +#include +#endif + +#if __has_include() +#include +#endif #define FAT_MAGIC 0xcafebabe #define FAT_CIGAM 0xbebafeca /* NXSwapLong(FAT_MAGIC) */ struct fat_header { - uint32_t magic; /* FAT_MAGIC */ + uint32_t magic; /* FAT_MAGIC or FAT_MAGIC_64 */ uint32_t nfat_arch; /* number of structs that follow */ }; struct fat_arch { - cpu_type_t cputype; /* cpu specifier (int) */ - cpu_subtype_t cpusubtype; /* machine specifier (int) */ + int32_t cputype; /* cpu specifier (int) */ + int32_t cpusubtype; /* machine specifier (int) */ uint32_t offset; /* file offset to this object file */ uint32_t size; /* size of this object file */ uint32_t align; /* alignment as a power of 2 */ }; +/* + * The support for the 64-bit fat file format described here is a work in + * progress and not yet fully supported in all the Apple Developer Tools. + * + * When a slice is greater than 4mb or an offset to a slice is greater than 4mb + * then the 64-bit fat file format is used. + */ +#define FAT_MAGIC_64 0xcafebabf +#define FAT_CIGAM_64 0xbfbafeca /* NXSwapLong(FAT_MAGIC_64) */ + +struct fat_arch_64 { + int32_t cputype; /* cpu specifier (int) */ + int32_t cpusubtype; /* machine specifier (int) */ + uint64_t offset; /* file offset to this object file */ + uint64_t size; /* size of this object file */ + uint32_t align; /* alignment as a power of 2 */ + uint32_t reserved; /* reserved */ +}; + #endif /* _MACH_O_FAT_H_ */ diff --git a/third_party/darwin_xnu_macho/mach-o/loader.h b/third_party/darwin_xnu_macho/mach-o/loader.h index 53a68756..b05adf03 100644 --- a/third_party/darwin_xnu_macho/mach-o/loader.h +++ b/third_party/darwin_xnu_macho/mach-o/loader.h @@ -32,13 +32,26 @@ * is needed here for the cpu_type_t and cpu_subtype_t types * and contains the constants for the possible values of these types. */ -#include "third_party/darwin_xnu_macho/mach/machine.h" +#if __has_include() +#include +#endif /* * is needed here for the vm_prot_t type and contains the * constants that are or'ed together for the possible values of this type. */ -#include "third_party/darwin_xnu_macho/mach/vm_prot.h" +#include "../mach/vm_prot.h" + +/* + * is expected to define the flavors of the thread + * states and the structures of those flavors for each machine. + */ +#if __has_include() +#include +#endif +#if __has_include() +#include +#endif /* * The 32-bit mach header appears at the very beginning of the object file for @@ -46,8 +59,8 @@ */ struct mach_header { uint32_t magic; /* mach magic number identifier */ - cpu_type_t cputype; /* cpu specifier */ - cpu_subtype_t cpusubtype; /* machine specifier */ + int32_t cputype; /* cpu specifier */ + int32_t cpusubtype; /* machine specifier */ uint32_t filetype; /* type of file */ uint32_t ncmds; /* number of load commands */ uint32_t sizeofcmds; /* the size of all the load commands */ @@ -64,8 +77,8 @@ struct mach_header { */ struct mach_header_64 { uint32_t magic; /* mach magic number identifier */ - cpu_type_t cputype; /* cpu specifier */ - cpu_subtype_t cpusubtype; /* machine specifier */ + int32_t cputype; /* cpu specifier */ + int32_t cpusubtype; /* machine specifier */ uint32_t filetype; /* type of file */ uint32_t ncmds; /* number of load commands */ uint32_t sizeofcmds; /* the size of all the load commands */ @@ -108,11 +121,17 @@ struct mach_header_64 { #define MH_DYLIB 0x6 /* dynamically bound shared library */ #define MH_DYLINKER 0x7 /* dynamic link editor */ #define MH_BUNDLE 0x8 /* dynamically bound bundle file */ -#define MH_DYLIB_STUB 0x9 /* shared library stub for static */ - /* linking only, no section contents */ -#define MH_DSYM 0xa /* companion file with only debug */ - /* sections */ +#define MH_DYLIB_STUB 0x9 /* shared library stub for static + linking only, no section contents */ +#define MH_DSYM 0xa /* companion file with only debug + sections */ #define MH_KEXT_BUNDLE 0xb /* x86_64 kexts */ +#define MH_FILESET 0xc /* a file composed of other Mach-Os to + be run in the same userspace sharing + a single linkedit. */ +#define MH_GPU_EXECUTE 0xd /* gpu program */ +#define MH_GPU_DYLIB 0xe /* gpu support functions */ + /* Constants for the flags field of the mach_header */ #define MH_NOUNDEFS 0x1 /* the object file has no undefined @@ -203,6 +222,27 @@ struct mach_header_64 { #define MH_APP_EXTENSION_SAFE 0x02000000 /* The code was linked for use in an application extension. */ +#define MH_NLIST_OUTOFSYNC_WITH_DYLDINFO 0x04000000 /* The external symbols + listed in the nlist symbol table do + not include all the symbols listed in + the dyld info. */ + +#define MH_SIM_SUPPORT 0x08000000 /* Allow LC_MIN_VERSION_MACOS and + LC_BUILD_VERSION load commands with + the platforms macOS, macCatalyst, + iOSSimulator, tvOSSimulator and + watchOSSimulator. */ + +#define MH_IMPLICIT_PAGEZERO 0x10000000 /* main executable has no __PAGEZERO + segment. Instead, loader (xnu) + will load program high and block + out all memory below it. */ + +#define MH_DYLIB_IN_CACHE 0x80000000 /* Only for use on dylibs. When this bit + is set, the dylib is part of the dyld + shared cache, rather than loose in + the filesystem. */ + /* * The load commands directly follow the mach_header. The total size of all * of the commands is given by the sizeofcmds field in the mach_header. All @@ -297,6 +337,15 @@ struct load_command { #define LC_VERSION_MIN_WATCHOS 0x30 /* build for Watch min OS version */ #define LC_NOTE 0x31 /* arbitrary data included within a Mach-O file */ #define LC_BUILD_VERSION 0x32 /* build for platform min OS version */ +#define LC_DYLD_EXPORTS_TRIE (0x33 | LC_REQ_DYLD) /* used with linkedit_data_command, payload is trie */ +#define LC_DYLD_CHAINED_FIXUPS (0x34 | LC_REQ_DYLD) /* used with linkedit_data_command */ +#define LC_FILESET_ENTRY (0x35 | LC_REQ_DYLD) /* used with fileset_entry_command */ +#define LC_ATOM_INFO 0x36 /* used with linkedit_data_command */ +#define LC_FUNCTION_VARIANTS 0x37 /* used with linkedit_data_command */ +#define LC_FUNCTION_VARIANT_FIXUPS 0x38 /* used with linkedit_data_command */ +#define LC_TARGET_TRIPLE 0x39 /* target triple used to compile */ + + /* * A variable length string in a load command is represented by an lc_str @@ -333,8 +382,8 @@ struct segment_command { /* for 32-bit architectures */ uint32_t vmsize; /* memory size of this segment */ uint32_t fileoff; /* file offset of this segment */ uint32_t filesize; /* amount to map from the file */ - vm_prot_t maxprot; /* maximum VM protection */ - vm_prot_t initprot; /* initial VM protection */ + int32_t maxprot; /* maximum VM protection */ + int32_t initprot; /* initial VM protection */ uint32_t nsects; /* number of sections in segment */ uint32_t flags; /* flags */ }; @@ -353,8 +402,8 @@ struct segment_command_64 { /* for 64-bit architectures */ uint64_t vmsize; /* memory size of this segment */ uint64_t fileoff; /* file offset of this segment */ uint64_t filesize; /* amount to map from the file */ - vm_prot_t maxprot; /* maximum VM protection */ - vm_prot_t initprot; /* initial VM protection */ + int32_t maxprot; /* maximum VM protection */ + int32_t initprot; /* initial VM protection */ uint32_t nsects; /* number of sections in segment */ uint32_t flags; /* flags */ }; @@ -374,6 +423,9 @@ struct segment_command_64 { /* for 64-bit architectures */ first page of the segment is not protected. All other pages of the segment are protected. */ +#define SG_READ_ONLY 0x10 /* This segment is made read-only after fixups */ + + /* * A segment is made up of zero or more sections. Non-MH_OBJECT files have @@ -499,6 +551,8 @@ struct section_64 { /* for 64-bit architectures */ #define S_THREAD_LOCAL_INIT_FUNCTION_POINTERS 0x15 /* functions to call to initialize TLV values */ +#define S_INIT_FUNC_OFFSETS 0x16 /* 32-bit offsets to + initializers */ /* * Constants for the section attributes part of the flags field of a section @@ -624,7 +678,7 @@ struct fvmlib_command { }; /* - * Dynamicly linked shared libraries are identified by two things. The + * Dynamically linked shared libraries are identified by two things. The * pathname (the name of the library as found for execution), and the * compatibility version number. The pathname must match and the compatibility * number in the user of the library must be greater than or equal to the @@ -653,6 +707,30 @@ struct dylib_command { struct dylib dylib; /* the library identification */ }; + +/* + * An alternate encoding for: LC_LOAD_DYLIB. + * The flags field contains independent flags DYLIB_USE_* + * First supported in macOS 15, iOS 18. + */ +struct dylib_use_command { + uint32_t cmd; /* LC_LOAD_DYLIB or LC_LOAD_WEAK_DYLIB */ + uint32_t cmdsize; /* overall size, including path */ + uint32_t nameoff; /* == 28, dylibs's path offset */ + uint32_t marker; /* == DYLIB_USE_MARKER */ + uint32_t current_version; /* dylib's current version number */ + uint32_t compat_version; /* dylib's compatibility version number */ + uint32_t flags; /* DYLIB_USE_... flags */ +}; +#define DYLIB_USE_WEAK_LINK 0x01 +#define DYLIB_USE_REEXPORT 0x02 +#define DYLIB_USE_UPWARD 0x04 +#define DYLIB_USE_DELAYED_INIT 0x08 + +#define DYLIB_USE_MARKER 0x1a741800 + + + /* * A dynamically linked shared library may be a subframework of an umbrella * framework. If so it will be linked with "-umbrella umbrella_name" where @@ -760,14 +838,14 @@ struct dylinker_command { * Thread commands contain machine-specific data structures suitable for * use in the thread state primitives. The machine specific data structures * follow the struct thread_command as follows. - * Each flavor of machine specific data structure is preceded by an unsigned - * long constant for the flavor of that data structure, an uint32_t - * that is the count of longs of the size of the state data structure and then + * Each flavor of machine specific data structure is preceded by an uint32_t + * constant for the flavor of that data structure, an uint32_t that is the + * count of uint32_t's of the size of the state data structure and then * the state data structure follows. This triple may be repeated for many * flavors. The constants for the flavors, counts and state data structure * definitions are expected to be in the header file . * These machine specific data structures sizes must be multiples of - * 4 bytes The cmdsize reflects the total size of the thread_command + * 4 bytes. The cmdsize reflects the total size of the thread_command * and all of the sizes of the constants for the flavors, counts and state * data structures. * @@ -781,7 +859,7 @@ struct thread_command { uint32_t cmd; /* LC_THREAD or LC_UNIXTHREAD */ uint32_t cmdsize; /* total size of this command */ /* uint32_t flavor flavor of thread state */ - /* uint32_t count count of longs in thread state */ + /* uint32_t count count of uint32_t's in thread state */ /* struct XXX_thread_state state thread state for this flavor */ /* ... */ }; @@ -1150,15 +1228,28 @@ struct rpath_command { union lc_str path; /* path to add to run path */ }; +/* + * The target_triple_command contains a string which specifies the + * target triple (e.g. "arm64e-apple-macosx15.0.0") used to compile the code. + */ +struct target_triple_command { + uint32_t cmd; /* LC_TARGET_TRIPLE */ + uint32_t cmdsize; /* including string */ + union lc_str triple; /* target triple string */ +}; + /* * The linkedit_data_command contains the offsets and sizes of a blob * of data in the __LINKEDIT segment. */ struct linkedit_data_command { uint32_t cmd; /* LC_CODE_SIGNATURE, LC_SEGMENT_SPLIT_INFO, - LC_FUNCTION_STARTS, LC_DATA_IN_CODE, - LC_DYLIB_CODE_SIGN_DRS or - LC_LINKER_OPTIMIZATION_HINT. */ + LC_FUNCTION_STARTS, LC_DATA_IN_CODE, + LC_DYLIB_CODE_SIGN_DRS, LC_ATOM_INFO, + LC_LINKER_OPTIMIZATION_HINT, + LC_DYLD_EXPORTS_TRIE, + LC_FUNCTION_VARIANTS, LC_FUNCTION_VARIANT_FIXUPS, or + LC_DYLD_CHAINED_FIXUPS. */ uint32_t cmdsize; /* sizeof(struct linkedit_data_command) */ uint32_t dataoff; /* file offset of data in __LINKEDIT segment */ uint32_t datasize; /* file size of data in __LINKEDIT segment */ @@ -1207,14 +1298,14 @@ struct version_min_command { }; /* - * The build_version_command contains the min OS version on which this + * The build_version_command contains the min OS version on which this * binary was built to run for its platform. The list of known platforms and * tool values following it. */ struct build_version_command { uint32_t cmd; /* LC_BUILD_VERSION */ uint32_t cmdsize; /* sizeof(struct build_version_command) plus */ - /* ntools * sizeof(struct build_tool_version) */ + /* ntools * sizeof(struct build_tool_version) */ uint32_t platform; /* platform */ uint32_t minos; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ uint32_t sdk; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ @@ -1227,15 +1318,53 @@ struct build_tool_version { }; /* Known values for the platform field above. */ +#define PLATFORM_UNKNOWN 0 +#define PLATFORM_ANY 0xFFFFFFFF #define PLATFORM_MACOS 1 #define PLATFORM_IOS 2 #define PLATFORM_TVOS 3 #define PLATFORM_WATCHOS 4 +#define PLATFORM_BRIDGEOS 5 +#define PLATFORM_MACCATALYST 6 +#define PLATFORM_IOSSIMULATOR 7 +#define PLATFORM_TVOSSIMULATOR 8 +#define PLATFORM_WATCHOSSIMULATOR 9 +#define PLATFORM_DRIVERKIT 10 +#define PLATFORM_VISIONOS 11 +#define PLATFORM_VISIONOSSIMULATOR 12 + +#define PLATFORM_FIRMWARE 13 +#define PLATFORM_SEPOS 14 + +#define PLATFORM_MACOS_EXCLAVECORE 15 +#define PLATFORM_MACOS_EXCLAVEKIT 16 +#define PLATFORM_IOS_EXCLAVECORE 17 +#define PLATFORM_IOS_EXCLAVEKIT 18 +#define PLATFORM_TVOS_EXCLAVECORE 19 +#define PLATFORM_TVOS_EXCLAVEKIT 20 +#define PLATFORM_WATCHOS_EXCLAVECORE 21 +#define PLATFORM_WATCHOS_EXCLAVEKIT 22 +#define PLATFORM_VISIONOS_EXCLAVECORE 23 +#define PLATFORM_VISIONOS_EXCLAVEKIT 24 + + + /* Known values for the tool field above. */ #define TOOL_CLANG 1 #define TOOL_SWIFT 2 #define TOOL_LD 3 +#define TOOL_LLD 4 + +/* values for gpu tools (1024 to 1048) */ +#define TOOL_METAL 1024 +#define TOOL_AIRLLD 1025 +#define TOOL_AIRNT 1026 +#define TOOL_AIRNT_PLUGIN 1027 +#define TOOL_AIRPACK 1028 +#define TOOL_GPUARCHIVER 1031 +#define TOOL_METAL_FRAMEWORK 1032 + /* * The dyld_info_command contains the file offsets and sizes of @@ -1323,18 +1452,18 @@ struct dyld_info_command { * the exported symbol information for the string so far. * If there is no exported symbol, the node starts with a zero byte. * If there is exported info, it follows the length. - * - * First is a uleb128 containing flags. Normally, it is followed by + * + * First is a uleb128 containing flags. Normally, it is followed by * a uleb128 encoded offset which is location of the content named * by the symbol from the mach_header for the image. If the flags * is EXPORT_SYMBOL_FLAGS_REEXPORT, then following the flags is * a uleb128 encoded library ordinal, then a zero terminated * UTF8 string. If the string is zero length, then the symbol * is re-export from the specified dylib with the same name. - * If the flags is EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER, then following - * the flags is two uleb128s: the stub offset and the resolver offset. - * The stub is used by non-lazy pointers. The resolver is used - * by lazy pointers and must be called to get the actual address to use. + * If the flags is EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER, then following + * the flags is two uleb128s: the stub offset and the resolver offset. + * The stub is used by non-lazy pointers. The resolver is used + * by lazy pointers and must be called to get the actual address to use. * * After the optional exported symbol information is a byte of * how many edges (0-255) that this node has leaving it, @@ -1378,6 +1507,7 @@ struct dyld_info_command { #define BIND_SPECIAL_DYLIB_SELF 0 #define BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE -1 #define BIND_SPECIAL_DYLIB_FLAT_LOOKUP -2 +#define BIND_SPECIAL_DYLIB_WEAK_LOOKUP -3 #define BIND_SYMBOL_FLAGS_WEAK_IMPORT 0x1 #define BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION 0x8 @@ -1397,6 +1527,9 @@ struct dyld_info_command { #define BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB 0xA0 #define BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED 0xB0 #define BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB 0xC0 +#define BIND_OPCODE_THREADED 0xD0 +#define BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB 0x00 +#define BIND_SUBOPCODE_THREADED_APPLY 0x01 /* @@ -1406,9 +1539,12 @@ struct dyld_info_command { #define EXPORT_SYMBOL_FLAGS_KIND_MASK 0x03 #define EXPORT_SYMBOL_FLAGS_KIND_REGULAR 0x00 #define EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL 0x01 +#define EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE 0x02 #define EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION 0x04 #define EXPORT_SYMBOL_FLAGS_REEXPORT 0x08 #define EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER 0x10 +#define EXPORT_SYMBOL_FLAGS_STATIC_RESOLVER 0x20 + /* * The linker_option_command contains linker options embedded in object files. @@ -1528,4 +1664,27 @@ struct note_command { uint64_t size; /* length of data region */ }; +/* + * LC_FILESET_ENTRY commands describe constituent Mach-O files that are part + * of a fileset. In one implementation, entries are dylibs with individual + * mach headers and repositionable text and data segments. Each entry is + * further described by its own mach header. + */ +struct fileset_entry_command { + uint32_t cmd; /* LC_FILESET_ENTRY */ + uint32_t cmdsize; /* includes entry_id string */ + uint64_t vmaddr; /* memory address of the entry */ + uint64_t fileoff; /* file offset of the entry */ + union lc_str entry_id; /* contained entry id */ + uint32_t reserved; /* reserved */ +}; + +/* + * These deprecated values may still be used within Apple but are mechanically + * removed from public API. The mechanical process may produce unusual results. + */ +#if (!defined(PLATFORM_IOSMAC)) +#define PLATFORM_IOSMAC PLATFORM_MACCATALYST +#endif + #endif /* _MACHO_LOADER_H_ */ diff --git a/third_party/darwin_xnu_macho/mach-o/nlist.h b/third_party/darwin_xnu_macho/mach-o/nlist.h index 133e36b4..2775fb8e 100644 --- a/third_party/darwin_xnu_macho/mach-o/nlist.h +++ b/third_party/darwin_xnu_macho/mach-o/nlist.h @@ -202,7 +202,7 @@ struct nlist_64 { /* * To simplify stripping of objects that use are used with the dynamic link * editor, the static link editor marks the symbols defined an object that are - * referenced by a dynamicly bound object (dynamic shared libraries, bundles). + * referenced by a dynamically bound object (dynamic shared libraries, bundles). * With this marking strip knows not to strip these symbols. */ #define REFERENCED_DYNAMICALLY 0x0010 @@ -302,6 +302,12 @@ struct nlist_64 { */ #define N_ALT_ENTRY 0x0200 +/* + * The N_COLD_FUNC bit of the n_desc field indicates that the symbol is used + * infrequently and the linker should order it towards the end of the section. + */ +#define N_COLD_FUNC 0x0400 + #ifndef __STRICT_BSD__ #ifdef __cplusplus extern "C" { diff --git a/third_party/darwin_xnu_macho/mach/machine.h b/third_party/darwin_xnu_macho/mach/machine.h index f8561a79..9516f4af 100644 --- a/third_party/darwin_xnu_macho/mach/machine.h +++ b/third_party/darwin_xnu_macho/mach/machine.h @@ -3,7 +3,7 @@ * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in @@ -12,10 +12,10 @@ * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. - * + * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -23,31 +23,31 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ -/* +/* * Mach Operating System * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University * All Rights Reserved. - * + * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. - * + * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * + * * Carnegie Mellon requests users of this software to return to - * + * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 - * + * * any improvements or extensions that they make and grant Carnegie Mellon * the rights to redistribute these changes. */ @@ -58,62 +58,124 @@ * Machine independent machine abstraction. */ -#ifndef _MACH_MACHINE_H_ +#ifndef _MACH_MACHINE_H_ #define _MACH_MACHINE_H_ #ifndef __ASSEMBLER__ #include +#if __has_include() +#include +#endif +#if __has_include() +#include +#endif + +/* Fallback definitions when system headers aren't available */ +#ifndef _MACH_MACHINE_VM_TYPES_H_ +typedef int32_t integer_t; +#endif + +typedef integer_t cpu_type_t; +typedef integer_t cpu_subtype_t; +typedef integer_t cpu_threadtype_t; + +#define CPU_STATE_MAX 4 + +#define CPU_STATE_USER 0 +#define CPU_STATE_SYSTEM 1 +#define CPU_STATE_IDLE 2 +#define CPU_STATE_NICE 3 + +#ifdef KERNEL_PRIVATE + +#include -typedef int32_t integer_t; +__BEGIN_DECLS +cpu_type_t cpu_type(void); -typedef integer_t cpu_type_t; -typedef integer_t cpu_subtype_t; -typedef integer_t cpu_threadtype_t; +cpu_subtype_t cpu_subtype(void); -#define CPU_STATE_MAX 4 +cpu_threadtype_t cpu_threadtype(void); +__END_DECLS -#define CPU_STATE_USER 0 -#define CPU_STATE_SYSTEM 1 -#define CPU_STATE_IDLE 2 -#define CPU_STATE_NICE 3 +#ifdef MACH_KERNEL_PRIVATE + +struct machine_info { + integer_t major_version; /* kernel major version id */ + integer_t minor_version; /* kernel minor version id */ + integer_t max_cpus; /* max number of CPUs possible */ + uint32_t memory_size; /* size of memory in bytes, capped at 2 GB */ + uint64_t max_mem; /* actual size of physical memory */ + uint32_t physical_cpu; /* number of physical CPUs now available */ + integer_t physical_cpu_max; /* max number of physical CPUs possible */ + uint32_t logical_cpu; /* number of logical cpu now available */ + integer_t logical_cpu_max; /* max number of physical CPUs possible */ +}; + +typedef struct machine_info *machine_info_t; +typedef struct machine_info machine_info_data_t; + +extern struct machine_info machine_info; + +__BEGIN_DECLS +cpu_type_t slot_type( + int slot_num); + +cpu_subtype_t slot_subtype( + int slot_num); + +cpu_threadtype_t slot_threadtype( + int slot_num); +__END_DECLS + +#endif /* MACH_KERNEL_PRIVATE */ +#endif /* KERNEL_PRIVATE */ /* * Capability bits used in the definition of cpu_type. */ -#define CPU_ARCH_MASK 0xff000000 /* mask for architecture bits */ -#define CPU_ARCH_ABI64 0x01000000 /* 64 bit ABI */ +#define CPU_ARCH_MASK 0xff000000 /* mask for architecture bits */ +#define CPU_ARCH_ABI64 0x01000000 /* 64 bit ABI */ +#define CPU_ARCH_ABI64_32 0x02000000 /* ABI for 64-bit hardware with 32-bit types; LP32 */ /* * Machine types known by all. */ - -#define CPU_TYPE_ANY ((cpu_type_t) -1) -#define CPU_TYPE_VAX ((cpu_type_t) 1) +#define CPU_TYPE_ANY ((cpu_type_t) -1) + +#define CPU_TYPE_VAX ((cpu_type_t) 1) /* skip ((cpu_type_t) 2) */ /* skip ((cpu_type_t) 3) */ /* skip ((cpu_type_t) 4) */ /* skip ((cpu_type_t) 5) */ -#define CPU_TYPE_MC680x0 ((cpu_type_t) 6) -#define CPU_TYPE_X86 ((cpu_type_t) 7) -#define CPU_TYPE_I386 CPU_TYPE_X86 /* compatibility */ -#define CPU_TYPE_X86_64 (CPU_TYPE_X86 | CPU_ARCH_ABI64) +#define CPU_TYPE_MC680x0 ((cpu_type_t) 6) +#define CPU_TYPE_X86 ((cpu_type_t) 7) +#define CPU_TYPE_I386 CPU_TYPE_X86 /* compatibility */ +#define CPU_TYPE_X86_64 (CPU_TYPE_X86 | CPU_ARCH_ABI64) /* skip CPU_TYPE_MIPS ((cpu_type_t) 8) */ -/* skip ((cpu_type_t) 9) */ -#define CPU_TYPE_MC98000 ((cpu_type_t) 10) +/* skip ((cpu_type_t) 9) */ +#define CPU_TYPE_MC98000 ((cpu_type_t) 10) #define CPU_TYPE_HPPA ((cpu_type_t) 11) -#define CPU_TYPE_ARM ((cpu_type_t) 12) +#define CPU_TYPE_ARM ((cpu_type_t) 12) #define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64) -#define CPU_TYPE_MC88000 ((cpu_type_t) 13) -#define CPU_TYPE_SPARC ((cpu_type_t) 14) -#define CPU_TYPE_I860 ((cpu_type_t) 15) +#define CPU_TYPE_ARM64_32 (CPU_TYPE_ARM | CPU_ARCH_ABI64_32) +#define CPU_TYPE_MC88000 ((cpu_type_t) 13) +#define CPU_TYPE_SPARC ((cpu_type_t) 14) +#define CPU_TYPE_I860 ((cpu_type_t) 15) /* skip CPU_TYPE_ALPHA ((cpu_type_t) 16) */ /* skip ((cpu_type_t) 17) */ -#define CPU_TYPE_POWERPC ((cpu_type_t) 18) -#define CPU_TYPE_POWERPC64 (CPU_TYPE_POWERPC | CPU_ARCH_ABI64) +#define CPU_TYPE_POWERPC ((cpu_type_t) 18) +#define CPU_TYPE_POWERPC64 (CPU_TYPE_POWERPC | CPU_ARCH_ABI64) +/* skip ((cpu_type_t) 19) */ +/* skip ((cpu_type_t) 20) */ +/* skip ((cpu_type_t) 21) */ +/* skip ((cpu_type_t) 22) */ +/* skip ((cpu_type_t) 23) */ +/* skip ((cpu_type_t) 24) */ /* * Machine subtypes (these are defined here, instead of in a machine @@ -124,9 +186,16 @@ typedef integer_t cpu_threadtype_t; /* * Capability bits used in the definition of cpu_subtype. */ -#define CPU_SUBTYPE_MASK 0xff000000 /* mask for feature flags */ -#define CPU_SUBTYPE_LIB64 0x80000000 /* 64 bit libraries */ +#define CPU_SUBTYPE_MASK 0xff000000 /* mask for feature flags */ +#define CPU_SUBTYPE_LIB64 0x80000000 /* 64 bit libraries */ +#define CPU_SUBTYPE_PTRAUTH_ABI 0x80000000 /* pointer authentication with versioned ABI */ +/* + * When selecting a slice, ANY will pick the slice with the best + * grading for the selected cpu_type_t, unlike the "ALL" subtypes, + * which are the slices that can run on any hardware for that cpu type. + */ +#define CPU_SUBTYPE_ANY ((cpu_subtype_t) -1) /* * Object files that are hand-crafted to run on any @@ -139,42 +208,42 @@ typedef integer_t cpu_threadtype_t; * It is the responsibility of the implementor to make sure the * software handles unsupported implementations elegantly. */ -#define CPU_SUBTYPE_MULTIPLE ((cpu_subtype_t) -1) -#define CPU_SUBTYPE_LITTLE_ENDIAN ((cpu_subtype_t) 0) -#define CPU_SUBTYPE_BIG_ENDIAN ((cpu_subtype_t) 1) +#define CPU_SUBTYPE_MULTIPLE ((cpu_subtype_t) -1) +#define CPU_SUBTYPE_LITTLE_ENDIAN ((cpu_subtype_t) 0) +#define CPU_SUBTYPE_BIG_ENDIAN ((cpu_subtype_t) 1) /* * Machine threadtypes. * This is none - not defined - for most machine types/subtypes. */ -#define CPU_THREADTYPE_NONE ((cpu_threadtype_t) 0) +#define CPU_THREADTYPE_NONE ((cpu_threadtype_t) 0) /* * VAX subtypes (these do *not* necessary conform to the actual cpu * ID assigned by DEC available via the SID register). */ -#define CPU_SUBTYPE_VAX_ALL ((cpu_subtype_t) 0) -#define CPU_SUBTYPE_VAX780 ((cpu_subtype_t) 1) -#define CPU_SUBTYPE_VAX785 ((cpu_subtype_t) 2) -#define CPU_SUBTYPE_VAX750 ((cpu_subtype_t) 3) -#define CPU_SUBTYPE_VAX730 ((cpu_subtype_t) 4) -#define CPU_SUBTYPE_UVAXI ((cpu_subtype_t) 5) -#define CPU_SUBTYPE_UVAXII ((cpu_subtype_t) 6) -#define CPU_SUBTYPE_VAX8200 ((cpu_subtype_t) 7) -#define CPU_SUBTYPE_VAX8500 ((cpu_subtype_t) 8) -#define CPU_SUBTYPE_VAX8600 ((cpu_subtype_t) 9) -#define CPU_SUBTYPE_VAX8650 ((cpu_subtype_t) 10) -#define CPU_SUBTYPE_VAX8800 ((cpu_subtype_t) 11) -#define CPU_SUBTYPE_UVAXIII ((cpu_subtype_t) 12) +#define CPU_SUBTYPE_VAX_ALL ((cpu_subtype_t) 0) +#define CPU_SUBTYPE_VAX780 ((cpu_subtype_t) 1) +#define CPU_SUBTYPE_VAX785 ((cpu_subtype_t) 2) +#define CPU_SUBTYPE_VAX750 ((cpu_subtype_t) 3) +#define CPU_SUBTYPE_VAX730 ((cpu_subtype_t) 4) +#define CPU_SUBTYPE_UVAXI ((cpu_subtype_t) 5) +#define CPU_SUBTYPE_UVAXII ((cpu_subtype_t) 6) +#define CPU_SUBTYPE_VAX8200 ((cpu_subtype_t) 7) +#define CPU_SUBTYPE_VAX8500 ((cpu_subtype_t) 8) +#define CPU_SUBTYPE_VAX8600 ((cpu_subtype_t) 9) +#define CPU_SUBTYPE_VAX8650 ((cpu_subtype_t) 10) +#define CPU_SUBTYPE_VAX8800 ((cpu_subtype_t) 11) +#define CPU_SUBTYPE_UVAXIII ((cpu_subtype_t) 12) /* - * 680x0 subtypes + * 680x0 subtypes * * The subtype definitions here are unusual for historical reasons. * NeXT used to consider 68030 code as generic 68000 code. For * backwards compatability: - * + * * CPU_SUBTYPE_MC68030 symbol has been preserved for source code * compatability. * @@ -185,119 +254,119 @@ typedef integer_t cpu_threadtype_t; * files to be tagged as containing 68030-specific instructions. */ -#define CPU_SUBTYPE_MC680x0_ALL ((cpu_subtype_t) 1) -#define CPU_SUBTYPE_MC68030 ((cpu_subtype_t) 1) /* compat */ -#define CPU_SUBTYPE_MC68040 ((cpu_subtype_t) 2) -#define CPU_SUBTYPE_MC68030_ONLY ((cpu_subtype_t) 3) +#define CPU_SUBTYPE_MC680x0_ALL ((cpu_subtype_t) 1) +#define CPU_SUBTYPE_MC68030 ((cpu_subtype_t) 1) /* compat */ +#define CPU_SUBTYPE_MC68040 ((cpu_subtype_t) 2) +#define CPU_SUBTYPE_MC68030_ONLY ((cpu_subtype_t) 3) /* * I386 subtypes */ -#define CPU_SUBTYPE_INTEL(f, m) ((cpu_subtype_t) (f) + ((m) << 4)) - -#define CPU_SUBTYPE_I386_ALL CPU_SUBTYPE_INTEL(3, 0) -#define CPU_SUBTYPE_386 CPU_SUBTYPE_INTEL(3, 0) -#define CPU_SUBTYPE_486 CPU_SUBTYPE_INTEL(4, 0) -#define CPU_SUBTYPE_486SX CPU_SUBTYPE_INTEL(4, 8) // 8 << 4 = 128 -#define CPU_SUBTYPE_586 CPU_SUBTYPE_INTEL(5, 0) -#define CPU_SUBTYPE_PENT CPU_SUBTYPE_INTEL(5, 0) -#define CPU_SUBTYPE_PENTPRO CPU_SUBTYPE_INTEL(6, 1) -#define CPU_SUBTYPE_PENTII_M3 CPU_SUBTYPE_INTEL(6, 3) -#define CPU_SUBTYPE_PENTII_M5 CPU_SUBTYPE_INTEL(6, 5) -#define CPU_SUBTYPE_CELERON CPU_SUBTYPE_INTEL(7, 6) -#define CPU_SUBTYPE_CELERON_MOBILE CPU_SUBTYPE_INTEL(7, 7) -#define CPU_SUBTYPE_PENTIUM_3 CPU_SUBTYPE_INTEL(8, 0) -#define CPU_SUBTYPE_PENTIUM_3_M CPU_SUBTYPE_INTEL(8, 1) -#define CPU_SUBTYPE_PENTIUM_3_XEON CPU_SUBTYPE_INTEL(8, 2) -#define CPU_SUBTYPE_PENTIUM_M CPU_SUBTYPE_INTEL(9, 0) -#define CPU_SUBTYPE_PENTIUM_4 CPU_SUBTYPE_INTEL(10, 0) -#define CPU_SUBTYPE_PENTIUM_4_M CPU_SUBTYPE_INTEL(10, 1) -#define CPU_SUBTYPE_ITANIUM CPU_SUBTYPE_INTEL(11, 0) -#define CPU_SUBTYPE_ITANIUM_2 CPU_SUBTYPE_INTEL(11, 1) -#define CPU_SUBTYPE_XEON CPU_SUBTYPE_INTEL(12, 0) -#define CPU_SUBTYPE_XEON_MP CPU_SUBTYPE_INTEL(12, 1) - -#define CPU_SUBTYPE_INTEL_FAMILY(x) ((x) & 15) -#define CPU_SUBTYPE_INTEL_FAMILY_MAX 15 - -#define CPU_SUBTYPE_INTEL_MODEL(x) ((x) >> 4) -#define CPU_SUBTYPE_INTEL_MODEL_ALL 0 +#define CPU_SUBTYPE_INTEL(f, m) ((cpu_subtype_t) (f) + ((m) << 4)) + +#define CPU_SUBTYPE_I386_ALL CPU_SUBTYPE_INTEL(3, 0) +#define CPU_SUBTYPE_386 CPU_SUBTYPE_INTEL(3, 0) +#define CPU_SUBTYPE_486 CPU_SUBTYPE_INTEL(4, 0) +#define CPU_SUBTYPE_486SX CPU_SUBTYPE_INTEL(4, 8) // 8 << 4 = 128 +#define CPU_SUBTYPE_586 CPU_SUBTYPE_INTEL(5, 0) +#define CPU_SUBTYPE_PENT CPU_SUBTYPE_INTEL(5, 0) +#define CPU_SUBTYPE_PENTPRO CPU_SUBTYPE_INTEL(6, 1) +#define CPU_SUBTYPE_PENTII_M3 CPU_SUBTYPE_INTEL(6, 3) +#define CPU_SUBTYPE_PENTII_M5 CPU_SUBTYPE_INTEL(6, 5) +#define CPU_SUBTYPE_CELERON CPU_SUBTYPE_INTEL(7, 6) +#define CPU_SUBTYPE_CELERON_MOBILE CPU_SUBTYPE_INTEL(7, 7) +#define CPU_SUBTYPE_PENTIUM_3 CPU_SUBTYPE_INTEL(8, 0) +#define CPU_SUBTYPE_PENTIUM_3_M CPU_SUBTYPE_INTEL(8, 1) +#define CPU_SUBTYPE_PENTIUM_3_XEON CPU_SUBTYPE_INTEL(8, 2) +#define CPU_SUBTYPE_PENTIUM_M CPU_SUBTYPE_INTEL(9, 0) +#define CPU_SUBTYPE_PENTIUM_4 CPU_SUBTYPE_INTEL(10, 0) +#define CPU_SUBTYPE_PENTIUM_4_M CPU_SUBTYPE_INTEL(10, 1) +#define CPU_SUBTYPE_ITANIUM CPU_SUBTYPE_INTEL(11, 0) +#define CPU_SUBTYPE_ITANIUM_2 CPU_SUBTYPE_INTEL(11, 1) +#define CPU_SUBTYPE_XEON CPU_SUBTYPE_INTEL(12, 0) +#define CPU_SUBTYPE_XEON_MP CPU_SUBTYPE_INTEL(12, 1) + +#define CPU_SUBTYPE_INTEL_FAMILY(x) ((x) & 15) +#define CPU_SUBTYPE_INTEL_FAMILY_MAX 15 + +#define CPU_SUBTYPE_INTEL_MODEL(x) ((x) >> 4) +#define CPU_SUBTYPE_INTEL_MODEL_ALL 0 /* * X86 subtypes. */ -#define CPU_SUBTYPE_X86_ALL ((cpu_subtype_t)3) -#define CPU_SUBTYPE_X86_64_ALL ((cpu_subtype_t)3) -#define CPU_SUBTYPE_X86_ARCH1 ((cpu_subtype_t)4) -#define CPU_SUBTYPE_X86_64_H ((cpu_subtype_t)8) /* Haswell feature subset */ +#define CPU_SUBTYPE_X86_ALL ((cpu_subtype_t)3) +#define CPU_SUBTYPE_X86_64_ALL ((cpu_subtype_t)3) +#define CPU_SUBTYPE_X86_ARCH1 ((cpu_subtype_t)4) +#define CPU_SUBTYPE_X86_64_H ((cpu_subtype_t)8) /* Haswell feature subset */ -#define CPU_THREADTYPE_INTEL_HTT ((cpu_threadtype_t) 1) +#define CPU_THREADTYPE_INTEL_HTT ((cpu_threadtype_t) 1) /* * Mips subtypes. */ -#define CPU_SUBTYPE_MIPS_ALL ((cpu_subtype_t) 0) -#define CPU_SUBTYPE_MIPS_R2300 ((cpu_subtype_t) 1) -#define CPU_SUBTYPE_MIPS_R2600 ((cpu_subtype_t) 2) -#define CPU_SUBTYPE_MIPS_R2800 ((cpu_subtype_t) 3) -#define CPU_SUBTYPE_MIPS_R2000a ((cpu_subtype_t) 4) /* pmax */ -#define CPU_SUBTYPE_MIPS_R2000 ((cpu_subtype_t) 5) -#define CPU_SUBTYPE_MIPS_R3000a ((cpu_subtype_t) 6) /* 3max */ -#define CPU_SUBTYPE_MIPS_R3000 ((cpu_subtype_t) 7) +#define CPU_SUBTYPE_MIPS_ALL ((cpu_subtype_t) 0) +#define CPU_SUBTYPE_MIPS_R2300 ((cpu_subtype_t) 1) +#define CPU_SUBTYPE_MIPS_R2600 ((cpu_subtype_t) 2) +#define CPU_SUBTYPE_MIPS_R2800 ((cpu_subtype_t) 3) +#define CPU_SUBTYPE_MIPS_R2000a ((cpu_subtype_t) 4) /* pmax */ +#define CPU_SUBTYPE_MIPS_R2000 ((cpu_subtype_t) 5) +#define CPU_SUBTYPE_MIPS_R3000a ((cpu_subtype_t) 6) /* 3max */ +#define CPU_SUBTYPE_MIPS_R3000 ((cpu_subtype_t) 7) /* * MC98000 (PowerPC) subtypes */ -#define CPU_SUBTYPE_MC98000_ALL ((cpu_subtype_t) 0) -#define CPU_SUBTYPE_MC98601 ((cpu_subtype_t) 1) +#define CPU_SUBTYPE_MC98000_ALL ((cpu_subtype_t) 0) +#define CPU_SUBTYPE_MC98601 ((cpu_subtype_t) 1) /* * HPPA subtypes for Hewlett-Packard HP-PA family of - * risc processors. Port by NeXT to 700 series. + * risc processors. Port by NeXT to 700 series. */ -#define CPU_SUBTYPE_HPPA_ALL ((cpu_subtype_t) 0) -#define CPU_SUBTYPE_HPPA_7100 ((cpu_subtype_t) 0) /* compat */ -#define CPU_SUBTYPE_HPPA_7100LC ((cpu_subtype_t) 1) +#define CPU_SUBTYPE_HPPA_ALL ((cpu_subtype_t) 0) +#define CPU_SUBTYPE_HPPA_7100 ((cpu_subtype_t) 0) /* compat */ +#define CPU_SUBTYPE_HPPA_7100LC ((cpu_subtype_t) 1) /* * MC88000 subtypes. */ -#define CPU_SUBTYPE_MC88000_ALL ((cpu_subtype_t) 0) -#define CPU_SUBTYPE_MC88100 ((cpu_subtype_t) 1) -#define CPU_SUBTYPE_MC88110 ((cpu_subtype_t) 2) +#define CPU_SUBTYPE_MC88000_ALL ((cpu_subtype_t) 0) +#define CPU_SUBTYPE_MC88100 ((cpu_subtype_t) 1) +#define CPU_SUBTYPE_MC88110 ((cpu_subtype_t) 2) /* * SPARC subtypes */ -#define CPU_SUBTYPE_SPARC_ALL ((cpu_subtype_t) 0) +#define CPU_SUBTYPE_SPARC_ALL ((cpu_subtype_t) 0) /* * I860 subtypes */ -#define CPU_SUBTYPE_I860_ALL ((cpu_subtype_t) 0) -#define CPU_SUBTYPE_I860_860 ((cpu_subtype_t) 1) +#define CPU_SUBTYPE_I860_ALL ((cpu_subtype_t) 0) +#define CPU_SUBTYPE_I860_860 ((cpu_subtype_t) 1) /* * PowerPC subtypes */ -#define CPU_SUBTYPE_POWERPC_ALL ((cpu_subtype_t) 0) -#define CPU_SUBTYPE_POWERPC_601 ((cpu_subtype_t) 1) -#define CPU_SUBTYPE_POWERPC_602 ((cpu_subtype_t) 2) -#define CPU_SUBTYPE_POWERPC_603 ((cpu_subtype_t) 3) -#define CPU_SUBTYPE_POWERPC_603e ((cpu_subtype_t) 4) -#define CPU_SUBTYPE_POWERPC_603ev ((cpu_subtype_t) 5) -#define CPU_SUBTYPE_POWERPC_604 ((cpu_subtype_t) 6) -#define CPU_SUBTYPE_POWERPC_604e ((cpu_subtype_t) 7) -#define CPU_SUBTYPE_POWERPC_620 ((cpu_subtype_t) 8) -#define CPU_SUBTYPE_POWERPC_750 ((cpu_subtype_t) 9) -#define CPU_SUBTYPE_POWERPC_7400 ((cpu_subtype_t) 10) -#define CPU_SUBTYPE_POWERPC_7450 ((cpu_subtype_t) 11) -#define CPU_SUBTYPE_POWERPC_970 ((cpu_subtype_t) 100) +#define CPU_SUBTYPE_POWERPC_ALL ((cpu_subtype_t) 0) +#define CPU_SUBTYPE_POWERPC_601 ((cpu_subtype_t) 1) +#define CPU_SUBTYPE_POWERPC_602 ((cpu_subtype_t) 2) +#define CPU_SUBTYPE_POWERPC_603 ((cpu_subtype_t) 3) +#define CPU_SUBTYPE_POWERPC_603e ((cpu_subtype_t) 4) +#define CPU_SUBTYPE_POWERPC_603ev ((cpu_subtype_t) 5) +#define CPU_SUBTYPE_POWERPC_604 ((cpu_subtype_t) 6) +#define CPU_SUBTYPE_POWERPC_604e ((cpu_subtype_t) 7) +#define CPU_SUBTYPE_POWERPC_620 ((cpu_subtype_t) 8) +#define CPU_SUBTYPE_POWERPC_750 ((cpu_subtype_t) 9) +#define CPU_SUBTYPE_POWERPC_7400 ((cpu_subtype_t) 10) +#define CPU_SUBTYPE_POWERPC_7450 ((cpu_subtype_t) 11) +#define CPU_SUBTYPE_POWERPC_970 ((cpu_subtype_t) 100) /* * ARM subtypes @@ -306,22 +375,47 @@ typedef integer_t cpu_threadtype_t; #define CPU_SUBTYPE_ARM_V4T ((cpu_subtype_t) 5) #define CPU_SUBTYPE_ARM_V6 ((cpu_subtype_t) 6) #define CPU_SUBTYPE_ARM_V5TEJ ((cpu_subtype_t) 7) -#define CPU_SUBTYPE_ARM_XSCALE ((cpu_subtype_t) 8) -#define CPU_SUBTYPE_ARM_V7 ((cpu_subtype_t) 9) -#define CPU_SUBTYPE_ARM_V7F ((cpu_subtype_t) 10) /* Cortex A9 */ -#define CPU_SUBTYPE_ARM_V7S ((cpu_subtype_t) 11) /* Swift */ -#define CPU_SUBTYPE_ARM_V7K ((cpu_subtype_t) 12) -#define CPU_SUBTYPE_ARM_V6M ((cpu_subtype_t) 14) /* Not meant to be run under xnu */ -#define CPU_SUBTYPE_ARM_V7M ((cpu_subtype_t) 15) /* Not meant to be run under xnu */ -#define CPU_SUBTYPE_ARM_V7EM ((cpu_subtype_t) 16) /* Not meant to be run under xnu */ - -#define CPU_SUBTYPE_ARM_V8 ((cpu_subtype_t) 13) +#define CPU_SUBTYPE_ARM_XSCALE ((cpu_subtype_t) 8) +#define CPU_SUBTYPE_ARM_V7 ((cpu_subtype_t) 9) /* ARMv7-A and ARMv7-R */ +#define CPU_SUBTYPE_ARM_V7F ((cpu_subtype_t) 10) /* Cortex A9 */ +#define CPU_SUBTYPE_ARM_V7S ((cpu_subtype_t) 11) /* Swift */ +#define CPU_SUBTYPE_ARM_V7K ((cpu_subtype_t) 12) +#define CPU_SUBTYPE_ARM_V8 ((cpu_subtype_t) 13) +#define CPU_SUBTYPE_ARM_V6M ((cpu_subtype_t) 14) /* Not meant to be run under xnu */ +#define CPU_SUBTYPE_ARM_V7M ((cpu_subtype_t) 15) /* Not meant to be run under xnu */ +#define CPU_SUBTYPE_ARM_V7EM ((cpu_subtype_t) 16) /* Not meant to be run under xnu */ +#define CPU_SUBTYPE_ARM_V8M ((cpu_subtype_t) 17) /* Not meant to be run under xnu */ +#define CPU_SUBTYPE_ARM_V8M_MAIN CPU_SUBTYPE_ARM_V8M /* Not meant to be run under xnu */ +#define CPU_SUBTYPE_ARM_V8M_BASE ((cpu_subtype_t) 18) /* Not meant to be run under xnu */ +#define CPU_SUBTYPE_ARM_V8_1M_MAIN ((cpu_subtype_t) 19) /* Not meant to be run under xnu */ /* * ARM64 subtypes */ #define CPU_SUBTYPE_ARM64_ALL ((cpu_subtype_t) 0) #define CPU_SUBTYPE_ARM64_V8 ((cpu_subtype_t) 1) +#define CPU_SUBTYPE_ARM64E ((cpu_subtype_t) 2) + +/* CPU subtype feature flags for ptrauth on arm64e platforms */ +#define CPU_SUBTYPE_ARM64_PTR_AUTH_MASK 0x0f000000 +#define CPU_SUBTYPE_ARM64_PTR_AUTH_VERSION(x) (((x) & CPU_SUBTYPE_ARM64_PTR_AUTH_MASK) >> 24) +#ifdef PRIVATE +#define CPU_SUBTYPE_ARM64_PTR_AUTHV0_VERSION 0 +#define CPU_SUBTYPE_ARM64_PTR_AUTHV1_VERSION 1 +#define CPU_SUBTYPE_ARM64_PTR_AUTH_CURRENT_VERSION CPU_SUBTYPE_ARM64_PTR_AUTHV0_VERSION +#if XNU_TARGET_OS_OSX +#define CPU_SUBTYPE_ARM64_PTR_AUTH_MAX_PREFERRED_VERSION CPU_SUBTYPE_ARM64_PTR_AUTHV1_VERSION +#else /* XNU_TARGET_OS_OSX */ +#define CPU_SUBTYPE_ARM64_PTR_AUTH_MAX_PREFERRED_VERSION CPU_SUBTYPE_ARM64_PTR_AUTHV0_VERSION +#endif /* XNU_TARGET_OS_OSX */ +#endif /* PRIVATE */ + +/* + * ARM64_32 subtypes + */ +#define CPU_SUBTYPE_ARM64_32_ALL ((cpu_subtype_t) 0) +#define CPU_SUBTYPE_ARM64_32_V8 ((cpu_subtype_t) 1) + #endif /* !__ASSEMBLER__ */ @@ -336,36 +430,59 @@ typedef integer_t cpu_threadtype_t; * Use feature flags (eg, hw.optional.altivec) to test for optional * functionality. */ -#define CPUFAMILY_UNKNOWN 0 -#define CPUFAMILY_POWERPC_G3 0xcee41549 -#define CPUFAMILY_POWERPC_G4 0x77c184ae -#define CPUFAMILY_POWERPC_G5 0xed76d8aa -#define CPUFAMILY_INTEL_6_13 0xaa33392b -#define CPUFAMILY_INTEL_PENRYN 0x78ea4fbc -#define CPUFAMILY_INTEL_NEHALEM 0x6b5a4cd2 -#define CPUFAMILY_INTEL_WESTMERE 0x573b5eec -#define CPUFAMILY_INTEL_SANDYBRIDGE 0x5490b78c -#define CPUFAMILY_INTEL_IVYBRIDGE 0x1f65e835 -#define CPUFAMILY_INTEL_HASWELL 0x10b282dc -#define CPUFAMILY_INTEL_BROADWELL 0x582ed09c -#define CPUFAMILY_INTEL_SKYLAKE 0x37fc219f -#define CPUFAMILY_INTEL_KABYLAKE 0x0f817246 -#define CPUFAMILY_ARM_9 0xe73283ae -#define CPUFAMILY_ARM_11 0x8ff620d8 -#define CPUFAMILY_ARM_XSCALE 0x53b005f5 +#define CPUFAMILY_UNKNOWN 0 +#define CPUFAMILY_POWERPC_G3 0xcee41549 +#define CPUFAMILY_POWERPC_G4 0x77c184ae +#define CPUFAMILY_POWERPC_G5 0xed76d8aa +#define CPUFAMILY_INTEL_6_13 0xaa33392b +#define CPUFAMILY_INTEL_PENRYN 0x78ea4fbc +#define CPUFAMILY_INTEL_NEHALEM 0x6b5a4cd2 +#define CPUFAMILY_INTEL_WESTMERE 0x573b5eec +#define CPUFAMILY_INTEL_SANDYBRIDGE 0x5490b78c +#define CPUFAMILY_INTEL_IVYBRIDGE 0x1f65e835 +#define CPUFAMILY_INTEL_HASWELL 0x10b282dc +#define CPUFAMILY_INTEL_BROADWELL 0x582ed09c +#define CPUFAMILY_INTEL_SKYLAKE 0x37fc219f +#define CPUFAMILY_INTEL_KABYLAKE 0x0f817246 +#define CPUFAMILY_INTEL_ICELAKE 0x38435547 +#define CPUFAMILY_INTEL_COMETLAKE 0x1cf8a03e +#define CPUFAMILY_ARM_9 0xe73283ae +#define CPUFAMILY_ARM_11 0x8ff620d8 +#define CPUFAMILY_ARM_XSCALE 0x53b005f5 #define CPUFAMILY_ARM_12 0xbd1b0ae9 -#define CPUFAMILY_ARM_13 0x0cc90e64 -#define CPUFAMILY_ARM_14 0x96077ef1 -#define CPUFAMILY_ARM_15 0xa8511bca -#define CPUFAMILY_ARM_SWIFT 0x1e2d6381 -#define CPUFAMILY_ARM_CYCLONE 0x37a09642 -#define CPUFAMILY_ARM_TYPHOON 0x2c91a47e -#define CPUFAMILY_ARM_TWISTER 0x92fb37c8 -#define CPUFAMILY_ARM_HURRICANE 0x67ceee93 +#define CPUFAMILY_ARM_13 0x0cc90e64 +#define CPUFAMILY_ARM_14 0x96077ef1 +#define CPUFAMILY_ARM_15 0xa8511bca +#define CPUFAMILY_ARM_SWIFT 0x1e2d6381 +#define CPUFAMILY_ARM_CYCLONE 0x37a09642 +#define CPUFAMILY_ARM_TYPHOON 0x2c91a47e +#define CPUFAMILY_ARM_TWISTER 0x92fb37c8 +#define CPUFAMILY_ARM_HURRICANE 0x67ceee93 +#define CPUFAMILY_ARM_MONSOON_MISTRAL 0xe81e7ef6 +#define CPUFAMILY_ARM_VORTEX_TEMPEST 0x07d34b9f +#define CPUFAMILY_ARM_LIGHTNING_THUNDER 0x462504d2 +#define CPUFAMILY_ARM_FIRESTORM_ICESTORM 0x1b588bb3 +#define CPUFAMILY_ARM_BLIZZARD_AVALANCHE 0xda33d83d +#define CPUFAMILY_ARM_EVEREST_SAWTOOTH 0x8765edea +#define CPUFAMILY_ARM_IBIZA 0xfa33415e +#define CPUFAMILY_ARM_PALMA 0x72015832 +#define CPUFAMILY_ARM_COLL 0x2876f5b5 +#define CPUFAMILY_ARM_LOBOS 0x5f4dea93 +#define CPUFAMILY_ARM_DONAN 0x6f5129ac +#define CPUFAMILY_ARM_BRAVA 0x17d5b93a + +/* Described in rdar://64125549 */ +#define CPUSUBFAMILY_UNKNOWN 0 +#define CPUSUBFAMILY_ARM_HP 1 +#define CPUSUBFAMILY_ARM_HG 2 +#define CPUSUBFAMILY_ARM_M 3 +#define CPUSUBFAMILY_ARM_HS 4 +#define CPUSUBFAMILY_ARM_HC_HD 5 +#define CPUSUBFAMILY_ARM_HA 6 /* The following synonyms are deprecated: */ -#define CPUFAMILY_INTEL_6_23 CPUFAMILY_INTEL_PENRYN -#define CPUFAMILY_INTEL_6_26 CPUFAMILY_INTEL_NEHALEM +#define CPUFAMILY_INTEL_6_23 CPUFAMILY_INTEL_PENRYN +#define CPUFAMILY_INTEL_6_26 CPUFAMILY_INTEL_NEHALEM -#endif /* _MACH_MACHINE_H_ */ +#endif /* _MACH_MACHINE_H_ */ diff --git a/third_party/darwin_xnu_macho/mach/vm_prot.h b/third_party/darwin_xnu_macho/mach/vm_prot.h index 6998a31f..a4ae13c3 100644 --- a/third_party/darwin_xnu_macho/mach/vm_prot.h +++ b/third_party/darwin_xnu_macho/mach/vm_prot.h @@ -1,8 +1,8 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2021 Apple Computer, Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in @@ -11,10 +11,10 @@ * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. - * + * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -22,34 +22,34 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* * @OSF_COPYRIGHT@ */ -/* +/* * Mach Operating System * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University * All Rights Reserved. - * + * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. - * + * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * + * * Carnegie Mellon requests users of this software to return to - * + * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 - * + * * any improvements or extensions that they make and grant Carnegie Mellon * the rights to redistribute these changes. */ @@ -63,8 +63,8 @@ * */ -#ifndef _MACH_VM_PROT_H_ -#define _MACH_VM_PROT_H_ +#ifndef _MACH_VM_PROT_H_ +#define _MACH_VM_PROT_H_ /* * Types defined: @@ -72,29 +72,40 @@ * vm_prot_t VM protection values. */ -typedef int vm_prot_t; +typedef int vm_prot_t; /* * Protection values, defined as bits within the vm_prot_t type + * + * When making a new VM_PROT_*, update tests vm_parameter_validation_[user|kern] + * and their expected results; they deliberately call VM functions with invalid + * vm_prot values and you may be turning one of those invalid protections valid. */ -#define VM_PROT_NONE ((vm_prot_t) 0x00) +#define VM_PROT_NONE ((vm_prot_t) 0x00) -#define VM_PROT_READ ((vm_prot_t) 0x01) /* read permission */ -#define VM_PROT_WRITE ((vm_prot_t) 0x02) /* write permission */ -#define VM_PROT_EXECUTE ((vm_prot_t) 0x04) /* execute permission */ +#define VM_PROT_READ ((vm_prot_t) 0x01) /* read permission */ +#define VM_PROT_WRITE ((vm_prot_t) 0x02) /* write permission */ +#define VM_PROT_EXECUTE ((vm_prot_t) 0x04) /* execute permission */ /* * The default protection for newly-created virtual memory */ -#define VM_PROT_DEFAULT (VM_PROT_READ|VM_PROT_WRITE) +#define VM_PROT_DEFAULT (VM_PROT_READ|VM_PROT_WRITE) /* * The maximum privileges possible, for parameter checking. */ -#define VM_PROT_ALL (VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE) +#define VM_PROT_ALL (VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE) + +/* + * This is an alias to VM_PROT_EXECUTE to identify callers that + * want to allocate an hardware assisted Read-only/read-write + * trusted path in userland. + */ +#define VM_PROT_RORW_TP (VM_PROT_EXECUTE) /* * An invalid protection value. @@ -103,15 +114,16 @@ typedef int vm_prot_t; * looks like VM_PROT_ALL and then some. */ -#define VM_PROT_NO_CHANGE ((vm_prot_t) 0x08) +#define VM_PROT_NO_CHANGE_LEGACY ((vm_prot_t) 0x08) +#define VM_PROT_NO_CHANGE ((vm_prot_t) 0x01000000) -/* +/* * When a caller finds that he cannot obtain write permission on a * mapped entry, the following flag can be used. The entry will * be made "needs copy" effectively copying the object (using COW), * and write permission will be added to the maximum protections - * for the associated entry. - */ + * for the associated entry. + */ #define VM_PROT_COPY ((vm_prot_t) 0x10) @@ -127,7 +139,7 @@ typedef int vm_prot_t; * walking down the shadow chain. */ -#define VM_PROT_WANTS_COPY ((vm_prot_t) 0x10) +#define VM_PROT_WANTS_COPY ((vm_prot_t) 0x10) #ifdef PRIVATE /* @@ -135,15 +147,15 @@ typedef int vm_prot_t; * code signature. */ -#define VM_PROT_TRUSTED ((vm_prot_t) 0x20) +#define VM_PROT_TRUSTED ((vm_prot_t) 0x20) #endif /* PRIVATE */ /* - * Another invalid protection value. + * Another invalid protection value. * Indicates that the other protection bits are to be applied as a mask * against the actual protection bits of the map entry. */ -#define VM_PROT_IS_MASK ((vm_prot_t) 0x40) +#define VM_PROT_IS_MASK ((vm_prot_t) 0x40) /* * Another invalid protection value to support execute-only protection. @@ -154,7 +166,42 @@ typedef int vm_prot_t; * the memory should be executable and explicitly not readable. It will * be ignored on platforms that do not support this type of protection. */ -#define VM_PROT_STRIP_READ ((vm_prot_t) 0x80) -#define VM_PROT_EXECUTE_ONLY (VM_PROT_EXECUTE|VM_PROT_STRIP_READ) +#define VM_PROT_STRIP_READ ((vm_prot_t) 0x80) +#define VM_PROT_EXECUTE_ONLY (VM_PROT_EXECUTE|VM_PROT_STRIP_READ) + +#ifdef PRIVATE +/* + * When using VM_PROT_COPY, fail instead of copying an executable mapping, + * since that could cause code-signing violations. + */ +#define VM_PROT_COPY_FAIL_IF_EXECUTABLE ((vm_prot_t)0x100) +#endif /* PRIVATE */ + +/* + * Another invalid protection value to support pager TPRO protection. + * VM_PROT_TPRO is a special marker that tells the a pager to + * set TPRO flags on a given entry. We do it this way to prevent + * bloating the pager structures and it allows dyld to pass through + * this flag in lieue of specifying explicit VM flags, allowing us to handle + * the final permissions internally. + */ +#define VM_PROT_TPRO ((vm_prot_t) 0x200) + +#if defined(__x86_64__) +/* + * Another invalid protection value to support specifying different + * execute permissions for user- and supervisor- modes. When + * MBE is enabled in a VM, VM_PROT_EXECUTE is used to indicate + * supervisor-mode execute permission, and VM_PROT_UEXEC specifies + * user-mode execute permission. Currently only used by the + * x86 Hypervisor kext. + */ +#define VM_PROT_UEXEC ((vm_prot_t) 0x8) /* User-mode Execute Permission */ + +#define VM_PROT_ALLEXEC (VM_PROT_EXECUTE | VM_PROT_UEXEC) +#else +#define VM_PROT_ALLEXEC (VM_PROT_EXECUTE) +#endif /* defined(__x86_64__) */ + -#endif /* _MACH_VM_PROT_H_ */ +#endif /* _MACH_VM_PROT_H_ */ From 145b78cb1d40a214d7b8a928f16c4e115c0b5bc3 Mon Sep 17 00:00:00 2001 From: Ryan Mansfield Date: Thu, 13 Nov 2025 13:22:11 -0500 Subject: [PATCH 2/2] Adds Python scripts and documentation to make the header update process fully reproducible. Usage: # To update headers to versions specified in METADATA: python3 update_headers.py # To regenerate patches after manual modifications: python3 generate_patches.py Current patches: - mach_machine.h.patch: Adds __has_include() guards and fallback typedefs - mach-o_loader.h.patch: Uses bundled header instead of system header Fixes #438 --- third_party/darwin_xnu_macho/README.md | 78 +++++ .../darwin_xnu_macho/generate_patches.py | 204 ++++++++++++ .../patches/mach-o_loader.h.patch | 13 + .../patches/mach_machine.h.patch | 21 ++ .../darwin_xnu_macho/update_headers.py | 308 ++++++++++++++++++ 5 files changed, 624 insertions(+) create mode 100644 third_party/darwin_xnu_macho/README.md create mode 100644 third_party/darwin_xnu_macho/generate_patches.py create mode 100644 third_party/darwin_xnu_macho/patches/mach-o_loader.h.patch create mode 100644 third_party/darwin_xnu_macho/patches/mach_machine.h.patch create mode 100644 third_party/darwin_xnu_macho/update_headers.py diff --git a/third_party/darwin_xnu_macho/README.md b/third_party/darwin_xnu_macho/README.md new file mode 100644 index 00000000..7acf4e1e --- /dev/null +++ b/third_party/darwin_xnu_macho/README.md @@ -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 ` to `#include "../mach/vm_prot.h"` to use bundled header diff --git a/third_party/darwin_xnu_macho/generate_patches.py b/third_party/darwin_xnu_macho/generate_patches.py new file mode 100644 index 00000000..e41c2a7f --- /dev/null +++ b/third_party/darwin_xnu_macho/generate_patches.py @@ -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()) diff --git a/third_party/darwin_xnu_macho/patches/mach-o_loader.h.patch b/third_party/darwin_xnu_macho/patches/mach-o_loader.h.patch new file mode 100644 index 00000000..86c70a89 --- /dev/null +++ b/third_party/darwin_xnu_macho/patches/mach-o_loader.h.patch @@ -0,0 +1,13 @@ +--- loader.h.orig 2025-11-05 14:28:11 ++++ loader.h 2025-11-05 14:16:53 +@@ -40,9 +40,7 @@ + * is needed here for the vm_prot_t type and contains the + * constants that are or'ed together for the possible values of this type. + */ +-#if __has_include() +-#include +-#endif ++#include "../mach/vm_prot.h" + + /* + * is expected to define the flavors of the thread diff --git a/third_party/darwin_xnu_macho/patches/mach_machine.h.patch b/third_party/darwin_xnu_macho/patches/mach_machine.h.patch new file mode 100644 index 00000000..4605925e --- /dev/null +++ b/third_party/darwin_xnu_macho/patches/mach_machine.h.patch @@ -0,0 +1,21 @@ +--- machine.h.orig 2025-11-05 14:28:10 ++++ machine.h 2025-11-05 14:16:53 +@@ -64,9 +64,18 @@ + #ifndef __ASSEMBLER__ + + #include ++#if __has_include() + #include ++#endif ++#if __has_include() + #include ++#endif + ++/* Fallback definitions when system headers aren't available */ ++#ifndef _MACH_MACHINE_VM_TYPES_H_ ++typedef int32_t integer_t; ++#endif ++ + typedef integer_t cpu_type_t; + typedef integer_t cpu_subtype_t; + typedef integer_t cpu_threadtype_t; diff --git a/third_party/darwin_xnu_macho/update_headers.py b/third_party/darwin_xnu_macho/update_headers.py new file mode 100644 index 00000000..a1d5882c --- /dev/null +++ b/third_party/darwin_xnu_macho/update_headers.py @@ -0,0 +1,308 @@ +#!/usr/bin/env python3 +""" +Script to update darwin_xnu_macho headers from upstream sources. + +This script fetches headers from Apple's open source repositories and applies +local modifications to make them work cross-platform in bloaty. + +Usage: python3 update_headers.py [--dry-run] + +The script will: +1. Parse METADATA to get the git repository URLs and commit hashes +2. Fetch the specified headers from those commits +3. Apply local modifications via patch files +4. Update the headers in place +""" + +import argparse +import os +import re +import subprocess +import sys +import urllib.request +import urllib.error +from pathlib import Path +from typing import Dict, List, Tuple + + +# Format: (source_path_in_repo, destination_path) +XNU_HEADERS = [ + ("osfmk/mach/machine.h", "mach/machine.h"), + ("osfmk/mach/vm_prot.h", "mach/vm_prot.h"), +] + +CCTOOLS_HEADERS = [ + ("include/mach-o/fat.h", "mach-o/fat.h"), + ("include/mach-o/loader.h", "mach-o/loader.h"), + ("include/mach-o/nlist.h", "mach-o/nlist.h"), +] + + +class MetadataParser: + """Parser for the METADATA file format.""" + + def __init__(self, metadata_path: Path): + self.metadata_path = metadata_path + with open(metadata_path, 'r') as f: + self.content = f.read() + + def parse_third_party_blocks(self) -> List[Dict[str, str]]: + """Parse all third_party blocks from METADATA.""" + blocks = [] + current_block = None + in_third_party = False + brace_depth = 0 + + for line in self.content.split('\n'): + original_line = line + line = line.strip() + + if line == 'third_party {': + in_third_party = True + brace_depth = 1 + current_block = {} + elif line.endswith('{') and in_third_party: + # Nested block like "url {", just track depth + brace_depth += 1 + elif line == '}' and in_third_party: + brace_depth -= 1 + if brace_depth == 0: + # End of third_party block + in_third_party = False + if current_block: + blocks.append(current_block) + current_block = None + elif in_third_party and current_block is not None: + # Parse fields like: value: "https://..." or version: "abc123" + # Also handle unquoted fields like: version: abc123 + match = re.match(r'(\w+):\s*"([^"]+)"', line) + if match: + key, value = match.groups() + current_block[key] = value + else: + # Try without quotes + match = re.match(r'(\w+):\s*(\S+)', line) + if match: + key, value = match.groups() + current_block[key] = value + + return blocks + + def get_repo_info(self, repo_name: str) -> Tuple[str, str]: + """ + Get repository URL and version for a specific repo. + + Args: + repo_name: Either "xnu" or "cctools" + + Returns: + Tuple of (url, version) + """ + blocks = self.parse_third_party_blocks() + + for block in blocks: + url = block.get('value', '') + if repo_name in url: + return url, block.get('version', '') + + raise ValueError(f"Could not find {repo_name} repository in METADATA") + + +def fetch_file_from_github(repo_url: str, commit: str, source_path: str) -> bytes: + """ + Fetch a file from GitHub at a specific commit. + + Args: + repo_url: Git repository URL (e.g., https://github.com/apple-oss-distributions/xnu) + commit: Git commit hash + source_path: Path to file within the repository + + Returns: + File contents as bytes + """ + # Convert git URL to raw.githubusercontent.com URL + # https://github.com/apple-oss-distributions/xnu -> + # https://raw.githubusercontent.com/apple-oss-distributions/xnu + if 'github.com' not in repo_url: + raise ValueError(f"Unsupported repository URL: {repo_url}") + + repo_path = repo_url.replace('https://github.com/', '') + repo_path = repo_path.replace('.git', '') + raw_url = f"https://raw.githubusercontent.com/{repo_path}/{commit}/{source_path}" + + print(f" Downloading: {raw_url}") + + try: + with urllib.request.urlopen(raw_url, timeout=30) as response: + return response.read() + except urllib.error.HTTPError as e: + raise RuntimeError(f"Failed to download {raw_url}: {e}") + except urllib.error.URLError as e: + raise RuntimeError(f"Network error downloading {raw_url}: {e}") + except Exception as e: + raise RuntimeError(f"Unexpected error downloading {raw_url}: {type(e).__name__}: {e}") + + +def apply_patches(script_dir: Path, dry_run: bool) -> None: + """ + Apply patch files from the patches/ directory to .new files. + After applying, the .new files are renamed to their final names. + + Args: + script_dir: Directory containing this script + dry_run: If True, only print what would be done + """ + patch_dir = script_dir / "patches" + + if not patch_dir.exists(): + print(" No patches directory found") + if not dry_run: + print(" Creating patches directory for future use") + patch_dir.mkdir(parents=True, exist_ok=True) + return + + patch_files = sorted(patch_dir.glob("*.patch")) + if not patch_files: + print(" No patch files found") + return + + # Temporarily rename .new files to their final names so patches can apply + renamed_files = [] + if not dry_run: + for new_file in script_dir.rglob("*.new"): + final_name = Path(str(new_file)[:-4]) # Remove '.new' + if final_name.exists(): + final_name.unlink() + new_file.rename(final_name) + renamed_files.append(final_name) + + # Map patch files to the directories where they should be applied + patch_dirs = { + "mach_machine.h.patch": "mach", + "mach_vm_prot.h.patch": "mach", + "mach-o_loader.h.patch": "mach-o", + "mach-o_fat.h.patch": "mach-o", + "mach-o_nlist.h.patch": "mach-o", + } + + for patch_file in patch_files: + print(f" Applying: {patch_file.name}") + if not dry_run: + # Determine which directory to apply the patch in + patch_dir = script_dir / patch_dirs.get(patch_file.name, ".") + + result = subprocess.run( + ["patch", "-p0", "-f", "--no-backup-if-mismatch", "-i", str(patch_file.absolute())], + cwd=patch_dir, + capture_output=True, + text=True, + input="" # Provide empty stdin to avoid hanging on prompts + ) + if result.returncode != 0: + print(f" Warning: patch returned {result.returncode}") + if result.stderr: + print(f" stderr: {result.stderr}") + if result.stdout: + print(f" stdout: {result.stdout}") + else: + print(f" Success") + + if not dry_run and renamed_files: + print(" Headers installed with local modifications applied") + + +def main(): + parser = argparse.ArgumentParser( + description="Update darwin_xnu_macho headers from upstream sources" + ) + parser.add_argument( + "--dry-run", + action="store_true", + help="Show what would be done without making changes" + ) + args = parser.parse_args() + + script_dir = Path(__file__).parent.resolve() + os.chdir(script_dir) + + print("=== Darwin XNU Mach-O Header Update Script ===") + print() + + if args.dry_run: + print("Dry run mode - No files will be modified") + print() + + metadata_path = script_dir / "METADATA" + if not metadata_path.exists(): + print(f"Error: METADATA file not found at {metadata_path}") + return 1 + + metadata_parser = MetadataParser(metadata_path) + + try: + xnu_url, xnu_version = metadata_parser.get_repo_info("xnu") + cctools_url, cctools_version = metadata_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() + + print("=== Fetching XNU headers ===") + for source_path, dest_path in XNU_HEADERS: + print(f" {source_path} -> {dest_path}") + if not args.dry_run: + try: + content = fetch_file_from_github(xnu_url, xnu_version, source_path) + dest_file = script_dir / (dest_path + ".new") + dest_file.parent.mkdir(parents=True, exist_ok=True) + with open(dest_file, 'wb') as f: + f.write(content) + print(f" Saved to: {dest_file}") + except Exception as e: + print(f" Error: {e}") + return 1 + print() + + print("=== Fetching cctools headers ===") + for source_path, dest_path in CCTOOLS_HEADERS: + print(f" {source_path} -> {dest_path}") + if not args.dry_run: + try: + content = fetch_file_from_github(cctools_url, cctools_version, source_path) + dest_file = script_dir / (dest_path + ".new") + dest_file.parent.mkdir(parents=True, exist_ok=True) + with open(dest_file, 'wb') as f: + f.write(content) + print(f" Saved to: {dest_file}") + except Exception as e: + print(f" Error: {e}") + return 1 + print() + + if args.dry_run: + print("=== Dry run complete ===") + return 0 + + print("=== Applying local modifications ===") + apply_patches(script_dir, args.dry_run) + print() + + print("=== Update complete ===") + print() + print("Next steps:") + print("1. Review the changes: git diff") + print("2. If there are new local modifications needed, edit the headers") + print("3. Generate patches: python3 generate_patches.py") + print("4. Update METADATA last_upgrade_date to today's date") + print("5. Commit the changes") + + return 0 + + +if __name__ == "__main__": + sys.exit(main())