PageRenderTime 52ms CodeModel.GetById 9ms app.highlight 35ms RepoModel.GetById 1ms app.codeStats 0ms

/red-system/formats/Mach-O.r

http://github.com/dockimbel/Red
R | 679 lines | 616 code | 63 blank | 0 comment | 26 complexity | dc255b26e0fe856cf0342ae5613d7ffe MD5 | raw file
  1REBOL [
  2	Title:	 "Red/System Mach-O format emitter"
  3	Author:  "Nenad Rakocevic"
  4	File:	 %Mach-O.r
  5	Rights:  "Copyright (C) 2011 Nenad Rakocevic. All rights reserved."
  6	License: "BSD-3 - https://github.com/dockimbel/Red/blob/master/BSD-3-License.txt"
  7]
  8
  9;; Reference doc: http://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html
 10
 11context [
 12	defs: compose [
 13		extensions [
 14			exe %""
 15			obj %.o
 16			lib %.a
 17			dll %.dylib
 18		]
 19
 20		base-address	0
 21		page-size		4096		;-- target-dependent
 22		
 23		file-type [					;-- Constants for the filetype field of the mach_header
 24			object   		1     	; relocatable object file
 25			execute  		2     	; demand paged executable file
 26			fvmlib   		3		; fixed VM shared library file
 27			core     		4		; core file
 28			preload  		5		; preloaded executable file
 29			dylib    		6		; dynamically bound shared library
 30			dylinker 		7		; dynamic link editor
 31			bundle   		8		; dynamically bound bundle file
 32			dylib_stub  	9		; shared library stub for static
 33			dsym			10		; file that store symbol information for a corresponding binary file
 34		]
 35		flags [					 	;-- Constants for the flags field of the mach_header
 36			noundefs 		1     	; no undefined references
 37			incrlink 	 	2     	; output of an incremental link against a base file
 38			dyldlink 	 	4     	; input for the dynamic linker
 39			bindatload   	8    	; undefined references are bound by the dynamic linker when loaded
 40			prebound 	 	16      ; dynamic undefined references prebound
 41			split_segs   	32      ; read-only and read-write segments split
 42			lazy_init    	64      ; (obsolete) shared library init routine run lazily
 43			twolevel 	 	128     ; the image is using two-level name space bindings
 44			force_flat   	256     ; forcing all images to use flat name space bindings
 45			nomultidefs  	512     ; no multiple defintions of symbols in its sub-images
 46			nofixprebinding	1024    ; do not have dyld notify the prebinding agent about this executable
 47			prebindable  	2048    ; not prebound but can have its prebinding redone
 48			allmodsbound 	4096    ; binds to all two-level namespace modules of its dependent libraries
 49			subsections		8192	; sections of the object file can be divided into individual blocks
 50			canonical    	16384   ; canonicalized via the unprebind operation
 51			weakdefs        32768	; ?? (MH_WEAK_DEFINES)
 52			bindstoweak     65536	; ?? (MH_BINDS_TO_WEAK)
 53			allowstackexec  131072	; ?? (MH_ALLOW_STACK_EXECUTION)
 54			validflags      262143	; ?? 0003ffff (mask)
 55		]
 56		load-type [					;-- Constants for the cmd field of all load commands
 57			req_dyld 		-2147483648
 58			segment 		1 		; segment of this file to be mapped
 59			symtab   		2 		; link-edit stab symbol table info
 60			symseg   		3 		; link-edit gdb symbol table info (obsolete)
 61			thread   		4 		; thread
 62			unixthread   	5 		; unix thread (includes a stack)
 63			loadfvmlib   	6 		; load a specified fixed VM shared library
 64			idfvmlib 		7 		; fixed VM shared library identification
 65			ident    		8 		; (obsolete) object identification info 
 66			fvmfile  		9 		; (internal use) fixed VM file inclusion
 67			prepage      	10     	; (internal use) prepage command
 68			dysymtab 		11 		; dynamic link-edit symbol table info
 69			load_dylib   	12 		; load a dynamically linked shared library
 70			id_dylib 		13 		; dynamically linked shared lib ident
 71			load_dylinker 	14    	; load a dynamic linker
 72			id_dylinker  	15 		; dynamic linker identification
 73			prebound_dylib 	16  	; modules prebound for a dynamically linked shared library
 74			routines 		17    	; image routines
 75			sub_framework 	18   	; sub framework
 76			sub_umbrella 	19    	; sub umbrella
 77			sub_client   	20   	; sub client
 78			sub_library  	21    	; sub library
 79			twolevel_hints 	22  	; two-level namespace lookup hints
 80			prebind_cksum  	23  	; prebind checksum
 81			uuid			27
 82			load_weak_dylib -2147483624	; (0x18 | REQ_DYLD)
 83		]
 84		rights [
 85			none			0
 86			read			1
 87			write			2
 88			execute			4
 89		]
 90		sect-type [								 ;-- Constants for the type of a section
 91			regular       			 #{00000000} ; regular section
 92			zerofill     	 	 	 #{00000001} ; zero fill on demand section
 93			cstring_literals  		 #{00000002} ; section with only literal C strings
 94			_4byte_literals    		 #{00000003} ; section with only 4 byte literals
 95			_8byte_literals    		 #{00000004} ; section with only 8 byte literals
 96			literal_pointers  		 #{00000005} ; section with only pointers to
 97			non_lazy_symbol_pointers #{00000006} ; section with only non-lazy
 98			lazy_symbol_pointers     #{00000007} ; section with only lazy symbol
 99			symbol_stubs        	 #{00000008} ; section with only symbol
100			mod_init_func_pointers   #{00000009} ; section with only function
101			mod_term_func_pointers   #{0000000a} ; section with only function
102			coalesced        		 #{0000000b} ; section contains symbols that
103			section_attributes_usr   #{ff000000} ; User setable attributes
104			attr_self_modifying_code #{04000000} ; section contains self-modifying code
105			attr_pure_instructions 	 #{80000000} ; section contains only true
106			attr_no_toc        	  	 #{40000000} ; section contains coalesced
107			attr_strip_static_syms   #{20000000} ; ok to strip static symbols
108			section_attributes_sys   #{00ffff00} ; system setable attributes
109			attr_some_instructions   #{00000400} ; section contains some machine instructions
110			attr_ext_reloc     		 #{00000200} ; section has external relocation entries
111			attr_loc_reloc     		 #{00000100} ; section has local relocation entries
112		]
113		sym-type [
114			n-stab					#{E0}		; stab entry
115			n-pext					#{10}		; private extern bit
116			n-type					#{0E}		; type of the symbol
117			n-ext					#{01}		; external symbol
118			;-- n-type flags --
119			n-undf					#{00}		; undefined symbol
120			n-abs					#{02}		; absolute symbol
121			n-sect					#{0E}		; symbol defined in section n-sect
122			n-pbud					#{0C}		; prebound valud for an undefined symbol
123			n-indr					#{0A}		; alias symbol (n-value points to reference symbol)
124		]
125		sym-desc [
126			undef-non-lazy			#{00}		; reference to an external non-lazy (data) symbol
127			undef-lazy				#{01}		; external lazy symbol—that is, to a function call
128			defined					#{02}		; symbol is defined in this module
129			priv-def				#{03}		; defined in module, but private
130			priv-def-non-lazy  		#{04}		; private, defined, non-lazy symbol
131			priv-def-lazy  			#{05}		; private, defined, lazy symbol
132			ref-dynamically			#{10}		; set for any defined symbol that is referenced by dynamic-loader APIs
133			desc-discarded			#{20}		; do not set this bit in a fully linked image
134			no-dead-strip			#{20}		; indicates to the static linker to never dead-strip the symbo
135			weak-ref				#{40}		; symbol is a weak reference
136			weak-def				#{80}		; symbol is a weak definition
137		]
138	]
139
140	;; Mach-O Structures
141
142	mach-header: make-struct [
143		magic			[integer!]	;; 0xfeedface
144		cpu-type		[integer!]	;; CPU_TYPE_I386 = 7
145		cpu-sub-type	[integer!]	;; CPU_SUBTYPE_I386_ALL = 3
146		file-type		[integer!]
147		nb-cmds			[integer!]	;; number of load commands
148		sz-cmds			[integer!]
149		flags			[integer!]
150	] none
151		
152	segment-command: make-struct [
153		cmd				[integer!]	; load-type/segment
154		size			[integer!]	; sizeof(segment_command + (sizeof(section) * segment->nsect))
155		segname1		[decimal!]	; char segname[16]
156		segname2		[decimal!]
157		vmaddr			[integer!]	; starting virtual memory address of this segment
158		vmsize			[integer!]	; number of bytes of virtual memory occupied by this segment
159		fileoff			[integer!]	; offset in this file of the data to be mapped at vmaddr
160		filesize		[integer!]	; number of bytes occupied by this segment on disk
161		maxprot			[integer!]	; maximum permitted virtual memory protections of this segment
162		initprot		[integer!]	; initial virtual memory protections of this segment
163		nsects			[integer!]  ; number of section data structures following this load command
164		flags			[integer!]	;
165	] none
166	
167	unix-thread-cmd: make-struct [
168		cmd				[integer!]	; load-type/segment
169		size			[integer!]	; sizeof(segment_command + (sizeof(section) * segment->nsect))
170		flavor			[integer!]	; x86_THREAD_STATE32 = 1
171		count			[integer!]	; nb of thread state 32-bit entries (16)
172		eax				[integer!]
173		ebx				[integer!]
174		ecx				[integer!]
175		edx				[integer!]
176		edi				[integer!]
177		esi				[integer!]
178		ebp				[integer!]
179		esp				[integer!]
180		ss				[integer!]
181		eflags			[integer!]
182		eip				[integer!]
183		cs				[integer!]
184		ds				[integer!]
185		es				[integer!]
186		fs				[integer!]
187		gs				[integer!]
188	] none
189	
190	load-dylib-cmd: make-struct [
191		cmd				[integer!]	; load-type/segment
192		size			[integer!]	; sizeof(segment_command + (sizeof(section) * segment->nsect))
193		offset			[integer!]	; = 24 (from the start of the load cmd)
194		timestamp		[integer!]	; date and time when the shared library was built
195		version			[integer!]	; current version of the shared library
196		compat			[integer!]	; compatibility version of the shared library
197	] none
198	
199	dylinker-cmd: make-struct [
200		cmd				[integer!]	; load-type/segment
201		size			[integer!]	; sizeof(segment_command + (sizeof(section) * segment->nsect))
202		offset			[integer!]	; = 12 (from the start of the load cmd)
203	] none
204	
205	section-header: make-struct [
206		sectname1		[decimal!]	; char sectname[16]
207		sectname2		[decimal!]
208		segname1		[decimal!]	; char segname[16]
209		segname2		[decimal!]
210		addr			[integer!]	; virtual memory address of this section
211		size			[integer!]	; size in bytes of the virtual memory occupied by this section
212		offset			[integer!]	; offset to this section in the file
213		align			[integer!]	; section’s byte alignment as power of two
214		reloff			[integer!]	; file offset of the first relocation entry for this section.
215		nreloc			[integer!]	; number of relocation entries located at reloff for this section.
216		flags			[integer!]
217		reserved1		[integer!]
218		reserved2		[integer!]
219	] none
220	
221	symtab-cmd: make-struct [
222		cmd				[integer!]	; load-type/segment
223		size			[integer!]	; sizeof(segment_command + (sizeof(section) * segment->nsect))
224		symoff			[integer!]	; symbol table file offset (from head of file)
225		nsyms			[integer!]	; nb of symbol entries
226		stroff			[integer!]	; string table file offset (from head of file)
227		strsize			[integer!]	; size of string table in bytes
228	] none
229	
230	dysymtab-cmd: make-struct [
231		cmd				[integer!]	; load-type/segment
232		size			[integer!]	; sizeof(segment_command + (sizeof(section) * segment->nsect))
233		ilocalsym		[integer!]	; index of the first symbol in the group of local symbols
234		nlocalsym		[integer!]	; total number of symbols in the group of local symbols
235		iextdefsym		[integer!]	; index of the first symbol in the group of defined external symbols
236		nextdefsym		[integer!]	; total number of symbols in the group of defined external symbols
237		iundefsym		[integer!]	; index of the first symbol in the group of undefined external symbols
238		nundefsym		[integer!]	; total number of symbols in the group of undefined external symbols
239		tocoff			[integer!]	; byte offset from the start of the file to the table of contents data
240		ntoc			[integer!]	; number of entries in the table of contents
241		modtaboff		[integer!]	; byte offset from the start of the file to the module table data
242		nmodtab			[integer!]	; number of entries in the module table
243		extrefsymoff	[integer!]	; byte offset from the start of the file to the external reference table data
244		nextrefsyms		[integer!]	; number of entries in the external reference table
245		indirectsymoff	[integer!]	; byte offset from the start of the file to the indirect symbol table data
246		nindirectsyms	[integer!]	; number of entries in the indirect symbol table
247		extreloff		[integer!]	; byte offset from the start of the file to the external relocation table data
248		nextrel			[integer!]	; number of entries in the external relocation table
249		locreloff		[integer!]	; byte offset from the start of the file to the local relocation table data
250		nlocrel			[integer!]	; number of entries in the local relocation table
251	] none
252	
253	nlist: make-struct [
254		n-strx			[integer!]	; index in the string table
255		n-type			[char!]		; bit flags
256		n-sect			[char!]		; NO-SECT (if external) or section index (one-based)
257		n-desc			[short]		; nature of symbol (for non-stab symbols)
258		n-value			[integer!]	; symbol type specific value
259	] none
260	
261	pointer: make-struct [
262		value [integer!]			;-- 32/64-bit, watch out for endianess!!
263	] none
264
265	;-- Globals --
266	
267	segments: [
268	;-- class ------ name ------ mem --- file - rights - payload - memalign
269	;						   - off sz  off sz	-
270	  segment		__PAGEZERO   0	page 0 	 0	[]		  - 	   page []
271	  segment 		__TEXT	 	 ?	 ? 	 ?	 ?	[r x]	  -		   page [
272		section		__text	 	 ?	 ?	 ?	 ?	 -		  code	   word
273	  ]
274	  segment 		__DATA	 	 ?	 ?	 ?	 ?	[r w]	  -		   page [
275		section		__data	 	 ?	 ?	 ?	 ?	 -		  data	   word
276	  ]
277	  uthread		-			 -	 -   -	 -   - 		  -		   -	[]
278	]
279	
280	imports-refs:		make block! 10		;-- [ptr [refs] ...]
281	dylink?:			no					;-- yes => dynamic library linking required
282	segment-sz:			length? form-struct segment-command
283	section-sz:			length? form-struct section-header
284	load-cmds-nb:		0
285	load-cmds-sz:		0
286	stub-size:			5					;-- imported functions slot size
287
288	;-- Mach-O structure builders --
289	
290	to-c-string: func [value][join value null]
291	
292	pad4: func [s [string!] /local rem][
293		unless zero? rem: (length? s) // 4 [
294			insert/dup tail s #"^@" 4 - rem
295		]
296		s
297	]
298	
299	get-ceiling: func [type [word!]][
300		switch/default type [
301			page [defs/page-size]
302			word [4]						;-- 4 => 32-bit, 8 => 64-bit @@
303			byte [1]
304		][4]								;-- 4 => 32-bit, 8 => 64-bit @@								
305	]
306	
307	sections?: func [list [block!]][(length? list) / 9]
308	
309	get-struct-size: func [type [word!]][
310		switch type [
311			segment  [segment-sz]
312			uthread  [length? form-struct unix-thread-cmd]
313			dylinker [length? form-struct dylinker-cmd]
314			lddylib  [length? form-struct load-dylib-cmd]
315			symtab	 [length? form-struct symtab-cmd]
316			dysymtab [length? form-struct dysymtab-cmd]
317		]
318	]
319	
320	get-rights?: func [spec [block!] /local flags][
321		flags: 0
322		foreach flag spec [
323			flags: flags + defs/rights/(select [r read w write x execute] flag)
324		]
325		flags
326	]
327	
328	get-flags: func [type [word!] /local flags][
329		flags: defs/sect-type
330		to integer! switch/default type [
331			code [
332				flags/attr_pure_instructions
333					or flags/attr_some_instructions
334			]
335			jmptbl [
336				flags/attr_pure_instructions
337					or flags/attr_some_instructions
338					or flags/attr_self_modifying_code
339					or flags/symbol_stubs
340			]
341		][flags/regular]
342	]
343	
344	get-section-addr: func [name [word!] /local addr][
345		parse segments [some [into [thru name set addr skip | none] | skip]]	
346		addr
347	]
348	
349	get-segment-info: func [name [word!] /local addr][
350		next find segments name
351	]
352	
353	process-debug-info: func [job [object!]][
354		linker/build-debug-lines job get-section-addr '__text pointer
355	]
356		
357	prepare-headers: func [
358		job [object!]
359		/local seg sec addr fpos get-value size sz header-sz hd-sz
360	][
361		get-value: func [n value][
362			switch/default seg/:n [? [value] page [defs/page-size]][seg/:n]
363		]
364		
365		load-cmds-sz: 0
366		seg: segments
367		until [
368			load-cmds-sz: load-cmds-sz + get-struct-size seg/1
369			if string? seg/2 [load-cmds-sz: load-cmds-sz + length? seg/2]	;-- account for load-dylib path
370			load-cmds-nb: load-cmds-nb + 1
371			unless empty? seg/10 [
372				load-cmds-sz: load-cmds-sz + (section-sz * sections? seg/10)
373			]
374			tail? seg: skip seg 10
375		]
376		
377		header-sz: load-cmds-sz + length? form-struct mach-header
378		addr: 0
379		fpos: header-sz
380		
381		seg: segments
382		until [
383			if seg/1 = 'segment [
384				seg/3: addr: round/ceiling/to get-value 3 addr get-ceiling seg/9 ;-- offset in memory (segment)
385				seg/5: fpos: round/ceiling/to get-value 5 fpos get-ceiling seg/9 ;-- offset in file (segment)
386
387				sec: seg/10
388				hd-sz: either seg/2 = '__TEXT [header-sz][0]	;-- account for headers
389				size: either seg/8 = '- [0][length? job/sections/(seg/8)/2]
390				while [not tail? sec][
391					sz: length? job/sections/(sec/8)/2					
392					sec/3: addr: round/ceiling/to addr + hd-sz get-ceiling sec/9 ;-- offset in memory (section)
393					sec/4: sz							;-- size in memory (section)
394					sec/5: fpos: round/ceiling/to fpos + hd-sz get-ceiling sec/9 ;-- offset in file (section)
395					sec/6: sz							;-- size in file (section)
396					size:  size + sz + hd-sz
397					addr:  addr + sz
398					fpos:  fpos + sz
399					sec: skip sec 9
400				]
401				size: round/ceiling/to size defs/page-size
402				seg/4: get-value 4 size 				;-- size in memory (segment)
403				seg/6: get-value 6 size					;-- size in file (segment)
404				if zero? size [
405					addr:  addr + seg/4
406					fpos:  fpos + seg/6
407				]
408				if all [seg/2 = '__TEXT job/debug?][
409					process-debug-info job
410				]
411			]
412			tail? seg: skip seg 10
413		]
414	]
415	
416	emit-page-aligned: func [buf [binary!] data [binary!] /local page rem][
417		append buf data
418		unless zero? rem: (length? buf) // page: defs/page-size [
419			insert/dup tail buf null page - rem
420		]
421	]
422	
423	resolve-data-refs: func [job [object!] /local cbuf dbuf data code][
424		cbuf: job/sections/code/2
425		dbuf: job/sections/data/2
426		forskip segments 10 [
427			switch segments/2 [
428				__TEXT [code: get-section-addr '__text]
429				__DATA [data: segments/3]
430			]
431		]
432		linker/resolve-symbol-refs job cbuf dbuf code data pointer
433	]
434	
435	resolve-import-refs: func [job [object!] /local code base][
436		code: job/sections/code/2
437		base: get-section-addr '__jump_table
438
439		foreach [ptr reloc] imports-refs [
440			pointer/value: ptr: base + ptr
441			foreach ref reloc [
442				change at code ref form-struct pointer 	;TBD: check endianness + x-compilation
443			]
444		]
445	]
446
447	build-imports: func [
448		job [object!]
449		/local sym-tbl dy-sym-tbl lib cnt entry
450	][
451		sym-tbl:    make binary! 1024
452		dy-sym-tbl: make binary! 1024
453		str-tbl: 	make binary! 1024
454		append str-tbl #{00000000}					;-- start with 4 null bytes @@
455		
456		insert find segments 'uthread [
457			segment			__IMPORT	 ?	 ? 	 ?	 ?	[r w x]	  -   	   page [
458				section		__jump_table ?	 ?   ?   ?  -		  jmptbl   byte
459			]
460			segment			__LINKEDIT	 ?	 ?	 ?	 ?  [r]		  symbols  page [] 
461			dylinker		-			 -	 -   -	 -   - 		  -		   -	[]
462			symtab			-			 -	 -   -	 -   - 		  -		   -	[]
463			dysymtab		-			 -	 -   -	 -   - 		  -		   -	[]
464			;twolvlhints	-			 -	 -   -	 -   - 		  -		   -	[]
465		]
466		segments/dylinker: pad4 to-c-string "/usr/lib/dyld"
467		
468		lib: 1										;-- one-based index
469		cnt: 0
470		foreach [name list] job/sections/import/3 [
471			name: to-c-string name
472			if name/1 <> slash [insert name "/usr/lib/"]
473			insert find segments 'symtab compose [
474				  lddylib (pad4 name) -	 -   -	 -   - 		  -		   -	[]
475			]
476			foreach [def reloc] list [		
477				entry: make-struct nlist none
478				entry/n-strx:  length? str-tbl
479				entry/n-type:  to integer! defs/sym-type/n-undf or defs/sym-type/n-ext
480				entry/n-sect:  0					;-- NO_SECT
481				entry/n-desc:  (to integer! defs/sym-desc/undef-lazy) or shift/left lib 8
482				entry/n-value: 0
483				append sym-tbl form-struct entry
484				
485				pointer/value: cnt
486				append dy-sym-tbl form-struct pointer
487				
488				repend imports-refs [cnt * stub-size reloc]		;-- store symbol jump table offset
489				
490				append str-tbl join "_" to-c-string def
491				cnt: cnt + 1
492			]
493			lib: lib + 1
494		]
495		repend job/sections [
496			'jmptbl reduce [
497				'- head insert/dup make binary! cnt * stub-size #{F4F4F4F4F4} cnt
498			]
499			'symbols reduce [
500				reduce [cnt length? sym-tbl length? dy-sym-tbl length? str-tbl]
501				rejoin [sym-tbl dy-sym-tbl str-tbl]
502			]
503		]
504	]
505	
506	build-dysymtab-command: func [job [object!] spec [block!] /local sc sym-info][
507		sym-info: job/sections/symbols/1
508
509		sc: make-struct dysymtab-cmd none
510		sc/cmd:			   defs/load-type/dysymtab
511		sc/size:		   get-struct-size 'dysymtab
512		sc/ilocalsym:	   0
513		sc/nlocalsym:	   0
514		sc/iextdefsym:	   0
515		sc/nextdefsym:	   0
516		sc/iundefsym:	   0
517		sc/nundefsym:	   sym-info/1
518		sc/tocoff:		   0
519		sc/ntoc:		   0
520		sc/modtaboff:	   0
521		sc/nmodtab:		   0
522		sc/extrefsymoff:   0
523		sc/nextrefsyms:	   0
524		sc/indirectsymoff: (third get-segment-info '__LINKEDIT) + sym-info/2
525		sc/nindirectsyms:  sym-info/1
526		sc/extreloff:	   0
527		sc/nextrel:		   0
528		sc/locreloff:	   0
529		sc/nlocrel:		   0
530		sc: form-struct sc
531		sc
532	]
533	
534	build-symtab-command: func [job [object!] spec [block!] /local sc sym-info][
535		sym-info: job/sections/symbols/1
536		
537		sc: make-struct symtab-cmd none
538		sc/cmd:			defs/load-type/symtab
539		sc/size:		get-struct-size 'symtab
540		sc/symoff:		third get-segment-info '__LINKEDIT
541		sc/nsyms:		sym-info/1
542		sc/stroff:		sc/symoff + sym-info/2 + sym-info/3
543		sc/strsize:		sym-info/4
544		sc: form-struct sc
545		sc
546	]
547	
548	build-lddylib-command: func [job [object!] spec [block!] /local lc][
549		lc: make-struct load-dylib-cmd none
550		lc/cmd:			defs/load-type/load_dylib
551		lc/size:		(get-struct-size 'lddylib) + length? spec/2
552		lc/offset:		24
553		lc/timestamp:	2
554		lc/version:		to integer! #{007D0000}	;-- 128.0.0
555		lc/compat:		to integer! #{00000000}	;-- 0.0.0		@@ should be configurable
556		lc: form-struct lc
557		append lc spec/2
558		lc
559	]
560	
561	build-dylinker-command: func [job [object!] spec [block!] /local dl][
562		dl: make-struct dylinker-cmd none
563		dl/cmd:			defs/load-type/load_dylinker
564		dl/size:		(get-struct-size 'dylinker) + length? spec/2
565		dl/offset:		12
566		dl: form-struct dl
567		append dl spec/2	
568		dl
569	]
570	
571	build-uthread-command: func [job [object!] spec [block!] /local ut][
572		ut: make-struct unix-thread-cmd none
573		ut/cmd:			defs/load-type/unixthread
574		ut/size:		get-struct-size 'uthread
575		ut/flavor:		1							;-- x86_THREAD_STATE32
576		ut/count:		16
577		ut/eip:			get-section-addr '__text
578		form-struct ut
579	]
580	
581	build-section-header: func [spec [block!] seg-name [word!] /local sh][
582		sh: make-struct section-header none
583		sh/addr:		spec/3
584		sh/size:		spec/6
585		sh/offset:		spec/5
586		sh/align:		to integer! log-2 select [byte 1 word 4 dword 8] spec/9	;-- 32/64-bit @@
587		sh/reloff:		0
588		sh/nreloc:		0
589		sh/flags:		get-flags spec/8
590		sh/reserved1:	0
591		sh/reserved2:	either spec/2 = '__jump_table [stub-size][0]
592		sh: form-struct sh
593		change sh to-c-string spec/2
594		change at sh 17 to-c-string seg-name
595		sh
596	]
597	
598	build-segment-command: func [job [object!] spec [block!] /local sc][
599		sc: make-struct segment-command none
600		sc/cmd:			defs/load-type/segment
601		sc/size:		segment-sz + (section-sz * sections? spec/10)
602		sc/vmaddr:		spec/3
603		sc/vmsize:		spec/4
604		sc/fileoff:		spec/5
605		sc/filesize:	spec/6
606		sc/maxprot:		either empty? spec/7 [0][get-rights? [r w x]]
607		sc/initprot:	get-rights? spec/7
608		sc/nsects:		sections? spec/10
609		sc/flags:		4						;-- SG_NORELOC
610		sc: form-struct sc
611		change at sc 9 to-c-string spec/2
612		sc
613	]
614		
615	build-mach-header: func [job [object!] /local mh][
616		mh: make-struct mach-header none
617		mh/magic:			to integer! #{FEEDFACE}
618		mh/cpu-type:		7					;-- CPU_TYPE_I386
619		mh/cpu-sub-type:	3					;-- CPU_SUBTYPE_I386_ALL
620		mh/file-type:		defs/file-type/execute
621		mh/nb-cmds:			load-cmds-nb
622		mh/sz-cmds:			load-cmds-sz
623		mh/flags:			defs/flags/noundefs
624		if dylink? [
625			mh/flags: mh/flags 
626				or defs/flags/dyldlink
627				or defs/flags/subsections
628				;or defs/flags/bindatload
629		]
630		form-struct mh
631	]
632
633	build: func [
634		job [object!]
635		/local
636			base-address dynamic-linker out sections
637
638	] [
639		base-address: any [job/base-address defs/base-address]
640		dynamic-linker: any [job/dynamic-linker ""]
641		
642		dylink?: not empty? job/sections/import/3
643		
644		clear imports-refs
645		if dylink? [build-imports job]
646		
647		prepare-headers job
648		
649		out: job/buffer
650		append out build-mach-header job
651		seg: segments
652		forskip seg 10 [
653			append out switch seg/1 [
654				segment  [build-segment-command  job seg]
655				uthread  [build-uthread-command  job seg]
656				dylinker [build-dylinker-command job seg]
657				lddylib  [build-lddylib-command  job seg]
658				symtab	 [build-symtab-command 	 job seg]
659				dysymtab [build-dysymtab-command job seg]
660			]
661			unless empty? sections: seg/10 [
662				forskip sections 9 [
663					append out build-section-header sections seg/2
664				]
665			]
666		]
667		
668		if dylink? [resolve-import-refs job]
669		resolve-data-refs job
670		
671		emit-page-aligned out job/sections/code/2
672		emit-page-aligned out job/sections/data/2
673	
674		if dylink? [
675			emit-page-aligned out job/sections/jmptbl/2
676			emit-page-aligned out job/sections/symbols/2
677		]
678	]
679]