diff options
author | jmmv <jmmv@pkgsrc.org> | 2007-01-06 15:11:57 +0000 |
---|---|---|
committer | jmmv <jmmv@pkgsrc.org> | 2007-01-06 15:11:57 +0000 |
commit | 5080918643400cb79975352a1bd61f0d95db5667 (patch) | |
tree | 759f19eae512976cc9f8b6a68280aca2c66f56ad /devel/nasm | |
parent | d0807088b2f6c517a2d79bb3e42aace325e836f5 (diff) | |
download | pkgsrc-5080918643400cb79975352a1bd61f0d95db5667.tar.gz |
Add support to generate Mach-O objects (for Intel Macs). Code taken from
the CVS repository, so it will be in the next public release of nasm.
Bump PKGREVISION to 3.
Diffstat (limited to 'devel/nasm')
-rw-r--r-- | devel/nasm/Makefile | 4 | ||||
-rw-r--r-- | devel/nasm/distinfo | 6 | ||||
-rw-r--r-- | devel/nasm/patches/patch-aa | 13 | ||||
-rw-r--r-- | devel/nasm/patches/patch-ad | 1322 | ||||
-rw-r--r-- | devel/nasm/patches/patch-ae | 61 |
5 files changed, 1400 insertions, 6 deletions
diff --git a/devel/nasm/Makefile b/devel/nasm/Makefile index bc8b7282510..3e322bcdf15 100644 --- a/devel/nasm/Makefile +++ b/devel/nasm/Makefile @@ -1,7 +1,7 @@ -# $NetBSD: Makefile,v 1.30 2006/11/02 18:17:22 joerg Exp $ +# $NetBSD: Makefile,v 1.31 2007/01/06 15:11:57 jmmv Exp $ DISTNAME= nasm-0.98.39 -PKGREVISION= 2 +PKGREVISION= 3 CATEGORIES= devel lang MASTER_SITES= ${MASTER_SITE_SOURCEFORGE:=nasm/} EXTRACT_SUFX= .tar.bz2 diff --git a/devel/nasm/distinfo b/devel/nasm/distinfo index ceccdecd774..1829fa585c3 100644 --- a/devel/nasm/distinfo +++ b/devel/nasm/distinfo @@ -1,8 +1,10 @@ -$NetBSD: distinfo,v 1.8 2005/05/05 20:12:46 adrianp Exp $ +$NetBSD: distinfo,v 1.9 2007/01/06 15:11:58 jmmv Exp $ SHA1 (nasm-0.98.39.tar.bz2) = 73d64812bb95774355f737c0fb0271382d23db67 RMD160 (nasm-0.98.39.tar.bz2) = b5587b1b81f58cef3a50e438e8efb365945df587 Size (nasm-0.98.39.tar.bz2) = 543976 bytes -SHA1 (patch-aa) = b0a4c91d7448ba630bfb482ab8f97e98753169cb +SHA1 (patch-aa) = 27409c3b71634dc5c3aa02b3cae49ebad2db6579 SHA1 (patch-ab) = bbe1d7219dd2e5ade8f97a4f3070bc87d3a7d4b5 SHA1 (patch-ac) = 7ae622ab78b1cf30ca027d652476d7d48deae182 +SHA1 (patch-ad) = 1f572247b2b6b46b4b8c4c2c055010459def496b +SHA1 (patch-ae) = f6029c8574c4e11d59d161819a379e9f687bc346 diff --git a/devel/nasm/patches/patch-aa b/devel/nasm/patches/patch-aa index 60d60833200..7a7e026813d 100644 --- a/devel/nasm/patches/patch-aa +++ b/devel/nasm/patches/patch-aa @@ -1,6 +1,6 @@ -$NetBSD: patch-aa,v 1.1 2003/09/17 16:40:14 jmmv Exp $ +$NetBSD: patch-aa,v 1.2 2007/01/06 15:11:58 jmmv Exp $ ---- Makefile.in.orig Fri Aug 29 21:56:40 2003 +--- Makefile.in.orig 2005-01-15 00:05:31.000000000 +0100 +++ Makefile.in @@ -18,7 +18,7 @@ CC = @CC@ CFLAGS = @CFLAGS@ @GCCFLAGS@ @DEFS@ -I$(srcdir) -I. @@ -11,3 +11,12 @@ $NetBSD: patch-aa,v 1.1 2003/09/17 16:40:14 jmmv Exp $ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ +@@ -51,7 +51,7 @@ NASM = nasm.$(O) nasmlib.$(O) float.$(O) + labels.$(O) parser.$(O) outform.$(O) output/outbin.$(O) \ + output/outaout.$(O) output/outcoff.$(O) output/outelf.$(O) \ + output/outobj.$(O) output/outas86.$(O) output/outrdf2.$(O) \ +- output/outdbg.$(O) output/outieee.$(O) \ ++ output/outdbg.$(O) output/outieee.$(O) output/outmacho.$(O) \ + preproc.$(O) listing.$(O) eval.$(O) + + NDISASM = ndisasm.$(O) disasm.$(O) sync.$(O) nasmlib.$(O) insnsd.$(O) diff --git a/devel/nasm/patches/patch-ad b/devel/nasm/patches/patch-ad new file mode 100644 index 00000000000..c1e25e516da --- /dev/null +++ b/devel/nasm/patches/patch-ad @@ -0,0 +1,1322 @@ +--- /dev/null 2007-01-06 13:50:40.000000000 +0100 ++++ output/outmacho.c 2006-02-02 22:50:47.000000000 +0100 +@@ -0,0 +1,1319 @@ ++/* outmacho.c output routines for the Netwide Assembler to produce ++ * NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X object files ++ * ++ * The Netwide Assembler is copyright (C) 1996 Simon Tatham and ++ * Julian Hall. All rights reserved. The software is ++ * redistributable under the licence given in the file "Licence" ++ * distributed in the NASM archive. ++ */ ++ ++/* Most of this file is, like Mach-O itself, based on a.out. For more ++ * guidelines see outaout.c. */ ++ ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#include <ctype.h> ++ ++#include "nasm.h" ++#include "nasmlib.h" ++#include "outform.h" ++ ++#if defined(OF_MACHO) ++ ++/* Mach-O in-file header structure sizes */ ++#define MACHO_HEADER_SIZE (28) ++#define MACHO_SEGCMD_SIZE (56) ++#define MACHO_SECTCMD_SIZE (68) ++#define MACHO_SYMCMD_SIZE (24) ++#define MACHO_NLIST_SIZE (12) ++#define MACHO_RELINFO_SIZE (8) ++ ++/* Mach-O file header values */ ++#define MH_MAGIC (0xfeedface) ++#define CPU_TYPE_I386 (7) /* x86 platform */ ++#define CPU_SUBTYPE_I386_ALL (3) /* all-x86 compatible */ ++#define MH_OBJECT (0x1) /* object file */ ++ ++#define LC_SEGMENT (0x1) /* segment load command */ ++#define LC_SYMTAB (0x2) /* symbol table load command */ ++ ++#define VM_PROT_NONE (0x00) ++#define VM_PROT_READ (0x01) ++#define VM_PROT_WRITE (0x02) ++#define VM_PROT_EXECUTE (0x04) ++ ++#define VM_PROT_DEFAULT (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE) ++#define VM_PROT_ALL (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE) ++ ++struct section { ++ /* nasm internal data */ ++ struct section *next; ++ struct SAA *data; ++ long index; ++ struct reloc *relocs; ++ int align; ++ ++ /* data that goes into the file */ ++ char sectname[16]; /* what this section is called */ ++ char segname[16]; /* segment this section will be in */ ++ unsigned long size; /* in-memory and -file size */ ++ unsigned long nreloc; /* relocation entry count */ ++ unsigned long flags; /* type and attributes (masked) */ ++}; ++ ++#define SECTION_TYPE 0x000000ff /* section type mask */ ++ ++#define S_REGULAR (0x0) /* standard section */ ++#define S_ZEROFILL (0x1) /* zerofill, in-memory only */ ++ ++#define SECTION_ATTRIBUTES_SYS 0x00ffff00 /* system setable attributes */ ++#define S_ATTR_SOME_INSTRUCTIONS 0x00000400 /* section contains some ++ machine instructions */ ++#define S_ATTR_EXT_RELOC 0x00000200 /* section has external ++ relocation entries */ ++#define S_ATTR_LOC_RELOC 0x00000100 /* section has local ++ relocation entries */ ++ ++ ++static struct sectmap { ++ const char *nasmsect; ++ const char *segname; ++ const char *sectname; ++ const long flags; ++} sectmap[] = { { ++".text", "__TEXT", "__text", S_REGULAR|S_ATTR_SOME_INSTRUCTIONS}, { ++".data", "__DATA", "__data", S_REGULAR}, { ++".rodata", "__DATA", "__const", S_REGULAR}, { ++".bss", "__DATA", "__bss", S_ZEROFILL}, { ++NULL, NULL, NULL}}; ++ ++struct reloc { ++ /* nasm internal data */ ++ struct reloc *next; ++ ++ /* data that goes into the file */ ++ long addr; /* op's offset in section */ ++ unsigned int snum:24, /* contains symbol index if ++ ** ext otherwise in-file ++ ** section number */ ++ pcrel:1, /* relative relocation */ ++ length:2, /* 0=byte, 1=word, 2=long */ ++ ext:1, /* external symbol referenced */ ++ type:4; /* reloc type, 0 for us */ ++}; ++ ++#define R_ABS 0 /* absolute relocation */ ++#define R_SCATTERED 0x80000000 /* reloc entry is scattered if ++ ** highest bit == 1 */ ++ ++struct symbol { ++ /* nasm internal data */ ++ struct symbol *next; /* next symbol in the list */ ++ char *name; /* name of this symbol */ ++ long initial_snum; /* symbol number used above in ++ reloc */ ++ long snum; /* true snum for reloc */ ++ ++ /* data that goes into the file */ ++ long strx; /* string table index */ ++ unsigned char type; /* symbol type */ ++ unsigned char sect; /* NO_SECT or section number */ ++ short desc; /* for stab debugging, 0 for us */ ++ unsigned long value; /* offset of symbol in section */ ++}; ++ ++/* symbol type bits */ ++#define N_EXT 0x01 /* global or external symbol */ ++ ++#define N_UNDF 0x0 /* undefined symbol | n_sect == */ ++#define N_ABS 0x2 /* absolute symbol | NO_SECT */ ++#define N_SECT 0xe /* defined symbol, n_sect holds ++ ** section number */ ++ ++#define N_TYPE 0x0e /* type bit mask */ ++ ++#define DEFAULT_SECTION_ALIGNMENT 0 /* byte (i.e. no) alignment */ ++ ++/* special section number values */ ++#define NO_SECT 0 /* no section, invalid */ ++#define MAX_SECT 255 /* maximum number of sections */ ++ ++static struct section *sects, **sectstail; ++static struct symbol *syms, **symstail; ++static unsigned long nsyms; ++ ++/* These variables are set by macho_layout_symbols() to organize ++ the symbol table and string table in order the dynamic linker ++ expects. They are then used in macho_write() to put out the ++ symbols and strings in that order. ++ ++ The order of the symbol table is: ++ local symbols ++ defined external symbols (sorted by name) ++ undefined external symbols (sorted by name) ++ ++ The order of the string table is: ++ strings for external symbols ++ strings for local symbols ++ */ ++static unsigned long ilocalsym = 0; ++static unsigned long iextdefsym = 0; ++static unsigned long iundefsym = 0; ++static unsigned long nlocalsym; ++static unsigned long nextdefsym; ++static unsigned long nundefsym; ++static struct symbol **extdefsyms = NULL; ++static struct symbol **undefsyms = NULL; ++ ++static struct RAA *extsyms; ++static struct SAA *strs; ++static unsigned long strslen; ++ ++static FILE *machofp; ++static efunc error; ++static evalfunc evaluate; ++ ++extern struct ofmt of_macho; ++ ++/* Global file information. This should be cleaned up into either ++ a structure or as function arguments. */ ++unsigned long head_ncmds = 0; ++unsigned long head_sizeofcmds = 0; ++unsigned long seg_filesize = 0; ++unsigned long seg_vmsize = 0; ++unsigned long seg_nsects = 0; ++unsigned long rel_padcnt = 0; ++ ++ ++#define xstrncpy(xdst, xsrc) \ ++ memset(xdst, '\0', sizeof(xdst)); /* zero out whole buffer */ \ ++ strncpy(xdst, xsrc, sizeof(xdst)); /* copy over string */ \ ++ xdst[sizeof(xdst) - 1] = '\0'; /* proper null-termination */ ++ ++#define align(x, y) \ ++ (((x) + (y) - 1) & ~((y) - 1)) /* align x to multiple of y */ ++ ++#define alignlong(x) \ ++ align(x, sizeof(long)) /* align x to long boundary */ ++ ++static void debug_reloc (struct reloc *); ++static void debug_section_relocs (struct section *) __attribute__ ((unused)); ++ ++static int exact_log2 (unsigned long align) { ++ if (align != (align & -align)) { ++ return -1; ++ } else { ++#ifdef __GNUC__ ++ return (align ? __builtin_ctzl (align) : 0); ++#else ++ unsigned long result = 0; ++ ++ while (align >>= 1) { ++ ++result; ++ } ++ ++ return result; ++#endif ++ } ++} ++ ++static struct section *get_section_by_name(const char *segname, ++ const char *sectname) ++{ ++ struct section *s; ++ ++ for (s = sects; s != NULL; s = s->next) ++ if (!strcmp(s->segname, segname) && !strcmp(s->sectname, sectname)) ++ break; ++ ++ return s; ++} ++ ++static struct section *get_section_by_index(const long index) ++{ ++ struct section *s; ++ ++ for (s = sects; s != NULL; s = s->next) ++ if (index == s->index) ++ break; ++ ++ return s; ++} ++ ++static long get_section_index_by_name(const char *segname, ++ const char *sectname) ++{ ++ struct section *s; ++ ++ for (s = sects; s != NULL; s = s->next) ++ if (!strcmp(s->segname, segname) && !strcmp(s->sectname, sectname)) ++ return s->index; ++ ++ return -1; ++} ++ ++static char *get_section_name_by_index(const long index) ++{ ++ struct section *s; ++ ++ for (s = sects; s != NULL; s = s->next) ++ if (index == s->index) ++ return s->sectname; ++ ++ return NULL; ++} ++ ++static unsigned char get_section_fileindex_by_index(const long index) ++{ ++ struct section *s; ++ unsigned char i = 1; ++ ++ for (s = sects; s != NULL && i < MAX_SECT; s = s->next, ++i) ++ if (index == s->index) ++ return i; ++ ++ if (i == MAX_SECT) ++ error(ERR_WARNING, ++ "too many sections (>255) - clipped by fileindex"); ++ ++ return NO_SECT; ++} ++ ++static void macho_init(FILE * fp, efunc errfunc, ldfunc ldef, ++ evalfunc eval) ++{ ++ char zero = 0; ++ ++ machofp = fp; ++ error = errfunc; ++ evaluate = eval; ++ ++ (void)ldef; /* placate optimisers */ ++ ++ sects = NULL; ++ sectstail = §s; ++ ++ syms = NULL; ++ symstail = &syms; ++ nsyms = 0; ++ nlocalsym = 0; ++ nextdefsym = 0; ++ nundefsym = 0; ++ ++ extsyms = raa_init(); ++ strs = saa_init(1L); ++ ++ /* string table starts with a zero byte - don't ask why */ ++ saa_wbytes(strs, &zero, sizeof(char)); ++ strslen = 1; ++} ++ ++static int macho_setinfo(enum geninfo type, char **val) ++{ ++ return 0; ++} ++ ++static void sect_write(struct section *sect, ++ const unsigned char *data, unsigned long len) ++{ ++ saa_wbytes(sect->data, data, len); ++ sect->size += len; ++} ++ ++static void add_reloc(struct section *sect, long section, ++ int pcrel, int bytes) ++{ ++ struct reloc *r; ++ long fi; ++ ++ /* NeXT as puts relocs in reversed order (address-wise) into the ++ ** files, so we do the same, doesn't seem to make much of a ++ ** difference either way */ ++ r = nasm_malloc(sizeof(struct reloc)); ++ r->next = sect->relocs; ++ sect->relocs = r; ++ ++ /* the current end of the section will be the symbol's address for ++ ** now, might have to be fixed by macho_fixup_relocs() later on. make ++ ** sure we don't make the symbol scattered by setting the highest ++ ** bit by accident */ ++ r->addr = sect->size & ~R_SCATTERED; ++ r->ext = 0; ++ r->pcrel = pcrel; ++ ++ /* match byte count 1, 2, 4 to length codes 0, 1, 2 respectively */ ++ r->length = bytes >> 1; ++ ++ /* vanilla relocation (GENERIC_RELOC_VANILLA) */ ++ r->type = 0; ++ ++ if (section == NO_SEG) { ++ /* absolute local symbol if no section index given */ ++ r->snum = R_ABS; ++ } else { ++ fi = get_section_fileindex_by_index(section); ++ ++ if (fi == NO_SECT) { ++ /* external symbol if no section with that index known, ++ ** symbol number was saved in macho_symdef() */ ++ r->snum = raa_read(extsyms, section); ++ r->ext = 1; ++ } else { ++ /* local symbol in section fi */ ++ r->snum = fi; ++ } ++ } ++ ++ ++sect->nreloc; ++} ++ ++static void macho_output(long secto, const void *data, unsigned long type, ++ long section, long wrt) ++{ ++ struct section *s, *sbss; ++ long realbytes = type & OUT_SIZMASK; ++ long addr; ++ unsigned char mydata[4], *p; ++ ++ type &= OUT_TYPMASK; ++ ++ if (wrt != NO_SEG) { ++ wrt = NO_SEG; ++ error(ERR_NONFATAL, "WRT not supported by Mach-O output format"); ++ /* continue to do _something_ */ ++ } ++ ++ if (secto == NO_SEG) { ++ if (type != OUT_RESERVE) ++ error(ERR_NONFATAL, "attempt to assemble code in " ++ "[ABSOLUTE] space"); ++ ++ return; ++ } ++ ++ s = get_section_by_index(secto); ++ ++ if (s == NULL) { ++ error(ERR_WARNING, "attempt to assemble code in" ++ " section %d: defaulting to `.text'", secto); ++ s = get_section_by_name("__TEXT", "__text"); ++ ++ /* should never happen */ ++ if (s == NULL) ++ error(ERR_PANIC, "text section not found"); ++ } ++ ++ sbss = get_section_by_name("__DATA", "__bss"); ++ ++ if (s == sbss && type != OUT_RESERVE) { ++ error(ERR_WARNING, "attempt to initialise memory in the" ++ " BSS section: ignored"); ++ ++ switch (type) { ++ case OUT_REL2ADR: ++ realbytes = 2; ++ break; ++ ++ case OUT_REL4ADR: ++ realbytes = 4; ++ break; ++ ++ default: ++ break; ++ } ++ ++ s->size += realbytes; ++ return; ++ } ++ ++ switch (type) { ++ case OUT_RESERVE: ++ if (s != sbss) { ++ error(ERR_WARNING, "uninitialised space declared in" ++ " %s section: zeroing", ++ get_section_name_by_index(secto)); ++ ++ sect_write(s, NULL, realbytes); ++ } else ++ s->size += realbytes; ++ ++ break; ++ ++ case OUT_RAWDATA: ++ if (section != NO_SEG) ++ error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG"); ++ ++ sect_write(s, data, realbytes); ++ break; ++ ++ case OUT_ADDRESS: ++ addr = *(long *)data; ++ ++ if (section != NO_SEG) { ++ if (section % 2) { ++ error(ERR_NONFATAL, "Mach-O format does not support" ++ " section base references"); ++ } else ++ add_reloc(s, section, 0, realbytes); ++ } ++ ++ p = mydata; ++ ++ if (realbytes == 2) ++ WRITESHORT(p, addr); ++ else ++ WRITELONG(p, addr); ++ ++ sect_write(s, mydata, realbytes); ++ break; ++ ++ case OUT_REL2ADR: ++ if (section == secto) ++ error(ERR_PANIC, "intra-section OUT_REL2ADR"); ++ ++ if (section != NO_SEG && section % 2) { ++ error(ERR_NONFATAL, "Mach-O format does not support" ++ " section base references"); ++ } else ++ add_reloc(s, section, 1, 2); ++ ++ p = mydata; ++ WRITESHORT(p, *(long *)data - (realbytes + s->size)); ++ sect_write(s, mydata, 2L); ++ break; ++ ++ case OUT_REL4ADR: ++ if (section == secto) ++ error(ERR_PANIC, "intra-section OUT_REL4ADR"); ++ ++ if (section != NO_SEG && section % 2) { ++ error(ERR_NONFATAL, "Mach-O format does not support" ++ " section base references"); ++ } else ++ add_reloc(s, section, 1, 4); ++ ++ p = mydata; ++ WRITELONG(p, *(long *)data - (realbytes + s->size)); ++ sect_write(s, mydata, 4L); ++ break; ++ ++ default: ++ error(ERR_PANIC, "unknown output type?"); ++ break; ++ } ++} ++ ++static long macho_section(char *name, int pass, int *bits) ++{ ++ long index, originalIndex; ++ char *sectionAttributes; ++ struct sectmap *sm; ++ struct section *s; ++ ++ /* Default to 32 bits. */ ++ if (!name) { ++ *bits = 32; ++ name = ".text"; ++ sectionAttributes = NULL; ++ } else { ++ sectionAttributes = name; ++ name = strsep(§ionAttributes, " \t"); ++ } ++ ++ for (sm = sectmap; sm->nasmsect != NULL; ++sm) { ++ /* make lookup into section name translation table */ ++ if (!strcmp(name, sm->nasmsect)) { ++ char *currentAttribute; ++ ++ /* try to find section with that name */ ++ originalIndex = index = get_section_index_by_name(sm->segname, ++ sm->sectname); ++ ++ /* create it if it doesn't exist yet */ ++ if (index == -1) { ++ s = *sectstail = nasm_malloc(sizeof(struct section)); ++ s->next = NULL; ++ sectstail = &s->next; ++ ++ s->data = saa_init(1L); ++ s->index = seg_alloc(); ++ s->relocs = NULL; ++ s->align = DEFAULT_SECTION_ALIGNMENT; ++ ++ xstrncpy(s->segname, sm->segname); ++ xstrncpy(s->sectname, sm->sectname); ++ s->size = 0; ++ s->nreloc = 0; ++ s->flags = sm->flags; ++ ++ index = s->index; ++ } else { ++ s = get_section_by_index(index); ++ } ++ ++ while ((NULL != sectionAttributes) ++ && (currentAttribute = strsep(§ionAttributes, " \t"))) { ++ if (0 != *currentAttribute) { ++ if (0 == strncasecmp("align=", currentAttribute, 6)) { ++ char *end; ++ int newAlignment, value; ++ ++ value = strtoul(currentAttribute + 6, &end, 0); ++ newAlignment = exact_log2(value); ++ ++ if (0 != *end) { ++ error(ERR_PANIC, ++ "unknown or missing alignment value \"%s\" " ++ "specified for section \"%s\"", ++ currentAttribute + 6, ++ name); ++ return NO_SEG; ++ } else if (0 > newAlignment) { ++ error(ERR_PANIC, ++ "alignment of %d (for section \"%s\") is not " ++ "a power of two", ++ value, ++ name); ++ return NO_SEG; ++ } ++ ++ if ((-1 != originalIndex) ++ && (s->align != newAlignment)) { ++ error(ERR_PANIC, ++ "section \"%s\" has already been specified " ++ "with alignment %d, conflicts with new " ++ "alignment of %d", ++ name, ++ (1 << s->align), ++ value); ++ return NO_SEG; ++ } ++ ++ s->align = newAlignment; ++ } else if (0 == strcasecmp("data", currentAttribute)) { ++ /* Do nothing; 'data' is implicit */ ++ } else { ++ error(ERR_PANIC, ++ "unknown section attribute %s for section %s", ++ currentAttribute, ++ name); ++ return NO_SEG; ++ } ++ } ++ } ++ ++ return index; ++ } ++ } ++ ++ error(ERR_PANIC, "invalid section name %s", name); ++ return NO_SEG; ++} ++ ++static void macho_symdef(char *name, long section, long offset, ++ int is_global, char *special) ++{ ++ struct symbol *sym; ++ ++ if (special) { ++ error(ERR_NONFATAL, "The Mach-O output format does " ++ "not support any special symbol types"); ++ return; ++ } ++ ++ if (is_global == 3) { ++ error(ERR_NONFATAL, "The Mach-O format does not " ++ "(yet) support forward reference fixups."); ++ return; ++ } ++ ++ sym = *symstail = nasm_malloc(sizeof(struct symbol)); ++ sym->next = NULL; ++ symstail = &sym->next; ++ ++ sym->name = name; ++ sym->strx = strslen; ++ sym->type = 0; ++ sym->desc = 0; ++ sym->value = offset; ++ sym->initial_snum = -1; ++ ++ /* external and common symbols get N_EXT */ ++ if (is_global != 0) ++ sym->type |= N_EXT; ++ ++ if (section == NO_SEG) { ++ /* symbols in no section get absolute */ ++ sym->type |= N_ABS; ++ sym->sect = NO_SECT; ++ } else { ++ sym->type |= N_SECT; ++ ++ /* get the in-file index of the section the symbol was defined in */ ++ sym->sect = get_section_fileindex_by_index(section); ++ ++ if (sym->sect == NO_SECT) { ++ /* remember symbol number of references to external ++ ** symbols, this works because every external symbol gets ++ ** its own section number allocated internally by nasm and ++ ** can so be used as a key */ ++ extsyms = raa_write(extsyms, section, nsyms); ++ sym->initial_snum = nsyms; ++ ++ switch (is_global) { ++ case 1: ++ case 2: ++ /* there isn't actually a difference between global ++ ** and common symbols, both even have their size in ++ ** sym->value */ ++ sym->type = N_EXT; ++ break; ++ ++ default: ++ /* give an error on unfound section if it's not an ++ ** external or common symbol (assemble_file() does a ++ ** seg_alloc() on every call for them) */ ++ error(ERR_PANIC, "in-file index for section %d not found", ++ section); ++ } ++ } ++ } ++ ++ ++nsyms; ++} ++ ++static long macho_segbase(long section) ++{ ++ return section; ++} ++ ++static int macho_directive(char *directive, char *value, int pass) ++{ ++ return 0; ++} ++ ++static void macho_filename(char *inname, char *outname, efunc error) ++{ ++ standard_extension(inname, outname, ".o", error); ++} ++ ++static const char *macho_stdmac[] = { ++ "%define __SECT__ [section .text]", ++ "%macro __NASM_CDecl__ 1", ++ "%endmacro", ++ NULL ++}; ++ ++/* Comparison function for qsort symbol layout. */ ++static int layout_compare (const struct symbol **s1, ++ const struct symbol **s2) ++{ ++ return (strcmp ((*s1)->name, (*s2)->name)); ++} ++ ++/* The native assembler does a few things in a similar function ++ ++ * Remove temporary labels ++ * Sort symbols according to local, external, undefined (by name) ++ * Order the string table ++ ++ We do not remove temporary labels right now. ++ ++ numsyms is the total number of symbols we have. strtabsize is the ++ number entries in the string table. */ ++ ++static void macho_layout_symbols (unsigned long *numsyms, ++ unsigned long *strtabsize) ++{ ++ struct symbol *sym, **symp; ++ unsigned long i,j; ++ ++ *numsyms = 0; ++ *strtabsize = sizeof (char); ++ ++ symp = &syms; ++ ++ while ((sym = *symp)) { ++ /* Undefined symbols are now external. */ ++ if (sym->type == N_UNDF) ++ sym->type |= N_EXT; ++ ++ if ((sym->type & N_EXT) == 0) { ++ sym->snum = *numsyms; ++ *numsyms = *numsyms + 1; ++ nlocalsym++; ++ } ++ else { ++ if ((sym->type & N_TYPE) != N_UNDF) ++ nextdefsym++; ++ else ++ nundefsym++; ++ ++ /* If we handle debug info we'll want ++ to check for it here instead of just ++ adding the symbol to the string table. */ ++ sym->strx = *strtabsize; ++ saa_wbytes (strs, sym->name, (long)(strlen(sym->name) + 1)); ++ *strtabsize += strlen(sym->name) + 1; ++ } ++ symp = &(sym->next); ++ } ++ ++ /* Next, sort the symbols. Most of this code is a direct translation from ++ the Apple cctools symbol layout. We need to keep compatibility with that. */ ++ /* Set the indexes for symbol groups into the symbol table */ ++ ilocalsym = 0; ++ iextdefsym = nlocalsym; ++ iundefsym = nlocalsym + nextdefsym; ++ ++ /* allocate arrays for sorting externals by name */ ++ extdefsyms = nasm_malloc(nextdefsym * sizeof(struct symbol *)); ++ undefsyms = nasm_malloc(nundefsym * sizeof(struct symbol *)); ++ ++ i = 0; ++ j = 0; ++ ++ symp = &syms; ++ ++ while ((sym = *symp)) { ++ ++ if((sym->type & N_EXT) == 0) { ++ sym->strx = *strtabsize; ++ saa_wbytes (strs, sym->name, (long)(strlen (sym->name) + 1)); ++ *strtabsize += strlen(sym->name) + 1; ++ } ++ else { ++ if((sym->type & N_TYPE) != N_UNDF) ++ extdefsyms[i++] = sym; ++ else ++ undefsyms[j++] = sym; ++ } ++ symp = &(sym->next); ++ } ++ ++ qsort(extdefsyms, nextdefsym, sizeof(struct symbol *), ++ (int (*)(const void *, const void *))layout_compare); ++ qsort(undefsyms, nundefsym, sizeof(struct symbol *), ++ (int (*)(const void *, const void *))layout_compare); ++ ++ for(i = 0; i < nextdefsym; i++) { ++ extdefsyms[i]->snum = *numsyms; ++ *numsyms += 1; ++ } ++ for(j = 0; j < nundefsym; j++) { ++ undefsyms[j]->snum = *numsyms; ++ *numsyms += 1; ++ } ++} ++ ++/* Calculate some values we'll need for writing later. */ ++ ++static void macho_calculate_sizes (void) ++{ ++ struct section *s; ++ ++ /* count sections and calculate in-memory and in-file offsets */ ++ for (s = sects; s != NULL; s = s->next) { ++ /* zerofill sections aren't actually written to the file */ ++ if ((s->flags & SECTION_TYPE) != S_ZEROFILL) ++ seg_filesize += s->size; ++ ++ seg_vmsize += s->size; ++ ++seg_nsects; ++ } ++ ++ /* calculate size of all headers, load commands and sections to ++ ** get a pointer to the start of all the raw data */ ++ if (seg_nsects > 0) { ++ ++head_ncmds; ++ head_sizeofcmds += ++ MACHO_SEGCMD_SIZE + seg_nsects * MACHO_SECTCMD_SIZE; ++ } ++ ++ if (nsyms > 0) { ++ ++head_ncmds; ++ head_sizeofcmds += MACHO_SYMCMD_SIZE; ++ } ++} ++ ++/* Write out the header information for the file. */ ++ ++static void macho_write_header (void) ++{ ++ fwritelong(MH_MAGIC, machofp); /* magic */ ++ fwritelong(CPU_TYPE_I386, machofp); /* CPU type */ ++ fwritelong(CPU_SUBTYPE_I386_ALL, machofp); /* CPU subtype */ ++ fwritelong(MH_OBJECT, machofp); /* Mach-O file type */ ++ fwritelong(head_ncmds, machofp); /* number of load commands */ ++ fwritelong(head_sizeofcmds, machofp); /* size of load commands */ ++ fwritelong(0, machofp); /* no flags */ ++} ++ ++/* Write out the segment load command at offset. */ ++ ++static unsigned long macho_write_segment (unsigned long offset) ++{ ++ unsigned long s_addr = 0; ++ unsigned long rel_base = alignlong (offset + seg_filesize); ++ unsigned long s_reloff = 0; ++ struct section *s; ++ ++ fwritelong(LC_SEGMENT, machofp); /* cmd == LC_SEGMENT */ ++ ++ /* size of load command including section load commands */ ++ fwritelong(MACHO_SEGCMD_SIZE + seg_nsects * ++ MACHO_SECTCMD_SIZE, machofp); ++ ++ /* in an MH_OBJECT file all sections are in one unnamed (name ++ ** all zeros) segment */ ++ fwrite("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16, 1, machofp); ++ fwritelong(0, machofp); /* in-memory offset */ ++ fwritelong(seg_vmsize, machofp); /* in-memory size */ ++ fwritelong(offset, machofp); /* in-file offset to data */ ++ fwritelong(seg_filesize, machofp); /* in-file size */ ++ fwritelong(VM_PROT_DEFAULT, machofp); /* maximum vm protection */ ++ fwritelong(VM_PROT_DEFAULT, machofp); /* initial vm protection */ ++ fwritelong(seg_nsects, machofp); /* number of sections */ ++ fwritelong(0, machofp); /* no flags */ ++ ++ /* emit section headers */ ++ for (s = sects; s != NULL; s = s->next) { ++ fwrite(s->sectname, sizeof(s->sectname), 1, machofp); ++ fwrite(s->segname, sizeof(s->segname), 1, machofp); ++ fwritelong(s_addr, machofp); ++ fwritelong(s->size, machofp); ++ ++ /* dummy data for zerofill sections or proper values */ ++ if ((s->flags & SECTION_TYPE) != S_ZEROFILL) { ++ fwritelong(offset, machofp); ++ /* Write out section alignment, as a power of two. ++ e.g. 32-bit word alignment would be 2 (2^^2 = 4). */ ++ fwritelong(s->align, machofp); ++ /* To be compatible with cctools as we emit ++ a zero reloff if we have no relocations. */ ++ fwritelong(s->nreloc ? rel_base + s_reloff : 0, machofp); ++ fwritelong(s->nreloc, machofp); ++ ++ offset += s->size; ++ s_reloff += s->nreloc * MACHO_RELINFO_SIZE; ++ } else { ++ fwritelong(0, machofp); ++ fwritelong(0, machofp); ++ fwritelong(0, machofp); ++ fwritelong(0, machofp); ++ } ++ ++ fwritelong(s->flags, machofp); /* flags */ ++ fwritelong(0, machofp); /* reserved */ ++ fwritelong(0, machofp); /* reserved */ ++ ++ s_addr += s->size; ++ } ++ ++ rel_padcnt = rel_base - offset; ++ offset = rel_base + s_reloff; ++ ++ return offset; ++} ++ ++/* For a given chain of relocs r, write out the entire relocation ++ chain to the object file. */ ++ ++static void macho_write_relocs (struct reloc *r) ++{ ++ while (r) { ++ unsigned long word2; ++ ++ fwritelong(r->addr, machofp); /* reloc offset */ ++ ++ word2 = r->snum; ++ word2 |= r->pcrel << 24; ++ word2 |= r->length << 25; ++ word2 |= r->ext << 27; ++ word2 |= r->type << 28; ++ fwritelong(word2, machofp); /* reloc data */ ++ ++ r = r->next; ++ } ++} ++ ++/* Write out the section data. */ ++static void macho_write_section (void) ++{ ++ struct section *s, *s2; ++ struct reloc *r; ++ char *rel_paddata = "\0\0\0"; ++ unsigned char fi, *p, *q, blk[4]; ++ long l; ++ ++ for (s = sects; s != NULL; s = s->next) { ++ if ((s->flags & SECTION_TYPE) == S_ZEROFILL) ++ continue; ++ ++ /* no padding needs to be done to the sections */ ++ ++ /* Like a.out Mach-O references things in the data or bss ++ * sections by addresses which are actually relative to the ++ * start of the _text_ section, in the _file_. See outaout.c ++ * for more information. */ ++ saa_rewind(s->data); ++ for (r = s->relocs; r != NULL; r = r->next) { ++ saa_fread(s->data, r->addr, blk, (long)r->length << 1); ++ p = q = blk; ++ l = *p++; ++ ++ /* get offset based on relocation type */ ++ if (r->length > 0) { ++ l += ((long)*p++) << 8; ++ ++ if (r->length == 2) { ++ l += ((long)*p++) << 16; ++ l += ((long)*p++) << 24; ++ } ++ } ++ ++ /* If the relocation is internal add to the current section ++ offset. Otherwise the only value we need is the symbol ++ offset which we already have. The linker takes care ++ of the rest of the address. */ ++ if (!r->ext) { ++ /* add sizes of previous sections to current offset */ ++ for (s2 = sects, fi = 1; ++ s2 != NULL && fi < r->snum; s2 = s2->next, fi++) ++ if ((s2->flags & SECTION_TYPE) != S_ZEROFILL) ++ l += s2->size; ++ } ++ ++ /* write new offset back */ ++ if (r->length == 2) ++ WRITELONG(q, l); ++ else if (r->length == 1) ++ WRITESHORT(q, l); ++ else ++ *q++ = l & 0xFF; ++ ++ saa_fwrite(s->data, r->addr, blk, (long)r->length << 1); ++ } ++ ++ /* dump the section data to file */ ++ saa_fpwrite(s->data, machofp); ++ } ++ ++ /* pad last section up to reloc entries on long boundary */ ++ fwrite(rel_paddata, rel_padcnt, 1, machofp); ++ ++ /* emit relocation entries */ ++ for (s = sects; s != NULL; s = s->next) ++ macho_write_relocs (s->relocs); ++} ++ ++/* Write out the symbol table. We should already have sorted this ++ before now. */ ++static void macho_write_symtab (void) ++{ ++ struct symbol *sym; ++ struct section *s; ++ long fi; ++ long i; ++ ++ /* we don't need to pad here since MACHO_RELINFO_SIZE == 8 */ ++ ++ for (sym = syms; sym != NULL; sym = sym->next) { ++ if ((sym->type & N_EXT) == 0) { ++ fwritelong(sym->strx, machofp); /* string table entry number */ ++ fwrite(&sym->type, 1, 1, machofp); /* symbol type */ ++ fwrite(&sym->sect, 1, 1, machofp); /* section */ ++ fwriteshort(sym->desc, machofp); /* description */ ++ ++ /* Fix up the symbol value now that we know the final section ++ sizes. */ ++ if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) { ++ for (s = sects, fi = 1; ++ s != NULL && fi < sym->sect; s = s->next, ++fi) ++ sym->value += s->size; ++ } ++ ++ fwritelong(sym->value, machofp); /* value (i.e. offset) */ ++ } ++ } ++ ++ for (i = 0; i < nextdefsym; i++) { ++ sym = extdefsyms[i]; ++ fwritelong(sym->strx, machofp); ++ fwrite(&sym->type, 1, 1, machofp); /* symbol type */ ++ fwrite(&sym->sect, 1, 1, machofp); /* section */ ++ fwriteshort(sym->desc, machofp); /* description */ ++ ++ /* Fix up the symbol value now that we know the final section ++ sizes. */ ++ if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) { ++ for (s = sects, fi = 1; ++ s != NULL && fi < sym->sect; s = s->next, ++fi) ++ sym->value += s->size; ++ } ++ ++ fwritelong(sym->value, machofp); /* value (i.e. offset) */ ++ } ++ ++ for (i = 0; i < nundefsym; i++) { ++ sym = undefsyms[i]; ++ fwritelong(sym->strx, machofp); ++ fwrite(&sym->type, 1, 1, machofp); /* symbol type */ ++ fwrite(&sym->sect, 1, 1, machofp); /* section */ ++ fwriteshort(sym->desc, machofp); /* description */ ++ ++ /* Fix up the symbol value now that we know the final section ++ sizes. */ ++ if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) { ++ for (s = sects, fi = 1; ++ s != NULL && fi < sym->sect; s = s->next, ++fi) ++ sym->value += s->size; ++ } ++ ++ fwritelong(sym->value, machofp); /* value (i.e. offset) */ ++ } ++} ++ ++/* Fixup the snum in the relocation entries, we should be ++ doing this only for externally undefined symbols. */ ++static void macho_fixup_relocs (struct reloc *r) ++{ ++ struct symbol *sym; ++ int i; ++ ++ while (r != NULL) { ++ if (r->ext) { ++ for (i = 0; i < nundefsym; i++) { ++ sym = undefsyms[i]; ++ if (sym->initial_snum == r->snum) { ++ r->snum = sym->snum; ++ } ++ } ++ } ++ r = r->next; ++ } ++} ++ ++/* Write out the object file. */ ++ ++static void macho_write (void) ++{ ++ unsigned long offset = 0; ++ ++ /* mach-o object file structure: ++ ** ++ ** mach header ++ ** ulong magic ++ ** int cpu type ++ ** int cpu subtype ++ ** ulong mach file type ++ ** ulong number of load commands ++ ** ulong size of all load commands ++ ** (includes section struct size of segment command) ++ ** ulong flags ++ ** ++ ** segment command ++ ** ulong command type == LC_SEGMENT ++ ** ulong size of load command ++ ** (including section load commands) ++ ** char[16] segment name ++ ** ulong in-memory offset ++ ** ulong in-memory size ++ ** ulong in-file offset to data area ++ ** ulong in-file size ++ ** (in-memory size excluding zerofill sections) ++ ** int maximum vm protection ++ ** int initial vm protection ++ ** ulong number of sections ++ ** ulong flags ++ ** ++ ** section commands ++ ** char[16] section name ++ ** char[16] segment name ++ ** ulong in-memory offset ++ ** ulong in-memory size ++ ** ulong in-file offset ++ ** ulong alignment ++ ** (irrelevant in MH_OBJECT) ++ ** ulong in-file offset of relocation entires ++ ** ulong number of relocations ++ ** ulong flags ++ ** ulong reserved ++ ** ulong reserved ++ ** ++ ** symbol table command ++ ** ulong command type == LC_SYMTAB ++ ** ulong size of load command ++ ** ulong symbol table offset ++ ** ulong number of symbol table entries ++ ** ulong string table offset ++ ** ulong string table size ++ ** ++ ** raw section data ++ ** ++ ** padding to long boundary ++ ** ++ ** relocation data (struct reloc) ++ ** long offset ++ ** uint data (symbolnum, pcrel, length, extern, type) ++ ** ++ ** symbol table data (struct nlist) ++ ** long string table entry number ++ ** uchar type ++ ** (extern, absolute, defined in section) ++ ** uchar section ++ ** (0 for global symbols, section number of definition (>= 1, <= ++ ** 254) for local symbols, size of variable for common symbols ++ ** [type == extern]) ++ ** short description ++ ** (for stab debugging format) ++ ** ulong value (i.e. file offset) of symbol or stab offset ++ ** ++ ** string table data ++ ** list of null-terminated strings ++ */ ++ ++ /* Emit the Mach-O header. */ ++ macho_write_header(); ++ ++ offset = MACHO_HEADER_SIZE + head_sizeofcmds; ++ ++ /* emit the segment load command */ ++ if (seg_nsects > 0) ++ offset = macho_write_segment (offset); ++ else ++ error(ERR_WARNING, "no sections?"); ++ ++ if (nsyms > 0) { ++ /* write out symbol command */ ++ fwritelong(LC_SYMTAB, machofp); /* cmd == LC_SYMTAB */ ++ fwritelong(MACHO_SYMCMD_SIZE, machofp); /* size of load command */ ++ fwritelong(offset, machofp); /* symbol table offset */ ++ fwritelong(nsyms, machofp); /* number of symbol ++ ** table entries */ ++ ++ offset += nsyms * MACHO_NLIST_SIZE; ++ fwritelong(offset, machofp); /* string table offset */ ++ fwritelong(strslen, machofp); /* string table size */ ++ } ++ ++ /* emit section data */ ++ if (seg_nsects > 0) ++ macho_write_section (); ++ ++ /* emit symbol table if we have symbols */ ++ if (nsyms > 0) ++ macho_write_symtab (); ++ ++ /* we don't need to pad here since MACHO_NLIST_SIZE == 12 */ ++ ++ /* emit string table */ ++ saa_fpwrite(strs, machofp); ++} ++/* We do quite a bit here, starting with finalizing all of the data ++ for the object file, writing, and then freeing all of the data from ++ the file. */ ++ ++static void macho_cleanup(int debuginfo) ++{ ++ struct section *s; ++ struct reloc *r; ++ struct symbol *sym; ++ ++ (void)debuginfo; ++ ++ /* Sort all symbols. */ ++ macho_layout_symbols (&nsyms, &strslen); ++ ++ /* Fixup relocation entries */ ++ for (s = sects; s != NULL; s = s->next) { ++ macho_fixup_relocs (s->relocs); ++ } ++ ++ /* First calculate and finalize needed values. */ ++ macho_calculate_sizes(); ++ macho_write(); ++ ++ /* done - yay! */ ++ fclose(machofp); ++ ++ /* free up everything */ ++ while (sects->next) { ++ s = sects; ++ sects = sects->next; ++ ++ saa_free(s->data); ++ while (s->relocs != NULL) { ++ r = s->relocs; ++ s->relocs = s->relocs->next; ++ nasm_free(r); ++ } ++ ++ nasm_free(s); ++ } ++ ++ saa_free(strs); ++ raa_free(extsyms); ++ ++ if (syms) { ++ while (syms->next) { ++ sym = syms; ++ syms = syms->next; ++ ++ nasm_free (sym); ++ } ++ } ++} ++ ++/* Debugging routines. */ ++static void debug_reloc (struct reloc *r) ++{ ++ fprintf (stdout, "reloc:\n"); ++ fprintf (stdout, "\taddr: %ld\n", r->addr); ++ fprintf (stdout, "\tsnum: %d\n", r->snum); ++ fprintf (stdout, "\tpcrel: %d\n", r->pcrel); ++ fprintf (stdout, "\tlength: %d\n", r->length); ++ fprintf (stdout, "\text: %d\n", r->ext); ++ fprintf (stdout, "\ttype: %d\n", r->type); ++} ++ ++static void debug_section_relocs (struct section *s) ++{ ++ struct reloc *r = s->relocs; ++ ++ fprintf (stdout, "relocs for section %s:\n\n", s->sectname); ++ ++ while (r != NULL) { ++ debug_reloc (r); ++ r = r->next; ++ } ++} ++ ++struct ofmt of_macho = { ++ "NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X object files", ++ "macho", ++ NULL, ++ null_debug_arr, ++ &null_debug_form, ++ macho_stdmac, ++ macho_init, ++ macho_setinfo, ++ macho_output, ++ macho_symdef, ++ macho_section, ++ macho_segbase, ++ macho_directive, ++ macho_filename, ++ macho_cleanup ++}; ++ ++#endif ++ ++/* ++ * Local Variables: ++ * mode:c ++ * c-basic-offset:4 ++ * End: ++ * ++ * end of file */ diff --git a/devel/nasm/patches/patch-ae b/devel/nasm/patches/patch-ae new file mode 100644 index 00000000000..2046e5058ca --- /dev/null +++ b/devel/nasm/patches/patch-ae @@ -0,0 +1,61 @@ +$NetBSD: patch-ae,v 1.3 2007/01/06 15:11:58 jmmv Exp $ + +--- outform.h.orig 2005-01-15 23:15:51.000000000 +0100 ++++ outform.h +@@ -57,7 +57,7 @@ + + /* ====configurable info begins here==== */ + /* formats configurable: +- * bin,obj,elf,aout,aoutb,coff,win32,as86,rdf2 */ ++ * bin,obj,elf,aout,aoutb,coff,win32,as86,rdf2,macho */ + + /* process options... */ + +@@ -98,6 +98,9 @@ + #ifndef OF_IEEE + #define OF_IEEE + #endif ++#ifndef OF_MACHO ++#define OF_MACHO ++#endif + #endif /* OF_ALL */ + + /* turn on groups of formats specified.... */ +@@ -141,6 +144,9 @@ + #ifndef OF_IEEE + #define OF_IEEE + #endif ++#ifndef OF_MACHO ++#define OF_MACHO ++#endif + #endif + + /* finally... override any format specifically specified to be off */ +@@ -174,6 +180,9 @@ + #ifdef OF_NO_IEEE + #undef OF_IEEE + #endif ++#ifdef OF_NO_MACHO ++#undef OF_MACHO ++#endif + + #ifndef OF_DEFAULT + #define OF_DEFAULT of_bin +@@ -194,6 +203,7 @@ extern struct ofmt of_obj; + extern struct ofmt of_win32; + extern struct ofmt of_rdf2; + extern struct ofmt of_ieee; ++extern struct ofmt of_macho; + extern struct ofmt of_dbg; + + struct ofmt *drivers[] = { +@@ -227,6 +237,9 @@ struct ofmt *drivers[] = { + #ifdef OF_IEEE + &of_ieee, + #endif ++#ifdef OF_MACHO ++ &of_macho, ++#endif + #ifdef OF_DBG + &of_dbg, + #endif |