macho-objfmt.c 58 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620
  1. /*
  2. * Mac OS X ABI Mach-O File Format
  3. *
  4. * Copyright (C) 2007 Henryk Richter, built upon xdf objfmt (C) Peter Johnson
  5. *
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
  17. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
  20. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  21. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  22. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  23. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  24. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  25. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  26. * POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. /*
  29. notes: This implementation is rather basic. There are several implementation
  30. issues to be sorted out for full compliance and error resilience.
  31. Some examples are given below (nasm syntax).
  32. 1) section placement
  33. Mach-O requires BSS sections to be placed last in object files. This
  34. has to be done manually.
  35. Example:
  36. section .text
  37. mov rax,[qword foo]
  38. section .data
  39. dw 0
  40. section .bss
  41. foo dw 0
  42. 2) addressing issues
  43. 2.1) symbol relative relocation (i.e. mov eax,[foo wrt bar])
  44. Not implemented yet.
  45. 2.2) data referencing in 64 bit mode
  46. While ELF allows 32 bit absolute relocations in 64 bit mode, Mach-O
  47. does not. Therefore code like
  48. lea rbx,[_foo] ;48 8d 1c 25 00 00 00 00
  49. mov rcx,[_bar] ;48 8b 0c 25 00 00 00 00
  50. with a 32 bit address field cannot be relocated into an address >= 0x100000000 (OSX actually
  51. uses that).
  52. Actually, the only register where a 64 bit displacement is allowed in x86-64, is rax
  53. as in the example 1).
  54. A plausible workaround is either classic PIC (like in C), which is in turn
  55. not implemented in this object format. The recommended was is PC relative
  56. code (called RIP-relative in x86-64). So instead of the lines above, just write:
  57. lea rbx,[_foo wrt rip]
  58. mov rcx,[_bar wrt rip]
  59. 2.3) section/data alignment
  60. Normally, you specify sections with a specific alignment
  61. and get your data layed out as desired. Unfortunately, the
  62. linker in MacOS X seems to ignore the section alignment requests.
  63. The workaround is an explicit alignment at the end of the text section.
  64. section .text
  65. movdqa xmm0,[_foo wrt rip]
  66. align 16
  67. section .data align=16
  68. _foo dw 32,32,32,32,32,32,32,32
  69. FIXME: perform that operation implicitly!
  70. 2.4) cross section symbol differences unsupported in current implementation
  71. [extern foo]
  72. [extern bar]
  73. section .data
  74. dq bar-foo
  75. Will currently produce an error though the necessary means are provided
  76. by the Mach-O specification.
  77. */
  78. #include <util.h>
  79. #include <libyasm.h>
  80. /* MACH-O DEFINES */
  81. /* Mach-O in-file header structure sizes (32 BIT, see below for 64 bit defs) */
  82. #define MACHO_HEADER_SIZE 28
  83. #define MACHO_SEGCMD_SIZE 56
  84. #define MACHO_SECTCMD_SIZE 68
  85. #define MACHO_SYMCMD_SIZE 24
  86. #define MACHO_NLIST_SIZE 12
  87. #define MACHO_RELINFO_SIZE 8
  88. /* 64 bit sizes */
  89. #define MACHO_HEADER64_SIZE 32
  90. #define MACHO_SEGCMD64_SIZE 72
  91. #define MACHO_SECTCMD64_SIZE 80
  92. #define MACHO_NLIST64_SIZE 16
  93. #define MACHO_RELINFO64_SIZE 8
  94. /* Mach-O file header values */
  95. #define MH_MAGIC 0xfeedface
  96. #define MH_MAGIC_64 0xfeedfacf
  97. /* CPU machine type */
  98. #define CPU_TYPE_I386 7 /* x86 platform */
  99. #define CPU_TYPE_X86_64 (CPU_TYPE_I386|CPU_ARCH_ABI64)
  100. #define CPU_ARCH_ABI64 0x01000000 /* 64 bit ABI */
  101. /* CPU machine subtype, e.g. processor */
  102. #define CPU_SUBTYPE_I386_ALL 3 /* all-x86 compatible */
  103. #define CPU_SUBTYPE_X86_64_ALL CPU_SUBTYPE_I386_ALL
  104. #define CPU_SUBTYPE_386 3
  105. #define CPU_SUBTYPE_486 4
  106. #define CPU_SUBTYPE_486SX (4 + 128)
  107. #define CPU_SUBTYPE_586 5
  108. #define CPU_SUBTYPE_INTEL(f, m) ((f) + ((m) << 4))
  109. #define CPU_SUBTYPE_PENT CPU_SUBTYPE_INTEL(5, 0)
  110. #define CPU_SUBTYPE_PENTPRO CPU_SUBTYPE_INTEL(6, 1)
  111. #define CPU_SUBTYPE_PENTII_M3 CPU_SUBTYPE_INTEL(6, 3)
  112. #define CPU_SUBTYPE_PENTII_M5 CPU_SUBTYPE_INTEL(6, 5)
  113. #define CPU_SUBTYPE_PENTIUM_4 CPU_SUBTYPE_INTEL(10, 0)
  114. #define CPU_SUBTYPE_INTEL_FAMILY(x) ((x) & 15)
  115. #define CPU_SUBTYPE_INTEL_FAMILY_MAX 15
  116. #define CPU_SUBTYPE_INTEL_MODEL(x) ((x) >> 4)
  117. #define CPU_SUBTYPE_INTEL_MODEL_ALL 0
  118. #define MH_OBJECT 0x1 /* object file */
  119. #define LC_SEGMENT 0x1 /* segment load command */
  120. #define LC_SYMTAB 0x2 /* symbol table load command */
  121. #define LC_SEGMENT_64 0x19 /* segment load command */
  122. #define VM_PROT_NONE 0x00
  123. #define VM_PROT_READ 0x01
  124. #define VM_PROT_WRITE 0x02
  125. #define VM_PROT_EXECUTE 0x04
  126. #define VM_PROT_DEFAULT (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE)
  127. #define VM_PROT_ALL (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE)
  128. #define SECTION_TYPE 0x000000ff /* section type mask */
  129. #define SECTION_ATTRIBUTES 0xffffff00UL/* section attributes mask */
  130. #define S_REGULAR 0x0 /* standard section */
  131. #define S_ZEROFILL 0x1 /* zerofill, in-memory only */
  132. #define S_CSTRING_LITERALS 0x2 /* literal C strings */
  133. #define S_4BYTE_LITERALS 0x3 /* only 4-byte literals */
  134. #define S_8BYTE_LITERALS 0x4 /* only 8-byte literals */
  135. #define S_LITERAL_POINTERS 0x5 /* only pointers to literals */
  136. #define S_NON_LAZY_SYMBOL_POINTERS 0x6 /* only non-lazy symbol pointers */
  137. #define S_LAZY_SYMBOL_POINTERS 0x7 /* only lazy symbol pointers */
  138. #define S_SYMBOL_STUBS 0x8 /* only symbol stubs; byte size of
  139. * stub in the reserved2 field */
  140. #define S_MOD_INIT_FUNC_POINTERS 0x9 /* only function pointers for init */
  141. #define S_MOD_TERM_FUNC_POINTERS 0xa /* only function pointers for term */
  142. #define S_COALESCED 0xb /* symbols that are to be coalesced */
  143. #define S_GB_ZEROFILL 0xc /* >4GB zero fill on demand section */
  144. #define S_INTERPOSING 0xd /* only pairs of function pointers for
  145. * interposing */
  146. #define S_16BYTE_LITERALS 0xe /* only 16 byte literals */
  147. #define S_ATTR_DEBUG 0x02000000 /* a debug section */
  148. #define SECTION_ATTRIBUTES_SYS 0x00ffff00 /* system setable attributes */
  149. #define S_ATTR_SOME_INSTRUCTIONS 0x00000400 /* section contains some
  150. * machine instructions */
  151. #define S_ATTR_EXT_RELOC 0x00000200 /* section has external
  152. * relocation entries */
  153. #define S_ATTR_LOC_RELOC 0x00000100 /* section has local
  154. * relocation entries */
  155. #define SECTION_ATTRIBUTES_USR 0xff000000UL /* User setable attributes */
  156. #define S_ATTR_PURE_INSTRUCTIONS 0x80000000UL /* only true machine insns */
  157. #define S_ATTR_NO_TOC 0x40000000UL /* coalesced symbols that are
  158. * not to be in a ranlib table
  159. * of contents */
  160. #define S_ATTR_STRIP_STATIC_SYMS 0x20000000UL /* ok to strip static symbols
  161. * in this section in files
  162. * with the MH_DYLDLINK flag */
  163. #define S_ATTR_NO_DEAD_STRIP 0x10000000UL /* no dead stripping */
  164. #define S_ATTR_LIVE_SUPPORT 0x08000000UL /* blocks are live if they
  165. * reference live blocks */
  166. #define S_ATTR_SELF_MODIFYING_CODE 0x04000000UL /* Used with i386 code stubs
  167. * written on by dyld */
  168. /* macho references symbols in different ways whether they are linked at
  169. * runtime (LAZY, read library functions) or at link time (NON_LAZY, mostly
  170. * data)
  171. *
  172. * TODO: proper support for dynamically linkable modules would require the
  173. * __import sections as well as the dsymtab command
  174. */
  175. #define REFERENCE_FLAG_UNDEFINED_NON_LAZY 0x0
  176. #define REFERENCE_FLAG_UNDEFINED_LAZY 0x1
  177. #define align(x, y) \
  178. (((x) + (y) - 1) & ~((y) - 1)) /* align x to multiple of y */
  179. #define align32(x) \
  180. align(x, 4) /* align x to 32 bit boundary */
  181. #define macho_MAGIC 0x87654322
  182. /* Symbol table type field bit masks */
  183. #define N_STAB 0xe0 /* mask indicating stab entry */
  184. #define N_PEXT 0x10 /* private external bit */
  185. #define N_TYPE 0x0e /* mask for all the type bits */
  186. #define N_EXT 0x01 /* external (global) bit */
  187. /* Symbol table type field values */
  188. #define N_UNDF 0x00 /* undefined */
  189. #define N_ABS 0x02 /* absolute address */
  190. #define N_SECT 0x0e /* symbol is defined in a section */
  191. #define NO_SECT 0 /* no section for symbol in nlist */
  192. #define REGULAR_OUTBUF_SIZE 1024
  193. typedef struct macho_reloc {
  194. yasm_reloc reloc;
  195. int pcrel;
  196. int length;
  197. int ext;
  198. enum reloc_type_x86_64 {
  199. /* x86 relocations */
  200. GENERIC_RELOC_VANILLA = 0, /* generic relocation */
  201. GENERIC_RELOC_PAIR = 1, /* Only follows a GENERIC_RELOC_SECTDIFF */
  202. GENERIC_RELOC_SECTDIFF = 2,
  203. GENERIC_RELOC_PB_LA_PTR = 3, /* prebound lazy pointer */
  204. GENERIC_RELOC_LOCAL_SECTDIFF = 4,
  205. /* x86-64 relocations */
  206. X86_64_RELOC_UNSIGNED = 0, /* for absolute addresses */
  207. X86_64_RELOC_SIGNED = 1, /* for signed 32-bit displacement */
  208. X86_64_RELOC_BRANCH = 2, /* a CALL/JMP insn with 32-bit disp */
  209. X86_64_RELOC_GOT_LOAD = 3, /* a MOVQ load of a GOT entry */
  210. X86_64_RELOC_GOT = 4, /* other GOT references */
  211. X86_64_RELOC_SUBTRACTOR = 5, /* must be followed by a X86_64_RELOC_UNSIGNED */
  212. X86_64_RELOC_SIGNED_1 = 6, /* signed 32-bit disp, -1 addend */
  213. X86_64_RELOC_SIGNED_2 = 7, /* signed 32-bit disp, -2 addend */
  214. X86_64_RELOC_SIGNED_4 = 8 /* signed 32-bit disp, -4 addend */
  215. } type;
  216. } macho_reloc;
  217. typedef struct macho_section_data {
  218. /*@dependent@*/ yasm_symrec *sym; /* symbol created for this section */
  219. long scnum; /* section number (0=first section) */
  220. /*@only@*/ char *segname; /* segment name in file */
  221. /*@only@*/ char *sectname; /* section name in file */
  222. unsigned long flags; /* S_* flags */
  223. unsigned long size; /* size of raw data (section data) in bytes */
  224. unsigned long offset; /* offset in raw data within file in bytes */
  225. unsigned long vmoff; /* memory offset */
  226. unsigned long nreloc; /* number of relocation entries */
  227. unsigned int extreloc; /* external relocations present (0/1) */
  228. } macho_section_data;
  229. typedef struct macho_symrec_data {
  230. unsigned long index; /* index in output order */
  231. yasm_intnum *value; /* valid after writing symtable to file */
  232. unsigned long length; /* length + 1 (plus auto underscore) */
  233. } macho_symrec_data;
  234. typedef struct yasm_objfmt_macho {
  235. yasm_objfmt_base objfmt; /* base structure */
  236. long parse_scnum; /* sect numbering in parser */
  237. int bits; /* 32 / 64 */
  238. yasm_symrec *gotpcrel_sym; /* ..gotpcrel */
  239. } yasm_objfmt_macho;
  240. typedef struct macho_objfmt_output_info {
  241. yasm_object *object;
  242. yasm_objfmt_macho *objfmt_macho;
  243. yasm_errwarns *errwarns;
  244. /*@dependent@ */ FILE *f;
  245. /*@only@ */ unsigned char *buf;
  246. yasm_section *sect;
  247. /*@dependent@ */ macho_section_data *msd;
  248. unsigned int is_64; /* write object in 64 bit mode */
  249. /* vmsize and filesize available after traversing section count routine */
  250. unsigned long vmsize; /* raw size of all sections (including BSS) */
  251. unsigned long filesize; /* size of sections in file (excluding BSS) */
  252. unsigned long offset; /* offset within file */
  253. /* forward offset tracking */
  254. unsigned long rel_base; /* first relocation in file */
  255. unsigned long s_reloff; /* in-file offset to relocations */
  256. unsigned long indx; /* current symbol size in bytes (name length+1) */
  257. unsigned long symindex; /* current symbol index in output order */
  258. int all_syms; /* outputting all symbols? */
  259. unsigned long strlength; /* length of all strings */
  260. } macho_objfmt_output_info;
  261. static void macho_section_data_destroy(/*@only@*/ void *d);
  262. static void macho_section_data_print(void *data, FILE *f, int indent_level);
  263. static const yasm_assoc_data_callback macho_section_data_cb = {
  264. macho_section_data_destroy,
  265. macho_section_data_print
  266. };
  267. static void macho_symrec_data_destroy(/*@only@*/ void *d);
  268. static void macho_symrec_data_print(void *data, FILE *f, int indent_level);
  269. static const yasm_assoc_data_callback macho_symrec_data_cb = {
  270. macho_symrec_data_destroy,
  271. macho_symrec_data_print
  272. };
  273. yasm_objfmt_module yasm_macho_LTX_objfmt;
  274. yasm_objfmt_module yasm_macho32_LTX_objfmt;
  275. yasm_objfmt_module yasm_macho64_LTX_objfmt;
  276. static yasm_objfmt *
  277. macho_objfmt_create_common(yasm_object *object, yasm_objfmt_module *module,
  278. int bits_pref)
  279. {
  280. yasm_objfmt_macho *objfmt_macho = yasm_xmalloc(sizeof(yasm_objfmt_macho));
  281. objfmt_macho->objfmt.module = module;
  282. /* Only support x86 arch for now */
  283. if (yasm__strcasecmp(yasm_arch_keyword(object->arch), "x86") != 0) {
  284. yasm_xfree(objfmt_macho);
  285. return NULL;
  286. }
  287. /* Support x86 and amd64 machines of x86 arch */
  288. if (yasm__strcasecmp(yasm_arch_get_machine(object->arch), "x86") == 0 &&
  289. (bits_pref == 0 || bits_pref == 32)) {
  290. objfmt_macho->bits = 32;
  291. objfmt_macho->gotpcrel_sym = NULL;
  292. } else if (yasm__strcasecmp(yasm_arch_get_machine(object->arch),
  293. "amd64") == 0 &&
  294. (bits_pref == 0 || bits_pref == 64)) {
  295. objfmt_macho->bits = 64;
  296. /* FIXME: misuse of NULL bytecode */
  297. objfmt_macho->gotpcrel_sym =
  298. yasm_symtab_define_label(object->symtab, "..gotpcrel", NULL, 0, 0);
  299. } else {
  300. yasm_xfree(objfmt_macho);
  301. return NULL;
  302. }
  303. objfmt_macho->parse_scnum = 0; /* section numbering starts at 0 */
  304. return (yasm_objfmt *)objfmt_macho;
  305. }
  306. static yasm_objfmt *
  307. macho_objfmt_create(yasm_object *object)
  308. {
  309. yasm_objfmt *objfmt;
  310. yasm_objfmt_macho *objfmt_macho;
  311. objfmt = macho_objfmt_create_common(object, &yasm_macho_LTX_objfmt, 0);
  312. if (objfmt) {
  313. objfmt_macho = (yasm_objfmt_macho *)objfmt;
  314. /* Figure out which bitness of object format to use */
  315. if (objfmt_macho->bits == 32)
  316. objfmt_macho->objfmt.module = &yasm_macho32_LTX_objfmt;
  317. else if (objfmt_macho->bits == 64)
  318. objfmt_macho->objfmt.module = &yasm_macho64_LTX_objfmt;
  319. }
  320. return objfmt;
  321. }
  322. static yasm_objfmt *
  323. macho32_objfmt_create(yasm_object *object)
  324. {
  325. return macho_objfmt_create_common(object, &yasm_macho32_LTX_objfmt, 32);
  326. }
  327. static yasm_objfmt *
  328. macho64_objfmt_create(yasm_object *object)
  329. {
  330. return macho_objfmt_create_common(object, &yasm_macho64_LTX_objfmt, 64);
  331. }
  332. static int
  333. macho_objfmt_output_value(yasm_value *value, unsigned char *buf,
  334. unsigned int destsize, unsigned long offset,
  335. yasm_bytecode *bc, int warn, /*@null@*/ void *d)
  336. {
  337. /*@null@*/ macho_objfmt_output_info *info = (macho_objfmt_output_info *)d;
  338. yasm_objfmt_macho *objfmt_macho;
  339. /*@dependent@*/ /*@null@*/ yasm_intnum *intn;
  340. unsigned long intn_minus = 0, intn_plus = 0;
  341. int retval;
  342. unsigned int valsize = value->size;
  343. macho_reloc *reloc = NULL;
  344. assert(info != NULL);
  345. objfmt_macho = info->objfmt_macho;
  346. if (value->abs)
  347. value->abs = yasm_expr_simplify(value->abs, 1);
  348. /* Try to output constant and PC-relative section-local first.
  349. * Note this does NOT output any value with a SEG, WRT, external,
  350. * cross-section, or non-PC-relative reference (those are handled below).
  351. */
  352. switch (yasm_value_output_basic(value, buf, destsize, bc, warn,
  353. info->object->arch)) {
  354. case -1:
  355. return 1;
  356. case 0:
  357. break;
  358. default:
  359. return 0;
  360. }
  361. if (value->section_rel) {
  362. yasm_error_set(YASM_ERROR_TOO_COMPLEX,
  363. N_("macho: relocation too complex for current implementation"));
  364. return 1;
  365. }
  366. if (value->rel) {
  367. yasm_sym_vis vis = yasm_symrec_get_visibility(value->rel);
  368. reloc = yasm_xcalloc(sizeof(macho_reloc), 1);
  369. reloc->reloc.addr = yasm_intnum_create_uint(bc->offset + offset);
  370. reloc->reloc.sym = value->rel;
  371. switch (valsize) {
  372. case 64:
  373. reloc->length = 3;
  374. break;
  375. case 32:
  376. reloc->length = 2;
  377. break;
  378. case 16:
  379. reloc->length = 1;
  380. break;
  381. case 8:
  382. reloc->length = 0;
  383. break;
  384. default:
  385. yasm_error_set(YASM_ERROR_TOO_COMPLEX,
  386. N_("macho: relocation size unsupported"));
  387. yasm_xfree(reloc);
  388. return 1;
  389. }
  390. reloc->pcrel = 0;
  391. reloc->ext = 0;
  392. reloc->type = GENERIC_RELOC_VANILLA;
  393. /* R_ABS */
  394. if (value->rshift > 0) {
  395. yasm_error_set(YASM_ERROR_TOO_COMPLEX,
  396. N_("macho: shifted relocations not supported"));
  397. yasm_xfree(reloc);
  398. return 1;
  399. }
  400. if (value->seg_of) {
  401. yasm_error_set(YASM_ERROR_TOO_COMPLEX,
  402. N_("macho: SEG not supported"));
  403. yasm_xfree(reloc);
  404. return 1;
  405. }
  406. if (value->curpos_rel && objfmt_macho->gotpcrel_sym &&
  407. value->wrt == objfmt_macho->gotpcrel_sym) {
  408. reloc->type = X86_64_RELOC_GOT;
  409. value->wrt = NULL;
  410. } else if (value->wrt) {
  411. yasm_error_set(YASM_ERROR_TOO_COMPLEX,
  412. N_("macho: invalid WRT"));
  413. yasm_xfree(reloc);
  414. return 1;
  415. }
  416. if (value->curpos_rel) {
  417. reloc->pcrel = 1;
  418. if (!info->is_64) {
  419. /* Adjust to start of section, so subtract out the bytecode
  420. * offset.
  421. */
  422. intn_minus = bc->offset;
  423. } else {
  424. /* Add in the offset plus value size to end up with 0. */
  425. intn_plus = offset+destsize;
  426. if (reloc->type == X86_64_RELOC_GOT) {
  427. /* XXX: This is a hack */
  428. if (offset >= 2 && buf[-2] == 0x8B)
  429. reloc->type = X86_64_RELOC_GOT_LOAD;
  430. } else if (value->jump_target)
  431. reloc->type = X86_64_RELOC_BRANCH;
  432. else
  433. reloc->type = X86_64_RELOC_SIGNED;
  434. }
  435. } else if (info->is_64) {
  436. if (valsize == 32) {
  437. yasm_error_set(YASM_ERROR_NOT_CONSTANT,
  438. N_("macho: sorry, cannot apply 32 bit absolute relocations in 64 bit mode, consider \"[_symbol wrt rip]\" for mem access, \"qword\" and \"dq _foo\" for pointers."));
  439. return 1;
  440. }
  441. reloc->type = X86_64_RELOC_UNSIGNED;
  442. }
  443. /* It seems that x86-64 objects need to have all extern relocs? */
  444. if (info->is_64)
  445. reloc->ext = 1;
  446. if ((vis & YASM_SYM_EXTERN) || (vis & YASM_SYM_COMMON)) {
  447. reloc->ext = 1;
  448. info->msd->extreloc = 1; /* section has external relocations */
  449. } else if (!info->is_64) {
  450. /*@dependent@*/ /*@null@*/ yasm_bytecode *sym_precbc;
  451. /* Local symbols need valued to their actual address */
  452. if (yasm_symrec_get_label(value->rel, &sym_precbc)) {
  453. yasm_section *sym_sect = yasm_bc_get_section(sym_precbc);
  454. /*@null@*/ macho_section_data *msd;
  455. msd = yasm_section_get_data(sym_sect, &macho_section_data_cb);
  456. assert(msd != NULL);
  457. intn_plus += msd->vmoff + yasm_bc_next_offset(sym_precbc);
  458. }
  459. }
  460. info->msd->nreloc++;
  461. /*printf("reloc %s type %d ",yasm_symrec_get_name(reloc->reloc.sym),reloc->type);*/
  462. yasm_section_add_reloc(info->sect, (yasm_reloc *)reloc, yasm_xfree);
  463. }
  464. if (intn_minus <= intn_plus)
  465. intn = yasm_intnum_create_uint(intn_plus-intn_minus);
  466. else {
  467. intn = yasm_intnum_create_uint(intn_minus-intn_plus);
  468. yasm_intnum_calc(intn, YASM_EXPR_NEG, NULL);
  469. }
  470. if (value->abs) {
  471. yasm_intnum *intn2 = yasm_expr_get_intnum(&value->abs, 0);
  472. if (!intn2) {
  473. yasm_error_set(YASM_ERROR_TOO_COMPLEX,
  474. N_("macho: relocation too complex"));
  475. yasm_intnum_destroy(intn);
  476. return 1;
  477. }
  478. yasm_intnum_calc(intn, YASM_EXPR_ADD, intn2);
  479. }
  480. retval = yasm_arch_intnum_tobytes(info->object->arch, intn, buf, destsize,
  481. valsize, 0, bc, warn);
  482. /*printf("val %ld\n",yasm_intnum_get_int(intn));*/
  483. yasm_intnum_destroy(intn);
  484. return retval;
  485. }
  486. static int
  487. macho_objfmt_output_bytecode(yasm_bytecode *bc, /*@null@*/ void *d)
  488. {
  489. /*@null@*/ macho_objfmt_output_info *info = (macho_objfmt_output_info *)d;
  490. /*@null@*/ /*@only@*/ unsigned char *bigbuf;
  491. unsigned long size = REGULAR_OUTBUF_SIZE;
  492. int gap;
  493. assert(info != NULL);
  494. bigbuf = yasm_bc_tobytes(bc, info->buf, &size, &gap, info,
  495. macho_objfmt_output_value, NULL);
  496. /* Don't bother doing anything else if size ended up being 0. */
  497. if (size == 0) {
  498. if (bigbuf)
  499. yasm_xfree(bigbuf);
  500. return 0;
  501. }
  502. /* Warn that gaps are converted to 0 and write out the 0's. */
  503. if (gap) {
  504. unsigned long left;
  505. yasm_warn_set(YASM_WARN_UNINIT_CONTENTS,
  506. N_("uninitialized space: zeroing"));
  507. /* Write out in chunks */
  508. memset(info->buf, 0, REGULAR_OUTBUF_SIZE);
  509. left = size;
  510. while (left > REGULAR_OUTBUF_SIZE) {
  511. fwrite(info->buf, REGULAR_OUTBUF_SIZE, 1, info->f);
  512. left -= REGULAR_OUTBUF_SIZE;
  513. }
  514. fwrite(info->buf, left, 1, info->f);
  515. } else {
  516. /* Output buf (or bigbuf if non-NULL) to file */
  517. fwrite(bigbuf ? bigbuf : info->buf, (size_t) size, 1, info->f);
  518. }
  519. /* If bigbuf was allocated, free it */
  520. if (bigbuf)
  521. yasm_xfree(bigbuf);
  522. return 0;
  523. }
  524. static int
  525. macho_objfmt_output_section(yasm_section *sect, /*@null@ */ void *d)
  526. {
  527. /*@null@ */ macho_objfmt_output_info *info =
  528. (macho_objfmt_output_info *) d;
  529. /*@dependent@ *//*@null@ */ macho_section_data *msd;
  530. assert(info != NULL);
  531. msd = yasm_section_get_data(sect, &macho_section_data_cb);
  532. assert(msd != NULL);
  533. if (!(msd->flags & S_ZEROFILL)) {
  534. /* Output non-BSS sections */
  535. info->sect = sect;
  536. info->msd = msd;
  537. yasm_section_bcs_traverse(sect, info->errwarns, info,
  538. macho_objfmt_output_bytecode);
  539. }
  540. return 0;
  541. }
  542. static int
  543. macho_objfmt_output_relocs(yasm_section *sect, /*@null@*/ void *d)
  544. {
  545. /*@null@*/ macho_objfmt_output_info *info = (macho_objfmt_output_info *)d;
  546. /*@dependent@*/ /*@null@*/ macho_section_data *msd;
  547. macho_reloc *reloc;
  548. reloc = (macho_reloc *)yasm_section_relocs_first(sect);
  549. while (reloc) {
  550. unsigned char *localbuf = info->buf;
  551. /*@null@*/ macho_symrec_data *xsymd;
  552. unsigned long symnum;
  553. xsymd = yasm_symrec_get_data(reloc->reloc.sym, &macho_symrec_data_cb);
  554. yasm_intnum_get_sized(reloc->reloc.addr, localbuf, 4, 32, 0, 0, 0);
  555. localbuf += 4; /* address of relocation */
  556. if (reloc->ext)
  557. symnum = xsymd->index;
  558. else {
  559. /* find section where the symbol relates to */
  560. /*@dependent@*/ /*@null@*/ yasm_section *dsect;
  561. /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc;
  562. symnum = 0; /* default to absolute */
  563. if (yasm_symrec_get_label(reloc->reloc.sym, &precbc) &&
  564. (dsect = yasm_bc_get_section(precbc)) &&
  565. (msd = yasm_section_get_data(dsect, &macho_section_data_cb)))
  566. symnum = msd->scnum+1;
  567. }
  568. YASM_WRITE_32_L(localbuf,
  569. (symnum & 0x00ffffff) |
  570. (((unsigned long)reloc->pcrel & 1) << 24) |
  571. (((unsigned long)reloc->length & 3) << 25) |
  572. (((unsigned long)reloc->ext & 1) << 27) |
  573. (((unsigned long)reloc->type & 0xf) << 28));
  574. fwrite(info->buf, 8, 1, info->f);
  575. reloc = (macho_reloc *)yasm_section_reloc_next((yasm_reloc *)reloc);
  576. }
  577. return 0;
  578. }
  579. static int
  580. exp2_to_bits(unsigned long val)
  581. {
  582. int ret = 0;
  583. while (val) {
  584. val >>= 1;
  585. ret++;
  586. }
  587. ret = (ret > 0) ? ret - 1 : 0;
  588. return ret;
  589. }
  590. static int
  591. macho_objfmt_is_section_label(yasm_symrec *sym)
  592. {
  593. /*@dependent@*/ /*@null@*/ yasm_section *sect;
  594. /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc;
  595. /* Look at symrec for value/scnum/etc. */
  596. if (yasm_symrec_get_label(sym, &precbc)) {
  597. if (precbc)
  598. sect = yasm_bc_get_section(precbc);
  599. else
  600. sect = NULL;
  601. /* it's a label: get value and offset.
  602. * If there is not a section, leave as debugging symbol.
  603. */
  604. if (sect) {
  605. /*@dependent@*/ /*@null@*/ macho_section_data *msd;
  606. msd = yasm_section_get_data(sect, &macho_section_data_cb);
  607. if (msd) {
  608. if (msd->sym == sym)
  609. return 1; /* don't store section names */
  610. }
  611. }
  612. }
  613. return 0;
  614. }
  615. static int
  616. macho_objfmt_output_secthead(yasm_section *sect, /*@null@*/ void *d)
  617. {
  618. /*@null@*/ macho_objfmt_output_info *info = (macho_objfmt_output_info *)d;
  619. /*@dependent@*/ /*@null@*/ macho_section_data *msd;
  620. unsigned char *localbuf;
  621. assert(info != NULL);
  622. msd = yasm_section_get_data(sect, &macho_section_data_cb);
  623. assert(msd != NULL);
  624. localbuf = info->buf;
  625. memset(localbuf, 0, 16);
  626. strncpy((char *)localbuf, msd->sectname, 16);
  627. localbuf += 16;
  628. memset(localbuf, 0, 16);
  629. strncpy((char *)localbuf, msd->segname, 16);
  630. localbuf += 16;
  631. /* section address, size depend on 32/64 bit mode */
  632. YASM_WRITE_32_L(localbuf, msd->vmoff); /* address in memory */
  633. if (info->is_64)
  634. YASM_WRITE_32_L(localbuf, 0); /* 64-bit mode: upper 32 bits = 0 */
  635. YASM_WRITE_32_L(localbuf, msd->size); /* size in memory */
  636. if (info->is_64)
  637. YASM_WRITE_32_L(localbuf, 0); /* 64-bit mode: upper 32 bits = 0 */
  638. /* offset,align,reloff,nreloc,flags,reserved1,reserved2 are 32 bit */
  639. if ((msd->flags & SECTION_TYPE) != S_ZEROFILL) {
  640. YASM_WRITE_32_L(localbuf, msd->offset);
  641. YASM_WRITE_32_L(localbuf, exp2_to_bits(yasm_section_get_align(sect)));
  642. if (msd->nreloc) {
  643. msd->flags |= S_ATTR_LOC_RELOC;
  644. if (msd->extreloc)
  645. msd->flags |= S_ATTR_EXT_RELOC;
  646. YASM_WRITE_32_L(localbuf,
  647. align32((long)(info->rel_base + info->s_reloff)));
  648. YASM_WRITE_32_L(localbuf, msd->nreloc); /* nreloc */
  649. } else {
  650. YASM_WRITE_32_L(localbuf, 0);
  651. YASM_WRITE_32_L(localbuf, 0);
  652. }
  653. info->s_reloff += msd->nreloc * MACHO_RELINFO_SIZE; /* nreloc */
  654. } else {
  655. YASM_WRITE_32_L(localbuf, 0); /* these are zero in BSS */
  656. YASM_WRITE_32_L(localbuf, 0);
  657. YASM_WRITE_32_L(localbuf, 0);
  658. YASM_WRITE_32_L(localbuf, 0);
  659. }
  660. YASM_WRITE_32_L(localbuf, msd->flags); /* flags */
  661. YASM_WRITE_32_L(localbuf, 0); /* reserved 1 */
  662. YASM_WRITE_32_L(localbuf, 0); /* reserved 2 */
  663. if (info->is_64)
  664. fwrite(info->buf, MACHO_SECTCMD64_SIZE, 1, info->f);
  665. else
  666. fwrite(info->buf, MACHO_SECTCMD_SIZE, 1, info->f);
  667. return 0;
  668. }
  669. static int
  670. macho_objfmt_count_sym(yasm_symrec *sym, /*@null@*/ void *d)
  671. {
  672. /*@null@*/ macho_objfmt_output_info *info = (macho_objfmt_output_info *)d;
  673. /*@only@*/ char *name;
  674. yasm_sym_vis vis = yasm_symrec_get_visibility(sym);
  675. assert(info != NULL);
  676. if (info->all_syms ||
  677. vis & (YASM_SYM_GLOBAL | YASM_SYM_COMMON | YASM_SYM_EXTERN)) {
  678. if (0 == macho_objfmt_is_section_label(sym)) {
  679. /* Save index in symrec data */
  680. macho_symrec_data *sym_data =
  681. yasm_symrec_get_data(sym, &macho_symrec_data_cb);
  682. if (!sym_data) {
  683. sym_data = yasm_xcalloc(sizeof(macho_symrec_data), 1);
  684. yasm_symrec_add_data(sym, &macho_symrec_data_cb, sym_data);
  685. }
  686. sym_data->index = info->symindex;
  687. info->symindex++;
  688. name = yasm_symrec_get_global_name(sym, info->object);
  689. /*printf("%s\n",name); */
  690. /* name length + delimiter */
  691. sym_data->length = (unsigned long)strlen(name) + 1;
  692. info->strlength += sym_data->length;
  693. info->indx++;
  694. yasm_xfree(name);
  695. }
  696. }
  697. return 0;
  698. }
  699. static int
  700. macho_objfmt_output_symtable(yasm_symrec *sym, /*@null@*/ void *d)
  701. {
  702. /*@null@*/ macho_objfmt_output_info *info = (macho_objfmt_output_info *)d;
  703. yasm_sym_vis vis = yasm_symrec_get_visibility(sym);
  704. assert(info != NULL);
  705. if (info->all_syms ||
  706. vis & (YASM_SYM_GLOBAL | YASM_SYM_COMMON | YASM_SYM_EXTERN)) {
  707. const yasm_expr *equ_val;
  708. const yasm_intnum *intn;
  709. unsigned long value = 0;
  710. long scnum = -3; /* -3 = debugging symbol */
  711. /*@dependent@*/ /*@null@*/ yasm_section *sect;
  712. /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc;
  713. unsigned char *localbuf;
  714. yasm_intnum *val;
  715. unsigned int long_int_bytes = (info->is_64) ? 8 : 4;
  716. unsigned int n_type = 0, n_sect = 0, n_desc = 0;
  717. macho_symrec_data *symd;
  718. val = yasm_intnum_create_uint(0);
  719. symd = yasm_symrec_get_data(sym, &macho_symrec_data_cb);
  720. /* Look at symrec for value/scnum/etc. */
  721. if (yasm_symrec_get_label(sym, &precbc)) {
  722. if (precbc)
  723. sect = yasm_bc_get_section(precbc);
  724. else
  725. sect = NULL;
  726. /* it's a label: get value and offset.
  727. * If there is not a section, leave as debugging symbol.
  728. */
  729. if (sect) {
  730. /*@dependent@*/ /*@null@*/ macho_section_data *msd;
  731. msd = yasm_section_get_data(sect, &macho_section_data_cb);
  732. if (msd) {
  733. if (msd->sym == sym) {
  734. /* don't store section names */
  735. yasm_intnum_destroy(val);
  736. return 0;
  737. }
  738. scnum = msd->scnum;
  739. n_type = N_SECT;
  740. } else
  741. yasm_internal_error(N_("didn't understand section"));
  742. if (precbc)
  743. value += yasm_bc_next_offset(precbc);
  744. /* all values are subject to correction: base offset is first
  745. * raw section, therefore add section offset
  746. */
  747. if (msd)
  748. value += msd->vmoff;
  749. yasm_intnum_set_uint(val, value);
  750. /*printf("%s offset %lx\n",name,value);*/
  751. }
  752. } else if ((equ_val = yasm_symrec_get_equ(sym))) {
  753. yasm_expr *equ_val_copy = yasm_expr_copy(equ_val);
  754. intn = yasm_expr_get_intnum(&equ_val_copy, 1);
  755. if (!intn) {
  756. if (vis & YASM_SYM_GLOBAL) {
  757. yasm_error_set(YASM_ERROR_NOT_CONSTANT,
  758. N_("global EQU value not an integer expression"));
  759. yasm_errwarn_propagate(info->errwarns, equ_val->line);
  760. }
  761. } else
  762. value = yasm_intnum_get_uint(intn);
  763. yasm_expr_destroy(equ_val_copy);
  764. yasm_intnum_set_uint(val, value);
  765. n_type = N_ABS;
  766. scnum = -2; /* -2 = absolute symbol */
  767. }
  768. if (vis & YASM_SYM_EXTERN) {
  769. n_type = N_EXT;
  770. scnum = -1;
  771. /*n_desc = REFERENCE_FLAG_UNDEFINED_LAZY; * FIXME: see definition of REFERENCE_FLAG_* above */
  772. } else if (vis & YASM_SYM_COMMON) {
  773. yasm_expr **csize = yasm_symrec_get_common_size(sym);
  774. n_type = N_UNDF | N_EXT;
  775. if (csize) {
  776. intn = yasm_expr_get_intnum(csize, 1);
  777. if (!intn) {
  778. yasm_error_set(YASM_ERROR_NOT_CONSTANT,
  779. N_("COMMON data size not an integer expression"));
  780. yasm_errwarn_propagate(info->errwarns, (*csize)->line);
  781. } else
  782. yasm_intnum_set_uint(val, yasm_intnum_get_uint(intn));
  783. }
  784. /*printf("common symbol %s val %lu\n", name, yasm_intnum_get_uint(val));*/
  785. } else if (vis & YASM_SYM_GLOBAL) {
  786. yasm_valparamhead *valparams =
  787. yasm_symrec_get_objext_valparams(sym);
  788. struct macho_global_data {
  789. unsigned long flag; /* N_PEXT */
  790. } data;
  791. data.flag = 0;
  792. if (valparams) {
  793. static const yasm_dir_help help[] = {
  794. { "private_extern", 0, yasm_dir_helper_flag_set,
  795. offsetof(struct macho_global_data, flag), N_PEXT },
  796. };
  797. yasm_dir_helper(sym, yasm_vps_first(valparams),
  798. yasm_symrec_get_decl_line(sym), help, NELEMS(help),
  799. &data, yasm_dir_helper_valparam_warn);
  800. }
  801. n_type |= N_EXT | data.flag;
  802. }
  803. localbuf = info->buf;
  804. YASM_WRITE_32_L(localbuf, info->indx); /* offset in string table */
  805. YASM_WRITE_8(localbuf, n_type); /* type of symbol entry */
  806. n_sect = (scnum >= 0) ? scnum + 1 : NO_SECT;
  807. YASM_WRITE_8(localbuf, n_sect); /* referring section where symbol is found */
  808. YASM_WRITE_16_L(localbuf, n_desc); /* extra description */
  809. yasm_intnum_get_sized(val, localbuf, long_int_bytes, ((long_int_bytes) << 3), 0, 0, 0); /* value/argument */
  810. localbuf += long_int_bytes;
  811. if (symd)
  812. symd->value = val;
  813. else
  814. yasm_intnum_destroy(val);
  815. info->indx += symd->length;
  816. fwrite(info->buf, 8 + long_int_bytes, 1, info->f);
  817. }
  818. return 0;
  819. }
  820. static int
  821. macho_objfmt_output_str(yasm_symrec *sym, /*@null@*/ void *d)
  822. {
  823. /*@null@*/ macho_objfmt_output_info *info = (macho_objfmt_output_info *)d;
  824. yasm_sym_vis vis = yasm_symrec_get_visibility(sym);
  825. assert(info != NULL);
  826. if (info->all_syms ||
  827. vis & (YASM_SYM_GLOBAL | YASM_SYM_COMMON | YASM_SYM_EXTERN)) {
  828. if (0 == macho_objfmt_is_section_label(sym)) {
  829. /*@only@*/ char *name =
  830. yasm_symrec_get_global_name(sym, info->object);
  831. size_t len = strlen(name);
  832. fwrite(name, len + 1, 1, info->f);
  833. yasm_xfree(name);
  834. }
  835. }
  836. return 0;
  837. }
  838. static int
  839. macho_objfmt_calc_sectsize(yasm_section *sect, /*@null@ */ void *d)
  840. {
  841. /*@null@ */ macho_objfmt_output_info *info =
  842. (macho_objfmt_output_info *) d;
  843. /*@dependent@ *//*@null@ */ macho_section_data *msd;
  844. unsigned long align;
  845. assert(info != NULL);
  846. msd = yasm_section_get_data(sect, &macho_section_data_cb);
  847. assert(msd != NULL);
  848. msd->size = yasm_bc_next_offset(yasm_section_bcs_last(sect));
  849. if (!(msd->flags & S_ZEROFILL)) {
  850. msd->offset = info->offset;
  851. info->offset += msd->size;
  852. info->filesize += msd->size;
  853. }
  854. /* accumulate size in memory */
  855. msd->vmoff = info->vmsize;
  856. info->vmsize += msd->size;
  857. /* align both start and end of section */
  858. align = yasm_section_get_align(sect);
  859. if (align != 0) {
  860. unsigned long delta = msd->vmoff % align;
  861. if (delta > 0) {
  862. msd->vmoff += align - delta;
  863. info->vmsize += align - delta;
  864. }
  865. }
  866. return 0;
  867. }
  868. /* write object */
  869. static void
  870. macho_objfmt_output(yasm_object *object, FILE *f, int all_syms,
  871. yasm_errwarns *errwarns)
  872. {
  873. yasm_objfmt_macho *objfmt_macho = (yasm_objfmt_macho *)object->objfmt;
  874. macho_objfmt_output_info info;
  875. unsigned char *localbuf;
  876. unsigned long symtab_count = 0;
  877. unsigned long headsize;
  878. unsigned int macho_segcmdsize, macho_sectcmdsize, macho_nlistsize;
  879. unsigned int macho_segcmd;
  880. unsigned int head_ncmds, head_sizeofcmds;
  881. unsigned long fileoffset, fileoff_sections;
  882. yasm_intnum *val;
  883. unsigned long long_int_bytes;
  884. const char pad_data[3] = "\0\0\0";
  885. info.object = object;
  886. info.objfmt_macho = objfmt_macho;
  887. info.errwarns = errwarns;
  888. info.f = f;
  889. info.buf = yasm_xmalloc(REGULAR_OUTBUF_SIZE);
  890. if (objfmt_macho->parse_scnum == 0) {
  891. yasm_internal_error(N_("no sections defined"));
  892. /*@notreached@*/
  893. return;
  894. }
  895. val = yasm_intnum_create_uint(0);
  896. /*
  897. * MACH-O Header, Seg CMD, Sect CMDs, Sym Tab, Reloc Data
  898. */
  899. info.is_64 = (objfmt_macho->bits == 32) ? 0 : 1;
  900. if (info.is_64) {
  901. /* this works only when SYMBOLS and SECTIONS present */
  902. headsize =
  903. MACHO_HEADER64_SIZE + MACHO_SEGCMD64_SIZE +
  904. (MACHO_SECTCMD64_SIZE * (objfmt_macho->parse_scnum)) +
  905. MACHO_SYMCMD_SIZE;
  906. macho_segcmd = LC_SEGMENT_64;
  907. macho_segcmdsize = MACHO_SEGCMD64_SIZE;
  908. macho_sectcmdsize = MACHO_SECTCMD64_SIZE;
  909. macho_nlistsize = MACHO_NLIST64_SIZE;
  910. long_int_bytes = 8;
  911. } else {
  912. headsize =
  913. MACHO_HEADER_SIZE + MACHO_SEGCMD_SIZE +
  914. (MACHO_SECTCMD_SIZE * (objfmt_macho->parse_scnum)) +
  915. MACHO_SYMCMD_SIZE;
  916. macho_segcmd = LC_SEGMENT;
  917. macho_segcmdsize = MACHO_SEGCMD_SIZE;
  918. macho_sectcmdsize = MACHO_SECTCMD_SIZE;
  919. macho_nlistsize = MACHO_NLIST_SIZE;
  920. long_int_bytes = 4;
  921. }
  922. /* Get number of symbols */
  923. info.symindex = 0;
  924. info.indx = 0;
  925. info.strlength = 1; /* string table starts with a zero byte */
  926. info.all_syms = all_syms || info.is_64;
  927. /*info.all_syms = 1; * force all syms into symbol table */
  928. yasm_symtab_traverse(object->symtab, &info, macho_objfmt_count_sym);
  929. symtab_count = info.indx;
  930. /* write raw section data first */
  931. if (fseek(f, (long)headsize, SEEK_SET) < 0) {
  932. yasm__fatal(N_("could not seek on output file"));
  933. /*@notreached@ */
  934. return;
  935. }
  936. /* get size of sections in memory (including BSS) and size of sections
  937. * in file (without BSS)
  938. */
  939. info.vmsize = 0;
  940. info.filesize = 0;
  941. info.offset = headsize;
  942. yasm_object_sections_traverse(object, &info, macho_objfmt_calc_sectsize);
  943. /* output sections to file */
  944. yasm_object_sections_traverse(object, &info, macho_objfmt_output_section);
  945. fileoff_sections = ftell(f);
  946. /* Write headers */
  947. if (fseek(f, 0, SEEK_SET) < 0) {
  948. yasm__fatal(N_("could not seek on output file"));
  949. /*@notreached@*/
  950. return;
  951. }
  952. localbuf = info.buf;
  953. /* header size is common to 32 bit and 64 bit variants */
  954. if (info.is_64) {
  955. YASM_WRITE_32_L(localbuf, MH_MAGIC_64); /* magic number */
  956. /* i386 64-bit ABI */
  957. YASM_WRITE_32_L(localbuf, CPU_ARCH_ABI64 | CPU_TYPE_I386);
  958. } else {
  959. YASM_WRITE_32_L(localbuf, MH_MAGIC); /* magic number */
  960. YASM_WRITE_32_L(localbuf, CPU_TYPE_I386); /* i386 32-bit ABI */
  961. }
  962. /* i386 all cpu subtype compatible */
  963. YASM_WRITE_32_L(localbuf, CPU_SUBTYPE_I386_ALL);
  964. YASM_WRITE_32_L(localbuf, MH_OBJECT); /* MACH file type */
  965. /* calculate number of commands and their size, put to stream */
  966. head_ncmds = 0;
  967. head_sizeofcmds = 0;
  968. if (objfmt_macho->parse_scnum > 0) {
  969. head_ncmds++;
  970. head_sizeofcmds +=
  971. macho_segcmdsize + macho_sectcmdsize * objfmt_macho->parse_scnum;
  972. }
  973. if (symtab_count > 0) {
  974. head_ncmds++;
  975. head_sizeofcmds += MACHO_SYMCMD_SIZE;
  976. }
  977. YASM_WRITE_32_L(localbuf, head_ncmds);
  978. YASM_WRITE_32_L(localbuf, head_sizeofcmds);
  979. YASM_WRITE_32_L(localbuf, 0); /* no flags (yet) */
  980. if (info.is_64) {
  981. YASM_WRITE_32_L(localbuf, 0); /* reserved in 64 bit */
  982. fileoffset = MACHO_HEADER64_SIZE + head_sizeofcmds;
  983. } else {
  984. /* initial offset to first section */
  985. fileoffset = MACHO_HEADER_SIZE + head_sizeofcmds;
  986. }
  987. /* --------------- write segment header command ---------------- */
  988. YASM_WRITE_32_L(localbuf, macho_segcmd); /* command LC_SEGMENT */
  989. /* size of load command including section load commands */
  990. YASM_WRITE_32_L(localbuf,
  991. macho_segcmdsize +
  992. macho_sectcmdsize * objfmt_macho->parse_scnum);
  993. /* in an MH_OBJECT file all sections are in one unnamed (name all zeros)
  994. * segment (16x0)
  995. */
  996. YASM_WRITE_32_L(localbuf, 0);
  997. YASM_WRITE_32_L(localbuf, 0);
  998. YASM_WRITE_32_L(localbuf, 0);
  999. YASM_WRITE_32_L(localbuf, 0);
  1000. /* in-memory offset, in-memory size */
  1001. yasm_intnum_set_uint(val, 0); /* offset in memory (vmaddr) */
  1002. yasm_intnum_get_sized(val, localbuf, long_int_bytes,
  1003. ((long_int_bytes) << 3), 0, 0, 0);
  1004. localbuf += long_int_bytes;
  1005. yasm_intnum_set_uint(val, info.vmsize); /* size in memory (vmsize) */
  1006. yasm_intnum_get_sized(val, localbuf, long_int_bytes,
  1007. ((long_int_bytes) << 3), 0, 0, 0);
  1008. localbuf += long_int_bytes;
  1009. /* offset in file to first section */
  1010. yasm_intnum_set_uint(val, fileoffset);
  1011. yasm_intnum_get_sized(val, localbuf, long_int_bytes,
  1012. ((long_int_bytes) << 3), 0, 0, 0);
  1013. localbuf += long_int_bytes;
  1014. yasm_intnum_set_uint(val, info.filesize); /* overall size in file */
  1015. yasm_intnum_get_sized(val, localbuf, long_int_bytes,
  1016. ((long_int_bytes) << 3), 0, 0, 0);
  1017. localbuf += long_int_bytes;
  1018. YASM_WRITE_32_L(localbuf, VM_PROT_DEFAULT); /* VM protection, maximum */
  1019. YASM_WRITE_32_L(localbuf, VM_PROT_DEFAULT); /* VM protection, initial */
  1020. /* number of sections */
  1021. YASM_WRITE_32_L(localbuf, objfmt_macho->parse_scnum);
  1022. YASM_WRITE_32_L(localbuf, 0); /* no flags */
  1023. /* write MACH-O header and segment command to outfile */
  1024. fwrite(info.buf, (size_t) (localbuf - info.buf), 1, f);
  1025. /* next: section headers */
  1026. /* offset to relocs for first section */
  1027. info.rel_base = align32((long)fileoff_sections);
  1028. info.s_reloff = 0; /* offset for relocs of following sections */
  1029. yasm_object_sections_traverse(object, &info, macho_objfmt_output_secthead);
  1030. localbuf = info.buf;
  1031. /* write out symbol command */
  1032. YASM_WRITE_32_L(localbuf, LC_SYMTAB); /* cmd == LC_SYMTAB */
  1033. YASM_WRITE_32_L(localbuf, MACHO_SYMCMD_SIZE);
  1034. /* symbol table offset */
  1035. YASM_WRITE_32_L(localbuf, info.rel_base + info.s_reloff);
  1036. YASM_WRITE_32_L(localbuf, symtab_count); /* number of symbols */
  1037. YASM_WRITE_32_L(localbuf, macho_nlistsize * symtab_count + info.rel_base +
  1038. info.s_reloff); /* string table offset */
  1039. YASM_WRITE_32_L(localbuf, info.strlength); /* string table size */
  1040. /* write symbol command */
  1041. fwrite(info.buf, (size_t)(localbuf - info.buf), 1, f);
  1042. /*printf("num symbols %d, vmsize %d, filesize %d\n",symtab_count,
  1043. info.vmsize, info.filesize ); */
  1044. /* get back to end of raw section data */
  1045. if (fseek(f, (long)fileoff_sections, SEEK_SET) < 0) {
  1046. yasm__fatal(N_("could not seek on output file"));
  1047. /*@notreached@*/
  1048. return;
  1049. }
  1050. /* padding to long boundary */
  1051. if ((info.rel_base - fileoff_sections) > 0) {
  1052. fwrite(pad_data, info.rel_base - fileoff_sections, 1, f);
  1053. }
  1054. /* relocation data */
  1055. yasm_object_sections_traverse(object, &info, macho_objfmt_output_relocs);
  1056. /* symbol table (NLIST) */
  1057. info.indx = 1; /* restart symbol table indices */
  1058. yasm_symtab_traverse(object->symtab, &info, macho_objfmt_output_symtable);
  1059. /* symbol strings */
  1060. fwrite(pad_data, 1, 1, f);
  1061. yasm_symtab_traverse(object->symtab, &info, macho_objfmt_output_str);
  1062. yasm_intnum_destroy(val);
  1063. yasm_xfree(info.buf);
  1064. }
  1065. static void
  1066. macho_objfmt_destroy(yasm_objfmt *objfmt)
  1067. {
  1068. yasm_xfree(objfmt);
  1069. }
  1070. static void
  1071. macho_objfmt_init_new_section(yasm_section *sect, unsigned long line)
  1072. {
  1073. yasm_object *object = yasm_section_get_object(sect);
  1074. const char *sectname = yasm_section_get_name(sect);
  1075. yasm_objfmt_macho *objfmt_macho = (yasm_objfmt_macho *)object->objfmt;
  1076. macho_section_data *data;
  1077. yasm_symrec *sym;
  1078. data = yasm_xmalloc(sizeof(macho_section_data));
  1079. data->scnum = objfmt_macho->parse_scnum++;
  1080. data->segname = NULL;
  1081. data->sectname = NULL;
  1082. data->flags = S_REGULAR;
  1083. data->size = 0;
  1084. data->offset = 0;
  1085. data->vmoff = 0;
  1086. data->nreloc = 0;
  1087. data->extreloc = 0;
  1088. yasm_section_add_data(sect, &macho_section_data_cb, data);
  1089. sym = yasm_symtab_define_label(object->symtab, sectname,
  1090. yasm_section_bcs_first(sect), 1, line);
  1091. data->sym = sym;
  1092. }
  1093. static yasm_section *
  1094. macho_objfmt_add_default_section(yasm_object *object)
  1095. {
  1096. yasm_section *retval;
  1097. macho_section_data *msd;
  1098. int isnew;
  1099. retval = yasm_object_get_general(object, "LC_SEGMENT.__TEXT.__text", 0, 1,
  1100. 0, &isnew, 0);
  1101. if (isnew) {
  1102. msd = yasm_section_get_data(retval, &macho_section_data_cb);
  1103. msd->segname = yasm__xstrdup("__TEXT");
  1104. msd->sectname = yasm__xstrdup("__text");
  1105. msd->flags = S_ATTR_PURE_INSTRUCTIONS;
  1106. yasm_section_set_align(retval, 0, 0);
  1107. yasm_section_set_default(retval, 1);
  1108. }
  1109. return retval;
  1110. }
  1111. static /*@observer@*/ /*@null@*/ yasm_section *
  1112. macho_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams,
  1113. /*@unused@*/ /*@null@*/
  1114. yasm_valparamhead *objext_valparams,
  1115. unsigned long line)
  1116. {
  1117. yasm_valparam *vp;
  1118. yasm_section *retval;
  1119. int isnew;
  1120. /*@only@*/ char *f_sectname;
  1121. unsigned long flags;
  1122. unsigned long align;
  1123. int flags_override = 0;
  1124. const char *sectname;
  1125. char *realname;
  1126. int resonly = 0;
  1127. macho_section_data *msd;
  1128. size_t i;
  1129. static const struct {
  1130. const char *in;
  1131. const char *seg;
  1132. const char *sect;
  1133. unsigned long flags;
  1134. unsigned long align;
  1135. } section_name_translation[] = {
  1136. {".text", "__TEXT", "__text", S_ATTR_PURE_INSTRUCTIONS, 0},
  1137. {".const", "__TEXT", "__const", S_REGULAR, 0},
  1138. {".static_const", "__TEXT", "__static_const", S_REGULAR, 0},
  1139. {".cstring", "__TEXT", "__cstring", S_CSTRING_LITERALS, 0},
  1140. {".literal4", "__TEXT", "__literal4", S_4BYTE_LITERALS, 4},
  1141. {".literal8", "__TEXT", "__literal8", S_8BYTE_LITERALS, 8},
  1142. {".literal16", "__TEXT", "__literal16", S_16BYTE_LITERALS, 16},
  1143. {".constructor", "__TEXT", "__constructor", S_REGULAR, 0},
  1144. {".destructor", "__TEXT", "__destructor", S_REGULAR, 0},
  1145. {".fvmlib_init0", "__TEXT", "__fvmlib_init0", S_REGULAR, 0},
  1146. {".fvmlib_init1", "__TEXT", "__fvmlib_init1", S_REGULAR, 0},
  1147. {".mod_init_func", "__DATA", "__mod_init_func",
  1148. S_MOD_INIT_FUNC_POINTERS, 4},
  1149. {".mod_term_func", "__DATA", "__mod_term_func",
  1150. S_MOD_TERM_FUNC_POINTERS, 4},
  1151. {".dyld", "__DATA", "__dyld", S_REGULAR, 0},
  1152. {".data", "__DATA", "__data", S_REGULAR, 0},
  1153. {".static_data", "__DATA", "__static_data", S_REGULAR, 0},
  1154. {".const_data", "__DATA", "__const", S_REGULAR, 0},
  1155. {".rodata", "__DATA", "__const", S_REGULAR, 0},
  1156. {".bss", "__DATA", "__bss", S_ZEROFILL, 0},
  1157. {".objc_class_names", "__TEXT", "__cstring", S_CSTRING_LITERALS, 0},
  1158. {".objc_meth_var_types","__TEXT", "__cstring", S_CSTRING_LITERALS, 0},
  1159. {".objc_meth_var_names","__TEXT", "__cstring", S_CSTRING_LITERALS, 0},
  1160. {".objc_selector_strs", "__OBJC", "__selector_strs",
  1161. S_CSTRING_LITERALS, 0},
  1162. {".objc_class", "__OBJC", "__class",
  1163. S_ATTR_NO_DEAD_STRIP, 0},
  1164. {".objc_meta_class", "__OBJC", "__meta_class",
  1165. S_ATTR_NO_DEAD_STRIP, 0},
  1166. {".objc_string_object", "__OBJC", "__string_object",
  1167. S_ATTR_NO_DEAD_STRIP, 0},
  1168. {".objc_protocol", "__OBJC", "__protocol",
  1169. S_ATTR_NO_DEAD_STRIP, 0},
  1170. {".objc_cat_cls_meth", "__OBJC", "__cat_cls_meth",
  1171. S_ATTR_NO_DEAD_STRIP, 0},
  1172. {".objc_cat_inst_meth", "__OBJC", "__cat_inst_meth",
  1173. S_ATTR_NO_DEAD_STRIP, 0},
  1174. {".objc_cls_meth", "__OBJC", "__cls_meth",
  1175. S_ATTR_NO_DEAD_STRIP, 0},
  1176. {".objc_inst_meth", "__OBJC", "__inst_meth",
  1177. S_ATTR_NO_DEAD_STRIP, 0},
  1178. {".objc_message_refs", "__OBJC", "__message_refs",
  1179. S_LITERAL_POINTERS|S_ATTR_NO_DEAD_STRIP, 4},
  1180. {".objc_cls_refs", "__OBJC", "__cls_refs",
  1181. S_LITERAL_POINTERS|S_ATTR_NO_DEAD_STRIP, 4},
  1182. {".objc_module_info", "__OBJC", "__module_info",
  1183. S_ATTR_NO_DEAD_STRIP, 0},
  1184. {".objc_symbols", "__OBJC", "__symbols",
  1185. S_ATTR_NO_DEAD_STRIP, 0},
  1186. {".objc_category", "__OBJC", "__category",
  1187. S_ATTR_NO_DEAD_STRIP, 0},
  1188. {".objc_class_vars", "__OBJC", "__class_vars",
  1189. S_ATTR_NO_DEAD_STRIP, 0},
  1190. {".objc_instance_vars", "__OBJC", "__instance_vars",
  1191. S_ATTR_NO_DEAD_STRIP, 0}
  1192. };
  1193. struct macho_section_switch_data {
  1194. /*@only@*/ /*@null@*/ char *f_segname;
  1195. /*@only@*/ /*@null@*/ yasm_intnum *align_intn;
  1196. } data;
  1197. static const yasm_dir_help help[] = {
  1198. { "segname", 1, yasm_dir_helper_string,
  1199. offsetof(struct macho_section_switch_data, f_segname), 0 },
  1200. { "align", 1, yasm_dir_helper_intn,
  1201. offsetof(struct macho_section_switch_data, align_intn), 0 }
  1202. };
  1203. data.f_segname = NULL;
  1204. data.align_intn = NULL;
  1205. vp = yasm_vps_first(valparams);
  1206. sectname = yasm_vp_string(vp);
  1207. if (!sectname)
  1208. return NULL;
  1209. vp = yasm_vps_next(vp);
  1210. /* translate .text,.data,.bss to __text,__data,__bss... */
  1211. for (i=0; i<NELEMS(section_name_translation); i++) {
  1212. if (yasm__strcasecmp(sectname, section_name_translation[i].in) == 0)
  1213. break;
  1214. }
  1215. if (i == NELEMS(section_name_translation)) {
  1216. const char *s;
  1217. if (vp && !vp->val && (s = yasm_vp_string(vp))) {
  1218. /* Treat as SEGNAME, SECTNAME */
  1219. if (strlen(sectname) > 16)
  1220. yasm_warn_set(YASM_WARN_GENERAL,
  1221. N_("segment name is too long, max 16 chars; truncating"));
  1222. data.f_segname = yasm__xstrndup(sectname, 16);
  1223. if (strlen(s) > 16)
  1224. yasm_warn_set(YASM_WARN_GENERAL,
  1225. N_("section name is too long, max 16 chars; truncating"));
  1226. f_sectname = yasm__xstrndup(s, 16);
  1227. flags = S_REGULAR;
  1228. align = 0;
  1229. sectname = s;
  1230. vp = yasm_vps_next(vp);
  1231. } else {
  1232. data.f_segname = NULL;
  1233. if (strlen(sectname) > 16)
  1234. yasm_warn_set(YASM_WARN_GENERAL,
  1235. N_("section name is too long, max 16 chars; truncating"));
  1236. f_sectname = yasm__xstrndup(sectname, 16);
  1237. flags = S_ATTR_SOME_INSTRUCTIONS;
  1238. align = 0;
  1239. }
  1240. } else {
  1241. data.f_segname = yasm__xstrdup(section_name_translation[i].seg);
  1242. f_sectname = yasm__xstrdup(section_name_translation[i].sect);
  1243. flags = section_name_translation[i].flags;
  1244. align = section_name_translation[i].align;
  1245. }
  1246. flags_override = yasm_dir_helper(object, vp, line, help, NELEMS(help),
  1247. &data, yasm_dir_helper_valparam_warn);
  1248. if (flags_override < 0)
  1249. return NULL; /* error occurred */
  1250. if (data.align_intn) {
  1251. align = yasm_intnum_get_uint(data.align_intn);
  1252. yasm_intnum_destroy(data.align_intn);
  1253. /* Alignments must be a power of two. */
  1254. if (!is_exp2(align)) {
  1255. yasm_error_set(YASM_ERROR_VALUE,
  1256. N_("argument to `%s' is not a power of two"),
  1257. vp->val);
  1258. return NULL;
  1259. }
  1260. /* Check to see if alignment is supported size */
  1261. if (align > 16384) {
  1262. yasm_error_set(YASM_ERROR_VALUE,
  1263. N_("macho implementation does not support alignments > 16384"));
  1264. return NULL;
  1265. }
  1266. }
  1267. if (!data.f_segname) {
  1268. yasm_warn_set(YASM_WARN_GENERAL,
  1269. N_("Unknown section name, defaulting to __TEXT segment"));
  1270. data.f_segname = yasm__xstrdup("__TEXT");
  1271. }
  1272. /* Build a unique sectname from f_segname and f_sectname. */
  1273. realname = yasm_xmalloc(strlen("LC_SEGMENT") + 1 + strlen(data.f_segname) + 1 +
  1274. strlen(f_sectname) + 1);
  1275. sprintf(realname, "LC_SEGMENT.%s.%s", data.f_segname, f_sectname);
  1276. retval = yasm_object_get_general(object, realname, align, 1, resonly,
  1277. &isnew, line);
  1278. yasm_xfree(realname);
  1279. msd = yasm_section_get_data(retval, &macho_section_data_cb);
  1280. if (isnew || yasm_section_is_default(retval)) {
  1281. yasm_section_set_default(retval, 0);
  1282. msd->segname = data.f_segname;
  1283. msd->sectname = f_sectname;
  1284. msd->flags = flags;
  1285. yasm_section_set_align(retval, align, line);
  1286. } else if (flags_override) {
  1287. /* align is the only value used from overrides. */
  1288. if (yasm_section_get_align(retval) != align) {
  1289. yasm_warn_set(YASM_WARN_GENERAL,
  1290. N_("section flags ignored on section redeclaration"));
  1291. }
  1292. }
  1293. return retval;
  1294. }
  1295. static /*@observer@*/ /*@null@*/ yasm_symrec *
  1296. macho_objfmt_get_special_sym(yasm_object *object, const char *name,
  1297. const char *parser)
  1298. {
  1299. yasm_objfmt_macho *objfmt_macho = (yasm_objfmt_macho *)object->objfmt;
  1300. if (yasm__strcasecmp(name, "gotpcrel") == 0) {
  1301. return objfmt_macho->gotpcrel_sym;
  1302. }
  1303. return NULL;
  1304. }
  1305. static void
  1306. macho_section_data_destroy(void *data)
  1307. {
  1308. macho_section_data *msd = (macho_section_data *) data;
  1309. yasm_xfree(msd->segname);
  1310. yasm_xfree(msd->sectname);
  1311. yasm_xfree(data);
  1312. }
  1313. static void
  1314. macho_section_data_print(void *data, FILE *f, int indent_level)
  1315. {
  1316. macho_section_data *msd = (macho_section_data *) data;
  1317. fprintf(f, "%*ssym=\n", indent_level, "");
  1318. yasm_symrec_print(msd->sym, f, indent_level + 1);
  1319. fprintf(f, "%*sscnum=%ld\n", indent_level, "", msd->scnum);
  1320. fprintf(f, "%*sflags=0x%lx\n", indent_level, "", msd->flags);
  1321. fprintf(f, "%*ssize=%lu\n", indent_level, "", msd->size);
  1322. fprintf(f, "%*snreloc=%lu\n", indent_level, "", msd->nreloc);
  1323. fprintf(f, "%*soffset=%lu\n", indent_level, "", msd->offset);
  1324. fprintf(f, "%*sextreloc=%u\n", indent_level, "", msd->extreloc);
  1325. }
  1326. static void
  1327. macho_symrec_data_destroy(void *data)
  1328. {
  1329. yasm_xfree(data);
  1330. }
  1331. static void
  1332. macho_symrec_data_print(void *data, FILE *f, int indent_level)
  1333. {
  1334. macho_symrec_data *msd = (macho_symrec_data *)data;
  1335. fprintf(f, "%*sindex=%ld\n", indent_level, "", msd->index);
  1336. fprintf(f, "%*svalue=", indent_level, "");
  1337. if (msd->value)
  1338. fprintf(f, "%ld\n", yasm_intnum_get_int(msd->value));
  1339. else
  1340. fprintf(f, "nil\n");
  1341. }
  1342. /* Define valid debug formats to use with this object format */
  1343. static const char *macho_objfmt_dbgfmt_keywords[] = {
  1344. "null",
  1345. NULL
  1346. };
  1347. /* Define objfmt structure -- see objfmt.h for details */
  1348. yasm_objfmt_module yasm_macho_LTX_objfmt = {
  1349. "Mac OS X ABI Mach-O File Format",
  1350. "macho",
  1351. "o",
  1352. 32,
  1353. 0,
  1354. macho_objfmt_dbgfmt_keywords,
  1355. "null",
  1356. NULL, /* no directives */
  1357. NULL, /* no standard macros */
  1358. macho_objfmt_create,
  1359. macho_objfmt_output,
  1360. macho_objfmt_destroy,
  1361. macho_objfmt_add_default_section,
  1362. macho_objfmt_init_new_section,
  1363. macho_objfmt_section_switch,
  1364. macho_objfmt_get_special_sym
  1365. };
  1366. yasm_objfmt_module yasm_macho32_LTX_objfmt = {
  1367. "Mac OS X ABI Mach-O File Format (32-bit)",
  1368. "macho32",
  1369. "o",
  1370. 32,
  1371. 0,
  1372. macho_objfmt_dbgfmt_keywords,
  1373. "null",
  1374. NULL, /* no directives */
  1375. NULL, /* no standard macros */
  1376. macho32_objfmt_create,
  1377. macho_objfmt_output,
  1378. macho_objfmt_destroy,
  1379. macho_objfmt_add_default_section,
  1380. macho_objfmt_init_new_section,
  1381. macho_objfmt_section_switch,
  1382. macho_objfmt_get_special_sym
  1383. };
  1384. yasm_objfmt_module yasm_macho64_LTX_objfmt = {
  1385. "Mac OS X ABI Mach-O File Format (64-bit)",
  1386. "macho64",
  1387. "o",
  1388. 64,
  1389. 0,
  1390. macho_objfmt_dbgfmt_keywords,
  1391. "null",
  1392. NULL, /* no directives */
  1393. NULL, /* no standard macros */
  1394. macho64_objfmt_create,
  1395. macho_objfmt_output,
  1396. macho_objfmt_destroy,
  1397. macho_objfmt_add_default_section,
  1398. macho_objfmt_init_new_section,
  1399. macho_objfmt_section_switch,
  1400. macho_objfmt_get_special_sym
  1401. };