1 | /* ----------------------------------------------------------------------- * |
2 | * |
3 | * Copyright 1996-2018 The NASM Authors - All Rights Reserved |
4 | * See the file AUTHORS included with the NASM distribution for |
5 | * the specific copyright holders. |
6 | * |
7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following |
9 | * conditions are met: |
10 | * |
11 | * * Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. |
13 | * * Redistributions in binary form must reproduce the above |
14 | * copyright notice, this list of conditions and the following |
15 | * disclaimer in the documentation and/or other materials provided |
16 | * with the distribution. |
17 | * |
18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND |
19 | * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, |
20 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
25 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
26 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
27 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
29 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, |
30 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
31 | * |
32 | * ----------------------------------------------------------------------- */ |
33 | |
34 | /* |
35 | * outmacho.c output routines for the Netwide Assembler to produce |
36 | * NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X object files |
37 | */ |
38 | |
39 | #include "compiler.h" |
40 | |
41 | #include <stdio.h> |
42 | #include <stdlib.h> |
43 | #include <string.h> |
44 | #include <ctype.h> |
45 | |
46 | #include "nasm.h" |
47 | #include "nasmlib.h" |
48 | #include "ilog2.h" |
49 | #include "labels.h" |
50 | #include "error.h" |
51 | #include "saa.h" |
52 | #include "raa.h" |
53 | #include "rbtree.h" |
54 | #include "hashtbl.h" |
55 | #include "outform.h" |
56 | #include "outlib.h" |
57 | #include "ver.h" |
58 | #include "dwarf.h" |
59 | |
60 | #if defined(OF_MACHO) || defined(OF_MACHO64) |
61 | |
62 | /* Mach-O in-file header structure sizes */ |
63 | #define 28 |
64 | #define MACHO_SEGCMD_SIZE 56 |
65 | #define MACHO_SECTCMD_SIZE 68 |
66 | #define MACHO_SYMCMD_SIZE 24 |
67 | #define MACHO_NLIST_SIZE 12 |
68 | #define MACHO_RELINFO_SIZE 8 |
69 | |
70 | #define 32 |
71 | #define MACHO_SEGCMD64_SIZE 72 |
72 | #define MACHO_SECTCMD64_SIZE 80 |
73 | #define MACHO_NLIST64_SIZE 16 |
74 | |
75 | /* Mach-O file header values */ |
76 | #define MH_MAGIC 0xfeedface |
77 | #define MH_MAGIC_64 0xfeedfacf |
78 | #define CPU_TYPE_I386 7 /* x86 platform */ |
79 | #define CPU_TYPE_X86_64 0x01000007 /* x86-64 platform */ |
80 | #define CPU_SUBTYPE_I386_ALL 3 /* all-x86 compatible */ |
81 | #define MH_OBJECT 0x1 /* object file */ |
82 | |
83 | /* Mach-O header flags */ |
84 | #define MH_SUBSECTIONS_VIA_SYMBOLS 0x2000 |
85 | |
86 | /* Mach-O load commands */ |
87 | #define LC_SEGMENT 0x1 /* 32-bit segment load cmd */ |
88 | #define LC_SEGMENT_64 0x19 /* 64-bit segment load cmd */ |
89 | #define LC_SYMTAB 0x2 /* symbol table load command */ |
90 | |
91 | /* Mach-O relocations numbers */ |
92 | |
93 | /* Generic relocs, used by i386 Mach-O */ |
94 | #define GENERIC_RELOC_VANILLA 0 /* Generic relocation */ |
95 | #define GENERIC_RELOC_TLV 5 /* Thread local */ |
96 | |
97 | #define X86_64_RELOC_UNSIGNED 0 /* Absolute address */ |
98 | #define X86_64_RELOC_SIGNED 1 /* Signed 32-bit disp */ |
99 | #define X86_64_RELOC_BRANCH 2 /* CALL/JMP with 32-bit disp */ |
100 | #define X86_64_RELOC_GOT_LOAD 3 /* MOVQ of GOT entry */ |
101 | #define X86_64_RELOC_GOT 4 /* Different GOT entry */ |
102 | #define X86_64_RELOC_SUBTRACTOR 5 /* Subtracting two symbols */ |
103 | #define X86_64_RELOC_SIGNED_1 6 /* SIGNED with -1 addend */ |
104 | #define X86_64_RELOC_SIGNED_2 7 /* SIGNED with -2 addend */ |
105 | #define X86_64_RELOC_SIGNED_4 8 /* SIGNED with -4 addend */ |
106 | #define X86_64_RELOC_TLV 9 /* Thread local */ |
107 | |
108 | /* Mach-O VM permission constants */ |
109 | #define VM_PROT_NONE (0x00) |
110 | #define VM_PROT_READ (0x01) |
111 | #define VM_PROT_WRITE (0x02) |
112 | #define VM_PROT_EXECUTE (0x04) |
113 | |
114 | #define VM_PROT_DEFAULT (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE) |
115 | #define VM_PROT_ALL (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE) |
116 | |
117 | /* Our internal relocation types */ |
118 | enum reltype { |
119 | RL_ABS, /* Absolute relocation */ |
120 | RL_REL, /* Relative relocation */ |
121 | RL_TLV, /* Thread local */ |
122 | RL_BRANCH, /* Relative direct branch */ |
123 | RL_SUB, /* X86_64_RELOC_SUBTRACT */ |
124 | RL_GOT, /* X86_64_RELOC_GOT */ |
125 | RL_GOTLOAD /* X86_64_RELOC_GOT_LOAD */ |
126 | }; |
127 | #define RL_MAX_32 RL_TLV |
128 | #define RL_MAX_64 RL_GOTLOAD |
129 | |
130 | struct macho_fmt { |
131 | uint32_t ptrsize; /* Pointer size in bytes */ |
132 | uint32_t mh_magic; /* Which magic number to use */ |
133 | uint32_t cpu_type; /* Which CPU type */ |
134 | uint32_t lc_segment; /* Which segment load command */ |
135 | uint32_t ; /* Header size */ |
136 | uint32_t segcmd_size; /* Segment command size */ |
137 | uint32_t sectcmd_size; /* Section command size */ |
138 | uint32_t nlist_size; /* Nlist (symbol) size */ |
139 | enum reltype maxreltype; /* Maximum entry in enum reltype permitted */ |
140 | uint32_t reloc_abs; /* Absolute relocation type */ |
141 | uint32_t reloc_rel; /* Relative relocation type */ |
142 | uint32_t reloc_tlv; /* Thread local relocation type */ |
143 | bool forcesym; /* Always use "external" (symbol-relative) relocations */ |
144 | }; |
145 | |
146 | static struct macho_fmt fmt; |
147 | |
148 | static void fwriteptr(uint64_t data, FILE * fp) |
149 | { |
150 | fwriteaddr(data, fmt.ptrsize, fp); |
151 | } |
152 | |
153 | struct section { |
154 | /* nasm internal data */ |
155 | struct section *next; |
156 | struct SAA *data; |
157 | int32_t index; /* Main section index */ |
158 | int32_t subsection; /* Current subsection index */ |
159 | int32_t fileindex; |
160 | struct reloc *relocs; |
161 | struct rbtree *syms[2]; /* All/global symbols symbols in section */ |
162 | int align; |
163 | bool by_name; /* This section was specified by full MachO name */ |
164 | char namestr[34]; /* segment,section as a C string */ |
165 | |
166 | /* data that goes into the file */ |
167 | char sectname[16]; /* what this section is called */ |
168 | char segname[16]; /* segment this section will be in */ |
169 | uint64_t addr; /* in-memory address (subject to alignment) */ |
170 | uint64_t size; /* in-memory and -file size */ |
171 | uint64_t offset; /* in-file offset */ |
172 | uint32_t pad; /* padding bytes before section */ |
173 | uint32_t nreloc; /* relocation entry count */ |
174 | uint32_t flags; /* type and attributes (masked) */ |
175 | uint32_t extreloc; /* external relocations */ |
176 | }; |
177 | |
178 | #define SECTION_TYPE 0x000000ff /* section type mask */ |
179 | |
180 | #define S_REGULAR (0x0) /* standard section */ |
181 | #define S_ZEROFILL (0x1) /* zerofill, in-memory only */ |
182 | |
183 | #define SECTION_ATTRIBUTES_SYS 0x00ffff00 /* system setable attributes */ |
184 | #define S_ATTR_SOME_INSTRUCTIONS 0x00000400 /* section contains some |
185 | machine instructions */ |
186 | #define S_ATTR_EXT_RELOC 0x00000200 /* section has external relocation entries */ |
187 | #define S_ATTR_LOC_RELOC 0x00000100 /* section has local relocation entries */ |
188 | #define S_ATTR_DEBUG 0x02000000 |
189 | #define S_ATTR_SELF_MODIFYING_CODE 0x04000000 |
190 | #define S_ATTR_LIVE_SUPPORT 0x08000000 |
191 | #define S_ATTR_NO_DEAD_STRIP 0x10000000 /* no dead stripping */ |
192 | #define S_ATTR_STRIP_STATIC_SYMS 0x20000000 |
193 | #define S_ATTR_NO_TOC 0x40000000 |
194 | #define S_ATTR_PURE_INSTRUCTIONS 0x80000000 /* section uses pure machine instructions */ |
195 | #define S_ATTR_DEBUG 0x02000000 /* debug section */ |
196 | |
197 | #define S_NASM_TYPE_MASK 0x800004ff /* we consider these bits "section type" */ |
198 | |
199 | /* fake section for absolute symbols, *not* part of the section linked list */ |
200 | static struct section absolute_sect; |
201 | |
202 | struct reloc { |
203 | /* nasm internal data */ |
204 | struct reloc *next; |
205 | |
206 | /* data that goes into the file */ |
207 | int32_t addr; /* op's offset in section */ |
208 | uint32_t snum:24, /* contains symbol index if |
209 | ** ext otherwise in-file |
210 | ** section number */ |
211 | pcrel:1, /* relative relocation */ |
212 | length:2, /* 0=byte, 1=word, 2=int32_t, 3=int64_t */ |
213 | ext:1, /* external symbol referenced */ |
214 | type:4; /* reloc type */ |
215 | }; |
216 | |
217 | #define R_ABS 0 /* absolute relocation */ |
218 | #define R_SCATTERED 0x80000000 /* reloc entry is scattered if |
219 | ** highest bit == 1 */ |
220 | |
221 | struct symbol { |
222 | /* nasm internal data */ |
223 | struct rbtree symv[2]; /* All/global symbol rbtrees; "key" contains the |
224 | symbol offset. */ |
225 | struct symbol *next; /* next symbol in the list */ |
226 | char *name; /* name of this symbol */ |
227 | int32_t initial_snum; /* symbol number used above in reloc */ |
228 | int32_t snum; /* true snum for reloc */ |
229 | |
230 | /* data that goes into the file */ |
231 | uint32_t strx; /* string table index */ |
232 | uint8_t type; /* symbol type */ |
233 | uint8_t sect; /* NO_SECT or section number */ |
234 | uint16_t desc; /* for stab debugging, 0 for us */ |
235 | }; |
236 | |
237 | /* symbol type bits */ |
238 | #define N_EXT 0x01 /* global or external symbol */ |
239 | #define N_PEXT 0x10 /* private external symbol */ |
240 | |
241 | #define N_UNDF 0x0 /* undefined symbol | n_sect == */ |
242 | #define N_ABS 0x2 /* absolute symbol | NO_SECT */ |
243 | #define N_SECT 0xe /* defined symbol, n_sect holds |
244 | ** section number */ |
245 | |
246 | #define N_TYPE 0x0e /* type bit mask */ |
247 | |
248 | #define DEFAULT_SECTION_ALIGNMENT 0 /* byte (i.e. no) alignment */ |
249 | |
250 | /* special section number values */ |
251 | #define NO_SECT 0 /* no section, invalid */ |
252 | #define MAX_SECT 255 /* maximum number of sections */ |
253 | |
254 | static struct section *sects, **sectstail, **sectstab; |
255 | static struct symbol *syms, **symstail; |
256 | static uint32_t nsyms; |
257 | |
258 | /* These variables are set by macho_layout_symbols() to organize |
259 | the symbol table and string table in order the dynamic linker |
260 | expects. They are then used in macho_write() to put out the |
261 | symbols and strings in that order. |
262 | |
263 | The order of the symbol table is: |
264 | local symbols |
265 | defined external symbols (sorted by name) |
266 | undefined external symbols (sorted by name) |
267 | |
268 | The order of the string table is: |
269 | strings for external symbols |
270 | strings for local symbols |
271 | */ |
272 | static uint32_t ilocalsym = 0; |
273 | static uint32_t iextdefsym = 0; |
274 | static uint32_t iundefsym = 0; |
275 | static uint32_t nlocalsym; |
276 | static uint32_t nextdefsym; |
277 | static uint32_t nundefsym; |
278 | static struct symbol **extdefsyms = NULL; |
279 | static struct symbol **undefsyms = NULL; |
280 | |
281 | static struct RAA *extsyms; |
282 | static struct SAA *strs; |
283 | static uint32_t strslen; |
284 | |
285 | /* Global file information. This should be cleaned up into either |
286 | a structure or as function arguments. */ |
287 | static uint32_t head_ncmds = 0; |
288 | static uint32_t head_sizeofcmds = 0; |
289 | static uint32_t head_flags = 0; |
290 | static uint64_t seg_filesize = 0; |
291 | static uint64_t seg_vmsize = 0; |
292 | static uint32_t seg_nsects = 0; |
293 | static uint64_t rel_padcnt = 0; |
294 | |
295 | /* |
296 | * Functions for handling fixed-length zero-padded string |
297 | * fields, that may or may not be null-terminated. |
298 | */ |
299 | |
300 | /* Copy a string into a zero-padded fixed-length field */ |
301 | #define xstrncpy(xdst, xsrc) strncpy(xdst, xsrc, sizeof(xdst)) |
302 | |
303 | /* Compare a fixed-length field with a string */ |
304 | #define xstrncmp(xdst, xsrc) strncmp(xdst, xsrc, sizeof(xdst)) |
305 | |
306 | #define alignint32_t(x) \ |
307 | ALIGN(x, sizeof(int32_t)) /* align x to int32_t boundary */ |
308 | |
309 | #define alignint64_t(x) \ |
310 | ALIGN(x, sizeof(int64_t)) /* align x to int64_t boundary */ |
311 | |
312 | #define alignptr(x) \ |
313 | ALIGN(x, fmt.ptrsize) /* align x to output format width */ |
314 | |
315 | static struct hash_table section_by_name; |
316 | static struct RAAPTR *section_by_index; |
317 | |
318 | static struct section * never_null |
319 | find_or_add_section(const char *segname, const char *sectname) |
320 | { |
321 | struct hash_insert hi; |
322 | void **sp; |
323 | struct section *s; |
324 | char sect[34]; |
325 | |
326 | snprintf(sect, sizeof sect, "%-16s,%-16s" , segname, sectname); |
327 | |
328 | sp = hash_find(§ion_by_name, sect, &hi); |
329 | if (sp) |
330 | return (struct section *)(*sp); |
331 | |
332 | s = nasm_zalloc(sizeof *s); |
333 | xstrncpy(s->segname, segname); |
334 | xstrncpy(s->sectname, sectname); |
335 | xstrncpy(s->namestr, sect); |
336 | hash_add(&hi, s->namestr, s); |
337 | |
338 | s->index = s->subsection = seg_alloc(); |
339 | section_by_index = raa_write_ptr(section_by_index, s->index >> 1, s); |
340 | |
341 | return s; |
342 | } |
343 | |
344 | static inline bool is_new_section(const struct section *s) |
345 | { |
346 | return !s->data; |
347 | } |
348 | |
349 | static struct section *get_section_by_name(const char *segname, |
350 | const char *sectname) |
351 | { |
352 | char sect[34]; |
353 | void **sp; |
354 | |
355 | snprintf(sect, sizeof sect, "%-16s,%-16s" , segname, sectname); |
356 | |
357 | sp = hash_find(§ion_by_name, sect, NULL); |
358 | return sp ? (struct section *)(*sp) : NULL; |
359 | } |
360 | |
361 | static struct section *get_section_by_index(int32_t index) |
362 | { |
363 | if (index < 0 || index >= SEG_ABS || (index & 1)) |
364 | return NULL; |
365 | |
366 | return raa_read_ptr(section_by_index, index >> 1); |
367 | } |
368 | |
369 | struct dir_list { |
370 | struct dir_list *next; |
371 | struct dir_list *last; |
372 | const char *dir_name; |
373 | uint32_t dir; |
374 | }; |
375 | |
376 | struct file_list { |
377 | struct file_list *next; |
378 | struct file_list *last; |
379 | const char *file_name; |
380 | uint32_t file; |
381 | struct dir_list *dir; |
382 | }; |
383 | |
384 | struct dw_sect_list { |
385 | struct SAA *psaa; |
386 | int32_t section; |
387 | uint32_t line; |
388 | uint64_t offset; |
389 | uint32_t file; |
390 | struct dw_sect_list *next; |
391 | struct dw_sect_list *last; |
392 | }; |
393 | |
394 | struct section_info { |
395 | uint64_t size; |
396 | int32_t secto; |
397 | }; |
398 | |
399 | #define DW_LN_BASE (-5) |
400 | #define DW_LN_RANGE 14 |
401 | #define DW_OPCODE_BASE 13 |
402 | #define DW_MAX_LN (DW_LN_BASE + DW_LN_RANGE) |
403 | #define DW_MAX_SP_OPCODE 256 |
404 | |
405 | static struct file_list *dw_head_file = 0, *dw_cur_file = 0, **dw_last_file_next = NULL; |
406 | static struct dir_list *dw_head_dir = 0, **dw_last_dir_next = NULL; |
407 | static struct dw_sect_list *dw_head_sect = 0, *dw_cur_sect = 0, *dw_last_sect = 0; |
408 | static uint32_t cur_line = 0, dw_num_files = 0, dw_num_dirs = 0, dw_num_sects = 0; |
409 | static bool dbg_immcall = false; |
410 | static const char *module_name = NULL; |
411 | |
412 | /* |
413 | * Special section numbers which are used to define Mach-O special |
414 | * symbols, which can be used with WRT to provide PIC relocation |
415 | * types. |
416 | */ |
417 | static int32_t macho_tlvp_sect; |
418 | static int32_t macho_gotpcrel_sect; |
419 | |
420 | static void macho_init(void) |
421 | { |
422 | module_name = inname; |
423 | sects = NULL; |
424 | sectstail = §s; |
425 | |
426 | /* Fake section for absolute symbols */ |
427 | absolute_sect.index = NO_SEG; |
428 | |
429 | syms = NULL; |
430 | symstail = &syms; |
431 | nsyms = 0; |
432 | nlocalsym = 0; |
433 | nextdefsym = 0; |
434 | nundefsym = 0; |
435 | |
436 | extsyms = raa_init(); |
437 | strs = saa_init(1L); |
438 | |
439 | section_by_index = raa_init_ptr(); |
440 | hash_init(§ion_by_name, HASH_MEDIUM); |
441 | |
442 | /* string table starts with a zero byte so index 0 is an empty string */ |
443 | saa_wbytes(strs, zero_buffer, 1); |
444 | strslen = 1; |
445 | |
446 | /* add special symbol for TLVP */ |
447 | macho_tlvp_sect = seg_alloc() + 1; |
448 | backend_label("..tlvp" , macho_tlvp_sect, 0L); |
449 | } |
450 | |
451 | static void sect_write(struct section *sect, |
452 | const uint8_t *data, uint32_t len) |
453 | { |
454 | saa_wbytes(sect->data, data, len); |
455 | sect->size += len; |
456 | } |
457 | |
458 | /* |
459 | * Find a suitable global symbol for a ..gotpcrel or ..tlvp reference |
460 | */ |
461 | static struct symbol *macho_find_sym(struct section *s, uint64_t offset, |
462 | bool global, bool exact) |
463 | { |
464 | struct rbtree *srb; |
465 | |
466 | srb = rb_search(s->syms[global], offset); |
467 | |
468 | if (!srb || (exact && srb->key != offset)) { |
469 | nasm_error(ERR_NONFATAL, "unable to find a suitable%s%s symbol" |
470 | " for this reference" , |
471 | global ? " global" : "" , |
472 | s == &absolute_sect ? " absolute " : "" ); |
473 | return NULL; |
474 | } |
475 | |
476 | return container_of(srb - global, struct symbol, symv); |
477 | } |
478 | |
479 | static int64_t add_reloc(struct section *sect, int32_t section, |
480 | int64_t offset, |
481 | enum reltype reltype, int bytes) |
482 | { |
483 | struct reloc *r; |
484 | struct section *s; |
485 | int32_t fi; |
486 | int64_t adjust; |
487 | |
488 | /* Double check this is a valid relocation type for this platform */ |
489 | nasm_assert(reltype <= fmt.maxreltype); |
490 | |
491 | /* the current end of the section will be the symbol's address for |
492 | ** now, might have to be fixed by macho_fixup_relocs() later on. make |
493 | ** sure we don't make the symbol scattered by setting the highest |
494 | ** bit by accident */ |
495 | r = nasm_malloc(sizeof(struct reloc)); |
496 | r->addr = sect->size & ~R_SCATTERED; |
497 | r->ext = 1; |
498 | adjust = 0; |
499 | |
500 | /* match byte count 1, 2, 4, 8 to length codes 0, 1, 2, 3 respectively */ |
501 | r->length = ilog2_32(bytes); |
502 | |
503 | /* set default relocation values */ |
504 | r->type = fmt.reloc_abs; |
505 | r->pcrel = 0; |
506 | r->snum = R_ABS; |
507 | |
508 | s = get_section_by_index(section); |
509 | fi = s ? s->fileindex : NO_SECT; |
510 | |
511 | /* absolute relocation */ |
512 | switch (reltype) { |
513 | case RL_ABS: |
514 | if (section == NO_SEG) { |
515 | /* absolute (can this even happen?) */ |
516 | r->ext = 0; |
517 | } else if (fi == NO_SECT) { |
518 | /* external */ |
519 | r->snum = raa_read(extsyms, section); |
520 | } else { |
521 | /* local */ |
522 | r->ext = 0; |
523 | r->snum = fi; |
524 | } |
525 | break; |
526 | |
527 | case RL_REL: |
528 | case RL_BRANCH: |
529 | r->type = fmt.reloc_rel; |
530 | r->pcrel = 1; |
531 | if (section == NO_SEG) { |
532 | /* may optionally be converted below by fmt.forcesym */ |
533 | r->ext = 0; |
534 | } else if (fi == NO_SECT) { |
535 | /* external */ |
536 | sect->extreloc = 1; |
537 | r->snum = raa_read(extsyms, section); |
538 | if (reltype == RL_BRANCH) |
539 | r->type = X86_64_RELOC_BRANCH; |
540 | } else { |
541 | /* local */ |
542 | r->ext = 0; |
543 | r->snum = fi; |
544 | if (reltype == RL_BRANCH) |
545 | r->type = X86_64_RELOC_BRANCH; |
546 | } |
547 | break; |
548 | |
549 | case RL_SUB: /* obsolete */ |
550 | nasm_error(ERR_WARNING, "relcation with subtraction" |
551 | "becomes to be obsolete" ); |
552 | r->ext = 0; |
553 | r->type = X86_64_RELOC_SUBTRACTOR; |
554 | break; |
555 | |
556 | case RL_GOT: |
557 | r->type = X86_64_RELOC_GOT; |
558 | goto needsym; |
559 | |
560 | case RL_GOTLOAD: |
561 | r->type = X86_64_RELOC_GOT_LOAD; |
562 | goto needsym; |
563 | |
564 | case RL_TLV: |
565 | r->type = fmt.reloc_tlv; |
566 | goto needsym; |
567 | |
568 | needsym: |
569 | r->pcrel = (fmt.ptrsize == 8 ? 1 : 0); |
570 | if (section == NO_SEG) { |
571 | nasm_error(ERR_NONFATAL, "Unsupported use of use of WRT" ); |
572 | goto bail; |
573 | } else if (fi == NO_SECT) { |
574 | /* external */ |
575 | r->snum = raa_read(extsyms, section); |
576 | } else { |
577 | /* internal - GOTPCREL doesn't need to be in global */ |
578 | struct symbol *sym = macho_find_sym(s, offset, |
579 | false, /* reltype != RL_TLV */ |
580 | true); |
581 | if (!sym) { |
582 | nasm_error(ERR_NONFATAL, "Symbol for WRT not found" ); |
583 | goto bail; |
584 | } |
585 | |
586 | adjust -= sym->symv[0].key; |
587 | r->snum = sym->initial_snum; |
588 | } |
589 | break; |
590 | } |
591 | |
592 | /* |
593 | * For 64-bit Mach-O, force a symbol reference if at all possible |
594 | * Allow for r->snum == R_ABS by searching absolute_sect |
595 | */ |
596 | if (!r->ext && fmt.forcesym) { |
597 | struct symbol *sym = macho_find_sym(s ? s : &absolute_sect, |
598 | offset, false, false); |
599 | if (sym) { |
600 | adjust -= sym->symv[0].key; |
601 | r->snum = sym->initial_snum; |
602 | r->ext = 1; |
603 | } |
604 | } |
605 | |
606 | if (r->pcrel) |
607 | adjust += ((r->ext && fmt.ptrsize == 8) ? bytes : -(int64_t)sect->size); |
608 | |
609 | /* NeXT as puts relocs in reversed order (address-wise) into the |
610 | ** files, so we do the same, doesn't seem to make much of a |
611 | ** difference either way */ |
612 | r->next = sect->relocs; |
613 | sect->relocs = r; |
614 | if (r->ext) |
615 | sect->extreloc = 1; |
616 | ++sect->nreloc; |
617 | |
618 | return adjust; |
619 | |
620 | bail: |
621 | nasm_free(r); |
622 | return 0; |
623 | } |
624 | |
625 | static void macho_output(int32_t secto, const void *data, |
626 | enum out_type type, uint64_t size, |
627 | int32_t section, int32_t wrt) |
628 | { |
629 | struct section *s; |
630 | int64_t addr, offset; |
631 | uint8_t mydata[16], *p; |
632 | bool is_bss; |
633 | enum reltype reltype; |
634 | |
635 | if (secto == NO_SEG) { |
636 | if (type != OUT_RESERVE) |
637 | nasm_error(ERR_NONFATAL, "attempt to assemble code in " |
638 | "[ABSOLUTE] space" ); |
639 | return; |
640 | } |
641 | |
642 | s = get_section_by_index(secto); |
643 | if (!s) { |
644 | nasm_error(ERR_WARNING, "attempt to assemble code in" |
645 | " section %d: defaulting to `.text'" , secto); |
646 | s = get_section_by_name("__TEXT" , "__text" ); |
647 | |
648 | /* should never happen */ |
649 | if (!s) |
650 | nasm_panic(0, "text section not found" ); |
651 | } |
652 | |
653 | /* debug code generation only for sections tagged with |
654 | * instruction attribute */ |
655 | if (s->flags & S_ATTR_SOME_INSTRUCTIONS) |
656 | { |
657 | struct section_info sinfo; |
658 | sinfo.size = s->size; |
659 | sinfo.secto = secto; |
660 | dfmt->debug_output(0, &sinfo); |
661 | } |
662 | |
663 | is_bss = (s->flags & SECTION_TYPE) == S_ZEROFILL; |
664 | |
665 | if (is_bss && type != OUT_RESERVE) { |
666 | nasm_error(ERR_WARNING, "attempt to initialize memory in " |
667 | "BSS section: ignored" ); |
668 | /* FIXME */ |
669 | nasm_error(ERR_WARNING, "section size may be negative" |
670 | "with address symbols" ); |
671 | s->size += realsize(type, size); |
672 | return; |
673 | } |
674 | |
675 | memset(mydata, 0, sizeof(mydata)); |
676 | |
677 | switch (type) { |
678 | case OUT_RESERVE: |
679 | if (!is_bss) { |
680 | nasm_error(ERR_WARNING, "uninitialized space declared in" |
681 | " %s,%s section: zeroing" , s->segname, s->sectname); |
682 | |
683 | sect_write(s, NULL, size); |
684 | } else |
685 | s->size += size; |
686 | |
687 | break; |
688 | |
689 | case OUT_RAWDATA: |
690 | if (section != NO_SEG) |
691 | nasm_panic(0, "OUT_RAWDATA with other than NO_SEG" ); |
692 | |
693 | sect_write(s, data, size); |
694 | break; |
695 | |
696 | case OUT_ADDRESS: |
697 | { |
698 | int asize = abs((int)size); |
699 | |
700 | addr = *(int64_t *)data; |
701 | if (section != NO_SEG) { |
702 | if (section % 2) { |
703 | nasm_error(ERR_NONFATAL, "Mach-O format does not support" |
704 | " section base references" ); |
705 | } else if (wrt == NO_SEG) { |
706 | if (fmt.ptrsize == 8 && asize != 8) { |
707 | nasm_error(ERR_NONFATAL, |
708 | "Mach-O 64-bit format does not support" |
709 | " 32-bit absolute addresses" ); |
710 | } else { |
711 | addr += add_reloc(s, section, addr, RL_ABS, asize); |
712 | } |
713 | } else if (wrt == macho_tlvp_sect && fmt.ptrsize != 8 && |
714 | asize == (int) fmt.ptrsize) { |
715 | addr += add_reloc(s, section, addr, RL_TLV, asize); |
716 | } else { |
717 | nasm_error(ERR_NONFATAL, "Mach-O format does not support" |
718 | " this use of WRT" ); |
719 | } |
720 | } |
721 | |
722 | p = mydata; |
723 | WRITEADDR(p, addr, asize); |
724 | sect_write(s, mydata, asize); |
725 | break; |
726 | } |
727 | |
728 | case OUT_REL1ADR: |
729 | case OUT_REL2ADR: |
730 | |
731 | p = mydata; |
732 | offset = *(int64_t *)data; |
733 | addr = offset - size; |
734 | |
735 | if (section != NO_SEG && section % 2) { |
736 | nasm_error(ERR_NONFATAL, "Mach-O format does not support" |
737 | " section base references" ); |
738 | } else if (fmt.ptrsize == 8) { |
739 | nasm_error(ERR_NONFATAL, "Unsupported non-32-bit" |
740 | " Macho-O relocation [2]" ); |
741 | } else if (wrt != NO_SEG) { |
742 | nasm_error(ERR_NONFATAL, "Mach-O format does not support" |
743 | " this use of WRT" ); |
744 | wrt = NO_SEG; /* we can at least _try_ to continue */ |
745 | } else { |
746 | addr += add_reloc(s, section, addr+size, RL_REL, |
747 | type == OUT_REL1ADR ? 1 : 2); |
748 | } |
749 | |
750 | WRITESHORT(p, addr); |
751 | sect_write(s, mydata, type == OUT_REL1ADR ? 1 : 2); |
752 | break; |
753 | |
754 | case OUT_REL4ADR: |
755 | case OUT_REL8ADR: |
756 | |
757 | p = mydata; |
758 | offset = *(int64_t *)data; |
759 | addr = offset - size; |
760 | reltype = RL_REL; |
761 | |
762 | if (section != NO_SEG && section % 2) { |
763 | nasm_error(ERR_NONFATAL, "Mach-O format does not support" |
764 | " section base references" ); |
765 | } else if (wrt == NO_SEG) { |
766 | if (fmt.ptrsize == 8 && |
767 | (s->flags & S_ATTR_SOME_INSTRUCTIONS)) { |
768 | uint8_t opcode[2]; |
769 | |
770 | opcode[0] = opcode[1] = 0; |
771 | |
772 | /* HACK: Retrieve instruction opcode */ |
773 | if (likely(s->data->datalen >= 2)) { |
774 | saa_fread(s->data, s->data->datalen-2, opcode, 2); |
775 | } else if (s->data->datalen == 1) { |
776 | saa_fread(s->data, 0, opcode+1, 1); |
777 | } |
778 | |
779 | if ((opcode[0] != 0x0f && (opcode[1] & 0xfe) == 0xe8) || |
780 | (opcode[0] == 0x0f && (opcode[1] & 0xf0) == 0x80)) { |
781 | /* Direct call, jmp, or jcc */ |
782 | reltype = RL_BRANCH; |
783 | } |
784 | } |
785 | } else if (wrt == macho_gotpcrel_sect) { |
786 | reltype = RL_GOT; |
787 | |
788 | if ((s->flags & S_ATTR_SOME_INSTRUCTIONS) && |
789 | s->data->datalen >= 3) { |
790 | uint8_t gotload[3]; |
791 | |
792 | /* HACK: Retrieve instruction opcode */ |
793 | saa_fread(s->data, s->data->datalen-3, gotload, 3); |
794 | if ((gotload[0] & 0xf8) == 0x48 && |
795 | gotload[1] == 0x8b && |
796 | (gotload[2] & 0307) == 0005) { |
797 | /* movq <reg>,[rel sym wrt ..gotpcrel] */ |
798 | reltype = RL_GOTLOAD; |
799 | } |
800 | } |
801 | } else if (wrt == macho_tlvp_sect && fmt.ptrsize == 8) { |
802 | reltype = RL_TLV; |
803 | } else { |
804 | nasm_error(ERR_NONFATAL, "Mach-O format does not support" |
805 | " this use of WRT" ); |
806 | /* continue with RL_REL */ |
807 | } |
808 | |
809 | addr += add_reloc(s, section, offset, reltype, |
810 | type == OUT_REL4ADR ? 4 : 8); |
811 | WRITELONG(p, addr); |
812 | sect_write(s, mydata, type == OUT_REL4ADR ? 4 : 8); |
813 | break; |
814 | |
815 | default: |
816 | nasm_error(ERR_NONFATAL, "Unrepresentable relocation in Mach-O" ); |
817 | break; |
818 | } |
819 | } |
820 | |
821 | /* Translation table from traditional Unix section names to Mach-O */ |
822 | static const struct sectmap { |
823 | const char *nasmsect; |
824 | const char *segname; |
825 | const char *sectname; |
826 | const uint32_t flags; |
827 | } sectmap[] = { |
828 | {".text" , "__TEXT" , "__text" , |
829 | S_REGULAR|S_ATTR_SOME_INSTRUCTIONS|S_ATTR_PURE_INSTRUCTIONS}, |
830 | {".data" , "__DATA" , "__data" , S_REGULAR}, |
831 | {".rodata" , "__DATA" , "__const" , S_REGULAR}, |
832 | {".bss" , "__DATA" , "__bss" , S_ZEROFILL}, |
833 | {".debug_abbrev" , "__DWARF" , "__debug_abbrev" , S_ATTR_DEBUG}, |
834 | {".debug_info" , "__DWARF" , "__debug_info" , S_ATTR_DEBUG}, |
835 | {".debug_line" , "__DWARF" , "__debug_line" , S_ATTR_DEBUG}, |
836 | {".debug_str" , "__DWARF" , "__debug_str" , S_ATTR_DEBUG}, |
837 | {NULL, NULL, NULL, 0} |
838 | }; |
839 | |
840 | #define NO_TYPE S_NASM_TYPE_MASK |
841 | |
842 | /* Section type or attribute directives */ |
843 | static const struct sect_attribs { |
844 | const char *name; |
845 | uint32_t flags; |
846 | } sect_attribs[] = { |
847 | { "data" , S_REGULAR }, |
848 | { "code" , S_REGULAR|S_ATTR_SOME_INSTRUCTIONS|S_ATTR_PURE_INSTRUCTIONS }, |
849 | { "mixed" , S_REGULAR|S_ATTR_SOME_INSTRUCTIONS }, |
850 | { "bss" , S_ZEROFILL }, |
851 | { "zerofill" , S_ZEROFILL }, |
852 | { "no_dead_strip" , NO_TYPE|S_ATTR_NO_DEAD_STRIP }, |
853 | { "live_support" , NO_TYPE|S_ATTR_LIVE_SUPPORT }, |
854 | { "strip_static_syms" , NO_TYPE|S_ATTR_STRIP_STATIC_SYMS }, |
855 | { "debug" , NO_TYPE|S_ATTR_DEBUG }, |
856 | { NULL, 0 } |
857 | }; |
858 | |
859 | static int32_t macho_section(char *name, int pass, int *bits) |
860 | { |
861 | char *sectionAttributes; |
862 | const struct sectmap *sm; |
863 | struct section *s; |
864 | const char *section, *segment; |
865 | uint32_t flags; |
866 | const struct sect_attribs *sa; |
867 | char *currentAttribute; |
868 | char *comma; |
869 | |
870 | bool new_seg; |
871 | |
872 | (void)pass; |
873 | |
874 | /* Default to the appropriate number of bits. */ |
875 | if (!name) { |
876 | *bits = fmt.ptrsize << 3; |
877 | name = ".text" ; |
878 | sectionAttributes = NULL; |
879 | } else { |
880 | sectionAttributes = name; |
881 | name = nasm_strsep(§ionAttributes, " \t" ); |
882 | } |
883 | |
884 | section = segment = NULL; |
885 | flags = 0; |
886 | |
887 | comma = strchr(name, ','); |
888 | if (comma) { |
889 | int len; |
890 | |
891 | *comma = '\0'; |
892 | segment = name; |
893 | section = comma+1; |
894 | |
895 | len = strlen(segment); |
896 | if (len == 0) { |
897 | nasm_error(ERR_NONFATAL, "empty segment name\n" ); |
898 | } else if (len > 16) { |
899 | nasm_error(ERR_NONFATAL, "segment name %s too long\n" , segment); |
900 | } |
901 | |
902 | len = strlen(section); |
903 | if (len == 0) { |
904 | nasm_error(ERR_NONFATAL, "empty section name\n" ); |
905 | } else if (len > 16) { |
906 | nasm_error(ERR_NONFATAL, "section name %s too long\n" , section); |
907 | } |
908 | |
909 | if (!strcmp(section, "__text" )) { |
910 | flags = S_REGULAR | S_ATTR_SOME_INSTRUCTIONS | |
911 | S_ATTR_PURE_INSTRUCTIONS; |
912 | } else if (!strcmp(section, "__bss" )) { |
913 | flags = S_ZEROFILL; |
914 | } else { |
915 | flags = S_REGULAR; |
916 | } |
917 | } else { |
918 | for (sm = sectmap; sm->nasmsect != NULL; ++sm) { |
919 | /* make lookup into section name translation table */ |
920 | if (!strcmp(name, sm->nasmsect)) { |
921 | segment = sm->segname; |
922 | section = sm->sectname; |
923 | flags = sm->flags; |
924 | goto found; |
925 | } |
926 | } |
927 | nasm_error(ERR_NONFATAL, "unknown section name\n" ); |
928 | return NO_SEG; |
929 | } |
930 | |
931 | found: |
932 | /* try to find section with that name, or create it */ |
933 | s = find_or_add_section(segment, section); |
934 | new_seg = is_new_section(s); |
935 | |
936 | /* initialize it if it is a brand new section */ |
937 | if (new_seg) { |
938 | *sectstail = s; |
939 | sectstail = &s->next; |
940 | |
941 | s->data = saa_init(1L); |
942 | s->fileindex = ++seg_nsects; |
943 | s->align = -1; |
944 | s->pad = -1; |
945 | s->offset = -1; |
946 | s->by_name = false; |
947 | |
948 | s->size = 0; |
949 | s->nreloc = 0; |
950 | s->flags = flags; |
951 | } |
952 | |
953 | if (comma) |
954 | *comma = ','; /* Restore comma */ |
955 | |
956 | s->by_name = s->by_name || comma; /* Was specified by name */ |
957 | |
958 | flags = NO_TYPE; |
959 | |
960 | while (sectionAttributes && |
961 | (currentAttribute = nasm_strsep(§ionAttributes, " \t" ))) { |
962 | if (!*currentAttribute) |
963 | continue; |
964 | |
965 | if (!nasm_strnicmp("align=" , currentAttribute, 6)) { |
966 | char *end; |
967 | int newAlignment, value; |
968 | |
969 | value = strtoul(currentAttribute + 6, (char**)&end, 0); |
970 | newAlignment = alignlog2_32(value); |
971 | |
972 | if (0 != *end) { |
973 | nasm_error(ERR_NONFATAL, |
974 | "unknown or missing alignment value \"%s\" " |
975 | "specified for section \"%s\"" , |
976 | currentAttribute + 6, |
977 | name); |
978 | } else if (0 > newAlignment) { |
979 | nasm_error(ERR_NONFATAL, |
980 | "alignment of %d (for section \"%s\") is not " |
981 | "a power of two" , |
982 | value, |
983 | name); |
984 | } |
985 | |
986 | if (s->align < newAlignment) |
987 | s->align = newAlignment; |
988 | } else { |
989 | for (sa = sect_attribs; sa->name; sa++) { |
990 | if (!nasm_stricmp(sa->name, currentAttribute)) { |
991 | if ((sa->flags & S_NASM_TYPE_MASK) != NO_TYPE) { |
992 | flags = (flags & ~S_NASM_TYPE_MASK) |
993 | | (sa->flags & S_NASM_TYPE_MASK); |
994 | } |
995 | flags |= sa->flags & ~S_NASM_TYPE_MASK; |
996 | break; |
997 | } |
998 | } |
999 | |
1000 | if (!sa->name) { |
1001 | nasm_error(ERR_NONFATAL, |
1002 | "unknown section attribute %s for section %s" , |
1003 | currentAttribute, name); |
1004 | } |
1005 | } |
1006 | } |
1007 | |
1008 | if ((flags & S_NASM_TYPE_MASK) != NO_TYPE) { |
1009 | if (!new_seg && ((s->flags ^ flags) & S_NASM_TYPE_MASK)) { |
1010 | nasm_error(ERR_NONFATAL, |
1011 | "inconsistent section attributes for section %s\n" , |
1012 | name); |
1013 | } else { |
1014 | s->flags = (s->flags & ~S_NASM_TYPE_MASK) | flags; |
1015 | } |
1016 | } else { |
1017 | s->flags |= flags & ~S_NASM_TYPE_MASK; |
1018 | } |
1019 | |
1020 | return s->subsection; |
1021 | } |
1022 | |
1023 | static int32_t macho_herelabel(const char *name, enum label_type type, |
1024 | int32_t section, int32_t *subsection, |
1025 | bool *copyoffset) |
1026 | { |
1027 | struct section *s; |
1028 | int32_t subsec; |
1029 | (void)name; |
1030 | |
1031 | if (!(head_flags & MH_SUBSECTIONS_VIA_SYMBOLS)) |
1032 | return section; |
1033 | |
1034 | /* No subsection only for local labels */ |
1035 | if (type == LBL_LOCAL) |
1036 | return section; |
1037 | |
1038 | s = get_section_by_index(section); |
1039 | if (!s) |
1040 | return section; |
1041 | |
1042 | subsec = *subsection; |
1043 | if (subsec == NO_SEG) { |
1044 | /* Allocate a new subsection index */ |
1045 | subsec = *subsection = seg_alloc(); |
1046 | section_by_index = raa_write_ptr(section_by_index, subsec >> 1, s); |
1047 | } |
1048 | |
1049 | s->subsection = subsec; |
1050 | *copyoffset = true; /* Maintain previous offset */ |
1051 | return subsec; |
1052 | } |
1053 | |
1054 | static void macho_symdef(char *name, int32_t section, int64_t offset, |
1055 | int is_global, char *special) |
1056 | { |
1057 | struct symbol *sym; |
1058 | struct section *s; |
1059 | bool special_used = false; |
1060 | |
1061 | #if defined(DEBUG) && DEBUG>2 |
1062 | nasm_error(ERR_DEBUG, |
1063 | " macho_symdef: %s, pass0=%d, passn=%" PRId64", sec=%" PRIx32", off=%" PRIx64", is_global=%d, %s\n" , |
1064 | name, pass0, passn, section, offset, is_global, special); |
1065 | #endif |
1066 | |
1067 | if (is_global == 3) { |
1068 | if (special) { |
1069 | int n = strcspn(special, " \t" ); |
1070 | |
1071 | if (!nasm_strnicmp(special, "private_extern" , n)) { |
1072 | for (sym = syms; sym != NULL; sym = sym->next) { |
1073 | if (!strcmp(name, sym->name)) { |
1074 | if (sym->type & N_PEXT) |
1075 | return; /* nothing to be done */ |
1076 | else |
1077 | break; |
1078 | } |
1079 | } |
1080 | } |
1081 | } |
1082 | nasm_error(ERR_NONFATAL, "The Mach-O format does not " |
1083 | "(yet) support forward reference fixups." ); |
1084 | return; |
1085 | } |
1086 | |
1087 | if (name[0] == '.' && name[1] == '.' && name[2] != '@') { |
1088 | /* |
1089 | * This is a NASM special symbol. We never allow it into |
1090 | * the Macho-O symbol table, even if it's a valid one. If it |
1091 | * _isn't_ a valid one, we should barf immediately. |
1092 | */ |
1093 | if (strcmp(name, "..gotpcrel" ) && strcmp(name, "..tlvp" )) |
1094 | nasm_error(ERR_NONFATAL, "unrecognized special symbol `%s'" , name); |
1095 | return; |
1096 | } |
1097 | |
1098 | sym = *symstail = nasm_zalloc(sizeof(struct symbol)); |
1099 | sym->next = NULL; |
1100 | symstail = &sym->next; |
1101 | |
1102 | sym->name = name; |
1103 | sym->strx = strslen; |
1104 | sym->type = 0; |
1105 | sym->desc = 0; |
1106 | sym->symv[0].key = offset; |
1107 | sym->symv[1].key = offset; |
1108 | sym->initial_snum = -1; |
1109 | |
1110 | /* external and common symbols get N_EXT */ |
1111 | if (is_global != 0) { |
1112 | sym->type |= N_EXT; |
1113 | } |
1114 | if (is_global == 1) { |
1115 | /* check special to see if the global symbol shall be marked as private external: N_PEXT */ |
1116 | if (special) { |
1117 | int n = strcspn(special, " \t" ); |
1118 | |
1119 | if (!nasm_strnicmp(special, "private_extern" , n)) |
1120 | sym->type |= N_PEXT; |
1121 | else |
1122 | nasm_error(ERR_NONFATAL, "unrecognised symbol type `%.*s'" , n, special); |
1123 | } |
1124 | special_used = true; |
1125 | } |
1126 | |
1127 | /* track the initially allocated symbol number for use in future fix-ups */ |
1128 | sym->initial_snum = nsyms; |
1129 | |
1130 | if (section == NO_SEG) { |
1131 | /* symbols in no section get absolute */ |
1132 | sym->type |= N_ABS; |
1133 | sym->sect = NO_SECT; |
1134 | |
1135 | s = &absolute_sect; |
1136 | } else { |
1137 | s = get_section_by_index(section); |
1138 | |
1139 | sym->type |= N_SECT; |
1140 | |
1141 | /* get the in-file index of the section the symbol was defined in */ |
1142 | sym->sect = s ? s->fileindex : NO_SECT; |
1143 | |
1144 | if (!s) { |
1145 | /* remember symbol number of references to external |
1146 | ** symbols, this works because every external symbol gets |
1147 | ** its own section number allocated internally by nasm and |
1148 | ** can so be used as a key */ |
1149 | extsyms = raa_write(extsyms, section, nsyms); |
1150 | |
1151 | switch (is_global) { |
1152 | case 1: |
1153 | case 2: |
1154 | /* there isn't actually a difference between global |
1155 | ** and common symbols, both even have their size in |
1156 | ** sym->symv[0].key */ |
1157 | sym->type = N_EXT; |
1158 | break; |
1159 | |
1160 | default: |
1161 | /* give an error on unfound section if it's not an |
1162 | ** external or common symbol (assemble_file() does a |
1163 | ** seg_alloc() on every call for them) */ |
1164 | nasm_panic(0, "in-file index for section %d not found, is_global = %d" , section, is_global); |
1165 | break; |
1166 | } |
1167 | } |
1168 | } |
1169 | |
1170 | if (s) { |
1171 | s->syms[0] = rb_insert(s->syms[0], &sym->symv[0]); |
1172 | if (is_global) |
1173 | s->syms[1] = rb_insert(s->syms[1], &sym->symv[1]); |
1174 | } |
1175 | |
1176 | ++nsyms; |
1177 | |
1178 | if (special && !special_used) |
1179 | nasm_error(ERR_NONFATAL, "no special symbol features supported here" ); |
1180 | } |
1181 | |
1182 | static void macho_sectalign(int32_t seg, unsigned int value) |
1183 | { |
1184 | struct section *s; |
1185 | int align; |
1186 | |
1187 | nasm_assert(!(seg & 1)); |
1188 | |
1189 | s = get_section_by_index(seg); |
1190 | |
1191 | if (!s || !is_power2(value)) |
1192 | return; |
1193 | |
1194 | align = alignlog2_32(value); |
1195 | if (s->align < align) |
1196 | s->align = align; |
1197 | } |
1198 | |
1199 | static int32_t macho_segbase(int32_t section) |
1200 | { |
1201 | return section; |
1202 | } |
1203 | |
1204 | extern macros_t macho_stdmac[]; |
1205 | |
1206 | /* Comparison function for qsort symbol layout. */ |
1207 | static int layout_compare (const struct symbol **s1, |
1208 | const struct symbol **s2) |
1209 | { |
1210 | return (strcmp ((*s1)->name, (*s2)->name)); |
1211 | } |
1212 | |
1213 | /* The native assembler does a few things in a similar function |
1214 | |
1215 | * Remove temporary labels |
1216 | * Sort symbols according to local, external, undefined (by name) |
1217 | * Order the string table |
1218 | |
1219 | We do not remove temporary labels right now. |
1220 | |
1221 | numsyms is the total number of symbols we have. strtabsize is the |
1222 | number entries in the string table. */ |
1223 | |
1224 | static void macho_layout_symbols (uint32_t *numsyms, |
1225 | uint32_t *strtabsize) |
1226 | { |
1227 | struct symbol *sym, **symp; |
1228 | uint32_t i,j; |
1229 | |
1230 | *numsyms = 0; |
1231 | *strtabsize = sizeof (char); |
1232 | |
1233 | symp = &syms; |
1234 | |
1235 | while ((sym = *symp)) { |
1236 | /* Undefined symbols are now external. */ |
1237 | if (sym->type == N_UNDF) |
1238 | sym->type |= N_EXT; |
1239 | |
1240 | if ((sym->type & N_EXT) == 0) { |
1241 | sym->snum = *numsyms; |
1242 | *numsyms = *numsyms + 1; |
1243 | nlocalsym++; |
1244 | } |
1245 | else { |
1246 | if ((sym->type & N_TYPE) != N_UNDF) { |
1247 | nextdefsym++; |
1248 | } else { |
1249 | nundefsym++; |
1250 | } |
1251 | |
1252 | /* If we handle debug info we'll want |
1253 | to check for it here instead of just |
1254 | adding the symbol to the string table. */ |
1255 | sym->strx = *strtabsize; |
1256 | saa_wbytes (strs, sym->name, (int32_t)(strlen(sym->name) + 1)); |
1257 | *strtabsize += strlen(sym->name) + 1; |
1258 | } |
1259 | symp = &(sym->next); |
1260 | } |
1261 | |
1262 | /* Next, sort the symbols. Most of this code is a direct translation from |
1263 | the Apple cctools symbol layout. We need to keep compatibility with that. */ |
1264 | /* Set the indexes for symbol groups into the symbol table */ |
1265 | ilocalsym = 0; |
1266 | iextdefsym = nlocalsym; |
1267 | iundefsym = nlocalsym + nextdefsym; |
1268 | |
1269 | /* allocate arrays for sorting externals by name */ |
1270 | extdefsyms = nasm_malloc(nextdefsym * sizeof(struct symbol *)); |
1271 | undefsyms = nasm_malloc(nundefsym * sizeof(struct symbol *)); |
1272 | |
1273 | i = 0; |
1274 | j = 0; |
1275 | |
1276 | symp = &syms; |
1277 | |
1278 | while ((sym = *symp)) { |
1279 | |
1280 | if((sym->type & N_EXT) == 0) { |
1281 | sym->strx = *strtabsize; |
1282 | saa_wbytes (strs, sym->name, (int32_t)(strlen (sym->name) + 1)); |
1283 | *strtabsize += strlen(sym->name) + 1; |
1284 | } |
1285 | else { |
1286 | if ((sym->type & N_TYPE) != N_UNDF) { |
1287 | extdefsyms[i++] = sym; |
1288 | } else { |
1289 | undefsyms[j++] = sym; |
1290 | } |
1291 | } |
1292 | symp = &(sym->next); |
1293 | } |
1294 | |
1295 | qsort(extdefsyms, nextdefsym, sizeof(struct symbol *), |
1296 | (int (*)(const void *, const void *))layout_compare); |
1297 | qsort(undefsyms, nundefsym, sizeof(struct symbol *), |
1298 | (int (*)(const void *, const void *))layout_compare); |
1299 | |
1300 | for(i = 0; i < nextdefsym; i++) { |
1301 | extdefsyms[i]->snum = *numsyms; |
1302 | *numsyms += 1; |
1303 | } |
1304 | for(j = 0; j < nundefsym; j++) { |
1305 | undefsyms[j]->snum = *numsyms; |
1306 | *numsyms += 1; |
1307 | } |
1308 | } |
1309 | |
1310 | /* Calculate some values we'll need for writing later. */ |
1311 | |
1312 | static void macho_calculate_sizes (void) |
1313 | { |
1314 | struct section *s; |
1315 | int fi; |
1316 | |
1317 | /* count sections and calculate in-memory and in-file offsets */ |
1318 | for (s = sects; s != NULL; s = s->next) { |
1319 | uint64_t newaddr; |
1320 | |
1321 | /* recalculate segment address based on alignment and vm size */ |
1322 | s->addr = seg_vmsize; |
1323 | |
1324 | /* we need section alignment to calculate final section address */ |
1325 | if (s->align == -1) |
1326 | s->align = DEFAULT_SECTION_ALIGNMENT; |
1327 | |
1328 | newaddr = ALIGN(s->addr, UINT64_C(1) << s->align); |
1329 | s->addr = newaddr; |
1330 | |
1331 | seg_vmsize = newaddr + s->size; |
1332 | |
1333 | /* zerofill sections aren't actually written to the file */ |
1334 | if ((s->flags & SECTION_TYPE) != S_ZEROFILL) { |
1335 | /* |
1336 | * LLVM/Xcode as always aligns the section data to 4 |
1337 | * bytes; there is a comment in the LLVM source code that |
1338 | * perhaps aligning to pointer size would be better. |
1339 | */ |
1340 | s->pad = ALIGN(seg_filesize, 4) - seg_filesize; |
1341 | s->offset = seg_filesize + s->pad; |
1342 | seg_filesize += s->size + s->pad; |
1343 | |
1344 | /* filesize and vmsize needs to be aligned */ |
1345 | seg_vmsize += s->pad; |
1346 | } |
1347 | } |
1348 | |
1349 | /* calculate size of all headers, load commands and sections to |
1350 | ** get a pointer to the start of all the raw data */ |
1351 | if (seg_nsects > 0) { |
1352 | ++head_ncmds; |
1353 | head_sizeofcmds += fmt.segcmd_size + seg_nsects * fmt.sectcmd_size; |
1354 | } |
1355 | |
1356 | if (nsyms > 0) { |
1357 | ++head_ncmds; |
1358 | head_sizeofcmds += MACHO_SYMCMD_SIZE; |
1359 | } |
1360 | |
1361 | if (seg_nsects > MAX_SECT) { |
1362 | nasm_fatal(0, "MachO output is limited to %d sections\n" , |
1363 | MAX_SECT); |
1364 | } |
1365 | |
1366 | /* Create a table of sections by file index to avoid linear search */ |
1367 | sectstab = nasm_malloc((seg_nsects + 1) * sizeof(*sectstab)); |
1368 | sectstab[NO_SECT] = &absolute_sect; |
1369 | for (s = sects, fi = 1; s != NULL; s = s->next, fi++) |
1370 | sectstab[fi] = s; |
1371 | } |
1372 | |
1373 | /* Write out the header information for the file. */ |
1374 | |
1375 | static void (void) |
1376 | { |
1377 | fwriteint32_t(fmt.mh_magic, ofile); /* magic */ |
1378 | fwriteint32_t(fmt.cpu_type, ofile); /* CPU type */ |
1379 | fwriteint32_t(CPU_SUBTYPE_I386_ALL, ofile); /* CPU subtype */ |
1380 | fwriteint32_t(MH_OBJECT, ofile); /* Mach-O file type */ |
1381 | fwriteint32_t(head_ncmds, ofile); /* number of load commands */ |
1382 | fwriteint32_t(head_sizeofcmds, ofile); /* size of load commands */ |
1383 | fwriteint32_t(head_flags, ofile); /* flags, if any */ |
1384 | fwritezero(fmt.header_size - 7*4, ofile); /* reserved fields */ |
1385 | } |
1386 | |
1387 | /* Write out the segment load command at offset. */ |
1388 | |
1389 | static uint32_t macho_write_segment (uint64_t offset) |
1390 | { |
1391 | uint64_t rel_base = alignptr(offset + seg_filesize); |
1392 | uint32_t s_reloff = 0; |
1393 | struct section *s; |
1394 | |
1395 | fwriteint32_t(fmt.lc_segment, ofile); /* cmd == LC_SEGMENT_64 */ |
1396 | |
1397 | /* size of load command including section load commands */ |
1398 | fwriteint32_t(fmt.segcmd_size + seg_nsects * fmt.sectcmd_size, |
1399 | ofile); |
1400 | |
1401 | /* in an MH_OBJECT file all sections are in one unnamed (name |
1402 | ** all zeros) segment */ |
1403 | fwritezero(16, ofile); |
1404 | fwriteptr(0, ofile); /* in-memory offset */ |
1405 | fwriteptr(seg_vmsize, ofile); /* in-memory size */ |
1406 | fwriteptr(offset, ofile); /* in-file offset to data */ |
1407 | fwriteptr(seg_filesize, ofile); /* in-file size */ |
1408 | fwriteint32_t(VM_PROT_DEFAULT, ofile); /* maximum vm protection */ |
1409 | fwriteint32_t(VM_PROT_DEFAULT, ofile); /* initial vm protection */ |
1410 | fwriteint32_t(seg_nsects, ofile); /* number of sections */ |
1411 | fwriteint32_t(0, ofile); /* no flags */ |
1412 | |
1413 | /* emit section headers */ |
1414 | for (s = sects; s != NULL; s = s->next) { |
1415 | if (s->nreloc) { |
1416 | nasm_assert((s->flags & SECTION_TYPE) != S_ZEROFILL); |
1417 | s->flags |= S_ATTR_LOC_RELOC; |
1418 | if (s->extreloc) |
1419 | s->flags |= S_ATTR_EXT_RELOC; |
1420 | } else if (!xstrncmp(s->segname, "__DATA" ) && |
1421 | !xstrncmp(s->sectname, "__const" ) && |
1422 | !s->by_name && |
1423 | !get_section_by_name("__TEXT" , "__const" )) { |
1424 | /* |
1425 | * The MachO equivalent to .rodata can be either |
1426 | * __DATA,__const or __TEXT,__const; the latter only if |
1427 | * there are no relocations. However, when mixed it is |
1428 | * better to specify the segments explicitly. |
1429 | */ |
1430 | xstrncpy(s->segname, "__TEXT" ); |
1431 | } |
1432 | |
1433 | nasm_write(s->sectname, sizeof(s->sectname), ofile); |
1434 | nasm_write(s->segname, sizeof(s->segname), ofile); |
1435 | fwriteptr(s->addr, ofile); |
1436 | fwriteptr(s->size, ofile); |
1437 | |
1438 | /* dummy data for zerofill sections or proper values */ |
1439 | if ((s->flags & SECTION_TYPE) != S_ZEROFILL) { |
1440 | nasm_assert(s->pad != (uint32_t)-1); |
1441 | offset += s->pad; |
1442 | fwriteint32_t(offset, ofile); |
1443 | offset += s->size; |
1444 | /* Write out section alignment, as a power of two. |
1445 | e.g. 32-bit word alignment would be 2 (2^2 = 4). */ |
1446 | fwriteint32_t(s->align, ofile); |
1447 | /* To be compatible with cctools as we emit |
1448 | a zero reloff if we have no relocations. */ |
1449 | fwriteint32_t(s->nreloc ? rel_base + s_reloff : 0, ofile); |
1450 | fwriteint32_t(s->nreloc, ofile); |
1451 | |
1452 | s_reloff += s->nreloc * MACHO_RELINFO_SIZE; |
1453 | } else { |
1454 | fwriteint32_t(0, ofile); |
1455 | fwriteint32_t(s->align, ofile); |
1456 | fwriteint32_t(0, ofile); |
1457 | fwriteint32_t(0, ofile); |
1458 | } |
1459 | |
1460 | fwriteint32_t(s->flags, ofile); /* flags */ |
1461 | fwriteint32_t(0, ofile); /* reserved */ |
1462 | fwriteptr(0, ofile); /* reserved */ |
1463 | } |
1464 | |
1465 | rel_padcnt = rel_base - offset; |
1466 | offset = rel_base + s_reloff; |
1467 | |
1468 | return offset; |
1469 | } |
1470 | |
1471 | /* For a given chain of relocs r, write out the entire relocation |
1472 | chain to the object file. */ |
1473 | |
1474 | static void macho_write_relocs (struct reloc *r) |
1475 | { |
1476 | while (r) { |
1477 | uint32_t word2; |
1478 | |
1479 | fwriteint32_t(r->addr, ofile); /* reloc offset */ |
1480 | |
1481 | word2 = r->snum; |
1482 | word2 |= r->pcrel << 24; |
1483 | word2 |= r->length << 25; |
1484 | word2 |= r->ext << 27; |
1485 | word2 |= r->type << 28; |
1486 | fwriteint32_t(word2, ofile); /* reloc data */ |
1487 | r = r->next; |
1488 | } |
1489 | } |
1490 | |
1491 | /* Write out the section data. */ |
1492 | static void macho_write_section (void) |
1493 | { |
1494 | struct section *s; |
1495 | struct reloc *r; |
1496 | uint8_t *p; |
1497 | int32_t len; |
1498 | int64_t l; |
1499 | union offset { |
1500 | uint64_t val; |
1501 | uint8_t buf[8]; |
1502 | } blk; |
1503 | |
1504 | for (s = sects; s != NULL; s = s->next) { |
1505 | if ((s->flags & SECTION_TYPE) == S_ZEROFILL) |
1506 | continue; |
1507 | |
1508 | /* Like a.out Mach-O references things in the data or bss |
1509 | * sections by addresses which are actually relative to the |
1510 | * start of the _text_ section, in the _file_. See outaout.c |
1511 | * for more information. */ |
1512 | saa_rewind(s->data); |
1513 | for (r = s->relocs; r != NULL; r = r->next) { |
1514 | len = (uint32_t)1 << r->length; |
1515 | if (len > 4) /* Can this ever be an issue?! */ |
1516 | len = 8; |
1517 | blk.val = 0; |
1518 | saa_fread(s->data, r->addr, blk.buf, len); |
1519 | |
1520 | /* get offset based on relocation type */ |
1521 | #ifdef WORDS_LITTLEENDIAN |
1522 | l = blk.val; |
1523 | #else |
1524 | l = blk.buf[0]; |
1525 | l += ((int64_t)blk.buf[1]) << 8; |
1526 | l += ((int64_t)blk.buf[2]) << 16; |
1527 | l += ((int64_t)blk.buf[3]) << 24; |
1528 | l += ((int64_t)blk.buf[4]) << 32; |
1529 | l += ((int64_t)blk.buf[5]) << 40; |
1530 | l += ((int64_t)blk.buf[6]) << 48; |
1531 | l += ((int64_t)blk.buf[7]) << 56; |
1532 | #endif |
1533 | |
1534 | /* If the relocation is internal add to the current section |
1535 | offset. Otherwise the only value we need is the symbol |
1536 | offset which we already have. The linker takes care |
1537 | of the rest of the address. */ |
1538 | if (!r->ext) { |
1539 | /* generate final address by section address and offset */ |
1540 | nasm_assert(r->snum <= seg_nsects); |
1541 | l += sectstab[r->snum]->addr; |
1542 | if (r->pcrel) |
1543 | l -= s->addr; |
1544 | } else if (r->pcrel && r->type == GENERIC_RELOC_VANILLA) { |
1545 | l -= s->addr; |
1546 | } |
1547 | |
1548 | /* write new offset back */ |
1549 | p = blk.buf; |
1550 | WRITEDLONG(p, l); |
1551 | saa_fwrite(s->data, r->addr, blk.buf, len); |
1552 | } |
1553 | |
1554 | /* dump the section data to file */ |
1555 | fwritezero(s->pad, ofile); |
1556 | saa_fpwrite(s->data, ofile); |
1557 | } |
1558 | |
1559 | /* pad last section up to reloc entries on pointer boundary */ |
1560 | fwritezero(rel_padcnt, ofile); |
1561 | |
1562 | /* emit relocation entries */ |
1563 | for (s = sects; s != NULL; s = s->next) |
1564 | macho_write_relocs (s->relocs); |
1565 | } |
1566 | |
1567 | /* Write out the symbol table. We should already have sorted this |
1568 | before now. */ |
1569 | static void macho_write_symtab (void) |
1570 | { |
1571 | struct symbol *sym; |
1572 | uint64_t i; |
1573 | |
1574 | /* we don't need to pad here since MACHO_RELINFO_SIZE == 8 */ |
1575 | |
1576 | for (sym = syms; sym != NULL; sym = sym->next) { |
1577 | if ((sym->type & N_EXT) == 0) { |
1578 | fwriteint32_t(sym->strx, ofile); /* string table entry number */ |
1579 | nasm_write(&sym->type, 1, ofile); /* symbol type */ |
1580 | nasm_write(&sym->sect, 1, ofile); /* section */ |
1581 | fwriteint16_t(sym->desc, ofile); /* description */ |
1582 | |
1583 | /* Fix up the symbol value now that we know the final section |
1584 | sizes. */ |
1585 | if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) { |
1586 | nasm_assert(sym->sect <= seg_nsects); |
1587 | sym->symv[0].key += sectstab[sym->sect]->addr; |
1588 | } |
1589 | |
1590 | fwriteptr(sym->symv[0].key, ofile); /* value (i.e. offset) */ |
1591 | } |
1592 | } |
1593 | |
1594 | for (i = 0; i < nextdefsym; i++) { |
1595 | sym = extdefsyms[i]; |
1596 | fwriteint32_t(sym->strx, ofile); |
1597 | nasm_write(&sym->type, 1, ofile); /* symbol type */ |
1598 | nasm_write(&sym->sect, 1, ofile); /* section */ |
1599 | fwriteint16_t(sym->desc, ofile); /* description */ |
1600 | |
1601 | /* Fix up the symbol value now that we know the final section |
1602 | sizes. */ |
1603 | if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) { |
1604 | nasm_assert(sym->sect <= seg_nsects); |
1605 | sym->symv[0].key += sectstab[sym->sect]->addr; |
1606 | } |
1607 | |
1608 | fwriteptr(sym->symv[0].key, ofile); /* value (i.e. offset) */ |
1609 | } |
1610 | |
1611 | for (i = 0; i < nundefsym; i++) { |
1612 | sym = undefsyms[i]; |
1613 | fwriteint32_t(sym->strx, ofile); |
1614 | nasm_write(&sym->type, 1, ofile); /* symbol type */ |
1615 | nasm_write(&sym->sect, 1, ofile); /* section */ |
1616 | fwriteint16_t(sym->desc, ofile); /* description */ |
1617 | |
1618 | /* Fix up the symbol value now that we know the final section |
1619 | sizes. */ |
1620 | if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) { |
1621 | nasm_assert(sym->sect <= seg_nsects); |
1622 | sym->symv[0].key += sectstab[sym->sect]->addr; |
1623 | } |
1624 | |
1625 | fwriteptr(sym->symv[0].key, ofile); /* value (i.e. offset) */ |
1626 | } |
1627 | |
1628 | } |
1629 | |
1630 | /* Fixup the snum in the relocation entries, we should be |
1631 | doing this only for externally referenced symbols. */ |
1632 | static void macho_fixup_relocs (struct reloc *r) |
1633 | { |
1634 | struct symbol *sym; |
1635 | |
1636 | while (r != NULL) { |
1637 | if (r->ext) { |
1638 | for (sym = syms; sym != NULL; sym = sym->next) { |
1639 | if (sym->initial_snum == r->snum) { |
1640 | r->snum = sym->snum; |
1641 | break; |
1642 | } |
1643 | } |
1644 | } |
1645 | r = r->next; |
1646 | } |
1647 | } |
1648 | |
1649 | /* Write out the object file. */ |
1650 | |
1651 | static void macho_write (void) |
1652 | { |
1653 | uint64_t offset = 0; |
1654 | |
1655 | /* mach-o object file structure: |
1656 | ** |
1657 | ** mach header |
1658 | ** uint32_t magic |
1659 | ** int cpu type |
1660 | ** int cpu subtype |
1661 | ** uint32_t mach file type |
1662 | ** uint32_t number of load commands |
1663 | ** uint32_t size of all load commands |
1664 | ** (includes section struct size of segment command) |
1665 | ** uint32_t flags |
1666 | ** |
1667 | ** segment command |
1668 | ** uint32_t command type == LC_SEGMENT[_64] |
1669 | ** uint32_t size of load command |
1670 | ** (including section load commands) |
1671 | ** char[16] segment name |
1672 | ** pointer in-memory offset |
1673 | ** pointer in-memory size |
1674 | ** pointer in-file offset to data area |
1675 | ** pointer in-file size |
1676 | ** (in-memory size excluding zerofill sections) |
1677 | ** int maximum vm protection |
1678 | ** int initial vm protection |
1679 | ** uint32_t number of sections |
1680 | ** uint32_t flags |
1681 | ** |
1682 | ** section commands |
1683 | ** char[16] section name |
1684 | ** char[16] segment name |
1685 | ** pointer in-memory offset |
1686 | ** pointer in-memory size |
1687 | ** uint32_t in-file offset |
1688 | ** uint32_t alignment |
1689 | ** (irrelevant in MH_OBJECT) |
1690 | ** uint32_t in-file offset of relocation entires |
1691 | ** uint32_t number of relocations |
1692 | ** uint32_t flags |
1693 | ** uint32_t reserved |
1694 | ** uint32_t reserved |
1695 | ** |
1696 | ** symbol table command |
1697 | ** uint32_t command type == LC_SYMTAB |
1698 | ** uint32_t size of load command |
1699 | ** uint32_t symbol table offset |
1700 | ** uint32_t number of symbol table entries |
1701 | ** uint32_t string table offset |
1702 | ** uint32_t string table size |
1703 | ** |
1704 | ** raw section data |
1705 | ** |
1706 | ** padding to pointer boundary |
1707 | ** |
1708 | ** relocation data (struct reloc) |
1709 | ** int32_t offset |
1710 | ** uint data (symbolnum, pcrel, length, extern, type) |
1711 | ** |
1712 | ** symbol table data (struct nlist) |
1713 | ** int32_t string table entry number |
1714 | ** uint8_t type |
1715 | ** (extern, absolute, defined in section) |
1716 | ** uint8_t section |
1717 | ** (0 for global symbols, section number of definition (>= 1, <= |
1718 | ** 254) for local symbols, size of variable for common symbols |
1719 | ** [type == extern]) |
1720 | ** int16_t description |
1721 | ** (for stab debugging format) |
1722 | ** pointer value (i.e. file offset) of symbol or stab offset |
1723 | ** |
1724 | ** string table data |
1725 | ** list of null-terminated strings |
1726 | */ |
1727 | |
1728 | /* Emit the Mach-O header. */ |
1729 | macho_write_header(); |
1730 | |
1731 | offset = fmt.header_size + head_sizeofcmds; |
1732 | |
1733 | /* emit the segment load command */ |
1734 | if (seg_nsects > 0) |
1735 | offset = macho_write_segment (offset); |
1736 | else |
1737 | nasm_error(ERR_WARNING, "no sections?" ); |
1738 | |
1739 | if (nsyms > 0) { |
1740 | /* write out symbol command */ |
1741 | fwriteint32_t(LC_SYMTAB, ofile); /* cmd == LC_SYMTAB */ |
1742 | fwriteint32_t(MACHO_SYMCMD_SIZE, ofile); /* size of load command */ |
1743 | fwriteint32_t(offset, ofile); /* symbol table offset */ |
1744 | fwriteint32_t(nsyms, ofile); /* number of symbol |
1745 | ** table entries */ |
1746 | offset += nsyms * fmt.nlist_size; |
1747 | fwriteint32_t(offset, ofile); /* string table offset */ |
1748 | fwriteint32_t(strslen, ofile); /* string table size */ |
1749 | } |
1750 | |
1751 | /* emit section data */ |
1752 | if (seg_nsects > 0) |
1753 | macho_write_section (); |
1754 | |
1755 | /* emit symbol table if we have symbols */ |
1756 | if (nsyms > 0) |
1757 | macho_write_symtab (); |
1758 | |
1759 | /* we don't need to pad here, we are already aligned */ |
1760 | |
1761 | /* emit string table */ |
1762 | saa_fpwrite(strs, ofile); |
1763 | } |
1764 | /* We do quite a bit here, starting with finalizing all of the data |
1765 | for the object file, writing, and then freeing all of the data from |
1766 | the file. */ |
1767 | |
1768 | static void macho_cleanup(void) |
1769 | { |
1770 | struct section *s; |
1771 | struct reloc *r; |
1772 | struct symbol *sym; |
1773 | |
1774 | dfmt->cleanup(); |
1775 | |
1776 | /* Sort all symbols. */ |
1777 | macho_layout_symbols (&nsyms, &strslen); |
1778 | |
1779 | /* Fixup relocation entries */ |
1780 | for (s = sects; s != NULL; s = s->next) { |
1781 | macho_fixup_relocs (s->relocs); |
1782 | } |
1783 | |
1784 | /* First calculate and finalize needed values. */ |
1785 | macho_calculate_sizes(); |
1786 | macho_write(); |
1787 | |
1788 | /* free up everything */ |
1789 | while (sects->next) { |
1790 | s = sects; |
1791 | sects = sects->next; |
1792 | |
1793 | saa_free(s->data); |
1794 | while (s->relocs != NULL) { |
1795 | r = s->relocs; |
1796 | s->relocs = s->relocs->next; |
1797 | nasm_free(r); |
1798 | } |
1799 | |
1800 | nasm_free(s); |
1801 | } |
1802 | |
1803 | saa_free(strs); |
1804 | |
1805 | raa_free(extsyms); |
1806 | |
1807 | while (syms) { |
1808 | sym = syms; |
1809 | syms = syms->next; |
1810 | nasm_free (sym); |
1811 | } |
1812 | |
1813 | nasm_free(extdefsyms); |
1814 | nasm_free(undefsyms); |
1815 | nasm_free(sectstab); |
1816 | raa_free_ptr(section_by_index); |
1817 | hash_free(§ion_by_name); |
1818 | } |
1819 | |
1820 | static bool macho_set_section_attribute_by_symbol(const char *label, uint32_t flags) |
1821 | { |
1822 | struct section *s; |
1823 | int32_t nasm_seg; |
1824 | int64_t offset; |
1825 | |
1826 | if (!lookup_label(label, &nasm_seg, &offset)) { |
1827 | nasm_error(ERR_NONFATAL, "unknown symbol `%s' in no_dead_strip" , label); |
1828 | return false; |
1829 | } |
1830 | |
1831 | s = get_section_by_index(nasm_seg); |
1832 | if (!s) { |
1833 | nasm_error(ERR_NONFATAL, "symbol `%s' is external or absolute" , label); |
1834 | return false; |
1835 | } |
1836 | |
1837 | s->flags |= flags; |
1838 | return true; |
1839 | } |
1840 | |
1841 | /* |
1842 | * Mark a symbol for no dead stripping |
1843 | */ |
1844 | static enum directive_result macho_no_dead_strip(const char *labels) |
1845 | { |
1846 | char *s, *p, *ep; |
1847 | char ec; |
1848 | enum directive_result rv = DIRR_ERROR; |
1849 | bool real = passn > 1; |
1850 | |
1851 | p = s = nasm_strdup(labels); |
1852 | while (*p) { |
1853 | ep = nasm_skip_identifier(p); |
1854 | if (!ep) { |
1855 | nasm_error(ERR_NONFATAL, "invalid symbol in NO_DEAD_STRIP" ); |
1856 | goto err; |
1857 | } |
1858 | ec = *ep; |
1859 | if (ec && ec != ',' && !nasm_isspace(ec)) { |
1860 | nasm_error(ERR_NONFATAL, "cannot parse contents after symbol" ); |
1861 | goto err; |
1862 | } |
1863 | *ep = '\0'; |
1864 | if (real) { |
1865 | if (!macho_set_section_attribute_by_symbol(p, S_ATTR_NO_DEAD_STRIP)) |
1866 | rv = DIRR_ERROR; |
1867 | } |
1868 | *ep = ec; |
1869 | p = nasm_skip_spaces(ep); |
1870 | if (*p == ',') |
1871 | p = nasm_skip_spaces(++p); |
1872 | } |
1873 | |
1874 | rv = DIRR_OK; |
1875 | |
1876 | err: |
1877 | nasm_free(s); |
1878 | return rv; |
1879 | } |
1880 | |
1881 | /* |
1882 | * Mach-O pragmas |
1883 | */ |
1884 | static enum directive_result |
1885 | macho_pragma(const struct pragma *pragma) |
1886 | { |
1887 | bool real = passn > 1; |
1888 | |
1889 | switch (pragma->opcode) { |
1890 | case D_SUBSECTIONS_VIA_SYMBOLS: |
1891 | if (*pragma->tail) |
1892 | return DIRR_BADPARAM; |
1893 | |
1894 | if (real) |
1895 | head_flags |= MH_SUBSECTIONS_VIA_SYMBOLS; |
1896 | |
1897 | /* Jmp-match optimization conflicts */ |
1898 | optimizing.flag |= OPTIM_DISABLE_JMP_MATCH; |
1899 | |
1900 | return DIRR_OK; |
1901 | |
1902 | case D_NO_DEAD_STRIP: |
1903 | return macho_no_dead_strip(pragma->tail); |
1904 | |
1905 | default: |
1906 | return DIRR_UNKNOWN; /* Not a Mach-O directive */ |
1907 | } |
1908 | } |
1909 | |
1910 | static const struct pragma_facility macho_pragma_list[] = { |
1911 | { "macho" , macho_pragma }, |
1912 | { NULL, macho_pragma } /* Implements macho32/macho64 namespaces */ |
1913 | }; |
1914 | |
1915 | static void macho_dbg_generate(void) |
1916 | { |
1917 | uint8_t *p_buf = NULL, *p_buf_base = NULL; |
1918 | size_t saa_len = 0, high_addr = 0, total_len = 0; |
1919 | struct section *p_section = NULL; |
1920 | /* calculated at debug_str and referenced at debug_info */ |
1921 | uint32_t producer_str_offset = 0, module_str_offset = 0, dir_str_offset = 0; |
1922 | |
1923 | /* debug section defines */ |
1924 | { |
1925 | int bits = 0; |
1926 | macho_section(".debug_abbrev" , 0, &bits); |
1927 | macho_section(".debug_info" , 0, &bits); |
1928 | macho_section(".debug_line" , 0, &bits); |
1929 | macho_section(".debug_str" , 0, &bits); |
1930 | } |
1931 | |
1932 | /* dw section walk to find high_addr and total_len */ |
1933 | { |
1934 | struct dw_sect_list *p_sect; |
1935 | |
1936 | list_for_each(p_sect, dw_head_sect) { |
1937 | uint64_t offset = get_section_by_index(p_sect->section)->size; |
1938 | struct SAA *p_linep = p_sect->psaa; |
1939 | |
1940 | saa_write8(p_linep, 2); /* std op 2 */ |
1941 | saa_write8(p_linep, offset - p_sect->offset); |
1942 | saa_write8(p_linep, DW_LNS_extended_op); |
1943 | saa_write8(p_linep, 1); /* operand length */ |
1944 | saa_write8(p_linep, DW_LNE_end_sequence); |
1945 | |
1946 | total_len += p_linep->datalen; |
1947 | high_addr += offset; |
1948 | } |
1949 | } |
1950 | |
1951 | /* debug line */ |
1952 | { |
1953 | struct dw_sect_list *p_sect; |
1954 | size_t linep_off, buf_size; |
1955 | struct SAA *p_lines = saa_init(1L); |
1956 | struct dir_list *p_dir; |
1957 | struct file_list *p_file; |
1958 | |
1959 | p_section = get_section_by_name("__DWARF" , "__debug_line" ); |
1960 | nasm_assert(p_section != NULL); |
1961 | |
1962 | saa_write8(p_lines, 1); /* minimum instruction length */ |
1963 | saa_write8(p_lines, 1); /* initial value of "is_stmt" */ |
1964 | saa_write8(p_lines, DW_LN_BASE); /* line base */ |
1965 | saa_write8(p_lines, DW_LN_RANGE); /* line range */ |
1966 | saa_write8(p_lines, DW_OPCODE_BASE); /* opcode base */ |
1967 | saa_write8(p_lines, 0); /* std opcode 1 length */ |
1968 | saa_write8(p_lines, 1); /* std opcode 2 length */ |
1969 | saa_write8(p_lines, 1); /* std opcode 3 length */ |
1970 | saa_write8(p_lines, 1); /* std opcode 4 length */ |
1971 | saa_write8(p_lines, 1); /* std opcode 5 length */ |
1972 | saa_write8(p_lines, 0); /* std opcode 6 length */ |
1973 | saa_write8(p_lines, 0); /* std opcode 7 length */ |
1974 | saa_write8(p_lines, 0); /* std opcode 8 length */ |
1975 | saa_write8(p_lines, 1); /* std opcode 9 length */ |
1976 | saa_write8(p_lines, 0); /* std opcode 10 length */ |
1977 | saa_write8(p_lines, 0); /* std opcode 11 length */ |
1978 | saa_write8(p_lines, 1); /* std opcode 12 length */ |
1979 | list_for_each(p_dir, dw_head_dir) { |
1980 | saa_wcstring(p_lines, p_dir->dir_name); |
1981 | } |
1982 | saa_write8(p_lines, 0); /* end of table */ |
1983 | |
1984 | list_for_each(p_file, dw_head_file) { |
1985 | saa_wcstring(p_lines, p_file->file_name); |
1986 | saa_write8(p_lines, p_file->dir->dir); /* directory id */ |
1987 | saa_write8(p_lines, 0); /* time */ |
1988 | saa_write8(p_lines, 0); /* size */ |
1989 | } |
1990 | saa_write8(p_lines, 0); /* end of table */ |
1991 | |
1992 | linep_off = p_lines->datalen; |
1993 | /* 10 bytes for initial & prolong length, and dwarf version info */ |
1994 | buf_size = saa_len = linep_off + total_len + 10; |
1995 | p_buf_base = p_buf = nasm_malloc(buf_size); |
1996 | |
1997 | WRITELONG(p_buf, saa_len - 4); /* initial length; size excluding itself */ |
1998 | WRITESHORT(p_buf, 2); /* dwarf version */ |
1999 | WRITELONG(p_buf, linep_off); /* prolong length */ |
2000 | |
2001 | saa_rnbytes(p_lines, p_buf, linep_off); |
2002 | p_buf += linep_off; |
2003 | saa_free(p_lines); |
2004 | |
2005 | list_for_each(p_sect, dw_head_sect) { |
2006 | struct SAA *p_linep = p_sect->psaa; |
2007 | |
2008 | saa_len = p_linep->datalen; |
2009 | saa_rnbytes(p_linep, p_buf, saa_len); |
2010 | p_buf += saa_len; |
2011 | |
2012 | saa_free(p_linep); |
2013 | } |
2014 | |
2015 | macho_output(p_section->index, p_buf_base, OUT_RAWDATA, buf_size, NO_SEG, 0); |
2016 | |
2017 | nasm_free(p_buf_base); |
2018 | } |
2019 | |
2020 | /* string section */ |
2021 | { |
2022 | struct SAA *p_str = saa_init(1L); |
2023 | char *cur_path = nasm_realpath(module_name); |
2024 | char *cur_file = nasm_basename(cur_path); |
2025 | char *cur_dir = nasm_dirname(cur_path); |
2026 | |
2027 | p_section = get_section_by_name("__DWARF" , "__debug_str" ); |
2028 | nasm_assert(p_section != NULL); |
2029 | |
2030 | producer_str_offset = 0; |
2031 | module_str_offset = dir_str_offset = saa_wcstring(p_str, nasm_signature); |
2032 | dir_str_offset += saa_wcstring(p_str, cur_file); |
2033 | saa_wcstring(p_str, cur_dir); |
2034 | |
2035 | saa_len = p_str->datalen; |
2036 | p_buf = nasm_malloc(saa_len); |
2037 | saa_rnbytes(p_str, p_buf, saa_len); |
2038 | macho_output(p_section->index, p_buf, OUT_RAWDATA, saa_len, NO_SEG, 0); |
2039 | |
2040 | nasm_free(cur_path); |
2041 | nasm_free(cur_file); |
2042 | nasm_free(cur_dir); |
2043 | saa_free(p_str); |
2044 | nasm_free(p_buf); |
2045 | } |
2046 | |
2047 | /* debug info */ |
2048 | { |
2049 | struct SAA *p_info = saa_init(1L); |
2050 | |
2051 | p_section = get_section_by_name("__DWARF" , "__debug_info" ); |
2052 | nasm_assert(p_section != NULL); |
2053 | |
2054 | /* size will be overwritten once determined, so skip in p_info layout */ |
2055 | saa_write16(p_info, 2); /* dwarf version */ |
2056 | saa_write32(p_info, 0); /* offset info abbrev */ |
2057 | saa_write8(p_info, (ofmt == &of_macho64) ? 8 : 4); /* pointer size */ |
2058 | |
2059 | saa_write8(p_info, 1); /* abbrev entry number */ |
2060 | |
2061 | saa_write32(p_info, producer_str_offset); /* offset from string table for DW_AT_producer */ |
2062 | saa_write16(p_info, DW_LANG_Mips_Assembler); /* DW_AT_language */ |
2063 | saa_write32(p_info, module_str_offset); /* offset from string table for DW_AT_name */ |
2064 | saa_write32(p_info, dir_str_offset); /* offset from string table for DW_AT_comp_dir */ |
2065 | saa_write32(p_info, 0); /* DW_AT_stmt_list */ |
2066 | |
2067 | if (ofmt == &of_macho64) { |
2068 | saa_write64(p_info, 0); /* DW_AT_low_pc */ |
2069 | saa_write64(p_info, high_addr); /* DW_AT_high_pc */ |
2070 | } else { |
2071 | saa_write32(p_info, 0); /* DW_AT_low_pc */ |
2072 | saa_write32(p_info, high_addr); /* DW_AT_high_pc */ |
2073 | } |
2074 | |
2075 | saa_write8(p_info, 2); /* abbrev entry number */ |
2076 | |
2077 | if (ofmt == &of_macho64) { |
2078 | saa_write64(p_info, 0); /* DW_AT_low_pc */ |
2079 | saa_write64(p_info, 0); /* DW_AT_frame_base */ |
2080 | } else { |
2081 | saa_write32(p_info, 0); /* DW_AT_low_pc */ |
2082 | saa_write32(p_info, 0); /* DW_AT_frame_base */ |
2083 | } |
2084 | saa_write8(p_info, DW_END_default); |
2085 | |
2086 | saa_len = p_info->datalen; |
2087 | p_buf_base = p_buf = nasm_malloc(saa_len + 4); /* 4B for size info */ |
2088 | |
2089 | WRITELONG(p_buf, saa_len); |
2090 | saa_rnbytes(p_info, p_buf, saa_len); |
2091 | macho_output(p_section->index, p_buf_base, OUT_RAWDATA, saa_len + 4, NO_SEG, 0); |
2092 | |
2093 | saa_free(p_info); |
2094 | nasm_free(p_buf_base); |
2095 | } |
2096 | |
2097 | /* abbrev section */ |
2098 | { |
2099 | struct SAA *p_abbrev = saa_init(1L); |
2100 | |
2101 | p_section = get_section_by_name("__DWARF" , "__debug_abbrev" ); |
2102 | nasm_assert(p_section != NULL); |
2103 | |
2104 | saa_write8(p_abbrev, 1); /* entry number */ |
2105 | |
2106 | saa_write8(p_abbrev, DW_TAG_compile_unit); |
2107 | saa_write8(p_abbrev, DW_CHILDREN_yes); |
2108 | |
2109 | saa_write8(p_abbrev, DW_AT_producer); |
2110 | saa_write8(p_abbrev, DW_FORM_strp); |
2111 | |
2112 | saa_write8(p_abbrev, DW_AT_language); |
2113 | saa_write8(p_abbrev, DW_FORM_data2); |
2114 | |
2115 | saa_write8(p_abbrev, DW_AT_name); |
2116 | saa_write8(p_abbrev, DW_FORM_strp); |
2117 | |
2118 | saa_write8(p_abbrev, DW_AT_comp_dir); |
2119 | saa_write8(p_abbrev, DW_FORM_strp); |
2120 | |
2121 | saa_write8(p_abbrev, DW_AT_stmt_list); |
2122 | saa_write8(p_abbrev, DW_FORM_data4); |
2123 | |
2124 | saa_write8(p_abbrev, DW_AT_low_pc); |
2125 | saa_write8(p_abbrev, DW_FORM_addr); |
2126 | |
2127 | saa_write8(p_abbrev, DW_AT_high_pc); |
2128 | saa_write8(p_abbrev, DW_FORM_addr); |
2129 | |
2130 | saa_write16(p_abbrev, DW_END_default); |
2131 | |
2132 | saa_write8(p_abbrev, 2); /* entry number */ |
2133 | |
2134 | saa_write8(p_abbrev, DW_TAG_subprogram); |
2135 | saa_write8(p_abbrev, DW_CHILDREN_no); |
2136 | |
2137 | saa_write8(p_abbrev, DW_AT_low_pc); |
2138 | saa_write8(p_abbrev, DW_FORM_addr); |
2139 | |
2140 | saa_write8(p_abbrev, DW_AT_frame_base); |
2141 | saa_write8(p_abbrev, DW_FORM_addr); |
2142 | |
2143 | saa_write16(p_abbrev, DW_END_default); |
2144 | |
2145 | saa_write8(p_abbrev, 0); /* Terminal zero entry */ |
2146 | |
2147 | saa_len = p_abbrev->datalen; |
2148 | |
2149 | p_buf = nasm_malloc(saa_len); |
2150 | |
2151 | saa_rnbytes(p_abbrev, p_buf, saa_len); |
2152 | macho_output(p_section->index, p_buf, OUT_RAWDATA, saa_len, NO_SEG, 0); |
2153 | |
2154 | saa_free(p_abbrev); |
2155 | nasm_free(p_buf); |
2156 | } |
2157 | } |
2158 | |
2159 | static void new_file_list (const char *file_name, const char *dir_name) |
2160 | { |
2161 | struct dir_list *dir_list; |
2162 | bool need_new_dir_list = true; |
2163 | |
2164 | nasm_new(dw_cur_file); |
2165 | dw_cur_file->file = ++dw_num_files; |
2166 | dw_cur_file->file_name = file_name; |
2167 | if(!dw_head_file) { |
2168 | dw_head_file = dw_cur_file; |
2169 | } else { |
2170 | *dw_last_file_next = dw_cur_file; |
2171 | } |
2172 | dw_last_file_next = &(dw_cur_file->next); |
2173 | |
2174 | if(dw_head_dir) { |
2175 | list_for_each(dir_list, dw_head_dir) { |
2176 | if(!(strcmp(dir_name, dir_list->dir_name))) { |
2177 | dw_cur_file->dir = dir_list; |
2178 | need_new_dir_list = false; |
2179 | break; |
2180 | } |
2181 | } |
2182 | } |
2183 | |
2184 | if(need_new_dir_list) |
2185 | { |
2186 | nasm_new(dir_list); |
2187 | dir_list->dir = dw_num_dirs++; |
2188 | dir_list->dir_name = dir_name; |
2189 | if(!dw_head_dir) { |
2190 | dw_head_dir = dir_list; |
2191 | } else { |
2192 | *dw_last_dir_next = dir_list; |
2193 | } |
2194 | dw_last_dir_next = &(dir_list->next); |
2195 | dw_cur_file->dir = dir_list; |
2196 | } |
2197 | } |
2198 | |
2199 | static void macho_dbg_init(void) |
2200 | { |
2201 | } |
2202 | |
2203 | static void macho_dbg_linenum(const char *file_name, int32_t line_num, int32_t segto) |
2204 | { |
2205 | bool need_new_list = true; |
2206 | const char *cur_file = nasm_basename(file_name); |
2207 | const char *cur_dir = nasm_dirname(file_name); |
2208 | (void)segto; |
2209 | |
2210 | if(!dw_cur_file || strcmp(cur_file, dw_cur_file->file_name) || |
2211 | strcmp(cur_dir, dw_cur_file->dir->dir_name)) { |
2212 | if(dw_head_file) { |
2213 | struct file_list *match; |
2214 | |
2215 | list_for_each(match, dw_head_file) { |
2216 | if(!(strcmp(cur_file, match->file_name)) && |
2217 | !(strcmp(cur_dir, match->dir->dir_name))) { |
2218 | dw_cur_file = match; |
2219 | dw_cur_file->dir = match->dir; |
2220 | need_new_list = false; |
2221 | break; |
2222 | } |
2223 | } |
2224 | } |
2225 | |
2226 | if(need_new_list) { |
2227 | new_file_list(cur_file, cur_dir); |
2228 | } |
2229 | } |
2230 | |
2231 | dbg_immcall = true; |
2232 | cur_line = line_num; |
2233 | } |
2234 | |
2235 | static void macho_dbg_output(int type, void *param) |
2236 | { |
2237 | struct section_info *sinfo_param = (struct section_info *)param; |
2238 | int32_t secto = sinfo_param->secto; |
2239 | bool need_new_sect = false; |
2240 | struct SAA *p_linep = NULL; |
2241 | (void)type; |
2242 | |
2243 | if(!(dw_cur_sect && (dw_cur_sect->section == secto))) { |
2244 | need_new_sect = true; |
2245 | if(dw_head_sect) { |
2246 | struct dw_sect_list *match = dw_head_sect; |
2247 | uint32_t idx = 0; |
2248 | |
2249 | for(; idx < dw_num_sects; idx++) { |
2250 | if(match->section == secto) { |
2251 | dw_cur_sect = match; |
2252 | need_new_sect = false; |
2253 | break; |
2254 | } |
2255 | match = match->next; |
2256 | } |
2257 | } |
2258 | } |
2259 | |
2260 | if(need_new_sect) { |
2261 | nasm_new(dw_cur_sect); |
2262 | dw_num_sects ++; |
2263 | p_linep = dw_cur_sect->psaa = saa_init(1L); |
2264 | dw_cur_sect->line = dw_cur_sect->file = 1; |
2265 | dw_cur_sect->offset = 0; |
2266 | dw_cur_sect->next = NULL; |
2267 | dw_cur_sect->section = secto; |
2268 | |
2269 | saa_write8(p_linep, DW_LNS_extended_op); |
2270 | saa_write8(p_linep, (ofmt == &of_macho64) ? 9 : 5); |
2271 | saa_write8(p_linep, DW_LNE_set_address); |
2272 | if (ofmt == &of_macho64) { |
2273 | saa_write64(p_linep, 0); |
2274 | } else { |
2275 | saa_write32(p_linep, 0); |
2276 | } |
2277 | |
2278 | if(!dw_head_sect) { |
2279 | dw_head_sect = dw_last_sect = dw_cur_sect; |
2280 | } else { |
2281 | dw_last_sect->next = dw_cur_sect; |
2282 | dw_last_sect = dw_cur_sect; |
2283 | } |
2284 | } |
2285 | |
2286 | if(dbg_immcall == true) { |
2287 | int32_t line_delta = cur_line - dw_cur_sect->line; |
2288 | int32_t offset_delta = sinfo_param->size - dw_cur_sect->offset; |
2289 | uint32_t cur_file = dw_cur_file->file; |
2290 | p_linep = dw_cur_sect->psaa; |
2291 | |
2292 | if(cur_file != dw_cur_sect->file) { |
2293 | saa_write8(p_linep, DW_LNS_set_file); |
2294 | saa_write8(p_linep, cur_file); |
2295 | dw_cur_sect->file = cur_file; |
2296 | } |
2297 | |
2298 | if(line_delta) { |
2299 | int special_opcode = (line_delta - DW_LN_BASE) + (DW_LN_RANGE * offset_delta) + |
2300 | DW_OPCODE_BASE; |
2301 | |
2302 | if((line_delta >= DW_LN_BASE) && (line_delta < DW_MAX_LN) && |
2303 | (special_opcode < DW_MAX_SP_OPCODE)) { |
2304 | saa_write8(p_linep, special_opcode); |
2305 | } else { |
2306 | saa_write8(p_linep, DW_LNS_advance_line); |
2307 | saa_wleb128s(p_linep, line_delta); |
2308 | if(offset_delta) { |
2309 | saa_write8(p_linep, DW_LNS_advance_pc); |
2310 | saa_wleb128u(p_linep, offset_delta); |
2311 | } |
2312 | saa_write8(p_linep, DW_LNS_copy); |
2313 | } |
2314 | |
2315 | dw_cur_sect->line = cur_line; |
2316 | dw_cur_sect->offset = sinfo_param->size; |
2317 | } |
2318 | |
2319 | dbg_immcall = false; |
2320 | } |
2321 | } |
2322 | |
2323 | static void macho_dbg_cleanup(void) |
2324 | { |
2325 | /* dwarf sectors generation */ |
2326 | macho_dbg_generate(); |
2327 | |
2328 | { |
2329 | struct dw_sect_list *p_sect = dw_head_sect; |
2330 | struct file_list *p_file = dw_head_file; |
2331 | uint32_t idx = 0; |
2332 | |
2333 | for(; idx < dw_num_sects; idx++) { |
2334 | struct dw_sect_list *next = p_sect->next; |
2335 | nasm_free(p_sect); |
2336 | p_sect = next; |
2337 | } |
2338 | |
2339 | for(idx = 0; idx < dw_num_files; idx++) { |
2340 | struct file_list *next = p_file->next; |
2341 | nasm_free(p_file); |
2342 | p_file = next; |
2343 | } |
2344 | } |
2345 | } |
2346 | |
2347 | #ifdef OF_MACHO32 |
2348 | static const struct macho_fmt macho32_fmt = { |
2349 | 4, |
2350 | MH_MAGIC, |
2351 | CPU_TYPE_I386, |
2352 | LC_SEGMENT, |
2353 | MACHO_HEADER_SIZE, |
2354 | MACHO_SEGCMD_SIZE, |
2355 | MACHO_SECTCMD_SIZE, |
2356 | MACHO_NLIST_SIZE, |
2357 | RL_MAX_32, |
2358 | GENERIC_RELOC_VANILLA, |
2359 | GENERIC_RELOC_VANILLA, |
2360 | GENERIC_RELOC_TLV, |
2361 | false /* Allow segment-relative relocations */ |
2362 | }; |
2363 | |
2364 | static void macho32_init(void) |
2365 | { |
2366 | fmt = macho32_fmt; |
2367 | macho_init(); |
2368 | |
2369 | macho_gotpcrel_sect = NO_SEG; |
2370 | } |
2371 | |
2372 | static const struct dfmt macho32_df_dwarf = { |
2373 | "MachO32 (i386) dwarf debug format for Darwin/MacOS" , |
2374 | "dwarf" , |
2375 | macho_dbg_init, |
2376 | macho_dbg_linenum, |
2377 | null_debug_deflabel, |
2378 | null_debug_directive, |
2379 | null_debug_typevalue, |
2380 | macho_dbg_output, |
2381 | macho_dbg_cleanup, |
2382 | NULL /*pragma list*/ |
2383 | }; |
2384 | |
2385 | static const struct dfmt * const macho32_df_arr[2] = |
2386 | { &macho32_df_dwarf, NULL }; |
2387 | |
2388 | const struct ofmt of_macho32 = { |
2389 | "NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (i386) object files" , |
2390 | "macho32" , |
2391 | ".o" , |
2392 | 0, |
2393 | 32, |
2394 | macho32_df_arr, |
2395 | &macho32_df_dwarf, |
2396 | macho_stdmac, |
2397 | macho32_init, |
2398 | null_reset, |
2399 | nasm_do_legacy_output, |
2400 | macho_output, |
2401 | macho_symdef, |
2402 | macho_section, |
2403 | macho_herelabel, |
2404 | macho_sectalign, |
2405 | macho_segbase, |
2406 | null_directive, |
2407 | macho_cleanup, |
2408 | macho_pragma_list |
2409 | }; |
2410 | #endif |
2411 | |
2412 | #ifdef OF_MACHO64 |
2413 | static const struct macho_fmt macho64_fmt = { |
2414 | 8, |
2415 | MH_MAGIC_64, |
2416 | CPU_TYPE_X86_64, |
2417 | LC_SEGMENT_64, |
2418 | MACHO_HEADER64_SIZE, |
2419 | MACHO_SEGCMD64_SIZE, |
2420 | MACHO_SECTCMD64_SIZE, |
2421 | MACHO_NLIST64_SIZE, |
2422 | RL_MAX_64, |
2423 | X86_64_RELOC_UNSIGNED, |
2424 | X86_64_RELOC_SIGNED, |
2425 | X86_64_RELOC_TLV, |
2426 | true /* Force symbol-relative relocations */ |
2427 | }; |
2428 | |
2429 | static void macho64_init(void) |
2430 | { |
2431 | fmt = macho64_fmt; |
2432 | macho_init(); |
2433 | |
2434 | /* add special symbol for ..gotpcrel */ |
2435 | macho_gotpcrel_sect = seg_alloc() + 1; |
2436 | backend_label("..gotpcrel" , macho_gotpcrel_sect, 0L); |
2437 | } |
2438 | |
2439 | static const struct dfmt macho64_df_dwarf = { |
2440 | "MachO64 (x86-64) dwarf debug format for Darwin/MacOS" , |
2441 | "dwarf" , |
2442 | macho_dbg_init, |
2443 | macho_dbg_linenum, |
2444 | null_debug_deflabel, |
2445 | null_debug_directive, |
2446 | null_debug_typevalue, |
2447 | macho_dbg_output, |
2448 | macho_dbg_cleanup, |
2449 | NULL /*pragma list*/ |
2450 | }; |
2451 | |
2452 | static const struct dfmt * const macho64_df_arr[2] = |
2453 | { &macho64_df_dwarf, NULL }; |
2454 | |
2455 | const struct ofmt of_macho64 = { |
2456 | "NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (x86_64) object files" , |
2457 | "macho64" , |
2458 | ".o" , |
2459 | 0, |
2460 | 64, |
2461 | macho64_df_arr, |
2462 | &macho64_df_dwarf, |
2463 | macho_stdmac, |
2464 | macho64_init, |
2465 | null_reset, |
2466 | nasm_do_legacy_output, |
2467 | macho_output, |
2468 | macho_symdef, |
2469 | macho_section, |
2470 | macho_herelabel, |
2471 | macho_sectalign, |
2472 | macho_segbase, |
2473 | null_directive, |
2474 | macho_cleanup, |
2475 | macho_pragma_list, |
2476 | }; |
2477 | #endif |
2478 | |
2479 | #endif |
2480 | |
2481 | /* |
2482 | * Local Variables: |
2483 | * mode:c |
2484 | * c-basic-offset:4 |
2485 | * End: |
2486 | * |
2487 | * end of file */ |
2488 | |