ARCH(3)
π ARCH(3) β the one where we learn everyone's architecture π
okay bestie, so this is ARCH(3), the Mach-O architecture-info page, and it's lowkey a whole vibe. it's all about the NXArchInfo world β asking the system what CPU types and subtypes exist, finding the right slice in a fat binary, all that. no cap, you're gonna want this one in your back pocket. π«Ά
β¨ NAME β¨
NXGetAllArchInfos, NXGetLocalArchInfo, NXGetArchInfoFromName, NXGetArchInfoFromCpuType, NXFreeArchInfo, NXFindBestFatArch, NXCombineCpuSubtypes β get architecture information
like, all of these are the little friend group that tells you everything about architectures. β¨ literally the whole squad is here:
NXGetAllArchInfosβ the "gimme the entire roster" oneNXGetLocalArchInfoβ the "what am I running on tho" oneNXGetArchInfoFromNameβ the "look it up by name" oneNXGetArchInfoFromCpuTypeβ the "look it up by cpu type + subtype" oneNXFreeArchInfoβ the cleanup crew, the one who takes out the trash ποΈNXFindBestFatArchβ the matchmaker for fat binaries (32-bit flavoured)NXCombineCpuSubtypesβ the "can we merge these two subtypes or nah" one
and don't forget the synopsis below is packing NXFindBestFatArch_64 too β it's in the header, she's just not in the NAME list. iykyk. π
π SYNOPSIS π
first thing's first, you gotta invite the header to the party:
#include <mach-o/arch.h>
and here's every single signature, exactly as they live in the wild β no touch-ups, promise π:
extern const NXArchInfo *
NXGetAllArchInfos(void);
extern const NXArchInfo *
NXGetLocalArchInfo(void);
extern const NXArchInfo *
NXGetArchInfoFromName(const char *name);
extern const NXArchInfo *
NXGetArchInfoFromCpuType(cpu_type_t cputype, cpu_subtype_t cpusubtype);
extern void
NXFreeArchInfo(NXArchInfo *x);
extern struct fat_arch *
NXFindBestFatArch(cpu_type_t cputype, cpu_subtype_t cpusubtype,
struct fat_arch *fat_archs, uint32_t nfat_archs);
extern struct fat_arch_64 *
NXFindBestFatArch_64(cpu_type_t cputype, cpu_subtype_t cpusubtype,
struct fat_arch_64 *fat_archs64, uint32_t nfat_archs);
extern cpu_subtype_t
NXCombineCpuSubtypes(cpu_type_t cputype, cpu_subtype_t cpusubtype1,
cpu_subtype_t cpusubtype2);
πΈ note bestie: five of these hand you back aconst NXArchInfo *,NXFreeArchInforeturnsvoid(she's just here to freex, no receipts), and the two fat-arch finders return pointers into your ownstruct fat_arch/struct fat_arch_64arrays. keep the exact types in mind βcpu_type_t,cpu_subtype_t,uint32_t,struct fat_arch,struct fat_arch_64. no guessing, no vibes-based typing. π
okay that's the header and the cast of characters β the juicy DESCRIPTION and OPTIONS bits are coming up next, so stay tuned bestie, we're not done yet π
π DESCRIPTION
okay so bestie, listen β these functions are literally made for programs that have to deal with universal files, or programs that can target multiple architectures at once. You know how a program will usually take a command-line argument that starts with -arch name, where that thing specifies an architecture? Yeah. That. These functions and data structures are here to help you process those architecture flags and then go deal with the contents of a universal file. π«Ά
The structure NXArchInfo is defined in β¨mach-o/arch.hβ©:
typedef struct {
const char *name;
cpu_type_t cputype;
cpu_subtype_t cpusubtype;
enum NXByteOrder byteorder;
const char *description;
} NXArchInfo;
It's the whole package, honestly β it holds the name of the architecture, the corresponding CPU type and CPU subtype, plus the architecture's byte order and a lil brief description string. Iconic behaviour. β¨
π the currently known architectures (yes, all of them, bestie)
The currently known architectures are:
x86_64β CPU typeCPU_TYPE_X86_64, CPU subtypeCPU_SUBTYPE_X86_64_ALLβ Intel x86-64i386β CPU typeCPU_TYPE_I386, CPU subtypeCPU_SUBTYPE_I386_ALLβ Intel 80x86armβ CPU typeCPU_TYPE_ARM, CPU subtypeCPU_SUBTYPE_ARM_ALLβ ARMarm64β CPU typeCPU_TYPE_ARM64, CPU subtypeCPU_SUBTYPE_ARM64_ALLβ ARM64arm64eβ CPU typeCPU_TYPE_ARM64, CPU subtypeCPU_SUBTYPE_ARM64Eβ ARM64Earm64_32β CPU typeCPU_TYPE_ARM64_32, CPU subtypeCPU_SUBTYPE_ARM64_32_V8β ARM64_32ppcβ CPU typeCPU_TYPE_POWERPC, CPU subtypeCPU_SUBTYPE_POWERPC_ALLβ PowerPCppc64β CPU typeCPU_TYPE_POWERPC64, CPU subtypeCPU_SUBTYPE_POWERPC64_ALLβ PowerPC 64-bitm68kβ CPU typeCPU_TYPE_MC680x0, CPU subtypeCPU_SUBTYPE_MC680x0_ALLβ Motorola 68Khppaβ CPU typeCPU_TYPE_HPPA, CPU subtypeCPU_SUBTYPE_HPPA_ALLβ HP-PAi860β CPU typeCPU_TYPE_I860, CPU subtypeCPU_SUBTYPE_I860_ALLβ Intel 860m88kβ CPU typeCPU_TYPE_MC88000, CPU subtypeCPU_SUBTYPE_MC88000_ALLβ Motorola 88Ksparcβ CPU typeCPU_TYPE_SPARC, CPU subtypeCPU_SUBTYPE_SPARC_ALLβ SPARCi486β CPU typeCPU_TYPE_I386, CPU subtypeCPU_SUBTYPE_486β Intel 486i486SXβ CPU typeCPU_TYPE_I386, CPU subtypeCPU_SUBTYPE_486SXβ Intel 486SXpentiumβ CPU typeCPU_TYPE_I386, CPU subtypeCPU_SUBTYPE_PENTβ Intel Pentiumi586β CPU typeCPU_TYPE_I386, CPU subtypeCPU_SUBTYPE_586β Intel 586pentproβ CPU typeCPU_TYPE_I386, CPU subtypeCPU_SUBTYPE_PENTPROβ Intel Pentium Proi686β CPU typeCPU_TYPE_I386, CPU subtypeCPU_SUBTYPE_PENTPROβ Intel Pentium PropentIIm3β CPU typeCPU_TYPE_I386, CPU subtypeCPU_SUBTYPE_PENTII_M3β Intel Pentium II Model 3pentIIm5β CPU typeCPU_TYPE_I386, CPU subtypeCPU_SUBTYPE_PENTII_M5β Intel Pentium II Model 5pentium4β CPU typeCPU_TYPE_I386, CPU subtypeCPU_SUBTYPE_PENTIUM_4β Intel Pentium 4armv4tβ CPU typeCPU_TYPE_ARM, CPU subtypeCPU_SUBTYPE_ARM_V4Tβ arm v4tarmv5β CPU typeCPU_TYPE_ARM, CPU subtypeCPU_SUBTYPE_ARM_V5TEJβ arm v5xscaleβ CPU typeCPU_TYPE_ARM, CPU subtypeCPU_SUBTYPE_ARM_XSCALEβ arm xscalearmv6β CPU typeCPU_TYPE_ARM, CPU subtypeCPU_SUBTYPE_ARM_V6β arm v6armv6mβ CPU typeCPU_TYPE_ARM, CPU subtypeCPU_SUBTYPE_ARM_V6Mβ arm v6marmv7β CPU typeCPU_TYPE_ARM, CPU subtypeCPU_SUBTYPE_ARM_V7β arm v7armv7fβ CPU typeCPU_TYPE_ARM, CPU subtypeCPU_SUBTYPE_ARM_V7Fβ arm v7farmv7sβ CPU typeCPU_TYPE_ARM, CPU subtypeCPU_SUBTYPE_ARM_V7Sβ arm v7sarmv7kβ CPU typeCPU_TYPE_ARM, CPU subtypeCPU_SUBTYPE_ARM_V7Kβ arm v7karmv7mβ CPU typeCPU_TYPE_ARM, CPU subtypeCPU_SUBTYPE_ARM_V7Mβ arm v7marmv7emβ CPU typeCPU_TYPE_ARM, CPU subtypeCPU_SUBTYPE_ARM_V7EMβ arm v7emarmv8β CPU typeCPU_TYPE_ARM, CPU subtypeCPU_SUBTYPE_ARM_V8β arm v8arm64β CPU typeCPU_TYPE_ARM64, CPU subtypeCPU_SUBTYPE_ARM64_V8β arm64 v8ppc601β CPU typeCPU_TYPE_POWERPC, CPU subtypeCPU_SUBTYPE_POWERPC_601β PowerPC 601ppc603β CPU typeCPU_TYPE_POWERPC, CPU subtypeCPU_SUBTYPE_POWERPC_603β PowerPC 603ppc604β CPU typeCPU_TYPE_POWERPC, CPU subtypeCPU_SUBTYPE_POWERPC_604β PowerPC 604ppc604eβ CPU typeCPU_TYPE_POWERPC, CPU subtypeCPU_SUBTYPE_POWERPC_604eβ PowerPC 604eppc750β CPU typeCPU_TYPE_POWERPC, CPU subtypeCPU_SUBTYPE_POWERPC_750β PowerPC 750ppc7400β CPU typeCPU_TYPE_POWERPC, CPU subtypeCPU_SUBTYPE_POWERPC_7400β PowerPC 7400ppc7450β CPU typeCPU_TYPE_POWERPC, CPU subtypeCPU_SUBTYPE_POWERPC_7450β PowerPC 7450ppc970β CPU typeCPU_TYPE_POWERPC, CPU subtypeCPU_SUBTYPE_POWERPC_970β PowerPC 970m68030β CPU typeCPU_TYPE_MC680x0, CPU subtypeCPU_SUBTYPE_MC68030_ONLYβ Motorola 68030m68040β CPU typeCPU_TYPE_MC680x0, CPU subtypeCPU_SUBTYPE_MC68040β Motorola 68040hppa7100LCβ CPU typeCPU_TYPE_HPPA, CPU subtypeCPU_SUBTYPE_HPPA_7100LCβ HP-PA 7100LC
The first set of entries is what you use for the architecture family, mkay? The second set of entries is for when you want one specific architecture β that's the case when more than one specific architecture is supported inside a family of architectures. π¦
π the functions, one by one
NXGetAllArchInfos() returns a pointer to an array of all known NXArchInfo structures. The last NXArchInfo is marked by a NULL name β that's how you know you've hit the end, bestie, don't keep walking. π
NXGetLocalArchInfo() returns the NXArchInfo for the local host, or NULL if none is known.
NXGetArchInfoFromName() and NXGetArchInfoFromCpuType() return the NXArchInfo from the architecture's name, or from the CPU type / CPU subtype combination. A CPU subtype of CPU_SUBTYPE_MULTIPLE can be used to request the most general NXArchInfo known for the given CPU type. NULL is returned if no matching NXArchInfo can be found. no match, no drama, just NULL. π
NXFreeArchInfo() gets passed a pointer to an NXArchInfo returned by the above interfaces, and if that thing is not in the array returned in NXGetAllArchInfos(), it will free(3) the description field and then the NXArchInfo pointer. clean up after yourself, it's giving main character energy. β¨
π the whole malloc situation (read this one, fr fr)
The above interfaces that return pointers to NXArchInfo structs in normal cases return a pointer from the array returned in NXGetAllArchInfos(). But in some cases, when the cputype is CPU_TYPE_I386 or CPU_TYPE_POWERPC, it will return a malloc(3)'ed NXArchInfo struct which contains a string in the description field that is also a malloc(3)'ed pointer. To allow programs not to leak memory, they can call NXFreeArchInfo() on pointers returned from the above interfaces. Since this is a new API on older systems, you can use the code below. Going forward, the above interfaces will only return pointers from the array returned in NXGetAllArchInfos().
static void NXFreeArchInfo(
const NXArchInfo *x)
{
const NXArchInfo *p;
p = NXGetAllArchInfos();
while(p->name != NULL){
if(x == p)
return;
p++;
}
free((char *)x->description);
free((NXArchInfo *)x);
}
lowkey important: use that snippet if you're on an older system, because leaking memory is not the vibe. π
NXFindBestFatArch() gets passed a CPU type and CPU subtype plus a set of fat_arch structs. It selects the best one that matches (if any) and returns a pointer to that fat_arch struct (or NULL). The fat_arch structs must be in the host byte order, and correct such that fat_archs really points to enough memory for nfat_archs structs. Heads up though: it's possible that this routine could fail if new CPU types or CPU subtypes are added and an old version of this routine is used. But β if there's an exact match between the CPU type and CPU subtype and one of the fat_arch structs, this routine will always succeed. always. π«Ά
NXFindBestFatArch_64() is the same as NXFindBestFatArch() but returns and takes fat_arch_64 structs. same energy, wider ints. π¦
NXCombineCpuSubtypes() returns the resulting CPU subtype when combining two different CPU subtypes for the specified CPU type. If the two CPU subtypes can't be combined (the specific subtypes are mutually exclusive), -1 is returned, indicating it's an error to combine them. This can also fail and return -1 if new CPU types or CPU subtypes are added and an old version of this routine is used. But if the CPU subtypes are the same, they can always be combined and this routine will return the CPU subtype passed in. them matching? slay. π
πΈ SEE ALSO
that's the whole page, bestie β go forth and process those architecture flags π
β§ο½₯οΎ ARCH(3), from the June 8, 2016 era, part of the macOS/BSD man page family β§ο½₯οΎ π
π¦ where this page comes from
- nixpkgs unstable: cctools 1010.6
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms