/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

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