{"slug":"dinh-dang-mach-o-mach-object-la-gi-nguon-goc-cau-truc-va-dac-ta-ky-thuat","title":"Định dạng Mach-O (Mach Object) là gì? Nguồn gốc, cấu trúc và đặc tả kỹ thuật","summary":"Mach-O (Mach Object) là định dạng tệp nhị phân được sử dụng trong hệ sinh thái Apple để biểu diễn mã đối tượng, tệp thực thi, thư viện dùng chung và những loại ảnh nhị phân khác. Mach-O cung cấp một hệ thống cấu trúc để mô tả kiến trúc bộ xử lý, loại tệp, các vùng mã lệnh và dữ liệu, thông tin ký hiệu, tái định vị, liên kết động và những yêu cầu phục vụ quá trình nạp chương trình.","excerpt":"Mach-O (Mach Object) là định dạng tệp nhị phân được sử dụng trong hệ sinh thái Apple để biểu diễn mã đối tượng, tệp thực thi, thư viện dùng chung và những loại ảnh nhị phân khác. Mach-O cung cấp một hệ thống cấu trúc để mô tả kiến trúc bộ xử lý, loại tệp, các vùng mã lệnh và dữ liệu, thông tin ký hiệu, tái định vị, liên kết động và những yêu cầu phục vụ quá trình nạp chương trình.","markdown":"# Định dạng Mach-O (Mach Object) là gì? Nguồn gốc, cấu trúc và đặc tả kỹ thuật\n\n## Tóm tắt\n\nMach-O (Mach Object) là định dạng tệp nhị phân được sử dụng trong hệ sinh thái Apple để biểu diễn mã đối tượng, tệp thực thi, thư viện dùng chung và những loại ảnh nhị phân khác. Mach-O cung cấp một hệ thống cấu trúc để mô tả kiến trúc bộ xử lý, loại tệp, các vùng mã lệnh và dữ liệu, thông tin ký hiệu, tái định vị, liên kết động và những yêu cầu phục vụ quá trình nạp chương trình.\n\nKhác với định dạng ELF (Executable and Linkable Format), vốn sử dụng hệ thống header dành cho section và program segment, Mach-O tổ chức một phần lớn thông tin điều khiển thông qua các lệnh nạp (Load Commands). Những lệnh này cho biết các vùng nào của tệp phải được ánh xạ vào bộ nhớ, thư viện nào cần được nạp và các cấu trúc liên kết bổ sung được lưu ở đâu.\n\nNguồn gốc Mach-O gắn với hệ sinh thái Mach, các hệ điều hành NeXT và quá trình hình thành Mac OS X. Qua nhiều thế hệ, định dạng này được mở rộng để phục vụ nhiều kiến trúc phần cứng, đặc biệt là PowerPC, x86-64 và ARM64.\n\nBài viết khảo sát lịch sử phát triển của Mach-O, cấu trúc nhị phân, các loại header, load command, segment, section, bảng ký hiệu, relocation, cơ chế liên kết động, universal binary, quá trình nạp và thực thi, cùng những quy định liên quan đến chữ ký mã trên các nền tảng Apple.\n\nBài viết sử dụng những định nghĩa trong mã nguồn XNU và tài liệu của Apple làm căn cứ chính cho phần mô tả cấu trúc. Các ví dụ về địa chỉ, bố cục và kết quả công cụ được trình bày dưới dạng minh họa khi không phải là dữ liệu trích xuất từ một tệp Mach-O thực tế.\n\n**Từ khóa:** Mach-O; Mach Object; định dạng nhị phân; tệp thực thi; Apple; macOS; XNU; dyld; load command; segment; section; relocation; universal binary; ABI.\n\n\n\n## 1. Mach-O là gì?\n\n### 1.1. Định nghĩa\n\nMach-O là một định dạng tệp đối tượng và ảnh nhị phân, được dùng để lưu trữ những thông tin mà bộ liên kết, bộ nạp và hệ điều hành cần sử dụng trong quá trình xây dựng hoặc thực thi chương trình.\n\nTùy thuộc vào mục đích, tệp Mach-O có thể chứa:\n\nMã máy đã được biên dịch.\nDữ liệu tĩnh và dữ liệu chỉ đọc.\nCác vùng bộ nhớ cần khởi tạo.\nBảng ký hiệu.\nThông tin tái định vị.\nThông tin liên kết với thư viện động.\nThông tin về điểm vào chương trình.\nChữ ký mã và siêu dữ liệu nền tảng.\n\nMach-O là định dạng nhị phân, không phải ngôn ngữ lập trình, tập lệnh CPU hay một loại mã máy riêng.\n\nMã máy được chứa trong tệp Mach-O vẫn phụ thuộc vào kiến trúc bộ xử lý, chẳng hạn x86-64 hoặc ARM64.\n\n### 1.2. Mach-O được sử dụng ở đâu?\n\nMach-O xuất hiện trong nhiều sản phẩm nhị phân của Apple:\n\n| Loại sản phẩm | Vai trò |\n|---|---|\n| Tệp đối tượng `.o` | Đầu vào hoặc đầu ra trung gian của quá trình liên kết |\n| Tệp thực thi | Chứa chương trình để hệ điều hành nạp và khởi chạy |\n| Thư viện động `.dylib` | Cung cấp mã và dữ liệu cho chương trình khác |\n| Bundle nhị phân | Thành phần mã có thể được nạp theo cơ chế phù hợp |\n| Tệp dSYM | Có thể chứa ảnh Mach-O phục vụ thông tin gỡ lỗi |\n| Ảnh nhị phân hệ thống | Một số thành phần của hệ điều hành và môi trường thực thi |\n\nMach-O được sử dụng trên macOS, iOS, iPadOS, watchOS, tvOS và những nền tảng Apple có liên quan, dù quyền thực thi và các quy định kỹ thuật của mỗi nền tảng có thể khác nhau.\n\n### 1.3. Mach-O và tệp ứng dụng `.app`\n\nMột ứng dụng macOS thường được đóng gói dưới dạng một thư mục bundle có phần mở rộng `.app`.\n\nVí dụ:\n\nExample.app/\n└── Contents/\n├── Info.plist\n├── MacOS/\n│   └── Example\n└── Resources/\n\n\nTrong ví dụ này:\n\n`Example.app` là gói ứng dụng.\n`Info.plist` chứa siêu dữ liệu ứng dụng.\n`Contents/MacOS/Example` có thể là tệp thực thi Mach-O.\n\nVì vậy, **Mach-O là định dạng của tệp nhị phân bên trong ứng dụng, không phải định dạng của toàn bộ thư mục `.app`.**\n\n\n\n## 2. Nguồn gốc và lịch sử phát triển\n\n### 2.1. Mối liên hệ với hệ thống Mach\n\nTên Mach-O bắt nguồn từ Mach Object.\n\nMach là một họ thiết kế nhân hệ điều hành được nghiên cứu tại Đại học Carnegie Mellon trong những năm 1980, với các cơ chế như tác vụ, luồng, bộ nhớ ảo và giao tiếp giữa tiến trình.\n\nMach-O gắn với lịch sử hệ điều hành dựa trên Mach, đặc biệt là các hệ thống NeXT và sau này là Darwin, nền tảng hệ thống của Mac OS X.\n\nCần lưu ý rằng Mach-O không phải một phần của tập lệnh CPU, cũng không đồng nghĩa với kiến trúc nhân Mach.\n\nNhân hệ điều hành và định dạng tệp thực thi là hai thành phần khác nhau, dù có quan hệ chặt chẽ trong quá trình nạp và quản lý chương trình.\n\n### 2.2. NeXTSTEP và sự chuyển tiếp sang Mac OS X\n\nNeXTSTEP là hệ điều hành do NeXT phát triển, kết hợp các thành phần dựa trên Mach và những đặc điểm của hệ thống Unix.\n\nMach-O được gắn với hệ sinh thái NeXT và tiếp tục giữ vai trò quan trọng trong dòng hệ điều hành phát triển từ công nghệ này.\n\nSau khi Apple mua lại NeXT vào năm 1997, nhiều thành phần công nghệ của NeXT trở thành cơ sở cho thế hệ hệ điều hành Mac OS X.\n\nMach-O tiếp tục được sử dụng làm định dạng nhị phân quan trọng trong nền tảng mới.\n\nMac OS X 10.0 được phát hành năm 2001, đánh dấu sự xuất hiện thương mại của thế hệ hệ điều hành này.\n\n### 2.3. Quá trình mở rộng theo kiến trúc CPU\n\nMach-O đã được sử dụng qua nhiều giai đoạn chuyển đổi phần cứng.\n\n| Giai đoạn | Kiến trúc tiêu biểu | Ý nghĩa |\n|---|---|---|\n| Hệ thống NeXT | Motorola 68k, x86 và những kiến trúc được hỗ trợ khác | Giai đoạn lịch sử của môi trường Mach/NeXT |\n| Mac OS X thời kỳ đầu | PowerPC | Mach-O trong hệ sinh thái Macintosh mới |\n| Chuyển sang Intel | x86, x86-64 | Hỗ trợ thế hệ máy Mac Intel |\n| Chuyển sang Apple silicon | ARM64 | Hỗ trợ kiến trúc ARM64 trên máy Mac |\n\nSự tồn tại của nhiều kiến trúc đã thúc đẩy việc sử dụng các tệp nhị phân đa kiến trúc, thường được gọi là universal binary.\n\n### 2.4. Mach-O 32 bit và 64 bit\n\nMach-O có cấu trúc header dành cho cả kiến trúc 32 bit và 64 bit.\n\nHai loại này không chỉ khác nhau về kích thước con trỏ, mà còn có các cấu trúc mô tả segment và section khác nhau.\n\nVí dụ, định nghĩa chính thức sử dụng:\n\nstruct mach_header;\nstruct mach_header_64;\n\n\nTương ứng với các loại tệp Mach-O 32 bit và 64 bit.\n\nCác trường địa chỉ và kích thước bộ nhớ trong những cấu trúc segment 64 bit được biểu diễn bằng kiểu dữ liệu rộng hơn.\n\n\n\n## 3. Cấu trúc tổng thể của tệp Mach-O\n\n### 3.1. Mô hình tổ chức\n\nMột tệp Mach-O thông thường có thể được hình dung như sau:\n\n┌─────────────────────────────────┐\n│ Mach Header                     │\n│ - Magic                         │\n│ - CPU Type                      │\n│ - File Type                     │\n│ - Number of Load Commands       │\n├─────────────────────────────────┤\n│ Load Commands                   │\n│ - Segment Commands              │\n│ - Symbol Table Information      │\n│ - Dynamic Linking Information   │\n│ - Entry Point Information       │\n├─────────────────────────────────┤\n│ Nội dung các Segment            │\n│ - Machine Code                  │\n│ - Read-only Data                │\n│ - Writable Data                 │\n├─────────────────────────────────┤\n│ Link-edit Data                  │\n│ - Symbols                       │\n│ - Fixups / Bindings             │\n│ - Other Metadata                │\n├─────────────────────────────────┤\n│ Code Signature, nếu có          │\n└─────────────────────────────────┘\n\n\nĐây là sơ đồ khái quát nhằm giúp người đọc hình dung các nhóm thông tin.\n\nKhông phải tất cả vùng dữ liệu đều nằm thành những khối liên tiếp theo đúng thứ tự minh họa. Vị trí thực tế được xác định bằng các trường offset, kích thước và quy tắc của từng cấu trúc.\n\n### 3.2. Ba thành phần cấu trúc cơ bản\n\nCó thể tiếp cận Mach-O qua ba thành phần chính.\n\n**Mach Header**\n\nXác định định dạng, kiến trúc CPU, loại tệp và thông tin tổng quát về danh sách lệnh nạp.\n\n**Load Commands**\n\nMô tả các cấu trúc quan trọng của ảnh nhị phân và cung cấp thông tin để bộ nạp, bộ liên kết hoặc công cụ phân tích xử lý tệp.\n\n**Segments và Sections**\n\nTổ chức mã máy, dữ liệu và những vùng bộ nhớ cần ánh xạ hoặc xử lý.\n\nCác thành phần khác như bảng ký hiệu và thông tin fixup được tham chiếu thông qua những cấu trúc phù hợp, thay vì bắt buộc có một bảng section toàn cục riêng như trong ELF.\n\n\n\n## 4. Mach Header\n\n### 4.1. Header 64 bit\n\nTrong tệp header chính thức `mach-o/loader.h`, Apple định nghĩa:\n\nstruct mach_header_64 {\nuint32_t magic;\ncpu_type_t cputype;\ncpu_subtype_t cpusubtype;\nuint32_t filetype;\nuint32_t ncmds;\nuint32_t sizeofcmds;\nuint32_t flags;\nuint32_t reserved;\n};\n\n\nỞ đây, `cpu_type_t` và `cpu_subtype_t` được biểu diễn bằng kiểu số nguyên 32 bit theo các định nghĩa liên quan.\n\nKích thước của `mach_header_64` là 32 byte.\n\n### 4.2. Bố cục từng trường\n\n| Offset | Trường | Kích thước | Ý nghĩa |\n|---|---|---:|---|\n| `0x00` | `magic` | 4 byte | Giá trị nhận diện định dạng |\n| `0x04` | `cputype` | 4 byte | Loại CPU |\n| `0x08` | `cpusubtype` | 4 byte | Phân loại chi tiết CPU |\n| `0x0C` | `filetype` | 4 byte | Loại tệp Mach-O |\n| `0x10` | `ncmds` | 4 byte | Số lượng load command |\n| `0x14` | `sizeofcmds` | 4 byte | Tổng số byte của load commands |\n| `0x18` | `flags` | 4 byte | Những cờ mô tả thuộc tính ảnh |\n| `0x1C` | `reserved` | 4 byte | Trường dự trữ |\n\nTổng kích thước:\n\n■\n\nHeader 32 bit có bảy trường đầu tiên và không có trường `reserved`, nên có kích thước 28 byte.\n\n### 4.3. Magic Number\n\nMach-O dùng những giá trị nhận diện để xác định loại header và thứ tự byte.\n\n| Hằng số | Giá trị |\n|---|---|\n| `MH_MAGIC` | `0xFEEDFACE` |\n| `MH_CIGAM` | `0xCEFAEDFE` |\n| `MH_MAGIC_64` | `0xFEEDFACF` |\n| `MH_CIGAM_64` | `0xCFFAEDFE` |\n\nCác giá trị `CIGAM` là dạng đảo thứ tự byte của những giá trị tương ứng.\n\nVí dụ, trên hệ little-endian, giá trị 32 bit `0xFEEDFACF` được lưu thành chuỗi byte:\n\nCF FA ED FE\n\n\nVì vậy, khi đọc một tệp nhị phân, cần xem xét chuỗi byte thực tế và cách giải mã endianness, thay vì chỉ đối chiếu văn bản hexa một cách máy móc.\n\n### 4.4. Loại tệp (File Type)\n\nTrường `filetype` xác định mục đích của ảnh Mach-O.\n\n| Hằng số | Giá trị | Ý nghĩa |\n|---|---|---|\n| `MH_OBJECT` | `0x1` | Tệp đối tượng có thể tái định vị |\n| `MH_EXECUTE` | `0x2` | Tệp thực thi |\n| `MH_CORE` | `0x4` | Ảnh core |\n| `MH_DYLIB` | `0x6` | Thư viện dùng chung động |\n| `MH_DYLINKER` | `0x7` | Bộ liên kết động |\n| `MH_BUNDLE` | `0x8` | Bundle nhị phân có thể liên kết động |\n| `MH_DSYM` | `0xA` | Ảnh phục vụ dữ liệu gỡ lỗi |\n| `MH_KEXT_BUNDLE` | `0xB` | Một dạng bundle mở rộng nhân có tính lịch sử và giới hạn nền tảng |\n| `MH_FILESET` | `0xC` | Ảnh chứa tập hợp các Mach-O theo cấu trúc fileset |\n\nCác hằng số này được định nghĩa trong `mach-o/loader.h`.\n\nKhông phải mọi loại tệp đều có thể được khởi chạy trực tiếp như một chương trình ứng dụng.\n\n\n\n## 5. Lệnh nạp (Load Commands)\n\n### 5.1. Khái niệm\n\nLoad command là một thành phần thiết yếu của Mach-O.\n\nSau Mach header là danh sách các load command, mỗi lệnh mô tả một loại thông tin phục vụ liên kết, ánh xạ bộ nhớ, nạp chương trình hoặc quản lý siêu dữ liệu.\n\nApple định nghĩa cấu trúc cơ sở:\n\nstruct load_command {\nuint32_t cmd;\nuint32_t cmdsize;\n};\n\n\nHai trường này có tổng kích thước 8 byte.\n\n`cmd`: Mã xác định loại load command.\n`cmdsize`: Kích thước toàn bộ command, bao gồm cả dữ liệu phụ thuộc nếu có.\n\nĐể tìm command tiếp theo, chương trình đọc nhị phân sử dụng `cmdsize` nhằm tính vị trí mới.\n\n### 5.2. Quy tắc căn chỉnh\n\nTheo định nghĩa của Apple:\n\nTrong Mach-O 32 bit, kích thước mỗi load command phải là bội số của 4 byte.\nTrong Mach-O 64 bit, kích thước mỗi load command phải là bội số của 8 byte.\n\nNhững byte đệm cần thiết được đặt về 0.\n\nVí dụ, nếu một command 64 bit chứa 27 byte dữ liệu thực tế, tổng kích thước phải được làm tròn phù hợp với yêu cầu căn chỉnh.\n\nViệc xử lý `cmdsize` không hợp lệ là một vấn đề quan trọng đối với trình đọc Mach-O, bởi một giá trị sai có thể khiến bộ phân tích truy cập vượt giới hạn dữ liệu đầu vào.\n\n### 5.3. Các load command quan trọng\n\n| Load Command | Chức năng |\n|---|---|\n| `LC_SEGMENT` | Mô tả segment 32 bit |\n| `LC_SEGMENT_64` | Mô tả segment 64 bit |\n| `LC_SYMTAB` | Thông tin bảng ký hiệu và bảng chuỗi |\n| `LC_DYSYMTAB` | Thông tin ký hiệu liên quan đến liên kết động theo cơ chế truyền thống |\n| `LC_LOAD_DYLIB` | Khai báo phụ thuộc thư viện động |\n| `LC_ID_DYLIB` | Nhận diện thư viện động |\n| `LC_LOAD_DYLINKER` | Khai báo bộ liên kết động |\n| `LC_MAIN` | Thông tin điểm vào của tệp thực thi |\n| `LC_RPATH` | Bổ sung đường dẫn tìm thư viện |\n| `LC_UUID` | Mã định danh của ảnh nhị phân |\n| `LC_CODE_SIGNATURE` | Vị trí dữ liệu chữ ký mã |\n| `LC_BUILD_VERSION` | Thông tin nền tảng, phiên bản hệ điều hành tối thiểu và SDK |\n| `LC_DYLD_EXPORTS_TRIE` | Vị trí cấu trúc xuất ký hiệu dạng trie |\n| `LC_DYLD_CHAINED_FIXUPS` | Thông tin fixup dạng chuỗi |\n| `LC_FILESET_ENTRY` | Thông tin thành phần trong ảnh fileset |\n\nKhông phải tệp Mach-O nào cũng chứa tất cả các lệnh trên.\n\nVí dụ, tệp đối tượng `MH_OBJECT` có yêu cầu khác với ảnh thực thi `MH_EXECUTE`.\n\n### 5.4. Load command bắt buộc đối với dyld\n\nMach-O sử dụng cờ `LC_REQ_DYLD` với giá trị:\n\n#define LC_REQ_DYLD 0x80000000\n\n\nCờ này đánh dấu những loại load command mà bộ liên kết động cần hiểu để xử lý ảnh đúng cách.\n\nTheo mô tả trong mã nguồn Apple, nếu dyld gặp một load command được đánh dấu bắt buộc nhưng không nhận biết được, nó có thể từ chối sử dụng ảnh đó.\n\nCơ chế này cho phép định dạng phát triển thêm những yêu cầu mới mà không mặc nhiên chấp nhận ảnh thực thi có ngữ nghĩa không được hỗ trợ.\n\n\n\n## 6. Segment và Section\n\n### 6.1. Segment là gì?\n\nSegment mô tả một vùng của tệp nhị phân được ánh xạ vào không gian địa chỉ của tiến trình.\n\nĐối với Mach-O 64 bit, Apple định nghĩa:\n\nstruct segment_command_64 {\nuint32_t cmd;\nuint32_t cmdsize;\nchar segname[16];\nuint64_t vmaddr;\nuint64_t vmsize;\nuint64_t fileoff;\nuint64_t filesize;\nvm_prot_t maxprot;\nvm_prot_t initprot;\nuint32_t nsects;\nuint32_t flags;\n};\n\n\nKích thước phần cố định của cấu trúc này là 72 byte.\n\nNếu segment chứa các section, những bản ghi `section_64` được đặt tiếp sau cấu trúc segment trong cùng load command.\n\n### 6.2. Các trường của Segment Command 64 bit\n\n| Trường | Kích thước | Ý nghĩa |\n|---|---:|---|\n| `cmd` | 4 byte | Loại command |\n| `cmdsize` | 4 byte | Kích thước command và các section đi kèm |\n| `segname` | 16 byte | Tên segment |\n| `vmaddr` | 8 byte | Địa chỉ bộ nhớ ảo |\n| `vmsize` | 8 byte | Kích thước trong bộ nhớ |\n| `fileoff` | 8 byte | Vị trí nội dung segment trong tệp |\n| `filesize` | 8 byte | Kích thước nội dung lưu trong tệp |\n| `maxprot` | 4 byte | Quyền bộ nhớ tối đa |\n| `initprot` | 4 byte | Quyền bộ nhớ ban đầu |\n| `nsects` | 4 byte | Số section |\n| `flags` | 4 byte | Các cờ của segment |\n\nTrong nhiều trường hợp:\n\n■\n\nPhần bộ nhớ lớn hơn lượng dữ liệu lưu trong tệp có thể được hệ thống cấp phát với giá trị ban đầu bằng 0 theo quy định của cơ chế nạp.\n\n### 6.3. Section là gì?\n\nSection là đơn vị tổ chức mã, dữ liệu hoặc siêu dữ liệu bên trong segment.\n\nMột cấu trúc `section_64` có các trường chính:\n\nstruct section_64 {\nchar sectname[16];\nchar segname[16];\nuint64_t addr;\nuint64_t size;\nuint32_t offset;\nuint32_t align;\nuint32_t reloff;\nuint32_t nreloc;\nuint32_t flags;\nuint32_t reserved1;\nuint32_t reserved2;\nuint32_t reserved3;\n};\n\n\nKích thước cấu trúc cố định là 80 byte.\n\nCác trường quan trọng:\n\n| Trường | Chức năng |\n|---|---|\n| `sectname` | Tên section |\n| `segname` | Tên segment chứa section |\n| `addr` | Địa chỉ bộ nhớ ảo của section |\n| `size` | Kích thước section |\n| `offset` | Offset dữ liệu trong tệp, đối với loại section có nội dung lưu trong tệp |\n| `align` | Số mũ của yêu cầu căn chỉnh |\n| `reloff` | Offset thông tin relocation |\n| `nreloc` | Số bản ghi relocation |\n| `flags` | Loại section và các thuộc tính |\n| `reserved1–3` | Các trường bổ sung, có ý nghĩa tùy loại section |\n\n### 6.4. Các segment thường gặp\n\n| Segment | Nội dung điển hình |\n|---|---|\n| `__PAGEZERO` | Vùng địa chỉ thấp không được ánh xạ, hỗ trợ hạn chế truy cập con trỏ null |\n| `__TEXT` | Mã thực thi và dữ liệu chỉ đọc hoặc tương ứng với cấu trúc liên kết |\n| `__DATA` | Dữ liệu có thể ghi và các cấu trúc liên quan |\n| `__DATA_CONST` | Dữ liệu cần xử lý trong quá trình liên kết động nhưng có thể được bảo vệ sau đó |\n| `__LINKEDIT` | Dữ liệu hỗ trợ liên kết, ký hiệu, fixup và các cấu trúc khác |\n\nDanh sách này chỉ là những tên phổ biến, không phải toàn bộ các segment hợp lệ.\n\nBố cục thực tế có thể thay đổi theo phiên bản hệ điều hành, trình biên dịch, linker và kiến trúc CPU.\n\n### 6.5. Các section thường gặp\n\nTrong segment `__TEXT`:\n\n| Section | Nội dung |\n|---|---|\n| `__text` | Mã máy |\n| `__cstring` | Chuỗi ký tự kiểu C |\n| `__const` | Một số dữ liệu hằng |\n| `__stubs` | Những đoạn mã hỗ trợ gọi hàm hoặc liên kết, nếu có |\n\nTrong segment dữ liệu:\n\n| Section | Nội dung |\n|---|---|\n| `__data` | Dữ liệu có giá trị khởi tạo |\n| `__bss` | Dữ liệu chưa khởi tạo |\n| `__common` | Một số đối tượng dữ liệu theo cơ chế truyền thống |\n| `__la_symbol_ptr` | Vùng con trỏ ký hiệu theo cơ chế liên kết truyền thống |\n\nTên và vị trí section không phải là một giao diện chung bất biến cho mọi thế hệ Mach-O.\n\n\n\n## 7. Bảng ký hiệu và cơ chế tái định vị\n\n### 7.1. Bảng ký hiệu (Symbol Table)\n\nMach-O hỗ trợ bảng ký hiệu để mô tả các hàm, đối tượng dữ liệu và những tên cần sử dụng trong quá trình liên kết hoặc phân tích nhị phân.\n\nLoad command `LC_SYMTAB` sử dụng cấu trúc:\n\nstruct symtab_command {\nuint32_t cmd;\nuint32_t cmdsize;\nuint32_t symoff;\nuint32_t nsyms;\nuint32_t stroff;\nuint32_t strsize;\n};\n\n\nCác trường cung cấp:\n\nVị trí bắt đầu bảng ký hiệu.\nSố lượng bản ghi.\nVị trí bảng chuỗi.\nKích thước bảng chuỗi.\n\nĐối với Mach-O 64 bit, một bản ghi ký hiệu truyền thống sử dụng cấu trúc `nlist_64`, với các trường như `n_strx`, `n_type`, `n_sect`, `n_desc` và `n_value`.\n\nKích thước của `nlist_64` là 16 byte.\n\n### 7.2. Phân giải ký hiệu\n\nGiả sử chương trình gọi hàm `calculate` từ một thư viện khác.\n\nỞ thời điểm biên dịch, định nghĩa của `calculate` có thể chưa nằm trong đơn vị đang được xử lý.\n\nBộ liên kết có trách nhiệm xác định ký hiệu tương ứng, theo những quy tắc về tính hiển thị, phạm vi liên kết và cơ chế nhập/xuất.\n\nĐối với thư viện động, một phần thông tin có thể tiếp tục được sử dụng bởi `dyld` khi chương trình nạp hoặc thực thi.\n\n### 7.3. Tái định vị (Relocation)\n\nTái định vị là quá trình xử lý các địa chỉ hoặc tham chiếu chưa thể xác định đầy đủ khi mã đối tượng được tạo ra.\n\nTrong tệp `MH_OBJECT`, thông tin relocation có thể được lưu trong những bản ghi và được tham chiếu bởi các trường `reloff`, `nreloc` của section.\n\nLoại relocation phụ thuộc vào kiến trúc CPU.\n\nVí dụ, cách xử lý lệnh gọi hàm và tham chiếu địa chỉ trên x86-64 không giống ARM64, bởi hai kiến trúc có cách mã hóa lệnh và phạm vi địa chỉ tương đối khác nhau.\n\n### 7.4. Tái định vị và fixup có giống nhau không?\n\nHai thuật ngữ có quan hệ gần gũi nhưng không nên sử dụng hoàn toàn thay thế cho nhau.\n\n**Relocation:** Thường nói đến bản ghi và phép xử lý cần thiết để điều chỉnh tham chiếu địa chỉ trong quá trình liên kết hoặc nạp.\n**Fixup:** Thuật ngữ tổng quát chỉ vị trí hoặc thao tác cần điều chỉnh trong ảnh nhị phân; trong Mach-O hiện đại còn chỉ những cấu trúc dữ liệu cụ thể phục vụ `dyld`.\n\nMột tệp đối tượng Mach-O có thể chứa các relocation truyền thống, trong khi một tệp thực thi hoặc thư viện động có thể sử dụng dữ liệu fixup được mã hóa bằng cấu trúc khác.\n\n\n\n## 8. Liên kết động trong Mach-O\n\n### 8.1. Bộ liên kết động dyld\n\n`dyld` là thành phần quan trọng trong cơ chế liên kết động của hệ sinh thái Apple.\n\nKhi một chương trình phụ thuộc vào thư viện động, những thông tin liên quan được ghi lại trong ảnh Mach-O để hệ thống có thể xác định thư viện cần thiết và xử lý những tham chiếu nhị phân.\n\nVí dụ, Mach-O có thể chứa các load command:\n\nLC_LOAD_DYLIB\nLC_LOAD_DYLINKER\nLC_RPATH\n\n\nCác command này lần lượt liên quan đến phụ thuộc thư viện, bộ liên kết động và đường dẫn tìm kiếm thư viện.\n\n### 8.2. Rebase và Bind\n\nHai thao tác quan trọng khi xử lý ảnh nhị phân động là:\n\n**Tái cơ sở địa chỉ (Rebase)**\n\nĐiều chỉnh các con trỏ hoặc tham chiếu khi ảnh được bố trí tại địa chỉ khác với địa chỉ cơ sở giả định.\n\n**Liên kết ký hiệu (Bind)**\n\nGiải quyết tham chiếu đến ký hiệu được cung cấp bởi ảnh hoặc thư viện khác.\n\nTrong tài liệu mã nguồn `dyld`, Apple mô tả sự khác biệt giữa rebase và bind trong cơ chế xây dựng shared cache: rebase áp dụng cho con trỏ hướng đến vị trí trong cùng ảnh; bind áp dụng cho tham chiếu đến thư viện khác.\n\n### 8.3. Fixup dạng chuỗi (Chained Fixups)\n\nMach-O hiện đại hỗ trợ cấu trúc được nhận diện bằng load command:\n\nLC_DYLD_CHAINED_FIXUPS\n\n\nCommand này chỉ đến dữ liệu fixup được tổ chức theo cơ chế chuỗi.\n\nThay vì chỉ sử dụng những danh sách relocation truyền thống, cấu trúc chained fixups cho phép mô tả và xử lý các vị trí cần điều chỉnh bằng định dạng phù hợp với các yêu cầu liên kết động hiện đại.\n\nCác chi tiết bao gồm:\n\nThông tin bắt đầu chuỗi fixup.\nCác định dạng con trỏ.\nCác mục nhập ký hiệu.\nNhững trường liên quan đến rebase hoặc bind.\nNhững biến thể phục vụ các kiến trúc và yêu cầu bảo mật khác nhau.\n\nCần lưu ý rằng chained fixups không phải là cấu trúc bắt buộc có trong mọi tệp Mach-O thuộc mọi thời kỳ.\n\n### 8.4. Cấu trúc xuất ký hiệu dạng Trie\n\nLoad command:\n\nLC_DYLD_EXPORTS_TRIE\n\n\nchỉ đến một cấu trúc dùng để biểu diễn thông tin xuất ký hiệu.\n\nTrie là cấu trúc dữ liệu dạng cây có thể tận dụng phần tiền tố chung giữa những chuỗi tên.\n\nCơ chế này cho phép tổ chức thông tin xuất ký hiệu bằng một cách khác với việc chỉ sử dụng bảng ký hiệu truyền thống.\n\n### 8.5. dyld Shared Cache\n\nHệ sinh thái Apple còn sử dụng bộ nhớ đệm thư viện dùng chung (dyld Shared Cache) để tổ chức những thư viện hệ thống và phục vụ cơ chế nạp hiệu quả hơn.\n\nĐây không đơn thuần là một tệp Mach-O riêng lẻ.\n\nShared cache có định dạng và siêu dữ liệu riêng, có thể chứa hoặc tổ chức nhiều ảnh thư viện Mach-O theo những quy tắc phù hợp với trình nạp.\n\nNó có thể thực hiện các bước chuẩn bị và tối ưu liên kết để giảm công việc cần thực hiện khi ứng dụng khởi chạy.\n\nVì vậy, không nên coi cấu trúc `dyld shared cache` là phần mở rộng trực tiếp bắt buộc của mỗi tệp Mach-O.\n\n\n\n## 9. Tệp nhị phân đa kiến trúc (Universal Binary)\n\n### 9.1. Khái niệm\n\nUniversal binary là loại tệp có thể chứa những phiên bản mã máy cho nhiều kiến trúc CPU.\n\nVí dụ, một ứng dụng macOS có thể hỗ trợ:\n\nx86-64, dành cho Mac Intel.\nARM64, dành cho Mac sử dụng Apple silicon.\n\nThay vì phân phối hai tệp thực thi riêng biệt, hệ thống xây dựng có thể đóng gói những phiên bản đã được biên dịch vào cùng một universal binary.\n\n### 9.2. Universal Binary và Mach-O đơn kiến trúc\n\nUniversal binary thường được gọi là Fat Binary.\n\nNó có một cấu trúc chứa bên ngoài với thông tin mô tả các thành phần kiến trúc, mỗi thành phần có thể là một ảnh Mach-O riêng.\n\nVí dụ:\n\n┌───────────────────────────────┐\n│ Fat Header                    │\n├───────────────────────────────┤\n│ Architecture Table            │\n│ ├─ x86_64                     │\n│ └─ arm64                      │\n├───────────────────────────────┤\n│ Mach-O Slice: x86_64          │\n├───────────────────────────────┤\n│ Mach-O Slice: arm64           │\n└───────────────────────────────┘\n\n\nMỗi slice có cấu trúc Mach-O tương ứng với kiến trúc của nó.\n\nCần lưu ý rằng bảng kiến trúc không thay thế header bên trong mỗi slice.\n\n### 9.3. Cấu trúc Fat Header\n\nCác định nghĩa truyền thống sử dụng những cấu trúc như:\n\nstruct fat_header {\nuint32_t magic;\nuint32_t nfat_arch;\n};\n\n\nTrong đó:\n\n`magic`: Giá trị nhận diện định dạng fat.\n`nfat_arch`: Số lượng bản ghi kiến trúc.\n\nMột bản ghi kiến trúc dạng 32 bit:\n\nstruct fat_arch {\ncpu_type_t cputype;\ncpu_subtype_t cpusubtype;\nuint32_t offset;\nuint32_t size;\nuint32_t align;\n};\n\n\nBản ghi này có kích thước 20 byte.\n\nCác dạng fat 64 bit sử dụng những cấu trúc riêng với offset và kích thước rộng hơn.\n\n### 9.4. Công cụ lipo\n\nApple cung cấp công cụ `lipo` để thao tác với các tệp nhị phân đa kiến trúc.\n\nVí dụ:\n\nlipo -archs program\n\n\nHiển thị danh sách kiến trúc có trong tệp.\n\nlipo -info program\n\n\nHiển thị thông tin tổng quát.\n\nlipo -thin arm64 program -output program-arm64\n\n\nTrích xuất slice ARM64 nếu có.\n\nlipo -create program-x86_64 program-arm64 \\\n-output program-universal\n\n\nKết hợp các ảnh tương thích thành universal binary.\n\nTheo tài liệu Apple, việc tạo universal macOS binary cho Apple silicon và Intel sử dụng hai bản mã máy dành cho `arm64` và `x86_64`, sau đó có thể kết hợp bằng `lipo`.\n\n### 9.5. Vai trò trong lịch sử Apple\n\nUniversal binary có ý nghĩa đặc biệt trong các giai đoạn Apple chuyển đổi kiến trúc bộ xử lý.\n\nTừ PowerPC sang Intel và sau đó từ Intel sang Apple silicon, cách đóng gói nhiều phiên bản mã máy giúp phần mềm có thể hỗ trợ các thế hệ thiết bị khác nhau.\n\nTuy nhiên, universal binary không tự động chuyển đổi mã máy giữa các kiến trúc.\n\nMỗi slice phải được biên dịch cho kiến trúc đích tương ứng.\n\n\n\n## 10. Điểm vào và quá trình nạp chương trình\n\n### 10.1. Điểm vào (Entry Point)\n\nMột chương trình thực thi cần cung cấp thông tin để hệ thống xác định nơi bắt đầu quá trình chạy.\n\nTrong Mach-O, một cơ chế hiện đại sử dụng:\n\nLC_MAIN\n\n\nCấu trúc tương ứng:\n\nstruct entry_point_command {\nuint32_t cmd;\nuint32_t cmdsize;\nuint64_t entryoff;\nuint64_t stacksize;\n};\n\n\nCác trường chính:\n\n| Trường | Chức năng |\n|---|---|\n| `cmd` | Nhận diện `LC_MAIN` |\n| `cmdsize` | Kích thước command |\n| `entryoff` | Offset điểm vào theo quy ước của command |\n| `stacksize` | Kích thước stack ban đầu được yêu cầu, nếu khác 0 |\n\nTrong mô hình sử dụng `LC_MAIN`, `entryoff` được mô tả theo offset liên quan đến segment `__TEXT`.\n\nKhông nên mặc nhiên hiểu đây là địa chỉ ảo tuyệt đối của hàm `main`.\n\n### 10.2. Chu trình nạp tổng quát\n\nMột chu trình thực thi Mach-O có thể được trình bày ở mức khái quát:\n\nTệp Mach-O\n│\n▼\nKiểm tra định dạng và kiến trúc\n│\n▼\nĐọc Header và Load Commands\n│\n▼\nThiết lập các vùng bộ nhớ\n│\n▼\nXử lý thông tin nạp và liên kết động\n│\n▼\nChuẩn bị môi trường thực thi\n│\n▼\nChuyển quyền điều khiển đến mã khởi động\n│\n▼\nChương trình thực thi\n\n\nCác bước này không phải lúc nào cũng diễn ra thành chuỗi tuần tự đơn giản.\n\nMột phần công việc thuộc về nhân hệ điều hành, một phần thuộc về `dyld`, runtime hoặc những cơ chế khởi động khác.\n\n### 10.3. Mach-O và ASLR\n\nNgẫu nhiên hóa bố trí không gian địa chỉ (Address Space Layout Randomization – ASLR) là kỹ thuật bảo mật giúp thay đổi vị trí nạp của các vùng bộ nhớ.\n\nMột ảnh Mach-O được thiết kế phù hợp có thể được nạp với độ dịch địa chỉ so với địa chỉ cơ sở dự kiến.\n\nCác tham chiếu cần điều chỉnh sẽ được xử lý theo thông tin fixup và quy tắc của nền tảng.\n\nTuy nhiên, Mach-O chỉ là một thành phần của cơ chế này. Khả năng áp dụng ASLR còn phụ thuộc vào hệ điều hành, thuộc tính nhị phân, kiến trúc và những chính sách liên quan.\n\n\n\n## 11. Chữ ký mã và các yêu cầu bảo mật\n\n### 11.1. Chữ ký mã (Code Signing)\n\nMach-O có thể chứa thông tin về chữ ký mã thông qua load command:\n\nLC_CODE_SIGNATURE\n\n\nCommand này chỉ đến vùng dữ liệu chứa thông tin chữ ký.\n\nBản thân command không có nghĩa tất cả các byte chữ ký đều nằm trong cấu trúc command; nó cung cấp vị trí và kích thước của dữ liệu tương ứng.\n\n### 11.2. Vai trò của chữ ký mã\n\nChữ ký mã có thể được sử dụng để:\n\nKiểm tra tính toàn vẹn của mã.\nXác định thông tin danh tính ký mã theo cơ chế nền tảng.\nHỗ trợ những chính sách bảo mật của hệ điều hành.\nPhục vụ quy trình phân phối và thực thi phần mềm.\n\nYêu cầu về chữ ký mã khác nhau giữa các nền tảng Apple và các loại mã thực thi.\n\nKhông nên xem việc một tệp có `LC_CODE_SIGNATURE` là điều kiện đủ để kết luận tệp đó sẽ được hệ điều hành cho phép chạy.\n\n### 11.3. Quan hệ giữa định dạng và bảo mật\n\nMach-O lưu trữ dữ liệu và siêu dữ liệu cần thiết.\n\nViệc kiểm tra chữ ký, áp dụng chính sách bảo mật và quyết định cho phép thực thi thuộc về những cơ chế của hệ điều hành và môi trường thực thi.\n\nDo đó, **một tệp Mach-O hợp lệ về mặt cấu trúc chưa chắc đã hợp lệ về mặt chính sách thực thi**.\n\n\n\n## 12. So sánh Mach-O, ELF và PE/COFF\n\n### 12.1. Bảng so sánh tổng quát\n\n| Tiêu chí | Mach-O | ELF | PE/COFF |\n|---|---|---|---|\n| Hệ sinh thái tiêu biểu | Apple | Linux và nhiều hệ Unix | Windows |\n| Nhận diện | Magic Number | ELF Magic | MZ/PE và COFF |\n| Header chính | Mach Header | ELF Header | DOS/PE/COFF Header |\n| Mô tả ánh xạ | Segment Load Commands | Program Headers | Section Table và cơ chế ảnh PE |\n| Tổ chức mã và dữ liệu | Segments và Sections | Segments và Sections | Sections |\n| Thông tin ký hiệu | Mach-O Symbol Table và dữ liệu liên kết | ELF Symbol Tables | COFF Symbols và PE Export/Import |\n| Liên kết động | dyld và dữ liệu Mach-O | Bộ nạp liên kết động ELF | Windows Loader |\n| Đa kiến trúc | Fat/Universal Binary | Thông thường một ảnh ELF cho một kiến trúc | Thông thường một ảnh PE cho một kiến trúc |\n| Thông tin phiên bản nền tảng | Các load command phù hợp | ABI, note và cơ chế riêng của nền tảng | Header, subsystem và metadata liên quan |\n\n### 12.2. Khác biệt về triết lý cấu trúc\n\nMach-O nổi bật bởi hệ thống load command, trong đó nhiều loại dữ liệu quan trọng được khai báo thông qua các command có kiểu riêng.\n\nELF nhấn mạnh hai cách nhìn:\n\nCách nhìn liên kết với section header.\nCách nhìn thực thi với program header.\n\nPE tổ chức ảnh thực thi bằng hệ thống header, bảng section và những data directory chỉ đến các cấu trúc như import, export và relocation.\n\nBa định dạng đều có khả năng biểu diễn chương trình thực thi, nhưng chúng không có cấu trúc nhị phân hoán đổi trực tiếp cho nhau.\n\n### 12.3. Có thể đổi Mach-O thành ELF bằng cách sửa header không?\n\nKhông thể thực hiện một cách tổng quát chỉ bằng việc thay magic number hoặc thay header.\n\nBởi các định dạng còn khác nhau ở:\n\nCấu trúc section và segment.\nLoại relocation.\nQuy ước ký hiệu.\nCách mô tả phụ thuộc thư viện.\nABI và quy ước thực thi.\nĐiểm vào chương trình.\nCơ chế nạp của hệ điều hành.\n\nNếu cần chuyển một chương trình từ macOS sang Linux, giải pháp thông thường là biên dịch và liên kết lại cho ABI và định dạng đích, đồng thời xử lý những phụ thuộc vào API của hệ điều hành.\n\n\n\n## 13. Phân tích tệp Mach-O bằng công cụ thực tế\n\n### 13.1. Tạo chương trình thử nghiệm\n\nTạo tệp `hello.c`:\n\n#include <stdio.h>\n\nint main(void) {\nputs(\"Hello, Mach-O!\");\nreturn 0;\n}\n\n\nTrên macOS có cài đặt công cụ biên dịch phù hợp:\n\nclang hello.c -o hello\n\n\nKết quả thường là tệp thực thi Mach-O cho kiến trúc được chọn.\n\n### 13.2. Nhận diện định dạng\n\nSử dụng:\n\nfile hello\n\n\nCông cụ có thể hiển thị thông tin như loại định dạng, kiến trúc và đặc điểm của tệp.\n\nKhông nên cố định một chuỗi kết quả cụ thể, vì kết quả phụ thuộc vào kiến trúc máy, hệ điều hành và tùy chọn biên dịch.\n\n### 13.3. Đọc Mach Header\n\nSử dụng:\n\notool -hv hello\n\n\nThông tin thường bao gồm:\n\nMagic Number.\nCPU Type.\nCPU Subtype.\nFile Type.\nSố lượng load command.\nTổng kích thước load commands.\nCác cờ.\n\n### 13.4. Đọc Load Commands\n\nSử dụng:\n\notool -l hello\n\n\nĐây là lệnh quan trọng để khảo sát cấu trúc của tệp Mach-O.\n\nCó thể kiểm tra:\n\nLC_SEGMENT_64\nLC_LOAD_DYLIB\nLC_MAIN\nLC_BUILD_VERSION\nLC_CODE_SIGNATURE\n\n\nDanh sách thực tế thay đổi theo cách xây dựng chương trình.\n\n### 13.5. Kiểm tra phụ thuộc thư viện\n\nSử dụng:\n\notool -L hello\n\n\nCông cụ sẽ liệt kê những thư viện động liên quan được biểu diễn trong ảnh Mach-O.\n\nThông tin này hữu ích khi phân tích lỗi liên kết động hoặc khả năng triển khai chương trình.\n\n### 13.6. Kiểm tra ký hiệu\n\nSử dụng:\n\nnm hello\n\n\nCó thể thêm những tùy chọn thích hợp để lọc ký hiệu.\n\nTuy nhiên, một tệp nhị phân đã bị loại bỏ ký hiệu (Stripped Binary) có thể không còn đầy đủ bảng ký hiệu truyền thống phục vụ việc kiểm tra.\n\n### 13.7. Kiểm tra kiến trúc\n\nSử dụng:\n\nlipo -info hello\n\n\nhoặc:\n\nlipo -archs hello\n\n\nNhững lệnh này giúp xác định tệp chứa một hay nhiều kiến trúc được hỗ trợ.\n\n### 13.8. Đọc cấu trúc với LLVM\n\nLLVM cung cấp những công cụ phân tích có thể xử lý Mach-O, tùy phiên bản và cấu hình:\n\nllvm-objdump --macho --private-headers hello\n\n\nKiểm tra mã hợp ngữ:\n\nllvm-objdump --disassemble hello\n\n\nKiểm tra nội dung section có thể thực hiện bằng những tùy chọn tương ứng của công cụ.\n\nKhi nghiên cứu chương trình đa kiến trúc, cần bảo đảm đang phân tích đúng slice.\n\n\n\n## 14. Những yêu cầu đối với trình đọc và trình sinh Mach-O\n\n### 14.1. Trình đọc Mach-O\n\nMột trình đọc Mach-O cần xử lý ít nhất các bước:\n\nĐọc magic number.\nXác định tệp thin Mach-O hay fat binary.\nXác định thứ tự byte và loại header.\nKiểm tra kích thước tối thiểu.\nĐọc Mach header.\nXác minh `ncmds` và `sizeofcmds`.\nDuyệt load commands.\nKiểm tra offset và kích thước segment, section.\nĐọc những bảng ký hiệu hoặc dữ liệu bổ sung khi cần.\nPhát hiện cấu trúc không hợp lệ hoặc nằm ngoài giới hạn tệp.\n\nViệc kiểm tra kích thước phải tránh tràn số nguyên.\n\nVí dụ, khi xác định một vùng tệp:\n\n■\n\nTrong triển khai an toàn, nên kiểm tra theo dạng không phát sinh tràn phép cộng, chẳng hạn xác minh `offset` không vượt `fileSize`, rồi kiểm tra `size` không lớn hơn `fileSize - offset`.\n\n### 14.2. Trình sinh Mach-O\n\nMột trình biên dịch hoặc linker có khả năng trực tiếp tạo Mach-O phải xây dựng đúng những cấu trúc cần thiết.\n\nĐối với tệp đối tượng, những nhiệm vụ thường bao gồm:\n\nTạo Mach header.\nXác định kiến trúc CPU.\nTạo segment và section phù hợp.\nBố trí mã máy và dữ liệu.\nXây dựng ký hiệu.\nTạo bản ghi relocation.\nTính toán các offset và kích thước.\n\nĐối với ảnh thực thi, công việc còn có thể bao gồm:\n\nThiết lập bố cục segment theo quy tắc nạp.\nTạo thông tin điểm vào.\nMô tả phụ thuộc thư viện động.\nTạo metadata cho dyld.\nĐáp ứng yêu cầu phiên bản nền tảng.\nBố trí hoặc bổ sung chữ ký mã khi môi trường yêu cầu.\n\nCần phân định việc **tạo tệp Mach-O đúng đặc tả** và việc **tạo một ứng dụng Apple có thể phân phối và thực thi thành công**. Mục tiêu thứ hai còn liên quan đến SDK, ABI, runtime, chính sách bảo mật và công cụ nền tảng.\n\n### 14.3. Kiểm thử tính tương thích\n\nNhững trường hợp kiểm thử quan trọng bao gồm:\n\n| Trường hợp | Mục tiêu |\n|---|---|\n| Mach-O 64 bit hợp lệ | Đọc đúng header và load commands |\n| Tệp bị cắt ngắn | Từ chối truy cập ngoài giới hạn |\n| `cmdsize` bằng 0 | Ngăn vòng lặp vô hạn hoặc xử lý sai |\n| Load command sai căn chỉnh | Phát hiện vi phạm quy tắc định dạng |\n| Offset vượt kích thước tệp | Phát hiện dữ liệu không hợp lệ |\n| Fat binary nhiều kiến trúc | Chọn đúng slice |\n| Section không có nội dung vật lý | Xử lý đúng loại section zerofill |\n| Relocation khác kiến trúc | Đọc đúng định dạng và loại relocation |\n| Tệp có chained fixups | Xác định đúng dữ liệu fixup |\n| Tệp có chữ ký mã | Đọc đúng vị trí và kích thước dữ liệu liên quan |\n\n\n\n## 15. Kết luận\n\nMach-O là một định dạng nhị phân quan trọng trong hệ sinh thái Apple, được sử dụng từ quá trình biên dịch và liên kết đến nạp và thực thi chương trình.\n\nĐịnh dạng này có nguồn gốc gắn với lịch sử hệ thống Mach và NeXT, sau đó tiếp tục phát triển trong Mac OS X, macOS và những nền tảng Apple khác.\n\nĐiểm đặc trưng nhất của Mach-O là hệ thống tổ chức dựa trên Mach header, load commands, segments và sections. Cách tổ chức này cho phép tệp mô tả không chỉ mã máy và dữ liệu, mà còn nhiều thông tin về liên kết động, nền tảng đích, điểm vào và những yêu cầu bảo mật.\n\nMach-O cũng hỗ trợ mô hình universal binary, trong đó nhiều ảnh nhị phân dành cho các kiến trúc CPU khác nhau được đóng gói trong cùng một tệp chứa.\n\nCùng với sự phát triển của dyld, các cấu trúc như chained fixups và export trie cho thấy định dạng Mach-O tiếp tục thích ứng với những yêu cầu mới của hệ thống nạp và liên kết.\n\nĐối với nghiên cứu trình biên dịch, linker và hệ điều hành, hiểu Mach-O là cơ sở để giải thích cách mã máy được tổ chức thành một ảnh có thể được hệ thống tiếp nhận, ánh xạ và thực thi.\n\nTuy nhiên, Mach-O chỉ là một phần của giao diện nhị phân giữa chương trình và hệ điều hành. Việc thực thi còn phụ thuộc vào ABI, kiến trúc CPU, thư viện runtime và những chính sách của nền tảng.\n\n\n\n## Phụ lục A. Thuật ngữ kỹ thuật\n\n| Thuật ngữ tiếng Việt | Thuật ngữ tiếng Anh | Ý nghĩa |\n|---|---|---|\n| Định dạng Mach-O | Mach Object | Định dạng tệp đối tượng và ảnh nhị phân trong hệ sinh thái Apple |\n| Header Mach | Mach Header | Cấu trúc thông tin tổng quát của tệp |\n| Lệnh nạp | Load Command | Bản ghi mô tả thông tin phục vụ nạp, liên kết hoặc xử lý tệp |\n| Vùng ánh xạ | Segment | Vùng tệp được mô tả để ánh xạ hoặc xử lý trong bộ nhớ |\n| Mục dữ liệu | Section | Đơn vị tổ chức mã hoặc dữ liệu trong segment |\n| Bảng ký hiệu | Symbol Table | Cấu trúc lưu thông tin về ký hiệu |\n| Tái định vị | Relocation | Điều chỉnh các tham chiếu địa chỉ |\n| Hiệu chỉnh tham chiếu | Fixup | Dữ liệu hoặc thao tác điều chỉnh tham chiếu nhị phân |\n| Liên kết động | Dynamic Linking | Kết nối thư viện theo cơ chế nạp và thực thi |\n| Bộ liên kết động | Dynamic Linker | Thành phần xử lý liên kết thư viện động |\n| Tệp nhị phân đa kiến trúc | Universal Binary | Tệp chứa nhiều ảnh dành cho các kiến trúc khác nhau |\n| Thành phần kiến trúc | Architecture Slice | Một ảnh Mach-O dành cho một kiến trúc trong fat binary |\n| Điểm vào | Entry Point | Vị trí bắt đầu chu trình thực thi chương trình |\n| Ngẫu nhiên hóa không gian địa chỉ | Address Space Layout Randomization | Cơ chế thay đổi vị trí nạp nhằm tăng cường bảo mật |\n| Chữ ký mã | Code Signing | Dữ liệu và cơ chế xác minh mã theo chính sách nền tảng |\n| Giao diện nhị phân ứng dụng | Application Binary Interface | Tập hợp quy tắc tương tác nhị phân giữa chương trình và môi trường thực thi |\n\n\n\n## Phụ lục B. Tài liệu tham khảo\n\n### B.1. Đặc tả và mã nguồn chính thức của Apple\n\n**[1] Apple, *mach-o/loader.h*, mã nguồn XNU.**\n\nNguồn định nghĩa trực tiếp các cấu trúc Mach header, segment command, section, load command và nhiều hằng số liên quan đến định dạng Mach-O.\n\nhttps://github.com/apple-oss-distributions/xnu/blob/main/EXTERNAL_HEADERS/mach-o/loader.h\n\n**[2] Apple, *mach-o/fat.h*.**\n\nNguồn định nghĩa cấu trúc fat binary, bao gồm header và các bản ghi kiến trúc.\n\nhttps://github.com/apple-oss-distributions/xnu/blob/main/EXTERNAL_HEADERS/mach-o/fat.h\n\n**[3] Apple, *mach-o/nlist.h*.**\n\nĐịnh nghĩa các bản ghi ký hiệu Mach-O và những thuộc tính liên quan.\n\nhttps://github.com/apple-oss-distributions/xnu/blob/main/EXTERNAL_HEADERS/mach-o/nlist.h\n\n**[4] Apple, *Mach-O Documentation*.**\n\nCác tài liệu kỹ thuật về định dạng Mach-O, cấu trúc ảnh nhị phân và cơ chế nạp.\n\nhttps://developer.apple.com/documentation/kernel/mach-o\n\n### B.2. Liên kết động và fixup\n\n**[5] Apple, *dyld*, mã nguồn công khai.**\n\nMã nguồn bộ liên kết động và các thành phần xử lý ảnh nhị phân thuộc hệ sinh thái Apple.\n\nhttps://github.com/apple-oss-distributions/dyld\n\n**[6] Apple, *MachOFile.cpp*.**\n\nMã nguồn xử lý và kiểm tra nhiều cấu trúc Mach-O, bao gồm thông tin liên kết và fixup.\n\nhttps://github.com/apple-oss-distributions/dyld/blob/main/common/MachOFile.cpp\n\n**[7] Apple, *fixup-chains.h*.**\n\nĐịnh nghĩa nhiều cấu trúc phục vụ chained fixups.\n\nhttps://github.com/apple-oss-distributions/dyld/blob/main/include/mach-o/fixup-chains.h\n\n**[8] Apple, *Cache Builder*.**\n\nTài liệu mô tả những cơ chế liên quan đến xây dựng dyld shared cache và xử lý fixup.\n\nhttps://github.com/apple-oss-distributions/dyld/blob/main/doc/CacheBuilder.md\n\n### B.3. Universal Binary\n\n**[9] Apple Developer Documentation, *Building a universal macOS binary*.**\n\nTài liệu chính thức về cách xây dựng chương trình hỗ trợ cả Intel và Apple silicon, sử dụng các kiến trúc x86-64 và ARM64.\n\nhttps://developer.apple.com/documentation/apple-silicon/building-a-universal-macos-binary\n\n### B.4. Công cụ và tài liệu bổ sung\n\n**[10] LLVM Project, *LLVM Object File Formats*.**\n\nMã nguồn và công cụ liên quan đến việc đọc, ghi hoặc phân tích nhiều định dạng tệp đối tượng.\n\nhttps://llvm.org/\n\n**[11] LLVM Project, *Mach-O LLD Port*.**\n\nTài liệu về phần triển khai linker Mach-O trong LLVM.\n\nhttps://lld.llvm.org/MachO/index.html\n\n**[12] John R. Levine, *Linkers and Loaders*, Morgan Kaufmann, 1999.**\n\nCông trình chuyên khảo về liên kết và nạp chương trình, cung cấp nền tảng để nghiên cứu các định dạng nhị phân.\n\n\n\n## Chú thích\n\n[^1]: Apple, `mach-o/loader.h`, các định nghĩa `mach_header`, `mach_header_64`, `load_command`, `segment_command_64`, `section_64` và các hằng số Mach-O. https://github.com/apple-oss-distributions/xnu/blob/main/EXTERNAL_HEADERS/mach-o/loader.h\n\n[^2]: Apple, `mach-o/fat.h`, các định nghĩa cấu trúc fat binary và bản ghi kiến trúc. https://github.com/apple-oss-distributions/xnu/blob/main/EXTERNAL_HEADERS/mach-o/fat.h\n\n[^3]: Apple, `mach-o/nlist.h`, định nghĩa bảng ký hiệu Mach-O. https://github.com/apple-oss-distributions/xnu/blob/main/EXTERNAL_HEADERS/mach-o/nlist.h\n\n[^4]: Apple, _dyld_, tài liệu và mã nguồn xử lý thông tin liên kết động. https://github.com/apple-oss-distributions/dyld\n\n[^5]: Apple, _Building a universal macOS binary_, tài liệu về các kiến trúc ARM64, x86-64 và công cụ `lipo`. https://developer.apple.com/documentation/apple-silicon/building-a-universal-macos-binary\n\n[^6]: Apple, `fixup-chains.h`, những định nghĩa phục vụ chained fixups. https://github.com/apple-oss-distributions/dyld/blob/main/include/mach-o/fixup-chains.h\n\n[^7]: Apple, _Cache Builder_, những cơ chế xử lý rebase, bind và shared cache. https://github.com/apple-oss-distributions/dyld/blob/main/doc/CacheBuilder.md\n\n### Ghi chú về phạm vi đặc tả\n\nMach-O là định dạng tiếp tục được phát triển thông qua các phiên bản SDK, hệ điều hành và công cụ của Apple. Những cấu trúc được định nghĩa trong mã nguồn công khai có giá trị quan trọng để nghiên cứu, nhưng không có nghĩa mọi chi tiết triển khai nội bộ đều là một giao diện ổn định được cam kết cho phần mềm bên thứ ba.\n\nĐặc biệt, những chương trình tự tạo tệp Mach-O cần đối chiếu quy định của SDK và hệ điều hành đích, thay vì giả định một cấu trúc hợp lệ trên phiên bản macOS nhất định sẽ luôn được chấp nhận trên mọi nền tảng Apple.","html":"<h1>Định dạng Mach-O (Mach Object) là gì? Nguồn gốc, cấu trúc và đặc tả kỹ thuật</h1>\n<h2>Tóm tắt</h2>\n<p>Mach-O (Mach Object) là định dạng tệp nhị phân được sử dụng trong hệ sinh thái Apple để biểu diễn mã đối tượng, tệp thực thi, thư viện dùng chung và những loại ảnh nhị phân khác. Mach-O cung cấp một hệ thống cấu trúc để mô tả kiến trúc bộ xử lý, loại tệp, các vùng mã lệnh và dữ liệu, thông tin ký hiệu, tái định vị, liên kết động và những yêu cầu phục vụ quá trình nạp chương trình.</p>\n<p>Khác với định dạng ELF (Executable and Linkable Format), vốn sử dụng hệ thống header dành cho section và program segment, Mach-O tổ chức một phần lớn thông tin điều khiển thông qua các lệnh nạp (Load Commands). Những lệnh này cho biết các vùng nào của tệp phải được ánh xạ vào bộ nhớ, thư viện nào cần được nạp và các cấu trúc liên kết bổ sung được lưu ở đâu.</p>\n<p>Nguồn gốc Mach-O gắn với hệ sinh thái Mach, các hệ điều hành NeXT và quá trình hình thành Mac OS X. Qua nhiều thế hệ, định dạng này được mở rộng để phục vụ nhiều kiến trúc phần cứng, đặc biệt là PowerPC, x86-64 và ARM64.</p>\n<p>Bài viết khảo sát lịch sử phát triển của Mach-O, cấu trúc nhị phân, các loại header, load command, segment, section, bảng ký hiệu, relocation, cơ chế liên kết động, universal binary, quá trình nạp và thực thi, cùng những quy định liên quan đến chữ ký mã trên các nền tảng Apple.</p>\n<p>Bài viết sử dụng những định nghĩa trong mã nguồn XNU và tài liệu của Apple làm căn cứ chính cho phần mô tả cấu trúc. Các ví dụ về địa chỉ, bố cục và kết quả công cụ được trình bày dưới dạng minh họa khi không phải là dữ liệu trích xuất từ một tệp Mach-O thực tế.</p>\n<p><strong>Từ khóa:</strong> Mach-O; Mach Object; định dạng nhị phân; tệp thực thi; Apple; macOS; XNU; dyld; load command; segment; section; relocation; universal binary; ABI.</p>\n<hr>\n<h2>1. Mach-O là gì?</h2>\n<h3>1.1. Định nghĩa</h3>\n<p>Mach-O là một định dạng tệp đối tượng và ảnh nhị phân, được dùng để lưu trữ những thông tin mà bộ liên kết, bộ nạp và hệ điều hành cần sử dụng trong quá trình xây dựng hoặc thực thi chương trình.</p>\n<p>Tùy thuộc vào mục đích, tệp Mach-O có thể chứa:</p>\n<ul>\n<li>Mã máy đã được biên dịch.</li>\n<li>Dữ liệu tĩnh và dữ liệu chỉ đọc.</li>\n<li>Các vùng bộ nhớ cần khởi tạo.</li>\n<li>Bảng ký hiệu.</li>\n<li>Thông tin tái định vị.</li>\n<li>Thông tin liên kết với thư viện động.</li>\n<li>Thông tin về điểm vào chương trình.</li>\n<li>Chữ ký mã và siêu dữ liệu nền tảng.</li>\n</ul>\n<p>Mach-O là định dạng nhị phân, không phải ngôn ngữ lập trình, tập lệnh CPU hay một loại mã máy riêng.</p>\n<p>Mã máy được chứa trong tệp Mach-O vẫn phụ thuộc vào kiến trúc bộ xử lý, chẳng hạn x86-64 hoặc ARM64.</p>\n<h3>1.2. Mach-O được sử dụng ở đâu?</h3>\n<p>Mach-O xuất hiện trong nhiều sản phẩm nhị phân của Apple:</p>\n<div class=\"article-table-wrap\">\n<table class=\"wiki-table\">\n<thead>\n<tr>\n  <th>Loại sản phẩm</th>\n  <th>Vai trò</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>Tệp đối tượng <code>.o</code></td>\n  <td>Đầu vào hoặc đầu ra trung gian của quá trình liên kết</td>\n</tr>\n<tr>\n  <td>Tệp thực thi</td>\n  <td>Chứa chương trình để hệ điều hành nạp và khởi chạy</td>\n</tr>\n<tr>\n  <td>Thư viện động <code>.dylib</code></td>\n  <td>Cung cấp mã và dữ liệu cho chương trình khác</td>\n</tr>\n<tr>\n  <td>Bundle nhị phân</td>\n  <td>Thành phần mã có thể được nạp theo cơ chế phù hợp</td>\n</tr>\n<tr>\n  <td>Tệp dSYM</td>\n  <td>Có thể chứa ảnh Mach-O phục vụ thông tin gỡ lỗi</td>\n</tr>\n<tr>\n  <td>Ảnh nhị phân hệ thống</td>\n  <td>Một số thành phần của hệ điều hành và môi trường thực thi</td>\n</tr>\n</tbody>\n</table>\n</div>\n<p>Mach-O được sử dụng trên macOS, iOS, iPadOS, watchOS, tvOS và những nền tảng Apple có liên quan, dù quyền thực thi và các quy định kỹ thuật của mỗi nền tảng có thể khác nhau.</p>\n<h3>1.3. Mach-O và tệp ứng dụng <code>.app</code></h3>\n<p>Một ứng dụng macOS thường được đóng gói dưới dạng một thư mục bundle có phần mở rộng <code>.app</code>.</p>\n<p>Ví dụ:</p>\n<pre><code class=\"language-text\">Example.app/\n└── Contents/\n    ├── Info.plist\n    ├── MacOS/\n    │   └── Example\n    └── Resources/</code></pre>\n<p>Trong ví dụ này:</p>\n<ul>\n<li><code>Example.app</code> là gói ứng dụng.</li>\n<li><code>Info.plist</code> chứa siêu dữ liệu ứng dụng.</li>\n<li><code>Contents/MacOS/Example</code> có thể là tệp thực thi Mach-O.</li>\n</ul>\n<p>Vì vậy, **Mach-O là định dạng của tệp nhị phân bên trong ứng dụng, không phải định dạng của toàn bộ thư mục <code>.app</code>.**</p>\n<hr>\n<h2>2. Nguồn gốc và lịch sử phát triển</h2>\n<h3>2.1. Mối liên hệ với hệ thống Mach</h3>\n<p>Tên Mach-O bắt nguồn từ Mach Object.</p>\n<p>Mach là một họ thiết kế nhân hệ điều hành được nghiên cứu tại Đại học Carnegie Mellon trong những năm 1980, với các cơ chế như tác vụ, luồng, bộ nhớ ảo và giao tiếp giữa tiến trình.</p>\n<p>Mach-O gắn với lịch sử hệ điều hành dựa trên Mach, đặc biệt là các hệ thống NeXT và sau này là Darwin, nền tảng hệ thống của Mac OS X.</p>\n<p>Cần lưu ý rằng Mach-O không phải một phần của tập lệnh CPU, cũng không đồng nghĩa với kiến trúc nhân Mach.</p>\n<p>Nhân hệ điều hành và định dạng tệp thực thi là hai thành phần khác nhau, dù có quan hệ chặt chẽ trong quá trình nạp và quản lý chương trình.</p>\n<h3>2.2. NeXTSTEP và sự chuyển tiếp sang Mac OS X</h3>\n<p>NeXTSTEP là hệ điều hành do NeXT phát triển, kết hợp các thành phần dựa trên Mach và những đặc điểm của hệ thống Unix.</p>\n<p>Mach-O được gắn với hệ sinh thái NeXT và tiếp tục giữ vai trò quan trọng trong dòng hệ điều hành phát triển từ công nghệ này.</p>\n<p>Sau khi Apple mua lại NeXT vào năm 1997, nhiều thành phần công nghệ của NeXT trở thành cơ sở cho thế hệ hệ điều hành Mac OS X.</p>\n<p>Mach-O tiếp tục được sử dụng làm định dạng nhị phân quan trọng trong nền tảng mới.</p>\n<p>Mac OS X 10.0 được phát hành năm 2001, đánh dấu sự xuất hiện thương mại của thế hệ hệ điều hành này.</p>\n<h3>2.3. Quá trình mở rộng theo kiến trúc CPU</h3>\n<p>Mach-O đã được sử dụng qua nhiều giai đoạn chuyển đổi phần cứng.</p>\n<div class=\"article-table-wrap\">\n<table class=\"wiki-table\">\n<thead>\n<tr>\n  <th>Giai đoạn</th>\n  <th>Kiến trúc tiêu biểu</th>\n  <th>Ý nghĩa</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>Hệ thống NeXT</td>\n  <td>Motorola 68k, x86 và những kiến trúc được hỗ trợ khác</td>\n  <td>Giai đoạn lịch sử của môi trường Mach/NeXT</td>\n</tr>\n<tr>\n  <td>Mac OS X thời kỳ đầu</td>\n  <td>PowerPC</td>\n  <td>Mach-O trong hệ sinh thái Macintosh mới</td>\n</tr>\n<tr>\n  <td>Chuyển sang Intel</td>\n  <td>x86, x86-64</td>\n  <td>Hỗ trợ thế hệ máy Mac Intel</td>\n</tr>\n<tr>\n  <td>Chuyển sang Apple silicon</td>\n  <td>ARM64</td>\n  <td>Hỗ trợ kiến trúc ARM64 trên máy Mac</td>\n</tr>\n</tbody>\n</table>\n</div>\n<p>Sự tồn tại của nhiều kiến trúc đã thúc đẩy việc sử dụng các tệp nhị phân đa kiến trúc, thường được gọi là universal binary.</p>\n<h3>2.4. Mach-O 32 bit và 64 bit</h3>\n<p>Mach-O có cấu trúc header dành cho cả kiến trúc 32 bit và 64 bit.</p>\n<p>Hai loại này không chỉ khác nhau về kích thước con trỏ, mà còn có các cấu trúc mô tả segment và section khác nhau.</p>\n<p>Ví dụ, định nghĩa chính thức sử dụng:</p>\n<pre><code class=\"language-c\">struct mach_header;\nstruct mach_header_64;</code></pre>\n<p>Tương ứng với các loại tệp Mach-O 32 bit và 64 bit.</p>\n<p>Các trường địa chỉ và kích thước bộ nhớ trong những cấu trúc segment 64 bit được biểu diễn bằng kiểu dữ liệu rộng hơn.</p>\n<hr>\n<h2>3. Cấu trúc tổng thể của tệp Mach-O</h2>\n<h3>3.1. Mô hình tổ chức</h3>\n<p>Một tệp Mach-O thông thường có thể được hình dung như sau:</p>\n<pre><code class=\"language-text\">┌─────────────────────────────────┐\n│ Mach Header                     │\n│ - Magic                         │\n│ - CPU Type                      │\n│ - File Type                     │\n│ - Number of Load Commands       │\n├─────────────────────────────────┤\n│ Load Commands                   │\n│ - Segment Commands              │\n│ - Symbol Table Information      │\n│ - Dynamic Linking Information   │\n│ - Entry Point Information       │\n├─────────────────────────────────┤\n│ Nội dung các Segment            │\n│ - Machine Code                  │\n│ - Read-only Data                │\n│ - Writable Data                 │\n├─────────────────────────────────┤\n│ Link-edit Data                  │\n│ - Symbols                       │\n│ - Fixups / Bindings             │\n│ - Other Metadata                │\n├─────────────────────────────────┤\n│ Code Signature, nếu có          │\n└─────────────────────────────────┘</code></pre>\n<p>Đây là sơ đồ khái quát nhằm giúp người đọc hình dung các nhóm thông tin.</p>\n<p>Không phải tất cả vùng dữ liệu đều nằm thành những khối liên tiếp theo đúng thứ tự minh họa. Vị trí thực tế được xác định bằng các trường offset, kích thước và quy tắc của từng cấu trúc.</p>\n<h3>3.2. Ba thành phần cấu trúc cơ bản</h3>\n<p>Có thể tiếp cận Mach-O qua ba thành phần chính.</p>\n<p><strong>Mach Header</strong></p>\n<p>Xác định định dạng, kiến trúc CPU, loại tệp và thông tin tổng quát về danh sách lệnh nạp.</p>\n<p><strong>Load Commands</strong></p>\n<p>Mô tả các cấu trúc quan trọng của ảnh nhị phân và cung cấp thông tin để bộ nạp, bộ liên kết hoặc công cụ phân tích xử lý tệp.</p>\n<p><strong>Segments và Sections</strong></p>\n<p>Tổ chức mã máy, dữ liệu và những vùng bộ nhớ cần ánh xạ hoặc xử lý.</p>\n<p>Các thành phần khác như bảng ký hiệu và thông tin fixup được tham chiếu thông qua những cấu trúc phù hợp, thay vì bắt buộc có một bảng section toàn cục riêng như trong ELF.</p>\n<hr>\n<h2>4. Mach Header</h2>\n<h3>4.1. Header 64 bit</h3>\n<p>Trong tệp header chính thức <code>mach-o/loader.h</code>, Apple định nghĩa:</p>\n<pre><code class=\"language-c\">struct mach_header_64 {\n    uint32_t magic;\n    cpu_type_t cputype;\n    cpu_subtype_t cpusubtype;\n    uint32_t filetype;\n    uint32_t ncmds;\n    uint32_t sizeofcmds;\n    uint32_t flags;\n    uint32_t reserved;\n};</code></pre>\n<p>Ở đây, <code>cpu_type_t</code> và <code>cpu_subtype_t</code> được biểu diễn bằng kiểu số nguyên 32 bit theo các định nghĩa liên quan.</p>\n<p>Kích thước của <code>mach_header_64</code> là 32 byte.</p>\n<h3>4.2. Bố cục từng trường</h3>\n<div class=\"article-table-wrap\">\n<table class=\"wiki-table\">\n<thead>\n<tr>\n  <th>Offset</th>\n  <th>Trường</th>\n  <th style=\"text-align: right;\">Kích thước</th>\n  <th>Ý nghĩa</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td><code>0x00</code></td>\n  <td><code>magic</code></td>\n  <td style=\"text-align: right;\">4 byte</td>\n  <td>Giá trị nhận diện định dạng</td>\n</tr>\n<tr>\n  <td><code>0x04</code></td>\n  <td><code>cputype</code></td>\n  <td style=\"text-align: right;\">4 byte</td>\n  <td>Loại CPU</td>\n</tr>\n<tr>\n  <td><code>0x08</code></td>\n  <td><code>cpusubtype</code></td>\n  <td style=\"text-align: right;\">4 byte</td>\n  <td>Phân loại chi tiết CPU</td>\n</tr>\n<tr>\n  <td><code>0x0C</code></td>\n  <td><code>filetype</code></td>\n  <td style=\"text-align: right;\">4 byte</td>\n  <td>Loại tệp Mach-O</td>\n</tr>\n<tr>\n  <td><code>0x10</code></td>\n  <td><code>ncmds</code></td>\n  <td style=\"text-align: right;\">4 byte</td>\n  <td>Số lượng load command</td>\n</tr>\n<tr>\n  <td><code>0x14</code></td>\n  <td><code>sizeofcmds</code></td>\n  <td style=\"text-align: right;\">4 byte</td>\n  <td>Tổng số byte của load commands</td>\n</tr>\n<tr>\n  <td><code>0x18</code></td>\n  <td><code>flags</code></td>\n  <td style=\"text-align: right;\">4 byte</td>\n  <td>Những cờ mô tả thuộc tính ảnh</td>\n</tr>\n<tr>\n  <td><code>0x1C</code></td>\n  <td><code>reserved</code></td>\n  <td style=\"text-align: right;\">4 byte</td>\n  <td>Trường dự trữ</td>\n</tr>\n</tbody>\n</table>\n</div>\n<p>Tổng kích thước:</p>\n<div class=\"math-display\" data-formula=\"8 \\times 4 = 32 \\text{ byte}\"><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7278em;vertical-align:-0.0833em;\"></span><span class=\"mord\">8</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">4</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8889em;vertical-align:-0.1944em;\"></span><span class=\"mord\">32</span><span class=\"mord text\"><span class=\"mord\">&nbsp;byte</span></span></span></span></span></span></div>\n<p>Header 32 bit có bảy trường đầu tiên và không có trường <code>reserved</code>, nên có kích thước 28 byte.</p>\n<h3>4.3. Magic Number</h3>\n<p>Mach-O dùng những giá trị nhận diện để xác định loại header và thứ tự byte.</p>\n<div class=\"article-table-wrap\">\n<table class=\"wiki-table\">\n<thead>\n<tr>\n  <th>Hằng số</th>\n  <th>Giá trị</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td><code>MH_MAGIC</code></td>\n  <td><code>0xFEEDFACE</code></td>\n</tr>\n<tr>\n  <td><code>MH_CIGAM</code></td>\n  <td><code>0xCEFAEDFE</code></td>\n</tr>\n<tr>\n  <td><code>MH_MAGIC_64</code></td>\n  <td><code>0xFEEDFACF</code></td>\n</tr>\n<tr>\n  <td><code>MH_CIGAM_64</code></td>\n  <td><code>0xCFFAEDFE</code></td>\n</tr>\n</tbody>\n</table>\n</div>\n<p>Các giá trị <code>CIGAM</code> là dạng đảo thứ tự byte của những giá trị tương ứng.</p>\n<p>Ví dụ, trên hệ little-endian, giá trị 32 bit <code>0xFEEDFACF</code> được lưu thành chuỗi byte:</p>\n<pre><code class=\"language-text\">CF FA ED FE</code></pre>\n<p>Vì vậy, khi đọc một tệp nhị phân, cần xem xét chuỗi byte thực tế và cách giải mã endianness, thay vì chỉ đối chiếu văn bản hexa một cách máy móc.</p>\n<h3>4.4. Loại tệp (File Type)</h3>\n<p>Trường <code>filetype</code> xác định mục đích của ảnh Mach-O.</p>\n<div class=\"article-table-wrap\">\n<table class=\"wiki-table\">\n<thead>\n<tr>\n  <th>Hằng số</th>\n  <th>Giá trị</th>\n  <th>Ý nghĩa</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td><code>MH_OBJECT</code></td>\n  <td><code>0x1</code></td>\n  <td>Tệp đối tượng có thể tái định vị</td>\n</tr>\n<tr>\n  <td><code>MH_EXECUTE</code></td>\n  <td><code>0x2</code></td>\n  <td>Tệp thực thi</td>\n</tr>\n<tr>\n  <td><code>MH_CORE</code></td>\n  <td><code>0x4</code></td>\n  <td>Ảnh core</td>\n</tr>\n<tr>\n  <td><code>MH_DYLIB</code></td>\n  <td><code>0x6</code></td>\n  <td>Thư viện dùng chung động</td>\n</tr>\n<tr>\n  <td><code>MH_DYLINKER</code></td>\n  <td><code>0x7</code></td>\n  <td>Bộ liên kết động</td>\n</tr>\n<tr>\n  <td><code>MH_BUNDLE</code></td>\n  <td><code>0x8</code></td>\n  <td>Bundle nhị phân có thể liên kết động</td>\n</tr>\n<tr>\n  <td><code>MH_DSYM</code></td>\n  <td><code>0xA</code></td>\n  <td>Ảnh phục vụ dữ liệu gỡ lỗi</td>\n</tr>\n<tr>\n  <td><code>MH_KEXT_BUNDLE</code></td>\n  <td><code>0xB</code></td>\n  <td>Một dạng bundle mở rộng nhân có tính lịch sử và giới hạn nền tảng</td>\n</tr>\n<tr>\n  <td><code>MH_FILESET</code></td>\n  <td><code>0xC</code></td>\n  <td>Ảnh chứa tập hợp các Mach-O theo cấu trúc fileset</td>\n</tr>\n</tbody>\n</table>\n</div>\n<p>Các hằng số này được định nghĩa trong <code>mach-o/loader.h</code>.</p>\n<p>Không phải mọi loại tệp đều có thể được khởi chạy trực tiếp như một chương trình ứng dụng.</p>\n<hr>\n<h2>5. Lệnh nạp (Load Commands)</h2>\n<h3>5.1. Khái niệm</h3>\n<p>Load command là một thành phần thiết yếu của Mach-O.</p>\n<p>Sau Mach header là danh sách các load command, mỗi lệnh mô tả một loại thông tin phục vụ liên kết, ánh xạ bộ nhớ, nạp chương trình hoặc quản lý siêu dữ liệu.</p>\n<p>Apple định nghĩa cấu trúc cơ sở:</p>\n<pre><code class=\"language-c\">struct load_command {\n    uint32_t cmd;\n    uint32_t cmdsize;\n};</code></pre>\n<p>Hai trường này có tổng kích thước 8 byte.</p>\n<ul>\n<li><code>cmd</code>: Mã xác định loại load command.</li>\n<li><code>cmdsize</code>: Kích thước toàn bộ command, bao gồm cả dữ liệu phụ thuộc nếu có.</li>\n</ul>\n<p>Để tìm command tiếp theo, chương trình đọc nhị phân sử dụng <code>cmdsize</code> nhằm tính vị trí mới.</p>\n<h3>5.2. Quy tắc căn chỉnh</h3>\n<p>Theo định nghĩa của Apple:</p>\n<ul>\n<li>Trong Mach-O 32 bit, kích thước mỗi load command phải là bội số của 4 byte.</li>\n<li>Trong Mach-O 64 bit, kích thước mỗi load command phải là bội số của 8 byte.</li>\n</ul>\n<p>Những byte đệm cần thiết được đặt về 0.</p>\n<p>Ví dụ, nếu một command 64 bit chứa 27 byte dữ liệu thực tế, tổng kích thước phải được làm tròn phù hợp với yêu cầu căn chỉnh.</p>\n<p>Việc xử lý <code>cmdsize</code> không hợp lệ là một vấn đề quan trọng đối với trình đọc Mach-O, bởi một giá trị sai có thể khiến bộ phân tích truy cập vượt giới hạn dữ liệu đầu vào.</p>\n<h3>5.3. Các load command quan trọng</h3>\n<div class=\"article-table-wrap\">\n<table class=\"wiki-table\">\n<thead>\n<tr>\n  <th>Load Command</th>\n  <th>Chức năng</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td><code>LC_SEGMENT</code></td>\n  <td>Mô tả segment 32 bit</td>\n</tr>\n<tr>\n  <td><code>LC_SEGMENT_64</code></td>\n  <td>Mô tả segment 64 bit</td>\n</tr>\n<tr>\n  <td><code>LC_SYMTAB</code></td>\n  <td>Thông tin bảng ký hiệu và bảng chuỗi</td>\n</tr>\n<tr>\n  <td><code>LC_DYSYMTAB</code></td>\n  <td>Thông tin ký hiệu liên quan đến liên kết động theo cơ chế truyền thống</td>\n</tr>\n<tr>\n  <td><code>LC_LOAD_DYLIB</code></td>\n  <td>Khai báo phụ thuộc thư viện động</td>\n</tr>\n<tr>\n  <td><code>LC_ID_DYLIB</code></td>\n  <td>Nhận diện thư viện động</td>\n</tr>\n<tr>\n  <td><code>LC_LOAD_DYLINKER</code></td>\n  <td>Khai báo bộ liên kết động</td>\n</tr>\n<tr>\n  <td><code>LC_MAIN</code></td>\n  <td>Thông tin điểm vào của tệp thực thi</td>\n</tr>\n<tr>\n  <td><code>LC_RPATH</code></td>\n  <td>Bổ sung đường dẫn tìm thư viện</td>\n</tr>\n<tr>\n  <td><code>LC_UUID</code></td>\n  <td>Mã định danh của ảnh nhị phân</td>\n</tr>\n<tr>\n  <td><code>LC_CODE_SIGNATURE</code></td>\n  <td>Vị trí dữ liệu chữ ký mã</td>\n</tr>\n<tr>\n  <td><code>LC_BUILD_VERSION</code></td>\n  <td>Thông tin nền tảng, phiên bản hệ điều hành tối thiểu và SDK</td>\n</tr>\n<tr>\n  <td><code>LC_DYLD_EXPORTS_TRIE</code></td>\n  <td>Vị trí cấu trúc xuất ký hiệu dạng trie</td>\n</tr>\n<tr>\n  <td><code>LC_DYLD_CHAINED_FIXUPS</code></td>\n  <td>Thông tin fixup dạng chuỗi</td>\n</tr>\n<tr>\n  <td><code>LC_FILESET_ENTRY</code></td>\n  <td>Thông tin thành phần trong ảnh fileset</td>\n</tr>\n</tbody>\n</table>\n</div>\n<p>Không phải tệp Mach-O nào cũng chứa tất cả các lệnh trên.</p>\n<p>Ví dụ, tệp đối tượng <code>MH_OBJECT</code> có yêu cầu khác với ảnh thực thi <code>MH_EXECUTE</code>.</p>\n<h3>5.4. Load command bắt buộc đối với dyld</h3>\n<p>Mach-O sử dụng cờ <code>LC_REQ_DYLD</code> với giá trị:</p>\n<pre><code class=\"language-c\">#define LC_REQ_DYLD 0x80000000</code></pre>\n<p>Cờ này đánh dấu những loại load command mà bộ liên kết động cần hiểu để xử lý ảnh đúng cách.</p>\n<p>Theo mô tả trong mã nguồn Apple, nếu dyld gặp một load command được đánh dấu bắt buộc nhưng không nhận biết được, nó có thể từ chối sử dụng ảnh đó.</p>\n<p>Cơ chế này cho phép định dạng phát triển thêm những yêu cầu mới mà không mặc nhiên chấp nhận ảnh thực thi có ngữ nghĩa không được hỗ trợ.</p>\n<hr>\n<h2>6. Segment và Section</h2>\n<h3>6.1. Segment là gì?</h3>\n<p>Segment mô tả một vùng của tệp nhị phân được ánh xạ vào không gian địa chỉ của tiến trình.</p>\n<p>Đối với Mach-O 64 bit, Apple định nghĩa:</p>\n<pre><code class=\"language-c\">struct segment_command_64 {\n    uint32_t cmd;\n    uint32_t cmdsize;\n    char segname[16];\n    uint64_t vmaddr;\n    uint64_t vmsize;\n    uint64_t fileoff;\n    uint64_t filesize;\n    vm_prot_t maxprot;\n    vm_prot_t initprot;\n    uint32_t nsects;\n    uint32_t flags;\n};</code></pre>\n<p>Kích thước phần cố định của cấu trúc này là 72 byte.</p>\n<p>Nếu segment chứa các section, những bản ghi <code>section_64</code> được đặt tiếp sau cấu trúc segment trong cùng load command.</p>\n<h3>6.2. Các trường của Segment Command 64 bit</h3>\n<div class=\"article-table-wrap\">\n<table class=\"wiki-table\">\n<thead>\n<tr>\n  <th>Trường</th>\n  <th style=\"text-align: right;\">Kích thước</th>\n  <th>Ý nghĩa</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td><code>cmd</code></td>\n  <td style=\"text-align: right;\">4 byte</td>\n  <td>Loại command</td>\n</tr>\n<tr>\n  <td><code>cmdsize</code></td>\n  <td style=\"text-align: right;\">4 byte</td>\n  <td>Kích thước command và các section đi kèm</td>\n</tr>\n<tr>\n  <td><code>segname</code></td>\n  <td style=\"text-align: right;\">16 byte</td>\n  <td>Tên segment</td>\n</tr>\n<tr>\n  <td><code>vmaddr</code></td>\n  <td style=\"text-align: right;\">8 byte</td>\n  <td>Địa chỉ bộ nhớ ảo</td>\n</tr>\n<tr>\n  <td><code>vmsize</code></td>\n  <td style=\"text-align: right;\">8 byte</td>\n  <td>Kích thước trong bộ nhớ</td>\n</tr>\n<tr>\n  <td><code>fileoff</code></td>\n  <td style=\"text-align: right;\">8 byte</td>\n  <td>Vị trí nội dung segment trong tệp</td>\n</tr>\n<tr>\n  <td><code>filesize</code></td>\n  <td style=\"text-align: right;\">8 byte</td>\n  <td>Kích thước nội dung lưu trong tệp</td>\n</tr>\n<tr>\n  <td><code>maxprot</code></td>\n  <td style=\"text-align: right;\">4 byte</td>\n  <td>Quyền bộ nhớ tối đa</td>\n</tr>\n<tr>\n  <td><code>initprot</code></td>\n  <td style=\"text-align: right;\">4 byte</td>\n  <td>Quyền bộ nhớ ban đầu</td>\n</tr>\n<tr>\n  <td><code>nsects</code></td>\n  <td style=\"text-align: right;\">4 byte</td>\n  <td>Số section</td>\n</tr>\n<tr>\n  <td><code>flags</code></td>\n  <td style=\"text-align: right;\">4 byte</td>\n  <td>Các cờ của segment</td>\n</tr>\n</tbody>\n</table>\n</div>\n<p>Trong nhiều trường hợp:</p>\n<div class=\"math-display\" data-formula=\"\\text{vmsize} \\geq \\text{filesize}\"><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8038em;vertical-align:-0.136em;\"></span><span class=\"mord text\"><span class=\"mord\">vmsize</span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≥</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord text\"><span class=\"mord\">filesize</span></span></span></span></span></span></div>\n<p>Phần bộ nhớ lớn hơn lượng dữ liệu lưu trong tệp có thể được hệ thống cấp phát với giá trị ban đầu bằng 0 theo quy định của cơ chế nạp.</p>\n<h3>6.3. Section là gì?</h3>\n<p>Section là đơn vị tổ chức mã, dữ liệu hoặc siêu dữ liệu bên trong segment.</p>\n<p>Một cấu trúc <code>section_64</code> có các trường chính:</p>\n<pre><code class=\"language-c\">struct section_64 {\n    char sectname[16];\n    char segname[16];\n    uint64_t addr;\n    uint64_t size;\n    uint32_t offset;\n    uint32_t align;\n    uint32_t reloff;\n    uint32_t nreloc;\n    uint32_t flags;\n    uint32_t reserved1;\n    uint32_t reserved2;\n    uint32_t reserved3;\n};</code></pre>\n<p>Kích thước cấu trúc cố định là 80 byte.</p>\n<p>Các trường quan trọng:</p>\n<div class=\"article-table-wrap\">\n<table class=\"wiki-table\">\n<thead>\n<tr>\n  <th>Trường</th>\n  <th>Chức năng</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td><code>sectname</code></td>\n  <td>Tên section</td>\n</tr>\n<tr>\n  <td><code>segname</code></td>\n  <td>Tên segment chứa section</td>\n</tr>\n<tr>\n  <td><code>addr</code></td>\n  <td>Địa chỉ bộ nhớ ảo của section</td>\n</tr>\n<tr>\n  <td><code>size</code></td>\n  <td>Kích thước section</td>\n</tr>\n<tr>\n  <td><code>offset</code></td>\n  <td>Offset dữ liệu trong tệp, đối với loại section có nội dung lưu trong tệp</td>\n</tr>\n<tr>\n  <td><code>align</code></td>\n  <td>Số mũ của yêu cầu căn chỉnh</td>\n</tr>\n<tr>\n  <td><code>reloff</code></td>\n  <td>Offset thông tin relocation</td>\n</tr>\n<tr>\n  <td><code>nreloc</code></td>\n  <td>Số bản ghi relocation</td>\n</tr>\n<tr>\n  <td><code>flags</code></td>\n  <td>Loại section và các thuộc tính</td>\n</tr>\n<tr>\n  <td><code>reserved1–3</code></td>\n  <td>Các trường bổ sung, có ý nghĩa tùy loại section</td>\n</tr>\n</tbody>\n</table>\n</div>\n<h3>6.4. Các segment thường gặp</h3>\n<div class=\"article-table-wrap\">\n<table class=\"wiki-table\">\n<thead>\n<tr>\n  <th>Segment</th>\n  <th>Nội dung điển hình</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td><code>__PAGEZERO</code></td>\n  <td>Vùng địa chỉ thấp không được ánh xạ, hỗ trợ hạn chế truy cập con trỏ null</td>\n</tr>\n<tr>\n  <td><code>__TEXT</code></td>\n  <td>Mã thực thi và dữ liệu chỉ đọc hoặc tương ứng với cấu trúc liên kết</td>\n</tr>\n<tr>\n  <td><code>__DATA</code></td>\n  <td>Dữ liệu có thể ghi và các cấu trúc liên quan</td>\n</tr>\n<tr>\n  <td><code>__DATA_CONST</code></td>\n  <td>Dữ liệu cần xử lý trong quá trình liên kết động nhưng có thể được bảo vệ sau đó</td>\n</tr>\n<tr>\n  <td><code>__LINKEDIT</code></td>\n  <td>Dữ liệu hỗ trợ liên kết, ký hiệu, fixup và các cấu trúc khác</td>\n</tr>\n</tbody>\n</table>\n</div>\n<p>Danh sách này chỉ là những tên phổ biến, không phải toàn bộ các segment hợp lệ.</p>\n<p>Bố cục thực tế có thể thay đổi theo phiên bản hệ điều hành, trình biên dịch, linker và kiến trúc CPU.</p>\n<h3>6.5. Các section thường gặp</h3>\n<p>Trong segment <code>__TEXT</code>:</p>\n<div class=\"article-table-wrap\">\n<table class=\"wiki-table\">\n<thead>\n<tr>\n  <th>Section</th>\n  <th>Nội dung</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td><code>__text</code></td>\n  <td>Mã máy</td>\n</tr>\n<tr>\n  <td><code>__cstring</code></td>\n  <td>Chuỗi ký tự kiểu C</td>\n</tr>\n<tr>\n  <td><code>__const</code></td>\n  <td>Một số dữ liệu hằng</td>\n</tr>\n<tr>\n  <td><code>__stubs</code></td>\n  <td>Những đoạn mã hỗ trợ gọi hàm hoặc liên kết, nếu có</td>\n</tr>\n</tbody>\n</table>\n</div>\n<p>Trong segment dữ liệu:</p>\n<div class=\"article-table-wrap\">\n<table class=\"wiki-table\">\n<thead>\n<tr>\n  <th>Section</th>\n  <th>Nội dung</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td><code>__data</code></td>\n  <td>Dữ liệu có giá trị khởi tạo</td>\n</tr>\n<tr>\n  <td><code>__bss</code></td>\n  <td>Dữ liệu chưa khởi tạo</td>\n</tr>\n<tr>\n  <td><code>__common</code></td>\n  <td>Một số đối tượng dữ liệu theo cơ chế truyền thống</td>\n</tr>\n<tr>\n  <td><code>__la_symbol_ptr</code></td>\n  <td>Vùng con trỏ ký hiệu theo cơ chế liên kết truyền thống</td>\n</tr>\n</tbody>\n</table>\n</div>\n<p>Tên và vị trí section không phải là một giao diện chung bất biến cho mọi thế hệ Mach-O.</p>\n<hr>\n<h2>7. Bảng ký hiệu và cơ chế tái định vị</h2>\n<h3>7.1. Bảng ký hiệu (Symbol Table)</h3>\n<p>Mach-O hỗ trợ bảng ký hiệu để mô tả các hàm, đối tượng dữ liệu và những tên cần sử dụng trong quá trình liên kết hoặc phân tích nhị phân.</p>\n<p>Load command <code>LC_SYMTAB</code> sử dụng cấu trúc:</p>\n<pre><code class=\"language-c\">struct symtab_command {\n    uint32_t cmd;\n    uint32_t cmdsize;\n    uint32_t symoff;\n    uint32_t nsyms;\n    uint32_t stroff;\n    uint32_t strsize;\n};</code></pre>\n<p>Các trường cung cấp:</p>\n<ul>\n<li>Vị trí bắt đầu bảng ký hiệu.</li>\n<li>Số lượng bản ghi.</li>\n<li>Vị trí bảng chuỗi.</li>\n<li>Kích thước bảng chuỗi.</li>\n</ul>\n<p>Đối với Mach-O 64 bit, một bản ghi ký hiệu truyền thống sử dụng cấu trúc <code>nlist_64</code>, với các trường như <code>n_strx</code>, <code>n_type</code>, <code>n_sect</code>, <code>n_desc</code> và <code>n_value</code>.</p>\n<p>Kích thước của <code>nlist_64</code> là 16 byte.</p>\n<h3>7.2. Phân giải ký hiệu</h3>\n<p>Giả sử chương trình gọi hàm <code>calculate</code> từ một thư viện khác.</p>\n<p>Ở thời điểm biên dịch, định nghĩa của <code>calculate</code> có thể chưa nằm trong đơn vị đang được xử lý.</p>\n<p>Bộ liên kết có trách nhiệm xác định ký hiệu tương ứng, theo những quy tắc về tính hiển thị, phạm vi liên kết và cơ chế nhập/xuất.</p>\n<p>Đối với thư viện động, một phần thông tin có thể tiếp tục được sử dụng bởi <code>dyld</code> khi chương trình nạp hoặc thực thi.</p>\n<h3>7.3. Tái định vị <span class=\"math-inline\" data-formula=\"Relocation\"><span class=\"katex\"><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\" style=\"margin-right:0.01968em;\">l</span><span class=\"mord mathnormal\">oc</span><span class=\"mord mathnormal\">a</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">o</span><span class=\"mord mathnormal\">n</span></span></span></span></span></h3>\n<p>Tái định vị là quá trình xử lý các địa chỉ hoặc tham chiếu chưa thể xác định đầy đủ khi mã đối tượng được tạo ra.</p>\n<p>Trong tệp <code>MH_OBJECT</code>, thông tin relocation có thể được lưu trong những bản ghi và được tham chiếu bởi các trường <code>reloff</code>, <code>nreloc</code> của section.</p>\n<p>Loại relocation phụ thuộc vào kiến trúc CPU.</p>\n<p>Ví dụ, cách xử lý lệnh gọi hàm và tham chiếu địa chỉ trên x86-64 không giống ARM64, bởi hai kiến trúc có cách mã hóa lệnh và phạm vi địa chỉ tương đối khác nhau.</p>\n<h3>7.4. Tái định vị và fixup có giống nhau không?</h3>\n<p>Hai thuật ngữ có quan hệ gần gũi nhưng không nên sử dụng hoàn toàn thay thế cho nhau.</p>\n<ul>\n<li><strong>Relocation:</strong> Thường nói đến bản ghi và phép xử lý cần thiết để điều chỉnh tham chiếu địa chỉ trong quá trình liên kết hoặc nạp.</li>\n<li><strong>Fixup:</strong> Thuật ngữ tổng quát chỉ vị trí hoặc thao tác cần điều chỉnh trong ảnh nhị phân; trong Mach-O hiện đại còn chỉ những cấu trúc dữ liệu cụ thể phục vụ <code>dyld</code>.</li>\n</ul>\n<p>Một tệp đối tượng Mach-O có thể chứa các relocation truyền thống, trong khi một tệp thực thi hoặc thư viện động có thể sử dụng dữ liệu fixup được mã hóa bằng cấu trúc khác.</p>\n<hr>\n<h2>8. Liên kết động trong Mach-O</h2>\n<h3>8.1. Bộ liên kết động dyld</h3>\n<p><code>dyld</code> là thành phần quan trọng trong cơ chế liên kết động của hệ sinh thái Apple.</p>\n<p>Khi một chương trình phụ thuộc vào thư viện động, những thông tin liên quan được ghi lại trong ảnh Mach-O để hệ thống có thể xác định thư viện cần thiết và xử lý những tham chiếu nhị phân.</p>\n<p>Ví dụ, Mach-O có thể chứa các load command:</p>\n<pre><code class=\"language-text\">LC_LOAD_DYLIB\nLC_LOAD_DYLINKER\nLC_RPATH</code></pre>\n<p>Các command này lần lượt liên quan đến phụ thuộc thư viện, bộ liên kết động và đường dẫn tìm kiếm thư viện.</p>\n<h3>8.2. Rebase và Bind</h3>\n<p>Hai thao tác quan trọng khi xử lý ảnh nhị phân động là:</p>\n<p><strong>Tái cơ sở địa chỉ <span class=\"math-inline\" data-formula=\"Rebase\"><span class=\"katex\"><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"mord mathnormal\">e</span><span class=\"mord mathnormal\">ba</span><span class=\"mord mathnormal\">se</span></span></span></span></span></strong></p>\n<p>Điều chỉnh các con trỏ hoặc tham chiếu khi ảnh được bố trí tại địa chỉ khác với địa chỉ cơ sở giả định.</p>\n<p><strong>Liên kết ký hiệu <span class=\"math-inline\" data-formula=\"Bind\"><span class=\"katex\"><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05017em;\">B</span><span class=\"mord mathnormal\">in</span><span class=\"mord mathnormal\">d</span></span></span></span></span></strong></p>\n<p>Giải quyết tham chiếu đến ký hiệu được cung cấp bởi ảnh hoặc thư viện khác.</p>\n<p>Trong tài liệu mã nguồn <code>dyld</code>, Apple mô tả sự khác biệt giữa rebase và bind trong cơ chế xây dựng shared cache: rebase áp dụng cho con trỏ hướng đến vị trí trong cùng ảnh; bind áp dụng cho tham chiếu đến thư viện khác.</p>\n<h3>8.3. Fixup dạng chuỗi (Chained Fixups)</h3>\n<p>Mach-O hiện đại hỗ trợ cấu trúc được nhận diện bằng load command:</p>\n<pre><code class=\"language-c\">LC_DYLD_CHAINED_FIXUPS</code></pre>\n<p>Command này chỉ đến dữ liệu fixup được tổ chức theo cơ chế chuỗi.</p>\n<p>Thay vì chỉ sử dụng những danh sách relocation truyền thống, cấu trúc chained fixups cho phép mô tả và xử lý các vị trí cần điều chỉnh bằng định dạng phù hợp với các yêu cầu liên kết động hiện đại.</p>\n<p>Các chi tiết bao gồm:</p>\n<ul>\n<li>Thông tin bắt đầu chuỗi fixup.</li>\n<li>Các định dạng con trỏ.</li>\n<li>Các mục nhập ký hiệu.</li>\n<li>Những trường liên quan đến rebase hoặc bind.</li>\n<li>Những biến thể phục vụ các kiến trúc và yêu cầu bảo mật khác nhau.</li>\n</ul>\n<p>Cần lưu ý rằng chained fixups không phải là cấu trúc bắt buộc có trong mọi tệp Mach-O thuộc mọi thời kỳ.</p>\n<h3>8.4. Cấu trúc xuất ký hiệu dạng Trie</h3>\n<p>Load command:</p>\n<pre><code class=\"language-c\">LC_DYLD_EXPORTS_TRIE</code></pre>\n<p>chỉ đến một cấu trúc dùng để biểu diễn thông tin xuất ký hiệu.</p>\n<p>Trie là cấu trúc dữ liệu dạng cây có thể tận dụng phần tiền tố chung giữa những chuỗi tên.</p>\n<p>Cơ chế này cho phép tổ chức thông tin xuất ký hiệu bằng một cách khác với việc chỉ sử dụng bảng ký hiệu truyền thống.</p>\n<h3>8.5. dyld Shared Cache</h3>\n<p>Hệ sinh thái Apple còn sử dụng bộ nhớ đệm thư viện dùng chung (dyld Shared Cache) để tổ chức những thư viện hệ thống và phục vụ cơ chế nạp hiệu quả hơn.</p>\n<p>Đây không đơn thuần là một tệp Mach-O riêng lẻ.</p>\n<p>Shared cache có định dạng và siêu dữ liệu riêng, có thể chứa hoặc tổ chức nhiều ảnh thư viện Mach-O theo những quy tắc phù hợp với trình nạp.</p>\n<p>Nó có thể thực hiện các bước chuẩn bị và tối ưu liên kết để giảm công việc cần thực hiện khi ứng dụng khởi chạy.</p>\n<p>Vì vậy, không nên coi cấu trúc <code>dyld shared cache</code> là phần mở rộng trực tiếp bắt buộc của mỗi tệp Mach-O.</p>\n<hr>\n<h2>9. Tệp nhị phân đa kiến trúc (Universal Binary)</h2>\n<h3>9.1. Khái niệm</h3>\n<p>Universal binary là loại tệp có thể chứa những phiên bản mã máy cho nhiều kiến trúc CPU.</p>\n<p>Ví dụ, một ứng dụng macOS có thể hỗ trợ:</p>\n<ul>\n<li>x86-64, dành cho Mac Intel.</li>\n<li>ARM64, dành cho Mac sử dụng Apple silicon.</li>\n</ul>\n<p>Thay vì phân phối hai tệp thực thi riêng biệt, hệ thống xây dựng có thể đóng gói những phiên bản đã được biên dịch vào cùng một universal binary.</p>\n<h3>9.2. Universal Binary và Mach-O đơn kiến trúc</h3>\n<p>Universal binary thường được gọi là Fat Binary.</p>\n<p>Nó có một cấu trúc chứa bên ngoài với thông tin mô tả các thành phần kiến trúc, mỗi thành phần có thể là một ảnh Mach-O riêng.</p>\n<p>Ví dụ:</p>\n<pre><code class=\"language-text\">┌───────────────────────────────┐\n│ Fat Header                    │\n├───────────────────────────────┤\n│ Architecture Table            │\n│ ├─ x86_64                     │\n│ └─ arm64                      │\n├───────────────────────────────┤\n│ Mach-O Slice: x86_64          │\n├───────────────────────────────┤\n│ Mach-O Slice: arm64           │\n└───────────────────────────────┘</code></pre>\n<p>Mỗi slice có cấu trúc Mach-O tương ứng với kiến trúc của nó.</p>\n<p>Cần lưu ý rằng bảng kiến trúc không thay thế header bên trong mỗi slice.</p>\n<h3>9.3. Cấu trúc Fat Header</h3>\n<p>Các định nghĩa truyền thống sử dụng những cấu trúc như:</p>\n<pre><code class=\"language-c\">struct fat_header {\n    uint32_t magic;\n    uint32_t nfat_arch;\n};</code></pre>\n<p>Trong đó:</p>\n<ul>\n<li><code>magic</code>: Giá trị nhận diện định dạng fat.</li>\n<li><code>nfat_arch</code>: Số lượng bản ghi kiến trúc.</li>\n</ul>\n<p>Một bản ghi kiến trúc dạng 32 bit:</p>\n<pre><code class=\"language-c\">struct fat_arch {\n    cpu_type_t cputype;\n    cpu_subtype_t cpusubtype;\n    uint32_t offset;\n    uint32_t size;\n    uint32_t align;\n};</code></pre>\n<p>Bản ghi này có kích thước 20 byte.</p>\n<p>Các dạng fat 64 bit sử dụng những cấu trúc riêng với offset và kích thước rộng hơn.</p>\n<h3>9.4. Công cụ lipo</h3>\n<p>Apple cung cấp công cụ <code>lipo</code> để thao tác với các tệp nhị phân đa kiến trúc.</p>\n<p>Ví dụ:</p>\n<pre><code class=\"language-bash\">lipo -archs program</code></pre>\n<p>Hiển thị danh sách kiến trúc có trong tệp.</p>\n<pre><code class=\"language-bash\">lipo -info program</code></pre>\n<p>Hiển thị thông tin tổng quát.</p>\n<pre><code class=\"language-bash\">lipo -thin arm64 program -output program-arm64</code></pre>\n<p>Trích xuất slice ARM64 nếu có.</p>\n<pre><code class=\"language-bash\">lipo -create program-x86_64 program-arm64 \\\n    -output program-universal</code></pre>\n<p>Kết hợp các ảnh tương thích thành universal binary.</p>\n<p>Theo tài liệu Apple, việc tạo universal macOS binary cho Apple silicon và Intel sử dụng hai bản mã máy dành cho <code>arm64</code> và <code>x86_64</code>, sau đó có thể kết hợp bằng <code>lipo</code>.</p>\n<h3>9.5. Vai trò trong lịch sử Apple</h3>\n<p>Universal binary có ý nghĩa đặc biệt trong các giai đoạn Apple chuyển đổi kiến trúc bộ xử lý.</p>\n<p>Từ PowerPC sang Intel và sau đó từ Intel sang Apple silicon, cách đóng gói nhiều phiên bản mã máy giúp phần mềm có thể hỗ trợ các thế hệ thiết bị khác nhau.</p>\n<p>Tuy nhiên, universal binary không tự động chuyển đổi mã máy giữa các kiến trúc.</p>\n<p>Mỗi slice phải được biên dịch cho kiến trúc đích tương ứng.</p>\n<hr>\n<h2>10. Điểm vào và quá trình nạp chương trình</h2>\n<h3>10.1. Điểm vào (Entry Point)</h3>\n<p>Một chương trình thực thi cần cung cấp thông tin để hệ thống xác định nơi bắt đầu quá trình chạy.</p>\n<p>Trong Mach-O, một cơ chế hiện đại sử dụng:</p>\n<pre><code class=\"language-c\">LC_MAIN</code></pre>\n<p>Cấu trúc tương ứng:</p>\n<pre><code class=\"language-c\">struct entry_point_command {\n    uint32_t cmd;\n    uint32_t cmdsize;\n    uint64_t entryoff;\n    uint64_t stacksize;\n};</code></pre>\n<p>Các trường chính:</p>\n<div class=\"article-table-wrap\">\n<table class=\"wiki-table\">\n<thead>\n<tr>\n  <th>Trường</th>\n  <th>Chức năng</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td><code>cmd</code></td>\n  <td>Nhận diện <code>LC_MAIN</code></td>\n</tr>\n<tr>\n  <td><code>cmdsize</code></td>\n  <td>Kích thước command</td>\n</tr>\n<tr>\n  <td><code>entryoff</code></td>\n  <td>Offset điểm vào theo quy ước của command</td>\n</tr>\n<tr>\n  <td><code>stacksize</code></td>\n  <td>Kích thước stack ban đầu được yêu cầu, nếu khác 0</td>\n</tr>\n</tbody>\n</table>\n</div>\n<p>Trong mô hình sử dụng <code>LC_MAIN</code>, <code>entryoff</code> được mô tả theo offset liên quan đến segment <code>__TEXT</code>.</p>\n<p>Không nên mặc nhiên hiểu đây là địa chỉ ảo tuyệt đối của hàm <code>main</code>.</p>\n<h3>10.2. Chu trình nạp tổng quát</h3>\n<p>Một chu trình thực thi Mach-O có thể được trình bày ở mức khái quát:</p>\n<pre><code class=\"language-text\">Tệp Mach-O\n     │\n     ▼\nKiểm tra định dạng và kiến trúc\n     │\n     ▼\nĐọc Header và Load Commands\n     │\n     ▼\nThiết lập các vùng bộ nhớ\n     │\n     ▼\nXử lý thông tin nạp và liên kết động\n     │\n     ▼\nChuẩn bị môi trường thực thi\n     │\n     ▼\nChuyển quyền điều khiển đến mã khởi động\n     │\n     ▼\nChương trình thực thi</code></pre>\n<p>Các bước này không phải lúc nào cũng diễn ra thành chuỗi tuần tự đơn giản.</p>\n<p>Một phần công việc thuộc về nhân hệ điều hành, một phần thuộc về <code>dyld</code>, runtime hoặc những cơ chế khởi động khác.</p>\n<h3>10.3. Mach-O và ASLR</h3>\n<p>Ngẫu nhiên hóa bố trí không gian địa chỉ (Address Space Layout Randomization – ASLR) là kỹ thuật bảo mật giúp thay đổi vị trí nạp của các vùng bộ nhớ.</p>\n<p>Một ảnh Mach-O được thiết kế phù hợp có thể được nạp với độ dịch địa chỉ so với địa chỉ cơ sở dự kiến.</p>\n<p>Các tham chiếu cần điều chỉnh sẽ được xử lý theo thông tin fixup và quy tắc của nền tảng.</p>\n<p>Tuy nhiên, Mach-O chỉ là một thành phần của cơ chế này. Khả năng áp dụng ASLR còn phụ thuộc vào hệ điều hành, thuộc tính nhị phân, kiến trúc và những chính sách liên quan.</p>\n<hr>\n<h2>11. Chữ ký mã và các yêu cầu bảo mật</h2>\n<h3>11.1. Chữ ký mã (Code Signing)</h3>\n<p>Mach-O có thể chứa thông tin về chữ ký mã thông qua load command:</p>\n<pre><code class=\"language-c\">LC_CODE_SIGNATURE</code></pre>\n<p>Command này chỉ đến vùng dữ liệu chứa thông tin chữ ký.</p>\n<p>Bản thân command không có nghĩa tất cả các byte chữ ký đều nằm trong cấu trúc command; nó cung cấp vị trí và kích thước của dữ liệu tương ứng.</p>\n<h3>11.2. Vai trò của chữ ký mã</h3>\n<p>Chữ ký mã có thể được sử dụng để:</p>\n<ul>\n<li>Kiểm tra tính toàn vẹn của mã.</li>\n<li>Xác định thông tin danh tính ký mã theo cơ chế nền tảng.</li>\n<li>Hỗ trợ những chính sách bảo mật của hệ điều hành.</li>\n<li>Phục vụ quy trình phân phối và thực thi phần mềm.</li>\n</ul>\n<p>Yêu cầu về chữ ký mã khác nhau giữa các nền tảng Apple và các loại mã thực thi.</p>\n<p>Không nên xem việc một tệp có <code>LC_CODE_SIGNATURE</code> là điều kiện đủ để kết luận tệp đó sẽ được hệ điều hành cho phép chạy.</p>\n<h3>11.3. Quan hệ giữa định dạng và bảo mật</h3>\n<p>Mach-O lưu trữ dữ liệu và siêu dữ liệu cần thiết.</p>\n<p>Việc kiểm tra chữ ký, áp dụng chính sách bảo mật và quyết định cho phép thực thi thuộc về những cơ chế của hệ điều hành và môi trường thực thi.</p>\n<p>Do đó, <strong>một tệp Mach-O hợp lệ về mặt cấu trúc chưa chắc đã hợp lệ về mặt chính sách thực thi</strong>.</p>\n<hr>\n<h2>12. So sánh Mach-O, ELF và PE/COFF</h2>\n<h3>12.1. Bảng so sánh tổng quát</h3>\n<div class=\"article-table-wrap\">\n<table class=\"wiki-table\">\n<thead>\n<tr>\n  <th>Tiêu chí</th>\n  <th>Mach-O</th>\n  <th>ELF</th>\n  <th>PE/COFF</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>Hệ sinh thái tiêu biểu</td>\n  <td>Apple</td>\n  <td>Linux và nhiều hệ Unix</td>\n  <td>Windows</td>\n</tr>\n<tr>\n  <td>Nhận diện</td>\n  <td>Magic Number</td>\n  <td>ELF Magic</td>\n  <td>MZ/PE và COFF</td>\n</tr>\n<tr>\n  <td>Header chính</td>\n  <td>Mach Header</td>\n  <td>ELF Header</td>\n  <td>DOS/PE/COFF Header</td>\n</tr>\n<tr>\n  <td>Mô tả ánh xạ</td>\n  <td>Segment Load Commands</td>\n  <td>Program Headers</td>\n  <td>Section Table và cơ chế ảnh PE</td>\n</tr>\n<tr>\n  <td>Tổ chức mã và dữ liệu</td>\n  <td>Segments và Sections</td>\n  <td>Segments và Sections</td>\n  <td>Sections</td>\n</tr>\n<tr>\n  <td>Thông tin ký hiệu</td>\n  <td>Mach-O Symbol Table và dữ liệu liên kết</td>\n  <td>ELF Symbol Tables</td>\n  <td>COFF Symbols và PE Export/Import</td>\n</tr>\n<tr>\n  <td>Liên kết động</td>\n  <td>dyld và dữ liệu Mach-O</td>\n  <td>Bộ nạp liên kết động ELF</td>\n  <td>Windows Loader</td>\n</tr>\n<tr>\n  <td>Đa kiến trúc</td>\n  <td>Fat/Universal Binary</td>\n  <td>Thông thường một ảnh ELF cho một kiến trúc</td>\n  <td>Thông thường một ảnh PE cho một kiến trúc</td>\n</tr>\n<tr>\n  <td>Thông tin phiên bản nền tảng</td>\n  <td>Các load command phù hợp</td>\n  <td>ABI, note và cơ chế riêng của nền tảng</td>\n  <td>Header, subsystem và metadata liên quan</td>\n</tr>\n</tbody>\n</table>\n</div>\n<h3>12.2. Khác biệt về triết lý cấu trúc</h3>\n<p>Mach-O nổi bật bởi hệ thống load command, trong đó nhiều loại dữ liệu quan trọng được khai báo thông qua các command có kiểu riêng.</p>\n<p>ELF nhấn mạnh hai cách nhìn:</p>\n<ul>\n<li>Cách nhìn liên kết với section header.</li>\n<li>Cách nhìn thực thi với program header.</li>\n</ul>\n<p>PE tổ chức ảnh thực thi bằng hệ thống header, bảng section và những data directory chỉ đến các cấu trúc như import, export và relocation.</p>\n<p>Ba định dạng đều có khả năng biểu diễn chương trình thực thi, nhưng chúng không có cấu trúc nhị phân hoán đổi trực tiếp cho nhau.</p>\n<h3>12.3. Có thể đổi Mach-O thành ELF bằng cách sửa header không?</h3>\n<p>Không thể thực hiện một cách tổng quát chỉ bằng việc thay magic number hoặc thay header.</p>\n<p>Bởi các định dạng còn khác nhau ở:</p>\n<ul>\n<li>Cấu trúc section và segment.</li>\n<li>Loại relocation.</li>\n<li>Quy ước ký hiệu.</li>\n<li>Cách mô tả phụ thuộc thư viện.</li>\n<li>ABI và quy ước thực thi.</li>\n<li>Điểm vào chương trình.</li>\n<li>Cơ chế nạp của hệ điều hành.</li>\n</ul>\n<p>Nếu cần chuyển một chương trình từ macOS sang Linux, giải pháp thông thường là biên dịch và liên kết lại cho ABI và định dạng đích, đồng thời xử lý những phụ thuộc vào API của hệ điều hành.</p>\n<hr>\n<h2>13. Phân tích tệp Mach-O bằng công cụ thực tế</h2>\n<h3>13.1. Tạo chương trình thử nghiệm</h3>\n<p>Tạo tệp <code>hello.c</code>:</p>\n<pre><code class=\"language-c\">#include &lt;stdio.h&gt;\n\nint mainvoid {\n    puts(\"Hello, Mach-O!\");\n    return 0;\n}</code></pre>\n<p>Trên macOS có cài đặt công cụ biên dịch phù hợp:</p>\n<pre><code class=\"language-bash\">clang hello.c -o hello</code></pre>\n<p>Kết quả thường là tệp thực thi Mach-O cho kiến trúc được chọn.</p>\n<h3>13.2. Nhận diện định dạng</h3>\n<p>Sử dụng:</p>\n<pre><code class=\"language-bash\">file hello</code></pre>\n<p>Công cụ có thể hiển thị thông tin như loại định dạng, kiến trúc và đặc điểm của tệp.</p>\n<p>Không nên cố định một chuỗi kết quả cụ thể, vì kết quả phụ thuộc vào kiến trúc máy, hệ điều hành và tùy chọn biên dịch.</p>\n<h3>13.3. Đọc Mach Header</h3>\n<p>Sử dụng:</p>\n<pre><code class=\"language-bash\">otool -hv hello</code></pre>\n<p>Thông tin thường bao gồm:</p>\n<ul>\n<li>Magic Number.</li>\n<li>CPU Type.</li>\n<li>CPU Subtype.</li>\n<li>File Type.</li>\n<li>Số lượng load command.</li>\n<li>Tổng kích thước load commands.</li>\n<li>Các cờ.</li>\n</ul>\n<h3>13.4. Đọc Load Commands</h3>\n<p>Sử dụng:</p>\n<pre><code class=\"language-bash\">otool -l hello</code></pre>\n<p>Đây là lệnh quan trọng để khảo sát cấu trúc của tệp Mach-O.</p>\n<p>Có thể kiểm tra:</p>\n<pre><code class=\"language-text\">LC_SEGMENT_64\nLC_LOAD_DYLIB\nLC_MAIN\nLC_BUILD_VERSION\nLC_CODE_SIGNATURE</code></pre>\n<p>Danh sách thực tế thay đổi theo cách xây dựng chương trình.</p>\n<h3>13.5. Kiểm tra phụ thuộc thư viện</h3>\n<p>Sử dụng:</p>\n<pre><code class=\"language-bash\">otool -L hello</code></pre>\n<p>Công cụ sẽ liệt kê những thư viện động liên quan được biểu diễn trong ảnh Mach-O.</p>\n<p>Thông tin này hữu ích khi phân tích lỗi liên kết động hoặc khả năng triển khai chương trình.</p>\n<h3>13.6. Kiểm tra ký hiệu</h3>\n<p>Sử dụng:</p>\n<pre><code class=\"language-bash\">nm hello</code></pre>\n<p>Có thể thêm những tùy chọn thích hợp để lọc ký hiệu.</p>\n<p>Tuy nhiên, một tệp nhị phân đã bị loại bỏ ký hiệu (Stripped Binary) có thể không còn đầy đủ bảng ký hiệu truyền thống phục vụ việc kiểm tra.</p>\n<h3>13.7. Kiểm tra kiến trúc</h3>\n<p>Sử dụng:</p>\n<pre><code class=\"language-bash\">lipo -info hello</code></pre>\n<p>hoặc:</p>\n<pre><code class=\"language-bash\">lipo -archs hello</code></pre>\n<p>Những lệnh này giúp xác định tệp chứa một hay nhiều kiến trúc được hỗ trợ.</p>\n<h3>13.8. Đọc cấu trúc với LLVM</h3>\n<p>LLVM cung cấp những công cụ phân tích có thể xử lý Mach-O, tùy phiên bản và cấu hình:</p>\n<pre><code class=\"language-bash\">llvm-objdump --macho --private-headers hello</code></pre>\n<p>Kiểm tra mã hợp ngữ:</p>\n<pre><code class=\"language-bash\">llvm-objdump --disassemble hello</code></pre>\n<p>Kiểm tra nội dung section có thể thực hiện bằng những tùy chọn tương ứng của công cụ.</p>\n<p>Khi nghiên cứu chương trình đa kiến trúc, cần bảo đảm đang phân tích đúng slice.</p>\n<hr>\n<h2>14. Những yêu cầu đối với trình đọc và trình sinh Mach-O</h2>\n<h3>14.1. Trình đọc Mach-O</h3>\n<p>Một trình đọc Mach-O cần xử lý ít nhất các bước:</p>\n<ol>\n<li>Đọc magic number.</li>\n<li>Xác định tệp thin Mach-O hay fat binary.</li>\n<li>Xác định thứ tự byte và loại header.</li>\n<li>Kiểm tra kích thước tối thiểu.</li>\n<li>Đọc Mach header.</li>\n<li>Xác minh <code>ncmds</code> và <code>sizeofcmds</code>.</li>\n<li>Duyệt load commands.</li>\n<li>Kiểm tra offset và kích thước segment, section.</li>\n<li>Đọc những bảng ký hiệu hoặc dữ liệu bổ sung khi cần.</li>\n<li>Phát hiện cấu trúc không hợp lệ hoặc nằm ngoài giới hạn tệp.</li>\n</ol>\n<p>Việc kiểm tra kích thước phải tránh tràn số nguyên.</p>\n<p>Ví dụ, khi xác định một vùng tệp:</p>\n<div class=\"math-display\" data-formula=\"\\text{offset} + \\text{size} \\leq \\text{fileSize}\"><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7778em;vertical-align:-0.0833em;\"></span><span class=\"mord text\"><span class=\"mord\">offset</span></span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8038em;vertical-align:-0.136em;\"></span><span class=\"mord text\"><span class=\"mord\">size</span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≤</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord text\"><span class=\"mord\">fileSize</span></span></span></span></span></span></div>\n<p>Trong triển khai an toàn, nên kiểm tra theo dạng không phát sinh tràn phép cộng, chẳng hạn xác minh <code>offset</code> không vượt <code>fileSize</code>, rồi kiểm tra <code>size</code> không lớn hơn <code>fileSize - offset</code>.</p>\n<h3>14.2. Trình sinh Mach-O</h3>\n<p>Một trình biên dịch hoặc linker có khả năng trực tiếp tạo Mach-O phải xây dựng đúng những cấu trúc cần thiết.</p>\n<p>Đối với tệp đối tượng, những nhiệm vụ thường bao gồm:</p>\n<ul>\n<li>Tạo Mach header.</li>\n<li>Xác định kiến trúc CPU.</li>\n<li>Tạo segment và section phù hợp.</li>\n<li>Bố trí mã máy và dữ liệu.</li>\n<li>Xây dựng ký hiệu.</li>\n<li>Tạo bản ghi relocation.</li>\n<li>Tính toán các offset và kích thước.</li>\n</ul>\n<p>Đối với ảnh thực thi, công việc còn có thể bao gồm:</p>\n<ul>\n<li>Thiết lập bố cục segment theo quy tắc nạp.</li>\n<li>Tạo thông tin điểm vào.</li>\n<li>Mô tả phụ thuộc thư viện động.</li>\n<li>Tạo metadata cho dyld.</li>\n<li>Đáp ứng yêu cầu phiên bản nền tảng.</li>\n<li>Bố trí hoặc bổ sung chữ ký mã khi môi trường yêu cầu.</li>\n</ul>\n<p>Cần phân định việc <strong>tạo tệp Mach-O đúng đặc tả</strong> và việc <strong>tạo một ứng dụng Apple có thể phân phối và thực thi thành công</strong>. Mục tiêu thứ hai còn liên quan đến SDK, ABI, runtime, chính sách bảo mật và công cụ nền tảng.</p>\n<h3>14.3. Kiểm thử tính tương thích</h3>\n<p>Những trường hợp kiểm thử quan trọng bao gồm:</p>\n<div class=\"article-table-wrap\">\n<table class=\"wiki-table\">\n<thead>\n<tr>\n  <th>Trường hợp</th>\n  <th>Mục tiêu</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>Mach-O 64 bit hợp lệ</td>\n  <td>Đọc đúng header và load commands</td>\n</tr>\n<tr>\n  <td>Tệp bị cắt ngắn</td>\n  <td>Từ chối truy cập ngoài giới hạn</td>\n</tr>\n<tr>\n  <td><code>cmdsize</code> bằng 0</td>\n  <td>Ngăn vòng lặp vô hạn hoặc xử lý sai</td>\n</tr>\n<tr>\n  <td>Load command sai căn chỉnh</td>\n  <td>Phát hiện vi phạm quy tắc định dạng</td>\n</tr>\n<tr>\n  <td>Offset vượt kích thước tệp</td>\n  <td>Phát hiện dữ liệu không hợp lệ</td>\n</tr>\n<tr>\n  <td>Fat binary nhiều kiến trúc</td>\n  <td>Chọn đúng slice</td>\n</tr>\n<tr>\n  <td>Section không có nội dung vật lý</td>\n  <td>Xử lý đúng loại section zerofill</td>\n</tr>\n<tr>\n  <td>Relocation khác kiến trúc</td>\n  <td>Đọc đúng định dạng và loại relocation</td>\n</tr>\n<tr>\n  <td>Tệp có chained fixups</td>\n  <td>Xác định đúng dữ liệu fixup</td>\n</tr>\n<tr>\n  <td>Tệp có chữ ký mã</td>\n  <td>Đọc đúng vị trí và kích thước dữ liệu liên quan</td>\n</tr>\n</tbody>\n</table>\n</div>\n<hr>\n<h2>15. Kết luận</h2>\n<p>Mach-O là một định dạng nhị phân quan trọng trong hệ sinh thái Apple, được sử dụng từ quá trình biên dịch và liên kết đến nạp và thực thi chương trình.</p>\n<p>Định dạng này có nguồn gốc gắn với lịch sử hệ thống Mach và NeXT, sau đó tiếp tục phát triển trong Mac OS X, macOS và những nền tảng Apple khác.</p>\n<p>Điểm đặc trưng nhất của Mach-O là hệ thống tổ chức dựa trên Mach header, load commands, segments và sections. Cách tổ chức này cho phép tệp mô tả không chỉ mã máy và dữ liệu, mà còn nhiều thông tin về liên kết động, nền tảng đích, điểm vào và những yêu cầu bảo mật.</p>\n<p>Mach-O cũng hỗ trợ mô hình universal binary, trong đó nhiều ảnh nhị phân dành cho các kiến trúc CPU khác nhau được đóng gói trong cùng một tệp chứa.</p>\n<p>Cùng với sự phát triển của dyld, các cấu trúc như chained fixups và export trie cho thấy định dạng Mach-O tiếp tục thích ứng với những yêu cầu mới của hệ thống nạp và liên kết.</p>\n<p>Đối với nghiên cứu trình biên dịch, linker và hệ điều hành, hiểu Mach-O là cơ sở để giải thích cách mã máy được tổ chức thành một ảnh có thể được hệ thống tiếp nhận, ánh xạ và thực thi.</p>\n<p>Tuy nhiên, Mach-O chỉ là một phần của giao diện nhị phân giữa chương trình và hệ điều hành. Việc thực thi còn phụ thuộc vào ABI, kiến trúc CPU, thư viện runtime và những chính sách của nền tảng.</p>\n<hr>\n<h2>Phụ lục A. Thuật ngữ kỹ thuật</h2>\n<div class=\"article-table-wrap\">\n<table class=\"wiki-table\">\n<thead>\n<tr>\n  <th>Thuật ngữ tiếng Việt</th>\n  <th>Thuật ngữ tiếng Anh</th>\n  <th>Ý nghĩa</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>Định dạng Mach-O</td>\n  <td>Mach Object</td>\n  <td>Định dạng tệp đối tượng và ảnh nhị phân trong hệ sinh thái Apple</td>\n</tr>\n<tr>\n  <td>Header Mach</td>\n  <td>Mach Header</td>\n  <td>Cấu trúc thông tin tổng quát của tệp</td>\n</tr>\n<tr>\n  <td>Lệnh nạp</td>\n  <td>Load Command</td>\n  <td>Bản ghi mô tả thông tin phục vụ nạp, liên kết hoặc xử lý tệp</td>\n</tr>\n<tr>\n  <td>Vùng ánh xạ</td>\n  <td>Segment</td>\n  <td>Vùng tệp được mô tả để ánh xạ hoặc xử lý trong bộ nhớ</td>\n</tr>\n<tr>\n  <td>Mục dữ liệu</td>\n  <td>Section</td>\n  <td>Đơn vị tổ chức mã hoặc dữ liệu trong segment</td>\n</tr>\n<tr>\n  <td>Bảng ký hiệu</td>\n  <td>Symbol Table</td>\n  <td>Cấu trúc lưu thông tin về ký hiệu</td>\n</tr>\n<tr>\n  <td>Tái định vị</td>\n  <td>Relocation</td>\n  <td>Điều chỉnh các tham chiếu địa chỉ</td>\n</tr>\n<tr>\n  <td>Hiệu chỉnh tham chiếu</td>\n  <td>Fixup</td>\n  <td>Dữ liệu hoặc thao tác điều chỉnh tham chiếu nhị phân</td>\n</tr>\n<tr>\n  <td>Liên kết động</td>\n  <td>Dynamic Linking</td>\n  <td>Kết nối thư viện theo cơ chế nạp và thực thi</td>\n</tr>\n<tr>\n  <td>Bộ liên kết động</td>\n  <td>Dynamic Linker</td>\n  <td>Thành phần xử lý liên kết thư viện động</td>\n</tr>\n<tr>\n  <td>Tệp nhị phân đa kiến trúc</td>\n  <td>Universal Binary</td>\n  <td>Tệp chứa nhiều ảnh dành cho các kiến trúc khác nhau</td>\n</tr>\n<tr>\n  <td>Thành phần kiến trúc</td>\n  <td>Architecture Slice</td>\n  <td>Một ảnh Mach-O dành cho một kiến trúc trong fat binary</td>\n</tr>\n<tr>\n  <td>Điểm vào</td>\n  <td>Entry Point</td>\n  <td>Vị trí bắt đầu chu trình thực thi chương trình</td>\n</tr>\n<tr>\n  <td>Ngẫu nhiên hóa không gian địa chỉ</td>\n  <td>Address Space Layout Randomization</td>\n  <td>Cơ chế thay đổi vị trí nạp nhằm tăng cường bảo mật</td>\n</tr>\n<tr>\n  <td>Chữ ký mã</td>\n  <td>Code Signing</td>\n  <td>Dữ liệu và cơ chế xác minh mã theo chính sách nền tảng</td>\n</tr>\n<tr>\n  <td>Giao diện nhị phân ứng dụng</td>\n  <td>Application Binary Interface</td>\n  <td>Tập hợp quy tắc tương tác nhị phân giữa chương trình và môi trường thực thi</td>\n</tr>\n</tbody>\n</table>\n</div>\n<hr>\n<h2>Phụ lục B. Tài liệu tham khảo</h2>\n<h3>B.1. Đặc tả và mã nguồn chính thức của Apple</h3>\n<p><strong>[1] Apple, <em>mach-o/loader.h</em>, mã nguồn XNU.</strong></p>\n<p>Nguồn định nghĩa trực tiếp các cấu trúc Mach header, segment command, section, load command và nhiều hằng số liên quan đến định dạng Mach-O.</p>\n<p><a href=\"/redirect?url=https%3A%2F%2Fgithub.com%2Fapple-oss-distributions%2Fxnu%2Fblob%2Fmain%2FEXTERNAL_HEADERS%2Fmach-o%2Floader.h&amp;locale=vi\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/apple-oss-distributions/xnu/blob/main/EXTERNAL_HEADERS/mach-o/loader.h</a></p>\n<p><strong>[2] Apple, <em>mach-o/fat.h</em>.</strong></p>\n<p>Nguồn định nghĩa cấu trúc fat binary, bao gồm header và các bản ghi kiến trúc.</p>\n<p><a href=\"/redirect?url=https%3A%2F%2Fgithub.com%2Fapple-oss-distributions%2Fxnu%2Fblob%2Fmain%2FEXTERNAL_HEADERS%2Fmach-o%2Ffat.h&amp;locale=vi\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/apple-oss-distributions/xnu/blob/main/EXTERNAL_HEADERS/mach-o/fat.h</a></p>\n<p><strong>[3] Apple, <em>mach-o/nlist.h</em>.</strong></p>\n<p>Định nghĩa các bản ghi ký hiệu Mach-O và những thuộc tính liên quan.</p>\n<p><a href=\"/redirect?url=https%3A%2F%2Fgithub.com%2Fapple-oss-distributions%2Fxnu%2Fblob%2Fmain%2FEXTERNAL_HEADERS%2Fmach-o%2Fnlist.h&amp;locale=vi\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/apple-oss-distributions/xnu/blob/main/EXTERNAL_HEADERS/mach-o/nlist.h</a></p>\n<p><strong>[4] Apple, <em>Mach-O Documentation</em>.</strong></p>\n<p>Các tài liệu kỹ thuật về định dạng Mach-O, cấu trúc ảnh nhị phân và cơ chế nạp.</p>\n<p><a href=\"/redirect?url=https%3A%2F%2Fdeveloper.apple.com%2Fdocumentation%2Fkernel%2Fmach-o&amp;locale=vi\" target=\"_blank\" rel=\"noopener noreferrer\">https://developer.apple.com/documentation/kernel/mach-o</a></p>\n<h3>B.2. Liên kết động và fixup</h3>\n<p><strong>[5] Apple, <em>dyld</em>, mã nguồn công khai.</strong></p>\n<p>Mã nguồn bộ liên kết động và các thành phần xử lý ảnh nhị phân thuộc hệ sinh thái Apple.</p>\n<p><a href=\"/redirect?url=https%3A%2F%2Fgithub.com%2Fapple-oss-distributions%2Fdyld&amp;locale=vi\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/apple-oss-distributions/dyld</a></p>\n<p><strong>[6] Apple, <em>MachOFile.cpp</em>.</strong></p>\n<p>Mã nguồn xử lý và kiểm tra nhiều cấu trúc Mach-O, bao gồm thông tin liên kết và fixup.</p>\n<p><a href=\"/redirect?url=https%3A%2F%2Fgithub.com%2Fapple-oss-distributions%2Fdyld%2Fblob%2Fmain%2Fcommon%2FMachOFile.cpp&amp;locale=vi\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/apple-oss-distributions/dyld/blob/main/common/MachOFile.cpp</a></p>\n<p><strong>[7] Apple, <em>fixup-chains.h</em>.</strong></p>\n<p>Định nghĩa nhiều cấu trúc phục vụ chained fixups.</p>\n<p><a href=\"/redirect?url=https%3A%2F%2Fgithub.com%2Fapple-oss-distributions%2Fdyld%2Fblob%2Fmain%2Finclude%2Fmach-o%2Ffixup-chains.h&amp;locale=vi\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/apple-oss-distributions/dyld/blob/main/include/mach-o/fixup-chains.h</a></p>\n<p><strong>[8] Apple, <em>Cache Builder</em>.</strong></p>\n<p>Tài liệu mô tả những cơ chế liên quan đến xây dựng dyld shared cache và xử lý fixup.</p>\n<p><a href=\"/redirect?url=https%3A%2F%2Fgithub.com%2Fapple-oss-distributions%2Fdyld%2Fblob%2Fmain%2Fdoc%2FCacheBuilder.md&amp;locale=vi\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/apple-oss-distributions/dyld/blob/main/doc/CacheBuilder.md</a></p>\n<h3>B.3. Universal Binary</h3>\n<p><strong>[9] Apple Developer Documentation, <em>Building a universal macOS binary</em>.</strong></p>\n<p>Tài liệu chính thức về cách xây dựng chương trình hỗ trợ cả Intel và Apple silicon, sử dụng các kiến trúc x86-64 và ARM64.</p>\n<p><a href=\"/redirect?url=https%3A%2F%2Fdeveloper.apple.com%2Fdocumentation%2Fapple-silicon%2Fbuilding-a-universal-macos-binary&amp;locale=vi\" target=\"_blank\" rel=\"noopener noreferrer\">https://developer.apple.com/documentation/apple-silicon/building-a-universal-macos-binary</a></p>\n<h3>B.4. Công cụ và tài liệu bổ sung</h3>\n<p><strong>[10] LLVM Project, <em>LLVM Object File Formats</em>.</strong></p>\n<p>Mã nguồn và công cụ liên quan đến việc đọc, ghi hoặc phân tích nhiều định dạng tệp đối tượng.</p>\n<p><a href=\"/redirect?url=https%3A%2F%2Fllvm.org%2F&amp;locale=vi\" target=\"_blank\" rel=\"noopener noreferrer\">https://llvm.org/</a></p>\n<p><strong>[11] LLVM Project, <em>Mach-O LLD Port</em>.</strong></p>\n<p>Tài liệu về phần triển khai linker Mach-O trong LLVM.</p>\n<p><a href=\"/redirect?url=https%3A%2F%2Flld.llvm.org%2FMachO%2Findex.html&amp;locale=vi\" target=\"_blank\" rel=\"noopener noreferrer\">https://lld.llvm.org/MachO/index.html</a></p>\n<p><strong>[12] John R. Levine, <em>Linkers and Loaders</em>, Morgan Kaufmann, 1999.</strong></p>\n<p>Công trình chuyên khảo về liên kết và nạp chương trình, cung cấp nền tảng để nghiên cứu các định dạng nhị phân.</p>\n<hr>\n<h2>Chú thích</h2>\n<div class=\"footnotes\" role=\"doc-endnotes\">\n<ol class=\"footnotes-list\">\n<li id=\"fn-1\" class=\"footnote-item\" role=\"doc-endnote\"><span class=\"footnote-text\">Apple, <code>mach-o/loader.h</code>, các định nghĩa <code>mach_header</code>, <code>mach_header_64</code>, <code>load_command</code>, <code>segment_command_64</code>, <code>section_64</code> và các hằng số Mach-O. <a href=\"/redirect?url=https%3A%2F%2Fgithub.com%2Fapple-oss-distributions%2Fxnu%2Fblob%2Fmain%2FEXTERNAL_HEADERS%2Fmach-o%2Floader.h&amp;locale=vi\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/apple-oss-distributions/xnu/blob/main/EXTERNAL_HEADERS/mach-o/loader.h</a></span> <span class=\"footnote-backrefs\"><a href=\"#fnref-1\" class=\"footnote-backref\" role=\"doc-backlink\" title=\"Quay lại nội dung\" aria-label=\"Quay lại nội dung\">↩</a></span></li>\n<li id=\"fn-2\" class=\"footnote-item\" role=\"doc-endnote\"><span class=\"footnote-text\">Apple, <code>mach-o/fat.h</code>, các định nghĩa cấu trúc fat binary và bản ghi kiến trúc. <a href=\"/redirect?url=https%3A%2F%2Fgithub.com%2Fapple-oss-distributions%2Fxnu%2Fblob%2Fmain%2FEXTERNAL_HEADERS%2Fmach-o%2Ffat.h&amp;locale=vi\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/apple-oss-distributions/xnu/blob/main/EXTERNAL_HEADERS/mach-o/fat.h</a></span> <span class=\"footnote-backrefs\"><a href=\"#fnref-2\" class=\"footnote-backref\" role=\"doc-backlink\" title=\"Quay lại nội dung\" aria-label=\"Quay lại nội dung\">↩</a></span></li>\n<li id=\"fn-3\" class=\"footnote-item\" role=\"doc-endnote\"><span class=\"footnote-text\">Apple, <code>mach-o/nlist.h</code>, định nghĩa bảng ký hiệu Mach-O. <a href=\"/redirect?url=https%3A%2F%2Fgithub.com%2Fapple-oss-distributions%2Fxnu%2Fblob%2Fmain%2FEXTERNAL_HEADERS%2Fmach-o%2Fnlist.h&amp;locale=vi\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/apple-oss-distributions/xnu/blob/main/EXTERNAL_HEADERS/mach-o/nlist.h</a></span> <span class=\"footnote-backrefs\"><a href=\"#fnref-3\" class=\"footnote-backref\" role=\"doc-backlink\" title=\"Quay lại nội dung\" aria-label=\"Quay lại nội dung\">↩</a></span></li>\n<li id=\"fn-4\" class=\"footnote-item\" role=\"doc-endnote\"><span class=\"footnote-text\">Apple, <em>dyld</em>, tài liệu và mã nguồn xử lý thông tin liên kết động. <a href=\"/redirect?url=https%3A%2F%2Fgithub.com%2Fapple-oss-distributions%2Fdyld&amp;locale=vi\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/apple-oss-distributions/dyld</a></span> <span class=\"footnote-backrefs\"><a href=\"#fnref-4\" class=\"footnote-backref\" role=\"doc-backlink\" title=\"Quay lại nội dung\" aria-label=\"Quay lại nội dung\">↩</a></span></li>\n<li id=\"fn-5\" class=\"footnote-item\" role=\"doc-endnote\"><span class=\"footnote-text\">Apple, <em>Building a universal macOS binary</em>, tài liệu về các kiến trúc ARM64, x86-64 và công cụ <code>lipo</code>. <a href=\"/redirect?url=https%3A%2F%2Fdeveloper.apple.com%2Fdocumentation%2Fapple-silicon%2Fbuilding-a-universal-macos-binary&amp;locale=vi\" target=\"_blank\" rel=\"noopener noreferrer\">https://developer.apple.com/documentation/apple-silicon/building-a-universal-macos-binary</a></span> <span class=\"footnote-backrefs\"><a href=\"#fnref-5\" class=\"footnote-backref\" role=\"doc-backlink\" title=\"Quay lại nội dung\" aria-label=\"Quay lại nội dung\">↩</a></span></li>\n<li id=\"fn-6\" class=\"footnote-item\" role=\"doc-endnote\"><span class=\"footnote-text\">Apple, <code>fixup-chains.h</code>, những định nghĩa phục vụ chained fixups. <a href=\"/redirect?url=https%3A%2F%2Fgithub.com%2Fapple-oss-distributions%2Fdyld%2Fblob%2Fmain%2Finclude%2Fmach-o%2Ffixup-chains.h&amp;locale=vi\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/apple-oss-distributions/dyld/blob/main/include/mach-o/fixup-chains.h</a></span> <span class=\"footnote-backrefs\"><a href=\"#fnref-6\" class=\"footnote-backref\" role=\"doc-backlink\" title=\"Quay lại nội dung\" aria-label=\"Quay lại nội dung\">↩</a></span></li>\n<li id=\"fn-7\" class=\"footnote-item\" role=\"doc-endnote\"><span class=\"footnote-text\">Apple, <em>Cache Builder</em>, những cơ chế xử lý rebase, bind và shared cache. <a href=\"/redirect?url=https%3A%2F%2Fgithub.com%2Fapple-oss-distributions%2Fdyld%2Fblob%2Fmain%2Fdoc%2FCacheBuilder.md&amp;locale=vi\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/apple-oss-distributions/dyld/blob/main/doc/CacheBuilder.md</a></span> <span class=\"footnote-backrefs\"><a href=\"#fnref-7\" class=\"footnote-backref\" role=\"doc-backlink\" title=\"Quay lại nội dung\" aria-label=\"Quay lại nội dung\">↩</a></span></li>\n</ol>\n</div>\n<h3>Ghi chú về phạm vi đặc tả</h3>\n<p>Mach-O là định dạng tiếp tục được phát triển thông qua các phiên bản SDK, hệ điều hành và công cụ của Apple. Những cấu trúc được định nghĩa trong mã nguồn công khai có giá trị quan trọng để nghiên cứu, nhưng không có nghĩa mọi chi tiết triển khai nội bộ đều là một giao diện ổn định được cam kết cho phần mềm bên thứ ba.</p>\n<p>Đặc biệt, những chương trình tự tạo tệp Mach-O cần đối chiếu quy định của SDK và hệ điều hành đích, thay vì giả định một cấu trúc hợp lệ trên phiên bản macOS nhất định sẽ luôn được chấp nhận trên mọi nền tảng Apple.</p>","tags":[],"author":"virgorilabs_112522","publishedAt":"2026-10-16T13:07:57.858Z","updatedAt":"2026-10-16T15:11:37.501Z","published_at":"2026-10-16T13:07:57.858Z","updated_at":"2026-10-16T15:11:37.501Z","view_count":2,"canonical":"https://wiki.quizzman.com/wiki/dinh-dang-mach-o-mach-object-la-gi-nguon-goc-cau-truc-va-dac-ta-ky-thuat","url":"https://wiki.quizzman.com/wiki/dinh-dang-mach-o-mach-object-la-gi-nguon-goc-cau-truc-va-dac-ta-ky-thuat","markdownUrl":"https://wiki.quizzman.com/api/articles/dinh-dang-mach-o-mach-object-la-gi-nguon-goc-cau-truc-va-dac-ta-ky-thuat.md","apiUrl":"https://wiki.quizzman.com/api/articles/dinh-dang-mach-o-mach-object-la-gi-nguon-goc-cau-truc-va-dac-ta-ky-thuat"}