Sign in Join
Wiki copytemporary

Mach-O: what changed

Revision 2 to 3. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11*(macOS only)*
22
33*Mach-O, short for Mach object file format, is a file format for executables, object code, shared libraries, dynamically-loaded code, and core dumps. A derivation of the a.out format, Mach-O offered more extensibility and faster access to information in the symbol table.* Source: [Wikipedia](http://en.wikipedia.org/wiki/Mach-O).
44
55The Apple file format reference can be found [here](https://developer.apple.com/library/archive/documentation/Performance/Conceptual/CodeFootprint/Articles/MachOOverview.html)
66
77The following tools are used in macOS to view Mach-O files:
88
99**otool** - object file displaying tool
1010
1111**nm** - display name list (symbol table)
1212
1313## Objective-C segment
1414
1515There is no documentation about __OBJC segment and its sections. The following information has been gathered from cctools [sources](http://opensource.apple.com/source/cctools/cctools-667.3/)
1616
1717### Structures strings
1818
1919Some structures in sections contain name pointers. These names are stored in the c-strings section (segment: __TEXT; section: __cstring). The file offset for the string name can be evaluated in the following way:
2020
21-`string_file_offset := cstr_section.offset + (name_addr - cstr_section.addr);`
21+``` pascal
22+string_file_offset := cstr_section.offset + (name_addr - cstr_section.addr);
23+```
2224
2325## Sections
2426
2527### __image_info
2628
2729The section contains only the image info information:
2830
29-`imageInfo = packed record`\
30-`  version : uint32_t;  // zero`\
31-`  flags   : uint32_t;  // for objc 1.0 - zero`\
32-`end;`
31+``` pascal
32+imageInfo = packed record
33+ version : uint32_t; // zero
34+ flags : uint32_t; // for objc 1.0 - zero
35+end;
36+```
3337
3438Flags values:
3539
36-`ImageInfo_F_and_C = $01;`\
37-`ImageInfo_GC      = $02;`\
38-`ImageInfo_GC_only = $04;`
40+```text
41+ImageInfo_F_and_C = $01;
42+ImageInfo_GC = $02;
43+ImageInfo_GC_only = $04;
44+```
3945
4046### __module_info
4147
4248(objc_module record is declared at objc headers).
4349
4450The number of objc_module structures depends on the number of .m files with objects declarations compiled. _symtab contains the number of classes and categories declared in the module.
4551
46-`objc_module = packed record`\
47-`  version : culong; // version number = 7 `\
48-`  size    : culong; // sizeof(objc_module)?`\
49-`  name    : PChar;  // virtual memory address of the module name`\
50-`                    // Usually mapped to NULL string`\
51-`  _symtab : Symtab; // virtual memory address of a proper objc_symtab structure (in __symbols section)`\
52-`end;`
52+``` pascal
53+objc_module = packed record
54+ version : culong; // version number = 7
55+ size : culong; // sizeof(objc_module)?
56+ name : PChar; // virtual memory address of the module name
57+ // Usually mapped to NULL string
58+ _symtab : Symtab; // virtual memory address of a proper objc_symtab structure (in __symbols section)
59+end;
60+```
5361
5462### __symbols
5563
5664the section contains symbol table for a module. (symtable record is declared at objc headers)
5765
58-` objc_symtab = record`\
59-`   sel_ref_cnt : culong;  // zero`\
60-`   refs        : PSEL;    // zero`\
61-`   cls_def_cnt : cushort; // number of declared classes in the module`\
62-`   cat_def_cnt : cushort; // number of declared categories`\
63-`   defs: array [0..cls_def_cnt+cat_def_cnt-1] of Pointer; // array of virtual address of declarations`\
64-`      // 0..cls_def_cnt - 1           : virtual address of class declarations (in "__class" section, can be empty)`\
65-`      // cls_def_cnt..cat_def_cnt-1   : virtual address of categories declarations (can be empty)`\
66-` end;`
66+``` pascal
67+ objc_symtab = record
68+ sel_ref_cnt : culong; // zero
69+ refs : PSEL; // zero
70+ cls_def_cnt : cushort; // number of declared classes in the module
71+ cat_def_cnt : cushort; // number of declared categories
72+ defs: array [0..cls_def_cnt+cat_def_cnt-1] of Pointer; // array of virtual address of declarations
73+ // 0..cls_def_cnt - 1 : virtual address of class declarations (in "__class" section, can be empty)
74+ // cls_def_cnt..cat_def_cnt-1 : virtual address of categories declarations (can be empty)
75+ end;
76+```
6777
6878### __class, __meta_class
6979
7080*the section may omit, if none of modules declare any custom classes*
7181
7282Both sections use identical structure objc_class. (objc_class record is declared at objc header) Objective-C classes are declared in pair with their meta_classes.
7383
74-`objc_class = record`\
75-`  isa           : PChar;   // for class declaration: virtual address of meta-class declaration`\
76-`                           // for meta-class declaration: virtual address of "NSObject" string?`\
84+``` pascal
85+objc_class = record
86+ isa : PChar; // for class declaration: virtual address of meta-class declaration
87+ // for meta-class declaration: virtual address of "NSObject" string?
7788
78-`  super_class   : PChar;   // contains the pointer to super_class name`\
79-`  name          : PChar;   // pointer to class name        `\
80-`  version       : PChar;   // = 0 (for obj-c version 1?)`\
89+ super_class : PChar; // contains the pointer to super_class name
90+ name : PChar; // pointer to class name
91+ version : PChar; // = 0 (for obj-c version 1?)
8192
82-`  info          : culong;  // CLS_CLASS for classes`\
83-`                           // CLS_META  for meta-classes `\
93+ info : culong; // CLS_CLASS for classes
94+ // CLS_META for meta-classes
8495
85-`  instance_size : culong;  // size of the instance:`\
86-`                           // class: size of the class instance `\
87-`                           // meta-class: 48 bytes `\
88-`                           `\
89-`  ivars         : Pobjc_ivar_list;       // virtual address of objc_ivar_list (stored in "__instance_vars" section)`\
90-`                                         // meta-classes don't have ivars list (=0)`\
96+ instance_size : culong; // size of the instance:
97+ // class: size of the class instance
98+ // meta-class: 48 bytes
99+
100+ ivars : Pobjc_ivar_list; // virtual address of objc_ivar_list (stored in "__instance_vars" section)
101+ // meta-classes don't have ivars list (=0)
91102
92-`  methodLists   : PPobjc_method_list;    // virtual address of objc_method_list`\
93-`                                         // class declaration has instance methods list (stored in "__inst_meth" section)`\
94-`                                         // meta-class declaration has class methods list (stored in "__cls_meth" section)`\
95-` `\
96-`  cache         : Pobjc_cache;           // zero`\
97-`  protocols     : Pobjc_protocol_list;   // pointer to protocols list. (stored in "__cat_cls_meth" section)`\
98-`end;`
103+ methodLists : PPobjc_method_list; // virtual address of objc_method_list
104+ // class declaration has instance methods list (stored in "__inst_meth" section)
105+ // meta-class declaration has class methods list (stored in "__cls_meth" section)
106+
107+ cache : Pobjc_cache; // zero
108+ protocols : Pobjc_protocol_list; // pointer to protocols list. (stored in "__cat_cls_meth" section)
109+end;
110+```
99111
100112### __instance_vars
101113
102114*the section is optional and may omit if none of classes declares instance variables*
103115
104116The section consists of number objc_ivar_list structutres. The number of structures depends upon number of declared classes using instance variables. (objc_ivar_list is declared in objc header)
105117
106-`objc_ivar_list = record`\
107-`  ivar_count  : cint;   // number of variables in the list`\
108-`  ivar_list   : array[0..ivar_count-1] of objc_ivar;  variable length structure }`\
109-`end;`
118+``` pascal
119+objc_ivar_list = record
120+ ivar_count : cint; // number of variables in the list
121+ ivar_list : array[0..ivar_count-1] of objc_ivar; variable length structure }
122+end;
123+```
110124
111-`objc_ivar = record`\
112-`  ivar_name   : PChar; // vm addr of the variable name`\
113-`  ivar_type   : PChar; // vm addr of obj-c variable encoded type `\
114-`  ivar_offset : cint;  // offset from the start of the instance. (the lowest ivar_offset is 40,`\
115-`                       // because sizeof(objc_class) = 40, and objc_class is also part of the instance)`\
116-`end;`
125+``` pascal
126+objc_ivar = record
127+ ivar_name : PChar; // vm addr of the variable name
128+ ivar_type : PChar; // vm addr of obj-c variable encoded type
129+ ivar_offset : cint; // offset from the start of the instance. (the lowest ivar_offset is 40,
130+ // because sizeof(objc_class) = 40, and objc_class is also part of the instance)
131+end;
132+```
117133
118134### __inst_meth, __cls_meth
119135
120136*the section is optional and may omit if none of classes declares any methods*
121137
122138Both section has identical format. They contain number of objc_method_list records. Number of records is depending on classes declared in modules.
123139
124-`objc_method_list = record`\
125-`  obsolete     : Pobjc_method_list;  // not used, always zero`\
126-`  method_count : cint;               // number of objc_method in method_list array `\
127-`  method_list  : array[0..method_count-1] of objc_method;  `\
128-`end;`
140+``` pascal
141+objc_method_list = record
142+ obsolete : Pobjc_method_list; // not used, always zero
143+ method_count : cint; // number of objc_method in method_list array
144+ method_list : array[0..method_count-1] of objc_method;
145+end;
146+```
129147
130-`objc_method = record`\
131-`  method_name   : SEL;   // virtual address of the selector name `\
132-`                         // (selector name is stored as other names is in __TEXT __cstring section)`\
133-`                         // selector name is short: i.e. "methodName:", and not "+[className methodName:]"`\
134-`  method_types  : PChar; // obj-c encoded function parameters `\
135-`  method_imp    : IMP;   // virtual address of method implementation function entry point (in __TEXT __text section)`\
136-`end;`
148+``` pascal
149+objc_method = record
150+ method_name : SEL; // virtual address of the selector name
151+ // (selector name is stored as other names is in __TEXT __cstring section)
152+ // selector name is short: i.e. "methodName:", and not "+[className methodName:]"
153+ method_types : PChar; // obj-c encoded function parameters
154+ method_imp : IMP; // virtual address of method implementation function entry point (in __TEXT __text section)
155+end;
156+```
137157
138158### __protocol
139159
140160### __cat_cls_meth (protocols list)
141161
142162### __cat_inst_meth
143163
144164### __cat_cls_meth
145165
146166## Mach-O additional 30Kb size
147167
148168FPC built mach-o executables are somehow larger, compared to the win32 target, for example
149169
150-`begin`\
151-`  writeln('hello world');`\
152-`end.`
170+``` pascal
171+begin
172+ writeln('hello world');
173+end.
174+```
153175
154176gives a 30k (stripped) executable for Win, and 60k for macOS.
155177
156178Jonas Maebe: *It's because there was a bug in older versions of the Darwin linker that required adding ".reference" assembler directives for routines that have more than one assembler name (most of the compiler helpers in the RTL have that). This fixed the problem, but as a result they are never smart linked out. It's only a fixed overhead of that 30kb (most programs don't contain any extra routines with multiple assembler names)*
157179
158180FPC 3.3.1 (trunk r44876) produces a 64 bit binary of 427,920 bytes; add -XX to smart link and it is reduced to 55,656 bytes; now strip it and it's just 47,224 bytes (~46K) which is pretty reasonable.
159181
160182---
161183*From the Free Pascal wiki, page "Mach-O", as it stood on 2020-05-17 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
162184Category: macOS

Back to history