diff options
author | Keith Kanios <keith@kanios.net> | 2009-07-07 23:55:03 -0500 |
---|---|---|
committer | Keith Kanios <keith@kanios.net> | 2009-07-07 23:55:03 -0500 |
commit | fabb245a364fbc071f4ac3ae7aaf90a190892e44 (patch) | |
tree | 2c782650c7f5640d684504a70b522016b0cb132f | |
parent | f6131ee4954086a19c34de9c761d4618017d7b84 (diff) | |
download | nasm-fabb245a364fbc071f4ac3ae7aaf90a190892e44.tar.gz |
Push files missed during last commit.
59 files changed, 7354 insertions, 0 deletions
diff --git a/headers/c b/headers/c new file mode 100644 index 00000000..31157c44 --- /dev/null +++ b/headers/c @@ -0,0 +1,33 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 1996-2009 The NASM Authors - All Rights Reserved + * See the file AUTHORS included with the NASM distribution for + * the specific copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following + * conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ----------------------------------------------------------------------- */ + diff --git a/headers/doc b/headers/doc new file mode 100644 index 00000000..38ab1332 --- /dev/null +++ b/headers/doc @@ -0,0 +1,33 @@ +\# -------------------------------------------------------------------------- +\# +\# Copyright 1996-2009 The NASM Authors - All Rights Reserved +\# See the file AUTHORS included with the NASM distribution for +\# the specific copyright holders. +\# +\# Redistribution and use in source and binary forms, with or without +\# modification, are permitted provided that the following +\# conditions are met: +\# +\# * Redistributions of source code must retain the above copyright +\# notice, this list of conditions and the following disclaimer. +\# * Redistributions in binary form must reproduce the above +\# copyright notice, this list of conditions and the following +\# disclaimer in the documentation and/or other materials provided +\# with the distribution. +\# +\# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +\# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +\# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +\# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +\# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +\# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +\# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +\# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +\# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +\# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +\# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +\# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +\# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\# +\# -------------------------------------------------------------------------- + diff --git a/headers/mac b/headers/mac new file mode 100644 index 00000000..b68288f6 --- /dev/null +++ b/headers/mac @@ -0,0 +1,33 @@ +;; -------------------------------------------------------------------------- +;; +;; Copyright 1996-2009 The NASM Authors - All Rights Reserved +;; See the file AUTHORS included with the NASM distribution for +;; the specific copyright holders. +;; +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following +;; conditions are met: +;; +;; * Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; * Redistributions in binary form must reproduce the above +;; copyright notice, this list of conditions and the following +;; disclaimer in the documentation and/or other materials provided +;; with the distribution. +;; +;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +;; CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +;; INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +;; MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +;; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +;; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +;; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +;; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +;; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +;; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +;; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +;; EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;; +;; -------------------------------------------------------------------------- + diff --git a/headers/perl b/headers/perl new file mode 100644 index 00000000..23170882 --- /dev/null +++ b/headers/perl @@ -0,0 +1,33 @@ +## -------------------------------------------------------------------------- +## +## Copyright 1996-2009 The NASM Authors - All Rights Reserved +## See the file AUTHORS included with the NASM distribution for +## the specific copyright holders. +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following +## conditions are met: +## +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above +## copyright notice, this list of conditions and the following +## disclaimer in the documentation and/or other materials provided +## with the distribution. +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +## CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +## INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +## DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +## NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +## LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +## OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +## EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +## +## -------------------------------------------------------------------------- + diff --git a/misc/genfma.pl b/misc/genfma.pl new file mode 100755 index 00000000..2b6a65c5 --- /dev/null +++ b/misc/genfma.pl @@ -0,0 +1,63 @@ +#!/usr/bin/perl +%packed_insns = ( + 'vfmadd' => 0x98, + 'vfmaddsub' => 0x96, + 'vfmsubadd' => 0x97, + 'vfmsub' => 0x9a, + 'vfnmadd' => 0x9c, + 'vfnmsub' => 0x9e + ); + +%scalar_insns = ( + 'vfmadd' => 0x99, + 'vfmsub' => 0x9b, + 'vfnmadd' => 0x9d, + 'vfnmsub' => 0x9f + ); + +foreach $pi ( sort(keys(%packed_insns)) ) { + $op = $packed_insns{$pi}; + foreach $order ('132', '213', '231') { + $xorder = substr($order,1,1).substr($order,0,1).substr($order,2,1); + foreach $o ($order, $xorder) { + for ($w = 0; $w < 2; $w++) { + $suf = $w ? 'pd' : 'ps'; + for ($l = 128; $l <= 256; $l <<= 1) { + $sx = ($l == 256) ? 'SY' : 'SO'; + $mm = ($l == 256) ? 'ymm' : 'xmm'; + printf "%-15s %-31s %-8s%-39s %s\n", + "\U${pi}${o}${suf}", + "${mm}reg,${mm}reg,${mm}rm", + "[rvm:", + sprintf("vex.dds.%d.66.0f38.w%d %02x /r]", + $l, $w, $op), + "FMA,FUTURE,${sx}"; + } + } + } + $op += 0x10; + } +} + +foreach $si ( sort(keys(%scalar_insns)) ) { + $op = $scalar_insns{$si}; + foreach $order ('132', '213', '231') { + $xorder = substr($order,1,1).substr($order,0,1).substr($order,2,1); + foreach $o ($order, $xorder) { + for ($w = 0; $w < 2; $w++) { + $suf = $w ? 'sd' : 'ss'; + $sx = $w ? 'SQ' : 'SD'; + $l = 128; + $mm = 'xmm'; + printf "%-15s %-31s %-8s%-39s %s\n", + "\U${si}${o}${suf}", + "${mm}reg,${mm}reg,${mm}rm", + '[rvm:', + sprintf("vex.dds.%d.66.0f38.w%d %02x /r]", + $l, $w, $op), + "FMA,FUTURE,${sx}"; + } + } + $op += 0x10; + } +} diff --git a/misc/omfdump.c b/misc/omfdump.c new file mode 100644 index 00000000..322971e9 --- /dev/null +++ b/misc/omfdump.c @@ -0,0 +1,223 @@ +/* + * omfdump.c + * + * Very simple program to dump the contents of an OMF (OBJ) file + * + * This assumes a littleendian, unaligned-load-capable host and a + * C compiler which handles basic C99. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <inttypes.h> +#include <ctype.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/mman.h> +#include <sys/stat.h> + +const char *progname; + +static const char *record_types[256] = +{ + [0x80] = "THEADR", + [0x82] = "LHEADR", + [0x88] = "COMENT", + [0x8a] = "MODEND16", + [0x8b] = "MODEND32", + [0x8c] = "EXTDEF", + [0x90] = "PUBDEF16", + [0x91] = "PUBDEF32", + [0x94] = "LINNUM16", + [0x95] = "LINNUM32", + [0x96] = "LNAMES", + [0x98] = "SEGDEF16", + [0x99] = "SEGDEF32", + [0x9a] = "GRPDEF", + [0x9c] = "FIXUPP16", + [0x9d] = "FIXUPP32", + [0xa0] = "LEDATA16", + [0xa1] = "LEDATA32", + [0xa2] = "LIDATA16", + [0xa3] = "LIDATA32", + [0xb0] = "COMDEF", + [0xb2] = "BAKPAT16", + [0xb3] = "BAKPAT32", + [0xb4] = "LEXTDEF", + [0xb6] = "LPUBDEF16", + [0xb7] = "LPUBDEF32", + [0xb8] = "LCOMDEF", + [0xbc] = "CEXTDEF", + [0xc2] = "COMDAT16", + [0xc3] = "COMDAT32", + [0xc4] = "LINSYM16", + [0xc5] = "LINSYM32", + [0xc6] = "ALIAS", + [0xc8] = "NBKPAT16", + [0xc9] = "NBKPAT32", + [0xca] = "LLNAMES", + [0xcc] = "VERNUM", + [0xce] = "VENDEXT", + [0xf0] = "LIBHDR", + [0xf1] = "LIBEND", +}; + +typedef void (*dump_func)(uint8_t, const uint8_t *, size_t); + +static void hexdump_data(unsigned int offset, const uint8_t *data, size_t n) +{ + unsigned int i, j; + + for (i = 0; i < n; i += 16) { + printf(" %04x: ", i+offset); + for (j = 0; j < 16; j++) { + if (i+j < n) + printf("%02x%c", data[i+j], (j == 7) ? '-' : ' '); + else + printf(" "); + } + printf(" : "); + for (j = 0; j < 16; j++) { + if (i+j < n) + putchar(isprint(data[i+j]) ? data[i+j] : '.'); + } + putchar('\n'); + } +} + +static void dump_unknown(uint8_t type, const uint8_t *data, size_t n) +{ + (void)type; + hexdump_data(0, data, n); +} + +static void dump_coment(uint8_t type, const uint8_t *data, size_t n) +{ + uint8_t class; + static const char *coment_class[256] = { + [0x00] = "Translator", + [0x01] = "Copyright", + [0x81] = "Library specifier", + [0x9c] = "MS-DOS version", + [0x9d] = "Memory model", + [0x9e] = "DOSSEG", + [0x9f] = "Library search", + [0xa0] = "OMF extensions", + [0xa1] = "New OMF extension", + [0xa2] = "Link pass separator", + [0xa3] = "LIBMOD", + [0xa4] = "EXESTR", + [0xa6] = "INCERR", + [0xa7] = "NOPAD", + [0xa8] = "WKEXT", + [0xa9] = "LZEXT", + [0xda] = "Comment", + [0xdb] = "Compiler", + [0xdc] = "Date", + [0xdd] = "Timestamp", + [0xdf] = "User", + [0xe9] = "Dependency file", + [0xff] = "Command line" + }; + + if (n < 2) { + dump_unknown(type, data, n); + return; + } + + type = data[0]; + class = data[1]; + + printf(" [NP=%d NL=%d UD=%02X] %02X %s\n", + (type >> 7) & 1, + (type >> 6) & 1, + type & 0x3f, + class, + coment_class[class] ? coment_class[class] : "???"); + + hexdump_data(2, data+2, n-2); +} + +static const dump_func dump_type[256] = +{ + [0x88] = dump_coment, +}; + +int dump_omf(int fd) +{ + struct stat st; + size_t len, n; + uint8_t type; + const uint8_t *p, *data; + + if (fstat(fd, &st)) + return -1; + + len = st.st_size; + + data = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0); + if (data == MAP_FAILED) + return -1; + + p = data; + while (len >= 3) { + uint8_t csum; + int i; + + type = p[0]; + n = *(uint16_t *)(p+1); + + printf("%02x %-10s %4zd bytes", + type, + record_types[type] ? record_types[type] : "???", + n); + + if (len < n+3) { + printf("\n (truncated, only %zd bytes left)\n", len-3); + break; /* Truncated */ + } + + p += 3; /* Header doesn't count in the length */ + n--; /* Remove checksum byte */ + + csum = 0; + for (i = -3; i < (int)n; i++) + csum -= p[i]; + + printf(", checksum %02X", p[i]); + if (csum == p[i]) + printf(" (valid)\n"); + else + printf(" (actual = %02X)\n", csum); + + if (dump_type[type]) + dump_type[type](type, p, n); + else + dump_unknown(type, p, n); + + p += n+1; + len -= (n+4); + } + + munmap((void *)data, st.st_size); + return 0; +} + +int main(int argc, char *argv[]) +{ + int fd; + int i; + + progname = argv[0]; + + for (i = 1; i < argc; i++) { + fd = open(argv[i], O_RDONLY); + if (fd < 0 || dump_omf(fd)) { + perror(argv[i]); + return 1; + } + close(fd); + } + + return 0; +} diff --git a/nasm.nsi b/nasm.nsi new file mode 100644 index 00000000..ba6b4a25 --- /dev/null +++ b/nasm.nsi @@ -0,0 +1,112 @@ +#!Nsis Installer Command Script + +# Copyright (c) 2009, Shao Miller (shao.miller@yrdsb.edu.on.ca) +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +!include "version.nsh" +!define PRODUCT_NAME "Netwide Assembler" +!define PRODUCT_SHORT_NAME "nasm" +!define PACKAGE_NAME "${PRODUCT_NAME} ${VERSION}" +!define PACKAGE_SHORT_NAME "${PRODUCT_SHORT_NAME}-${VERSION}" + +Name "${PACKAGE_NAME}" +OutFile "${PACKAGE_SHORT_NAME}-installer.exe" +InstallDir "$PROGRAMFILES\NASM" +InstallDirRegKey HKLM "SOFTWARE\${PACKAGE_SHORT_NAME}" "InstallDir" +SetCompressor lzma + +XPStyle on + +DirText "Please select the installation folder." +Page directory + +ComponentText "Select which optional components you want to install." +Page components + +ShowInstDetails hide +ShowUninstDetails hide +Page instfiles + +Section "${PACKAGE_NAME}" + SectionIn RO + + SetOutPath "$INSTDIR\." + File "LICENSE" + File "nasm.exe" + File "ndisasm.exe" + File "doc/nasmdoc.pdf" + File "rdoff/ldrdf.exe" + File "rdoff/rdf2bin.exe" + File "rdoff/rdf2com.exe" + File "rdoff/rdf2ith.exe" + File "rdoff/rdf2ihx.exe" + File "rdoff/rdf2srec.exe" + File "rdoff/rdfdump.exe" + File "rdoff/rdflib.exe" + File "rdoff/rdx.exe" + FileOpen $0 "nasmpath.bat" w + IfErrors skip + FileWrite $0 "@set path=$INSTDIR;%path%$\r$\n" + FileWrite $0 "@%comspec%" + FileClose $0 + skip: +SectionEnd + +Section "Start Menu Shortcuts" + CreateDirectory "$SMPROGRAMS\${PACKAGE_NAME}" + CreateShortCut "$SMPROGRAMS\${PACKAGE_NAME}\Uninstall ${PACKAGE_NAME}.lnk" "$INSTDIR\Uninstall ${PACKAGE_NAME}.exe" "" "$INSTDIR\Uninstall ${PACKAGE_NAME}.exe" 0 + CreateShortCut "$SMPROGRAMS\${PACKAGE_NAME}\NASM Shell.lnk" "$INSTDIR\nasmpath.bat" "" "$INSTDIR\nasmpath.bat" 0 + CreateShortCut "$SMPROGRAMS\${PACKAGE_NAME}\NASM Manual.lnk" "$INSTDIR\nasmdoc.pdf" "" "$INSTDIR\nasmdoc.pdf" 0 +SectionEnd + +Section "Desktop Icons" + CreateShortCut "$DESKTOP\NASM.lnk" "$INSTDIR\nasmpath.bat" "" "$INSTDIR\nasmpath.bat" 0 +SectionEnd + +Section "Uninstall" + Delete /rebootok "$DESKTOP\NASM.lnk" + Delete /rebootok "$SMPROGRAMS\${PACKAGE_NAME}\NASM Shell.lnk" + Delete /rebootok "$SMPROGRAMS\${PACKAGE_NAME}\NASM Manual.lnk" + Delete /rebootok "$SMPROGRAMS\${PACKAGE_NAME}\Uninstall ${PACKAGE_NAME}.lnk" + RMDir "$SMPROGRAMS\${PACKAGE_NAME}" + + Delete /rebootok "$INSTDIR\nasmpath.bat" + Delete /rebootok "$INSTDIR\rdx.exe" + Delete /rebootok "$INSTDIR\rdflib.exe" + Delete /rebootok "$INSTDIR\rdfdump.exe" + Delete /rebootok "$INSTDIR\rdf2srec.exe" + Delete /rebootok "$INSTDIR\rdf2ihx.exe" + Delete /rebootok "$INSTDIR\rdf2ith.exe" + Delete /rebootok "$INSTDIR\rdf2com.exe" + Delete /rebootok "$INSTDIR\rdf2bin.exe" + Delete /rebootok "$INSTDIR\ndisasm.exe" + Delete /rebootok "$INSTDIR\nasmdoc.pdf" + Delete /rebootok "$INSTDIR\nasm.exe" + Delete /rebootok "$INSTDIR\ldrdf.exe" + Delete /rebootok "$INSTDIR\LICENSE" + RMDir "$INSTDIR" +SectionEnd + +Section -post + WriteUninstaller "$INSTDIR\Uninstall ${PACKAGE_NAME}.exe" +SectionEnd + diff --git a/output/dwarf.h b/output/dwarf.h new file mode 100644 index 00000000..4994464b --- /dev/null +++ b/output/dwarf.h @@ -0,0 +1,59 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 1996-2009 The NASM Authors - All Rights Reserved + * See the file AUTHORS included with the NASM distribution for + * the specific copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following + * conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ----------------------------------------------------------------------- */ + +#ifndef OUTPUT_DWARF_H +#define OUTPUT_DWARF_H + +#define DW_TAG_compile_unit 0x11 +#define DW_TAG_subprogram 0x2e +#define DW_AT_name 0x03 +#define DW_AT_stmt_list 0x10 +#define DW_AT_low_pc 0x11 +#define DW_AT_high_pc 0x12 +#define DW_AT_language 0x13 +#define DW_AT_producer 0x25 +#define DW_AT_frame_base 0x40 +#define DW_FORM_addr 0x01 +#define DW_FORM_data2 0x05 +#define DW_FORM_data4 0x06 +#define DW_FORM_string 0x08 +#define DW_LNS_extended_op 0 +#define DW_LNS_advance_pc 2 +#define DW_LNS_advance_line 3 +#define DW_LNS_set_file 4 +#define DW_LNE_end_sequence 1 +#define DW_LNE_set_address 2 +#define DW_LNE_define_file 3 +#define DW_LANG_Mips_Assembler 0x8001 + +#endif /* OUTPUT_DWARF_H */ diff --git a/output/elf32.h b/output/elf32.h new file mode 100644 index 00000000..b40a9ffa --- /dev/null +++ b/output/elf32.h @@ -0,0 +1,167 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 1996-2009 The NASM Authors - All Rights Reserved + * See the file AUTHORS included with the NASM distribution for + * the specific copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following + * conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ----------------------------------------------------------------------- */ + +#ifndef OUTPUT_ELF32_H +#define OUTPUT_ELF32_H + +#include "output/elfcommon.h" + +/* ELF standard typedefs (yet more proof that <stdint.h> was way overdue) */ +typedef uint16_t Elf32_Half; +typedef int16_t Elf32_SHalf; +typedef uint32_t Elf32_Word; +typedef int32_t Elf32_Sword; +typedef uint64_t Elf32_Xword; +typedef int64_t Elf32_Sxword; + +typedef uint32_t Elf32_Off; +typedef uint32_t Elf32_Addr; +typedef uint16_t Elf32_Section; + +/* Dynamic header */ + +typedef struct elf32_dyn { + Elf32_Sword d_tag; + union { + Elf32_Sword d_val; + Elf32_Addr d_ptr; + } d_un; +} Elf32_Dyn; + +/* Relocations */ + +#define ELF32_R_SYM(x) ((x) >> 8) +#define ELF32_R_TYPE(x) ((x) & 0xff) + +typedef struct elf32_rel { + Elf32_Addr r_offset; + Elf32_Word r_info; +} Elf32_Rel; + +typedef struct elf32_rela { + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; +} Elf32_Rela; + +enum reloc32_type { + R_386_32 = 1, /* ordinary absolute relocation */ + R_386_PC32 = 2, /* PC-relative relocation */ + R_386_GOT32 = 3, /* an offset into GOT */ + R_386_PLT32 = 4, /* a PC-relative offset into PLT */ + R_386_COPY = 5, /* ??? */ + R_386_GLOB_DAT = 6, /* ??? */ + R_386_JUMP_SLOT = 7, /* ??? */ + R_386_RELATIVE = 8, /* ??? */ + R_386_GOTOFF = 9, /* an offset from GOT base */ + R_386_GOTPC = 10, /* a PC-relative offset _to_ GOT */ + R_386_TLS_TPOFF = 14, /* Offset in static TLS block */ + R_386_TLS_IE = 15, /* Address of GOT entry for static TLS + block offset */ + /* These are GNU extensions, but useful */ + R_386_16 = 20, /* A 16-bit absolute relocation */ + R_386_PC16 = 21, /* A 16-bit PC-relative relocation */ + R_386_8 = 22, /* An 8-bit absolute relocation */ + R_386_PC8 = 23 /* An 8-bit PC-relative relocation */ +}; + +/* Symbol */ + +typedef struct elf32_sym { + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; +} Elf32_Sym; + +/* Main file header */ + +typedef struct elf32_hdr { + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; +} Elf32_Ehdr; + +/* Program header */ + +typedef struct elf32_phdr { + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} Elf32_Phdr; + +/* Section header */ + +typedef struct elf32_shdr { + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +} Elf32_Shdr; + +/* Note header */ +typedef struct elf32_note { + Elf32_Word n_namesz; /* Name size */ + Elf32_Word n_descsz; /* Content size */ + Elf32_Word n_type; /* Content type */ +} Elf32_Nhdr; + +/* How to extract and insert information held in the st_info field. */ +#define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4) +#define ELF32_ST_TYPE(val) ((val) & 0xf) + +#endif /* OUTPUT_ELF32_H */ diff --git a/output/elf64.h b/output/elf64.h new file mode 100644 index 00000000..efbc4f2f --- /dev/null +++ b/output/elf64.h @@ -0,0 +1,189 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 1996-2009 The NASM Authors - All Rights Reserved + * See the file AUTHORS included with the NASM distribution for + * the specific copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following + * conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ----------------------------------------------------------------------- */ + +#ifndef OUTPUT_ELF64_H +#define OUTPUT_ELF64_H + +#include "output/elfcommon.h" + +/* ELF standard typedefs (yet more proof that <stdint.h> was way overdue) */ +typedef uint16_t Elf64_Half; +typedef int16_t Elf64_SHalf; +typedef uint32_t Elf64_Word; +typedef int32_t Elf64_Sword; +typedef uint64_t Elf64_Xword; +typedef int64_t Elf64_Sxword; + +typedef uint64_t Elf64_Off; +typedef uint64_t Elf64_Addr; +typedef uint16_t Elf64_Section; + +/* Dynamic header */ + +typedef struct elf64_dyn { + Elf64_Sxword d_tag; + union { + Elf64_Xword d_val; + Elf64_Addr d_ptr; + } d_un; +} Elf64_Dyn; + +/* Relocations */ + +#define ELF64_R_SYM(x) ((x) >> 32) +#define ELF64_R_TYPE(x) ((x) & 0xffffffff) + +typedef struct elf64_rel { + Elf64_Addr r_offset; + Elf64_Xword r_info; +} Elf64_Rel; + +typedef struct elf64_rela { + Elf64_Addr r_offset; + Elf64_Xword r_info; + Elf64_Sxword r_addend; +} Elf64_Rela; + +enum reloc64_type { + R_X86_64_NONE = 0, /* No reloc */ + R_X86_64_64 = 1, /* Direct 64 bit */ + R_X86_64_PC32 = 2, /* PC relative 32 bit signed */ + R_X86_64_GOT32 = 3, /* 32 bit GOT entry */ + R_X86_64_PLT32 = 4, /* 32 bit PLT address */ + R_X86_64_COPY = 5, /* Copy symbol at runtime */ + R_X86_64_GLOB_DAT = 6, /* Create GOT entry */ + R_X86_64_JUMP_SLOT = 7, /* Create PLT entry */ + R_X86_64_RELATIVE = 8, /* Adjust by program base */ + R_X86_64_GOTPCREL = 9, /* 32 bit signed PC relative offset to GOT */ + R_X86_64_32 = 10, /* Direct 32 bit zero extended */ + R_X86_64_32S = 11, /* Direct 32 bit sign extended */ + R_X86_64_16 = 12, /* Direct 16 bit zero extended */ + R_X86_64_PC16 = 13, /* 16 bit sign extended pc relative */ + R_X86_64_8 = 14, /* Direct 8 bit sign extended */ + R_X86_64_PC8 = 15, /* 8 bit sign extended pc relative */ + R_X86_64_DTPMOD64 = 16, /* ID of module containing symbol */ + R_X86_64_DTPOFF64 = 17, /* Offset in module's TLS block */ + R_X86_64_TPOFF64 = 18, /* Offset in initial TLS block */ + R_X86_64_TLSGD = 19, /* 32 bit signed PC relative offset + to two GOT entries for GD symbol */ + R_X86_64_TLSLD = 20, /* 32 bit signed PC relative offset + to two GOT entries for LD symbol */ + R_X86_64_DTPOFF32 = 21, /* Offset in TLS block */ + R_X86_64_GOTTPOFF = 22, /* 32 bit signed PC relative offset + to GOT entry for IE symbol */ + R_X86_64_TPOFF32 = 23, /* Offset in initial TLS block */ + R_X86_64_PC64 = 24, /* word64 S + A - P */ + R_X86_64_GOTOFF64 = 25, /* word64 S + A - GOT */ + R_X86_64_GOTPC32 = 26, /* word32 GOT + A - P */ + R_X86_64_GOT64 = 27, /* word64 G + A */ + R_X86_64_GOTPCREL64 = 28, /* word64 G + GOT - P + A */ + R_X86_64_GOTPC64 = 29, /* word64 GOT - P + A */ + R_X86_64_GOTPLT64 = 30, /* word64 G + A */ + R_X86_64_PLTOFF64 = 31, /* word64 L - GOT + A */ + R_X86_64_SIZE32 = 32, /* word32 Z + A */ + R_X86_64_SIZE64 = 33, /* word64 Z + A */ + R_X86_64_GOTPC32_TLSDESC = 34, /* word32 */ + R_X86_64_TLSDESC_CALL = 35, /* none */ + R_X86_64_TLSDESC = 36 /* word64×2 */ +}; + +/* Symbol */ + +typedef struct elf64_sym { + Elf64_Word st_name; + unsigned char st_info; + unsigned char st_other; + Elf64_Half st_shndx; + Elf64_Addr st_value; + Elf64_Xword st_size; +} Elf64_Sym; + +/* Main file header */ + +typedef struct elf64_hdr { + unsigned char e_ident[EI_NIDENT]; + Elf64_Half e_type; + Elf64_Half e_machine; + Elf64_Word e_version; + Elf64_Addr e_entry; + Elf64_Off e_phoff; + Elf64_Off e_shoff; + Elf64_Word e_flags; + Elf64_Half e_ehsize; + Elf64_Half e_phentsize; + Elf64_Half e_phnum; + Elf64_Half e_shentsize; + Elf64_Half e_shnum; + Elf64_Half e_shstrndx; +} Elf64_Ehdr; + +/* Program header */ + +typedef struct elf64_phdr { + Elf64_Word p_type; + Elf64_Word p_flags; + Elf64_Off p_offset; + Elf64_Addr p_vaddr; + Elf64_Addr p_paddr; + Elf64_Xword p_filesz; + Elf64_Xword p_memsz; + Elf64_Xword p_align; +} Elf64_Phdr; + +/* Section header */ + +typedef struct elf64_shdr { + Elf64_Word sh_name; + Elf64_Word sh_type; + Elf64_Xword sh_flags; + Elf64_Addr sh_addr; + Elf64_Off sh_offset; + Elf64_Xword sh_size; + Elf64_Word sh_link; + Elf64_Word sh_info; + Elf64_Xword sh_addralign; + Elf64_Xword sh_entsize; +} Elf64_Shdr; + +/* Note header */ +typedef struct elf64_note { + Elf64_Word n_namesz; /* Name size */ + Elf64_Word n_descsz; /* Content size */ + Elf64_Word n_type; /* Content type */ +} Elf64_Nhdr; + +/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */ +#define ELF64_ST_BIND(val) ELF32_ST_BIND (val) +#define ELF64_ST_TYPE(val) ELF32_ST_TYPE (val) + +#endif /* OUTPUT_ELF64_H */ diff --git a/output/elfcommon.h b/output/elfcommon.h new file mode 100644 index 00000000..608da9c8 --- /dev/null +++ b/output/elfcommon.h @@ -0,0 +1,250 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 1996-2009 The NASM Authors - All Rights Reserved + * See the file AUTHORS included with the NASM distribution for + * the specific copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following + * conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ----------------------------------------------------------------------- */ + +#ifndef OUTPUT_ELFCOMMON_H +#define OUTPUT_ELFCOMMON_H + +#include "compiler.h" +#include <inttypes.h> + +/* Segment types */ +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 +#define PT_LOOS 0x60000000 +#define PT_HIOS 0x6fffffff +#define PT_LOPROC 0x70000000 +#define PT_HIPROC 0x7fffffff +#define PT_GNU_EH_FRAME 0x6474e550 /* Extension, eh? */ + +/* ELF file types */ +#define ET_NONE 0 +#define ET_REL 1 +#define ET_EXEC 2 +#define ET_DYN 3 +#define ET_CORE 4 +#define ET_LOPROC 0xff00 +#define ET_HIPROC 0xffff + +/* ELF machine types */ +#define EM_NONE 0 +#define EM_M32 1 +#define EM_SPARC 2 +#define EM_386 3 +#define EM_68K 4 +#define EM_88K 5 +#define EM_486 6 /* Not used in Linux at least */ +#define EM_860 7 +#define EM_MIPS 8 /* R3k, bigendian(?) */ +#define EM_MIPS_RS4_BE 10 /* R4k BE */ +#define EM_PARISC 15 +#define EM_SPARC32PLUS 18 +#define EM_PPC 20 +#define EM_PPC64 21 +#define EM_S390 22 +#define EM_SH 42 +#define EM_SPARCV9 43 /* v9 = SPARC64 */ +#define EM_H8_300H 47 +#define EM_H8S 48 +#define EM_IA_64 50 +#define EM_X86_64 62 +#define EM_CRIS 76 +#define EM_V850 87 +#define EM_ALPHA 0x9026 /* Interrim Alpha that stuck around */ +#define EM_CYGNUS_V850 0x9080 /* Old v850 ID used by Cygnus */ +#define EM_S390_OLD 0xA390 /* Obsolete interrim value for S/390 */ + +/* Dynamic type values */ +#define DT_NULL 0 +#define DT_NEEDED 1 +#define DT_PLTRELSZ 2 +#define DT_PLTGOT 3 +#define DT_HASH 4 +#define DT_STRTAB 5 +#define DT_SYMTAB 6 +#define DT_RELA 7 +#define DT_RELASZ 8 +#define DT_RELAENT 9 +#define DT_STRSZ 10 +#define DT_SYMENT 11 +#define DT_INIT 12 +#define DT_FINI 13 +#define DT_SONAME 14 +#define DT_RPATH 15 +#define DT_SYMBOLIC 16 +#define DT_REL 17 +#define DT_RELSZ 18 +#define DT_RELENT 19 +#define DT_PLTREL 20 +#define DT_DEBUG 21 +#define DT_TEXTREL 22 +#define DT_JMPREL 23 +#define DT_LOPROC 0x70000000 +#define DT_HIPROC 0x7fffffff + +/* Auxilliary table entries */ +#define AT_NULL 0 /* end of vector */ +#define AT_IGNORE 1 /* entry should be ignored */ +#define AT_EXECFD 2 /* file descriptor of program */ +#define AT_PHDR 3 /* program headers for program */ +#define AT_PHENT 4 /* size of program header entry */ +#define AT_PHNUM 5 /* number of program headers */ +#define AT_PAGESZ 6 /* system page size */ +#define AT_BASE 7 /* base address of interpreter */ +#define AT_FLAGS 8 /* flags */ +#define AT_ENTRY 9 /* entry point of program */ +#define AT_NOTELF 10 /* program is not ELF */ +#define AT_UID 11 /* real uid */ +#define AT_EUID 12 /* effective uid */ +#define AT_GID 13 /* real gid */ +#define AT_EGID 14 /* effective gid */ +#define AT_PLATFORM 15 /* string identifying CPU for optimizations */ +#define AT_HWCAP 16 /* arch dependent hints at CPU capabilities */ +#define AT_CLKTCK 17 /* frequency at which times() increments */ +/* 18..22 = ? */ +#define AT_SECURE 23 /* secure mode boolean */ + +/* Program header permission flags */ +#define PF_X 0x1 +#define PF_W 0x2 +#define PF_R 0x4 + +/* Section header types */ +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 +#define SHT_NUM 12 +#define SHT_LOPROC 0x70000000 +#define SHT_HIPROC 0x7fffffff +#define SHT_LOUSER 0x80000000 +#define SHT_HIUSER 0xffffffff + +/* Section header flags */ +#define SHF_WRITE (1 << 0) /* Writable */ +#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ +#define SHF_EXECINSTR (1 << 2) /* Executable */ +#define SHF_MERGE (1 << 4) /* Might be merged */ +#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */ +#define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */ +#define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */ +#define SHF_OS_NONCONFORMING (1 << 8) /* Non-standard OS specific handling + required */ +#define SHF_GROUP (1 << 9) /* Section is member of a group. */ +#define SHF_TLS (1 << 10) /* Section hold thread-local data. */ + +/* Special section numbers */ +#define SHN_UNDEF 0 +#define SHN_LORESERVE 0xff00 +#define SHN_LOPROC 0xff00 +#define SHN_HIPROC 0xff1f +#define SHN_ABS 0xfff1 +#define SHN_COMMON 0xfff2 +#define SHN_HIRESERVE 0xffff + +/* Lenght of magic at the start of a file */ +#define EI_NIDENT 16 + +/* Magic number constants... */ +#define EI_MAG0 0 /* e_ident[] indexes */ +#define EI_MAG1 1 +#define EI_MAG2 2 +#define EI_MAG3 3 +#define EI_CLASS 4 +#define EI_DATA 5 +#define EI_VERSION 6 +#define EI_OSABI 7 +#define EI_PAD 8 + +#define ELFMAG0 0x7f /* EI_MAG */ +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +#define ELFCLASSNONE 0 /* EI_CLASS */ +#define ELFCLASS32 1 +#define ELFCLASS64 2 +#define ELFCLASSNUM 3 + +#define ELFDATANONE 0 /* e_ident[EI_DATA] */ +#define ELFDATA2LSB 1 +#define ELFDATA2MSB 2 + +#define EV_NONE 0 /* e_version, EI_VERSION */ +#define EV_CURRENT 1 +#define EV_NUM 2 + +#define ELFOSABI_NONE 0 +#define ELFOSABI_LINUX 3 + +/* Legal values for ST_BIND subfield of st_info (symbol binding). */ +#define STB_LOCAL 0 /* Local symbol */ +#define STB_GLOBAL 1 /* Global symbol */ +#define STB_WEAK 2 /* Weak symbol */ +#define STB_NUM 3 /* Number of defined types. */ +#define STB_LOOS 10 /* Start of OS-specific */ +#define STB_HIOS 12 /* End of OS-specific */ +#define STB_LOPROC 13 /* Start of processor-specific */ +#define STB_HIPROC 15 /* End of processor-specific */ + +/* Symbol types */ +#define STT_NOTYPE 0 /* Symbol type is unspecified */ +#define STT_OBJECT 1 /* Symbol is a data object */ +#define STT_FUNC 2 /* Symbol is a code object */ +#define STT_SECTION 3 /* Symbol associated with a section */ +#define STT_FILE 4 /* Symbol's name is file name */ +#define STT_COMMON 5 /* Symbol is a common data object */ +#define STT_TLS 6 /* Symbol is thread-local data object*/ +#define STT_NUM 7 /* Number of defined types. */ + +/* Symbol visibilities */ +#define STV_DEFAULT 0 /* Default symbol visibility rules */ +#define STV_INTERNAL 1 /* Processor specific hidden class */ +#define STV_HIDDEN 2 /* Sym unavailable in other modules */ +#define STV_PROTECTED 3 /* Not preemptible, not exported */ + +#endif /* OUTPUT_ELFCOMMON_H */ diff --git a/output/nulldbg.c b/output/nulldbg.c new file mode 100644 index 00000000..54a45802 --- /dev/null +++ b/output/nulldbg.c @@ -0,0 +1,89 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 1996-2009 The NASM Authors - All Rights Reserved + * See the file AUTHORS included with the NASM distribution for + * the specific copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following + * conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ----------------------------------------------------------------------- */ + +#include "nasm.h" +#include "nasmlib.h" + +void null_debug_init(struct ofmt *of, void *id, FILE * fp, efunc error) +{ + (void)of; + (void)id; + (void)fp; + (void)error; +} +void null_debug_linenum(const char *filename, int32_t linenumber, int32_t segto) +{ + (void)filename; + (void)linenumber; + (void)segto; +} +void null_debug_deflabel(char *name, int32_t segment, int64_t offset, + int is_global, char *special) +{ + (void)name; + (void)segment; + (void)offset; + (void)is_global; + (void)special; +} +void null_debug_routine(const char *directive, const char *params) +{ + (void)directive; + (void)params; +} +void null_debug_typevalue(int32_t type) +{ + (void)type; +} +void null_debug_output(int type, void *param) +{ + (void)type; + (void)param; +} +void null_debug_cleanup(void) +{ +} + +struct dfmt null_debug_form = { + "Null debug format", + "null", + null_debug_init, + null_debug_linenum, + null_debug_deflabel, + null_debug_routine, + null_debug_typevalue, + null_debug_output, + null_debug_cleanup +}; + +struct dfmt *null_debug_arr[2] = { &null_debug_form, NULL }; diff --git a/output/outaout.mac b/output/outaout.mac new file mode 100644 index 00000000..cd23852d --- /dev/null +++ b/output/outaout.mac @@ -0,0 +1,37 @@ +;; -------------------------------------------------------------------------- +;; +;; Copyright 1996-2009 The NASM Authors - All Rights Reserved +;; See the file AUTHORS included with the NASM distribution for +;; the specific copyright holders. +;; +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following +;; conditions are met: +;; +;; * Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; * Redistributions in binary form must reproduce the above +;; copyright notice, this list of conditions and the following +;; disclaimer in the documentation and/or other materials provided +;; with the distribution. +;; +;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +;; CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +;; INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +;; MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +;; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +;; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +;; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +;; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +;; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +;; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +;; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +;; EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;; +;; -------------------------------------------------------------------------- + +OUT: aout aoutb +%define __SECT__ [section .text] +%macro __NASM_CDecl__ 1 +%endmacro diff --git a/output/outas86.mac b/output/outas86.mac new file mode 100644 index 00000000..f0bd2e41 --- /dev/null +++ b/output/outas86.mac @@ -0,0 +1,37 @@ +;; -------------------------------------------------------------------------- +;; +;; Copyright 1996-2009 The NASM Authors - All Rights Reserved +;; See the file AUTHORS included with the NASM distribution for +;; the specific copyright holders. +;; +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following +;; conditions are met: +;; +;; * Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; * Redistributions in binary form must reproduce the above +;; copyright notice, this list of conditions and the following +;; disclaimer in the documentation and/or other materials provided +;; with the distribution. +;; +;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +;; CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +;; INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +;; MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +;; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +;; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +;; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +;; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +;; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +;; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +;; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +;; EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;; +;; -------------------------------------------------------------------------- + +OUT: as86 +%define __SECT__ [section .text] +%macro __NASM_CDecl__ 1 +%endmacro diff --git a/output/outelf.c b/output/outelf.c new file mode 100644 index 00000000..a8654403 --- /dev/null +++ b/output/outelf.c @@ -0,0 +1,67 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 1996-2009 The NASM Authors - All Rights Reserved + * See the file AUTHORS included with the NASM distribution for + * the specific copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following + * conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ----------------------------------------------------------------------- */ + +/* + * Common code for outelf32 and outelf64 + */ + +#include "compiler.h" + +#include <stdio.h> +#include <stdlib.h> +#include <inttypes.h> + +#include "nasm.h" +#include "output/outform.h" + +#include "output/elfcommon.h" +#include "output/dwarf.h" +#include "output/outelf.h" + +#if defined(OF_ELF32) || defined(OF_ELF64) + +const struct elf_known_section elf_known_sections[] = { + { ".text", SHT_PROGBITS, SHF_ALLOC|SHF_EXECINSTR, 16 }, + { ".rodata", SHT_PROGBITS, SHF_ALLOC, 4 }, + { ".lrodata", SHT_PROGBITS, SHF_ALLOC, 4 }, + { ".data", SHT_PROGBITS, SHF_ALLOC|SHF_WRITE, 4 }, + { ".ldata", SHT_PROGBITS, SHF_ALLOC|SHF_WRITE, 4 }, + { ".bss", SHT_NOBITS, SHF_ALLOC|SHF_WRITE, 4 }, + { ".lbss", SHT_NOBITS, SHF_ALLOC|SHF_WRITE, 4 }, + { ".tdata", SHT_PROGBITS, SHF_ALLOC|SHF_WRITE|SHF_TLS, 4 }, + { ".tbss", SHT_NOBITS, SHF_ALLOC|SHF_WRITE|SHF_TLS, 4 }, + { ".comment", SHT_PROGBITS, 0, 1 }, + { NULL, SHT_PROGBITS, SHF_ALLOC, 1 } /* default */ +}; + +#endif /* defined(OF_ELF32) || defined(OF_ELF64) */ diff --git a/output/outelf.h b/output/outelf.h new file mode 100644 index 00000000..a5bbd563 --- /dev/null +++ b/output/outelf.h @@ -0,0 +1,96 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 1996-2009 The NASM Authors - All Rights Reserved + * See the file AUTHORS included with the NASM distribution for + * the specific copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following + * conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ----------------------------------------------------------------------- */ + +/* + * Internal definitions common to outelf32 and outelf64 + */ +#ifndef OUTPUT_OUTELF_H +#define OUTPUT_OUTELF_H + +#define SYM_GLOBAL 0x10 + +#define GLOBAL_TEMP_BASE 0x40000000 /* bigger than any sane symbol index */ + +#define SEG_ALIGN 16 /* alignment of sections in file */ +#define SEG_ALIGN_1 (SEG_ALIGN-1) + +/* this stuff is needed for the stabs debugging format */ +#define N_SO 0x64 /* ID for main source file */ +#define N_SOL 0x84 /* ID for sub-source file */ +#define N_BINCL 0x82 +#define N_EINCL 0xA2 +#define N_SLINE 0x44 +#define TY_STABSSYMLIN 0x40 /* ouch */ + +/* this stuff is needed for the dwarf debugging format */ +#define TY_DEBUGSYMLIN 0x40 /* internal call to debug_out */ + +/* Known sections with nonstandard defaults */ +struct elf_known_section { + const char *name; /* Name of section */ + int type; /* Section type (SHT_) */ + uint32_t flags; /* Section flags (SHF_) */ + uint32_t align; /* Section alignment */ +}; +extern const struct elf_known_section elf_known_sections[]; + +/* + * Special ELF sections (after the real sections but before debugging ones) + */ +#define sec_shstrtab (nsects + 1) +#define sec_symtab (nsects + 2) +#define sec_strtab (nsects + 3) +#define sec_numspecial 3 + +/* + * Debugging ELF sections (last in the file) + */ + +/* stabs */ +#define sec_stab (nsections-3) +#define sec_stabstr (nsections-2) +#define sec_rel_stab (nsections-1) + +/* dwarf */ +#define sec_debug_aranges (nsections-10) +#define sec_rela_debug_aranges (nsections-9) +#define sec_debug_pubnames (nsections-8) +#define sec_debug_info (nsections-7) +#define sec_rela_debug_info (nsections-6) +#define sec_debug_abbrev (nsections-5) +#define sec_debug_line (nsections-4) +#define sec_rela_debug_line (nsections-3) +#define sec_debug_frame (nsections-2) +#define sec_debug_loc (nsections-1) + +#endif /* OUTPUT_OUTELF_H */ diff --git a/output/outform.c b/output/outform.c new file mode 100644 index 00000000..f8cdca87 --- /dev/null +++ b/output/outform.c @@ -0,0 +1,101 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 1996-2009 The NASM Authors - All Rights Reserved + * See the file AUTHORS included with the NASM distribution for + * the specific copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following + * conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ----------------------------------------------------------------------- */ + +/* + * outform.c manages a list of output formats, and associates + * them with their relevant drivers. Also has a + * routine to find the correct driver given a name + * for it + */ + +#include "compiler.h" + +#include <stdio.h> +#include <string.h> +#include <inttypes.h> + +#define BUILD_DRIVERS_ARRAY +#include "output/outform.h" + +static int ndrivers = 0; + +struct ofmt *ofmt_find(char *name) +{ /* find driver */ + int i; + + for (i = 0; i < ndrivers; i++) + if (!strcmp(name, drivers[i]->shortname)) + return drivers[i]; + + return NULL; +} +struct dfmt *dfmt_find(struct ofmt *ofmt, char *name) +{ /* find driver */ + struct dfmt **dfmt = ofmt->debug_formats; + while (*dfmt) { + if (!strcmp(name, (*dfmt)->shortname)) + return (*dfmt); + dfmt++; + } + return NULL; +} + +void ofmt_list(struct ofmt *deffmt, FILE * fp) +{ + int i; + for (i = 0; i < ndrivers; i++) + fprintf(fp, " %c %-10s%s\n", + drivers[i] == deffmt ? '*' : ' ', + drivers[i]->shortname, drivers[i]->fullname); +} +void dfmt_list(struct ofmt *ofmt, FILE * fp) +{ + struct dfmt **drivers = ofmt->debug_formats; + while (*drivers) { + fprintf(fp, " %c %-10s%s\n", + drivers[0] == ofmt->current_dfmt ? '*' : ' ', + drivers[0]->shortname, drivers[0]->fullname); + drivers++; + } +} +struct ofmt *ofmt_register(efunc error) +{ + for (ndrivers = 0; drivers[ndrivers] != NULL; ndrivers++) ; + + if (ndrivers == 0) { + error(ERR_PANIC | ERR_NOFILE, + "No output drivers given at compile time"); + } + + return (&OF_DEFAULT); +} diff --git a/output/outform.h b/output/outform.h new file mode 100644 index 00000000..3dfbc9c7 --- /dev/null +++ b/output/outform.h @@ -0,0 +1,344 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 1996-2009 The NASM Authors - All Rights Reserved + * See the file AUTHORS included with the NASM distribution for + * the specific copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following + * conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ----------------------------------------------------------------------- */ + +/* + * outform.h header file for binding output format drivers to the + * remainder of the code in the Netwide Assembler + */ + +/* + * This header file allows configuration of which output formats + * get compiled into the NASM binary. You can configure by defining + * various preprocessor symbols beginning with "OF_", either on the + * compiler command line or at the top of this file. + * + * OF_ONLY -- only include specified object formats + * OF_name -- ensure that output format 'name' is included + * OF_NO_name -- remove output format 'name' + * OF_DOS -- ensure that 'obj', 'bin' & 'win32' are included. + * OF_UNIX -- ensure that 'aout', 'aoutb', 'coff', 'elf32' 'elf64' are in. + * OF_OTHERS -- ensure that 'bin', 'as86' & 'rdf' are in. + * OF_ALL -- ensure that all formats are included. + * note that this doesn't include 'dbg', which is + * only really useful if you're doing development + * work on NASM. Define OF_DBG if you want this. + * + * OF_DEFAULT=of_name -- ensure that 'name' is the default format. + * + * eg: -DOF_UNIX -DOF_ELF32 -DOF_DEFAULT=of_elf32 would be a suitable config + * for an average linux system. + * + * Default config = -DOF_ALL -DOF_DEFAULT=of_bin + * + * You probably only want to set these options while compiling 'nasm.c'. */ + +#ifndef NASM_OUTFORM_H +#define NASM_OUTFORM_H + +#include "nasm.h" + +/* -------------- USER MODIFIABLE PART ---------------- */ + +/* + * Insert #defines here in accordance with the configuration + * instructions above. + * + * E.g. + * + * #define OF_ONLY + * #define OF_OBJ + * #define OF_BIN + * + * for a 16-bit DOS assembler with no extraneous formats. + */ + +/* ------------ END USER MODIFIABLE PART -------------- */ + +/* ====configurable info begins here==== */ +/* formats configurable: + * bin,obj,elf32,elf64,aout,aoutb,coff,win32,as86,rdf2,macho */ + +/* process options... */ + +#ifndef OF_ONLY +#ifndef OF_ALL +#define OF_ALL /* default is to have all formats */ +#endif +#endif + +#ifdef OF_ALL /* set all formats on... */ +#ifndef OF_BIN +#define OF_BIN +#endif +#ifndef OF_OBJ +#define OF_OBJ +#endif +#ifndef OF_ELF32 +#define OF_ELF32 +#endif +#ifndef OF_ELF64 +#define OF_ELF64 +#endif +#ifndef OF_COFF +#define OF_COFF +#endif +#ifndef OF_AOUT +#define OF_AOUT +#endif +#ifndef OF_AOUTB +#define OF_AOUTB +#endif +#ifndef OF_WIN32 +#define OF_WIN32 +#endif +#ifndef OF_WIN64 +#define OF_WIN64 +#endif +#ifndef OF_AS86 +#define OF_AS86 +#endif +#ifndef OF_RDF2 +#define OF_RDF2 +#endif +#ifndef OF_IEEE +#define OF_IEEE +#endif +#ifndef OF_MACHO32 +#define OF_MACHO32 +#endif +#ifndef OF_MACHO64 +#define OF_MACHO64 +#endif +#ifndef OF_DBG +#define OF_DBG +#endif +#endif /* OF_ALL */ + +/* turn on groups of formats specified.... */ +#ifdef OF_DOS +#ifndef OF_OBJ +#define OF_OBJ +#endif +#ifndef OF_BIN +#define OF_BIN +#endif +#ifndef OF_COFF +#define OF_COFF /* COFF is used by DJGPP */ +#endif +#ifndef OF_WIN32 +#define OF_WIN32 +#endif +#ifndef OF_WIN64 +#define OF_WIN64 +#endif +#endif + +#ifdef OF_UNIX +#ifndef OF_AOUT +#define OF_AOUT +#endif +#ifndef OF_AOUTB +#define OF_AOUTB +#endif +#ifndef OF_COFF +#define OF_COFF +#endif +#ifndef OF_ELF32 +#define OF_ELF32 +#endif +#ifndef OF_ELF64 +#define OF_ELF64 +#endif +#endif + +#ifdef OF_OTHERS +#ifndef OF_BIN +#define OF_BIN +#endif +#ifndef OF_AS86 +#define OF_AS86 +#endif +#ifndef OF_RDF2 +#define OF_RDF2 +#endif +#ifndef OF_IEEE +#define OF_IEEE +#endif +#ifndef OF_MACHO32 +#define OF_MACHO32 +#endif +#ifndef OF_MACHO64 +#define OF_MACHO64 +#endif +#endif + +/* finally... override any format specifically specified to be off */ +#ifdef OF_NO_BIN +#undef OF_BIN +#endif +#ifdef OF_NO_OBJ +#undef OF_OBJ +#endif +#ifdef OF_NO_ELF32 +#undef OF_ELF32 +#endif +#ifdef OF_NO_ELF64 +#undef OF_ELF64 +#endif +#ifdef OF_NO_AOUT +#undef OF_AOUT +#endif +#ifdef OF_NO_AOUTB +#undef OF_AOUTB +#endif +#ifdef OF_NO_COFF +#undef OF_COFF +#endif +#ifdef OF_NO_WIN32 +#undef OF_WIN32 +#endif +#ifdef OF_NO_WIN64 +#undef OF_WIN64 +#endif +#ifdef OF_NO_AS86 +#undef OF_AS86 +#endif +#ifdef OF_NO_RDF2 +#undef OF_RDF +#endif +#ifdef OF_NO_IEEE +#undef OF_IEEE +#endif +#ifdef OF_NO_MACHO32 +#undef OF_MACHO32 +#endif +#ifdef OF_NO_MACHO64 +#undef OF_MACHO64 +#endif +#ifdef OF_NO_DBG +#undef OF_DBG +#endif + +#ifndef OF_DEFAULT +#define OF_DEFAULT of_bin +#endif + +#ifdef BUILD_DRIVERS_ARRAY /* only if included from outform.c */ + +/* pull in the externs for the different formats, then make the *drivers + * array based on the above defines */ + +extern struct ofmt of_bin; +extern struct ofmt of_ith; +extern struct ofmt of_srec; +extern struct ofmt of_aout; +extern struct ofmt of_aoutb; +extern struct ofmt of_coff; +extern struct ofmt of_elf32; +extern struct ofmt of_elf; +extern struct ofmt of_elf64; +extern struct ofmt of_as86; +extern struct ofmt of_obj; +extern struct ofmt of_win32; +extern struct ofmt of_win64; +extern struct ofmt of_rdf2; +extern struct ofmt of_ieee; +extern struct ofmt of_macho32; +extern struct ofmt of_macho; +extern struct ofmt of_macho64; +extern struct ofmt of_dbg; + +struct ofmt *drivers[] = { +#ifdef OF_BIN + &of_bin, + &of_ith, + &of_srec, +#endif +#ifdef OF_AOUT + &of_aout, +#endif +#ifdef OF_AOUTB + &of_aoutb, +#endif +#ifdef OF_COFF + &of_coff, +#endif +#ifdef OF_ELF32 + &of_elf32, + &of_elf, +#endif +#ifdef OF_ELF64 + &of_elf64, +#endif +#ifdef OF_AS86 + &of_as86, +#endif +#ifdef OF_OBJ + &of_obj, +#endif +#ifdef OF_WIN32 + &of_win32, +#endif +#ifdef OF_WIN64 + &of_win64, +#endif +#ifdef OF_RDF2 + &of_rdf2, +#endif +#ifdef OF_IEEE + &of_ieee, +#endif +#ifdef OF_MACHO32 + &of_macho32, + &of_macho, +#endif +#ifdef OF_MACHO64 + &of_macho64, +#endif +#ifdef OF_DBG + &of_dbg, +#endif + + NULL +}; + +#endif /* BUILD_DRIVERS_ARRAY */ + +struct ofmt *ofmt_find(char *); +struct dfmt *dfmt_find(struct ofmt *, char *); +void ofmt_list(struct ofmt *, FILE *); +void dfmt_list(struct ofmt *ofmt, FILE * fp); +struct ofmt *ofmt_register(efunc error); +extern struct dfmt null_debug_form; + +#endif /* NASM_OUTFORM_H */ diff --git a/output/outlib.c b/output/outlib.c new file mode 100644 index 00000000..56ac6cd5 --- /dev/null +++ b/output/outlib.c @@ -0,0 +1,56 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 1996-2009 The NASM Authors - All Rights Reserved + * See the file AUTHORS included with the NASM distribution for + * the specific copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following + * conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ----------------------------------------------------------------------- */ + +/* + * libout.c + * + * Common routines for the output backends. + */ + +#include "compiler.h" +#include "nasm.h" +#include "output/outlib.h" + +uint64_t realsize(enum out_type type, uint64_t size) +{ + switch (type) { + case OUT_REL2ADR: + return 2; + case OUT_REL4ADR: + return 4; + case OUT_REL8ADR: + return 8; + default: + return size; + } +} diff --git a/output/outlib.h b/output/outlib.h new file mode 100644 index 00000000..964da5c8 --- /dev/null +++ b/output/outlib.h @@ -0,0 +1,55 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 1996-2009 The NASM Authors - All Rights Reserved + * See the file AUTHORS included with the NASM distribution for + * the specific copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following + * conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ----------------------------------------------------------------------- */ + +#ifndef NASM_OUTLIB_H +#define NASM_OUTLIB_H + +#include "nasm.h" + +uint64_t realsize(enum out_type type, uint64_t size); + +/* Do-nothing versions of all the debug routines */ +struct ofmt; +void null_debug_init(struct ofmt *of, void *id, FILE * fp, efunc error); +void null_debug_linenum(const char *filename, int32_t linenumber, + int32_t segto); +void null_debug_deflabel(char *name, int32_t segment, int64_t offset, + int is_global, char *special); +void null_debug_routine(const char *directive, const char *params); +void null_debug_typevalue(int32_t type); +void null_debug_output(int type, void *param); +void null_debug_cleanup(void); +extern struct dfmt *null_debug_arr[2]; + +#endif /* NASM_OUTLIB_H */ + diff --git a/output/outmacho.mac b/output/outmacho.mac new file mode 100644 index 00000000..f1cdf180 --- /dev/null +++ b/output/outmacho.mac @@ -0,0 +1,37 @@ +;; -------------------------------------------------------------------------- +;; +;; Copyright 1996-2009 The NASM Authors - All Rights Reserved +;; See the file AUTHORS included with the NASM distribution for +;; the specific copyright holders. +;; +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following +;; conditions are met: +;; +;; * Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; * Redistributions in binary form must reproduce the above +;; copyright notice, this list of conditions and the following +;; disclaimer in the documentation and/or other materials provided +;; with the distribution. +;; +;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +;; CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +;; INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +;; MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +;; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +;; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +;; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +;; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +;; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +;; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +;; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +;; EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;; +;; -------------------------------------------------------------------------- + +OUT: macho macho32 macho64 +%define __SECT__ [section .text] +%macro __NASM_CDecl__ 1 +%endmacro diff --git a/output/outmacho32.c b/output/outmacho32.c new file mode 100644 index 00000000..c9e43659 --- /dev/null +++ b/output/outmacho32.c @@ -0,0 +1,1382 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 1996-2009 The NASM Authors - All Rights Reserved + * See the file AUTHORS included with the NASM distribution for + * the specific copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following + * conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ----------------------------------------------------------------------- */ + +/* + * outmacho.c output routines for the Netwide Assembler to produce + * NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X object files + */ + +/* Most of this file is, like Mach-O itself, based on a.out. For more + * guidelines see outaout.c. */ + +#include "compiler.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <inttypes.h> + +#include "nasm.h" +#include "nasmlib.h" +#include "saa.h" +#include "raa.h" +#include "output/outform.h" +#include "output/outlib.h" + +#if defined(OF_MACHO32) + +/* 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; + int32_t 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 */ + uint32_t addr; /* in-memory address (subject to alignment) */ + uint32_t size; /* in-memory and -file size */ + uint32_t nreloc; /* relocation entry count */ + uint32_t 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 int32_t 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, 0} +}; + +struct reloc { + /* nasm internal data */ + struct reloc *next; + + /* data that goes into the file */ + int32_t 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=int32_t */ + 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 */ + int32_t initial_snum; /* symbol number used above in + reloc */ + int32_t snum; /* true snum for reloc */ + + /* data that goes into the file */ + int32_t strx; /* string table index */ + uint8_t type; /* symbol type */ + uint8_t sect; /* NO_SECT or section number */ + int16_t desc; /* for stab debugging, 0 for us */ + uint32_t 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 uint32_t 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 uint32_t ilocalsym = 0; +static uint32_t iextdefsym = 0; +static uint32_t iundefsym = 0; +static uint32_t nlocalsym; +static uint32_t nextdefsym; +static uint32_t nundefsym; +static struct symbol **extdefsyms = NULL; +static struct symbol **undefsyms = NULL; + +static struct RAA *extsyms; +static struct SAA *strs; +static uint32_t 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. */ +uint32_t head_ncmds = 0; +uint32_t head_sizeofcmds = 0; +uint32_t seg_filesize = 0; +uint32_t seg_vmsize = 0; +uint32_t seg_nsects = 0; +uint32_t 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 alignint32_t(x) \ + align(x, sizeof(int32_t)) /* align x to int32_t boundary */ + +static void debug_reloc (struct reloc *); +static void debug_section_relocs (struct section *) _unused; + +static int exact_log2 (uint32_t align) +{ + if (align == 0) { + return 0; + } else if (align & (align-1)) { + return -1; /* Not a power of 2 */ + } else { +#ifdef HAVE_GNUC_4 + return __builtin_ctzl (align); +#else + uint32_t result = 0; + + /* We know exactly one bit is set at this point. */ + if (align & 0xffff0000) + result |= 16; + if (align & 0xff00ff00) + result |= 8; + if (align & 0xf0f0f0f0) + result |= 4; + if (align & 0xcccccccc) + result |= 2; + if (align & 0xaaaaaaaa) + result |= 1; + + 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 int32_t index) +{ + struct section *s; + + for (s = sects; s != NULL; s = s->next) + if (index == s->index) + break; + + return s; +} + +static int32_t 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 int32_t index) +{ + struct section *s; + + for (s = sects; s != NULL; s = s->next) + if (index == s->index) + return s->sectname; + + return NULL; +} + +static uint8_t get_section_fileindex_by_index(const int32_t index) +{ + struct section *s; + uint8_t 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) +{ + (void)type; + (void)val; + return 0; +} + +static void sect_write(struct section *sect, + const uint8_t *data, uint32_t len) +{ + saa_wbytes(sect->data, data, len); + sect->size += len; +} + +static void add_reloc(struct section *sect, int32_t section, + int pcrel, int bytes) +{ + struct reloc *r; + int32_t 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(int32_t secto, const void *data, + enum out_type type, uint64_t size, + int32_t section, int32_t wrt) +{ + struct section *s, *sbss; + int32_t addr; + uint8_t mydata[4], *p; + + 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 initialize memory in the" + " BSS section: ignored"); + s->size += realsize(type, size); + return; + } + + switch (type) { + case OUT_RESERVE: + if (s != sbss) { + error(ERR_WARNING, "uninitialized space declared in" + " %s section: zeroing", + get_section_name_by_index(secto)); + + sect_write(s, NULL, size); + } else + s->size += size; + + break; + + case OUT_RAWDATA: + if (section != NO_SEG) + error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG"); + + sect_write(s, data, size); + break; + + case OUT_ADDRESS: + addr = *(int64_t *)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, size); + } + + p = mydata; + WRITEADDR(p, addr, size); + sect_write(s, mydata, size); + 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, *(int32_t *)data - (size + 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, *(int32_t *)data - (size + s->size)); + sect_write(s, mydata, 4L); + break; + + default: + error(ERR_PANIC, "unknown output type?"); + break; + } +} + +static int32_t macho_section(char *name, int pass, int *bits) +{ + int32_t index, originalIndex; + char *sectionAttributes; + struct sectmap *sm; + struct section *s; + + (void)pass; + + /* Default to 32 bits. */ + if (!name) { + *bits = 32; + name = ".text"; + sectionAttributes = NULL; + } else { + sectionAttributes = name; + name = nasm_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 = -1; + + 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 = nasm_strsep(§ionAttributes, " \t"))) { + if (0 != *currentAttribute) { + if (!nasm_strnicmp("align=", currentAttribute, 6)) { + char *end; + int newAlignment, value; + + value = strtoul(currentAttribute + 6, (char**)&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) + && (s->align != -1)) { + 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 (!nasm_stricmp("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, int32_t section, int64_t 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 int32_t macho_segbase(int32_t section) +{ + return section; +} + +static int macho_directive(char *directive, char *value, int pass) +{ + (void)directive; + (void)value; + (void)pass; + return 0; +} + +static void macho_filename(char *inname, char *outname, efunc error) +{ + standard_extension(inname, outname, ".o", error); +} + +extern macros_t macho_stdmac[]; + +/* 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 (uint32_t *numsyms, + uint32_t *strtabsize) +{ + struct symbol *sym, **symp; + uint32_t 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, (int32_t)(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, (int32_t)(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) { + uint32_t pad = 0; + + /* zerofill sections aren't actually written to the file */ + if ((s->flags & SECTION_TYPE) != S_ZEROFILL) + seg_filesize += s->size; + + /* recalculate segment address based on alignment and vm size */ + s->addr = seg_vmsize; + /* we need section alignment to calculate final section address */ + if (s->align == -1) + s->align = DEFAULT_SECTION_ALIGNMENT; + if(s->align) { + uint32_t newaddr = align(s->addr, 1 << s->align); + pad = newaddr - s->addr; + s->addr = newaddr; + } + + seg_vmsize += s->size + pad; + ++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) +{ + fwriteint32_t(MH_MAGIC, machofp); /* magic */ + fwriteint32_t(CPU_TYPE_I386, machofp); /* CPU type */ + fwriteint32_t(CPU_SUBTYPE_I386_ALL, machofp); /* CPU subtype */ + fwriteint32_t(MH_OBJECT, machofp); /* Mach-O file type */ + fwriteint32_t(head_ncmds, machofp); /* number of load commands */ + fwriteint32_t(head_sizeofcmds, machofp); /* size of load commands */ + fwriteint32_t(0, machofp); /* no flags */ +} + +/* Write out the segment load command at offset. */ + +static uint32_t macho_write_segment (uint32_t offset) +{ + uint32_t rel_base = alignint32_t (offset + seg_filesize); + uint32_t s_reloff = 0; + struct section *s; + + fwriteint32_t(LC_SEGMENT, machofp); /* cmd == LC_SEGMENT */ + + /* size of load command including section load commands */ + fwriteint32_t(MACHO_SEGCMD_SIZE + seg_nsects * + MACHO_SECTCMD_SIZE, machofp); + + /* in an MH_OBJECT file all sections are in one unnamed (name + ** all zeros) segment */ + fwritezero(16, machofp); + fwriteint32_t(0, machofp); /* in-memory offset */ + fwriteint32_t(seg_vmsize, machofp); /* in-memory size */ + fwriteint32_t(offset, machofp); /* in-file offset to data */ + fwriteint32_t(seg_filesize, machofp); /* in-file size */ + fwriteint32_t(VM_PROT_DEFAULT, machofp); /* maximum vm protection */ + fwriteint32_t(VM_PROT_DEFAULT, machofp); /* initial vm protection */ + fwriteint32_t(seg_nsects, machofp); /* number of sections */ + fwriteint32_t(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); + fwriteint32_t(s->addr, machofp); + fwriteint32_t(s->size, machofp); + + /* dummy data for zerofill sections or proper values */ + if ((s->flags & SECTION_TYPE) != S_ZEROFILL) { + fwriteint32_t(offset, machofp); + /* Write out section alignment, as a power of two. + e.g. 32-bit word alignment would be 2 (2^^2 = 4). */ + if (s->align == -1) + s->align = DEFAULT_SECTION_ALIGNMENT; + fwriteint32_t(s->align, machofp); + /* To be compatible with cctools as we emit + a zero reloff if we have no relocations. */ + fwriteint32_t(s->nreloc ? rel_base + s_reloff : 0, machofp); + fwriteint32_t(s->nreloc, machofp); + + offset += s->size; + s_reloff += s->nreloc * MACHO_RELINFO_SIZE; + } else { + fwriteint32_t(0, machofp); + fwriteint32_t(0, machofp); + fwriteint32_t(0, machofp); + fwriteint32_t(0, machofp); + } + + fwriteint32_t(s->flags, machofp); /* flags */ + fwriteint32_t(0, machofp); /* reserved */ + fwriteint32_t(0, machofp); /* reserved */ + } + + 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) { + uint32_t word2; + + fwriteint32_t(r->addr, machofp); /* reloc offset */ + + word2 = r->snum; + word2 |= r->pcrel << 24; + word2 |= r->length << 25; + word2 |= r->ext << 27; + word2 |= r->type << 28; + fwriteint32_t(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; + uint8_t fi, *p, *q, blk[4]; + int32_t 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, (int32_t)r->length << 1); + p = q = blk; + l = *p++; + + /* get offset based on relocation type */ + if (r->length > 0) { + l += ((int32_t)*p++) << 8; + + if (r->length == 2) { + l += ((int32_t)*p++) << 16; + l += ((int32_t)*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) { + /* generate final address by section address and offset */ + for (s2 = sects, fi = 1; + s2 != NULL; s2 = s2->next, fi++) { + if (fi == r->snum) { + l += s2->addr; + break; + } + } + } + + /* 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, (int32_t)r->length << 1); + } + + /* dump the section data to file */ + saa_fpwrite(s->data, machofp); + } + + /* pad last section up to reloc entries on int32_t boundary */ + fwritezero(rel_padcnt, 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; + int32_t fi; + uint32_t 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) { + fwriteint32_t(sym->strx, machofp); /* string table entry number */ + fwrite(&sym->type, 1, 1, machofp); /* symbol type */ + fwrite(&sym->sect, 1, 1, machofp); /* section */ + fwriteint16_t(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; + } + + fwriteint32_t(sym->value, machofp); /* value (i.e. offset) */ + } + } + + for (i = 0; i < nextdefsym; i++) { + sym = extdefsyms[i]; + fwriteint32_t(sym->strx, machofp); + fwrite(&sym->type, 1, 1, machofp); /* symbol type */ + fwrite(&sym->sect, 1, 1, machofp); /* section */ + fwriteint16_t(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; + } + + fwriteint32_t(sym->value, machofp); /* value (i.e. offset) */ + } + + for (i = 0; i < nundefsym; i++) { + sym = undefsyms[i]; + fwriteint32_t(sym->strx, machofp); + fwrite(&sym->type, 1, 1, machofp); /* symbol type */ + fwrite(&sym->sect, 1, 1, machofp); /* section */ + fwriteint16_t(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; + } + + fwriteint32_t(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; + uint32_t 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; + break; + } + } + } + r = r->next; + } +} + +/* Write out the object file. */ + +static void macho_write (void) +{ + uint32_t offset = 0; + + /* mach-o object file structure: + ** + ** mach header + ** uint32_t magic + ** int cpu type + ** int cpu subtype + ** uint32_t mach file type + ** uint32_t number of load commands + ** uint32_t size of all load commands + ** (includes section struct size of segment command) + ** uint32_t flags + ** + ** segment command + ** uint32_t command type == LC_SEGMENT + ** uint32_t size of load command + ** (including section load commands) + ** char[16] segment name + ** uint32_t in-memory offset + ** uint32_t in-memory size + ** uint32_t in-file offset to data area + ** uint32_t in-file size + ** (in-memory size excluding zerofill sections) + ** int maximum vm protection + ** int initial vm protection + ** uint32_t number of sections + ** uint32_t flags + ** + ** section commands + ** char[16] section name + ** char[16] segment name + ** uint32_t in-memory offset + ** uint32_t in-memory size + ** uint32_t in-file offset + ** uint32_t alignment + ** (irrelevant in MH_OBJECT) + ** uint32_t in-file offset of relocation entires + ** uint32_t number of relocations + ** uint32_t flags + ** uint32_t reserved + ** uint32_t reserved + ** + ** symbol table command + ** uint32_t command type == LC_SYMTAB + ** uint32_t size of load command + ** uint32_t symbol table offset + ** uint32_t number of symbol table entries + ** uint32_t string table offset + ** uint32_t string table size + ** + ** raw section data + ** + ** padding to int32_t boundary + ** + ** relocation data (struct reloc) + ** int32_t offset + ** uint data (symbolnum, pcrel, length, extern, type) + ** + ** symbol table data (struct nlist) + ** int32_t string table entry number + ** uint8_t type + ** (extern, absolute, defined in section) + ** uint8_t section + ** (0 for global symbols, section number of definition (>= 1, <= + ** 254) for local symbols, size of variable for common symbols + ** [type == extern]) + ** int16_t description + ** (for stab debugging format) + ** uint32_t 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 */ + fwriteint32_t(LC_SYMTAB, machofp); /* cmd == LC_SYMTAB */ + fwriteint32_t(MACHO_SYMCMD_SIZE, machofp); /* size of load command */ + fwriteint32_t(offset, machofp); /* symbol table offset */ + fwriteint32_t(nsyms, machofp); /* number of symbol + ** table entries */ + + offset += nsyms * MACHO_NLIST_SIZE; + fwriteint32_t(offset, machofp); /* string table offset */ + fwriteint32_t(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: %"PRId32"\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_macho32 = { + "NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (i386) object files", + "macho32", + 0, + 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 +}; + +struct ofmt of_macho = { + "MACHO (short name for MACHO32)", + "macho", + 0, + 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/output/outmacho64.c b/output/outmacho64.c new file mode 100644 index 00000000..0a8b77b9 --- /dev/null +++ b/output/outmacho64.c @@ -0,0 +1,1528 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 1996-2009 The NASM Authors - All Rights Reserved + * See the file AUTHORS included with the NASM distribution for + * the specific copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following + * conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ----------------------------------------------------------------------- */ + +/* + * outmacho64.c output routines for the Netwide Assembler to produce + * NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (x86_64) object files + */ + +/* Most of this file is, like Mach-O itself, based on a.out. For more + * guidelines see outaout.c. */ + +#include "compiler.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <inttypes.h> + +#include "nasm.h" +#include "nasmlib.h" +#include "saa.h" +#include "raa.h" +#include "output/outform.h" +#include "output/outlib.h" + +#if defined(OF_MACHO64) + +/* Mach-O in-file header structure sizes */ +#define MACHO_HEADER64_SIZE (32) +#define MACHO_SEGCMD64_SIZE (72) +#define MACHO_SECTCMD64_SIZE (80) +#define MACHO_SYMCMD_SIZE (24) +#define MACHO_NLIST64_SIZE (16) +#define MACHO_RELINFO64_SIZE (8) + +/* Mach-O file header values */ +#define MH_MAGIC_64 (0xfeedfacf) +#define CPU_TYPE_X86_64 (0x01000007) /* x86-64 platform */ +#define CPU_SUBTYPE_I386_ALL (3) /* all-x86 compatible */ +#define MH_OBJECT (0x1) /* object file */ + +#define LC_SEGMENT_64 (0x19) /* 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; + int32_t 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 */ + uint64_t addr; /* in-memory address (subject to alignment) */ + uint64_t size; /* in-memory and -file size */ + uint32_t nreloc; /* relocation entry count */ + uint32_t flags; /* type and attributes (masked) */ + uint32_t extreloc; /* external relocations */ +}; + +#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 */ +#define S_ATTR_PURE_INSTRUCTIONS 0x80000000 /* section uses pure + machine instructions */ + +static struct sectmap { + const char *nasmsect; + const char *segname; + const char *sectname; + const int32_t flags; +} sectmap[] = { + {".text", "__TEXT", "__text", S_REGULAR|S_ATTR_SOME_INSTRUCTIONS|S_ATTR_PURE_INSTRUCTIONS}, + {".data", "__DATA", "__data", S_REGULAR}, + {".rodata", "__DATA", "__const", S_REGULAR}, + {".bss", "__DATA", "__bss", S_ZEROFILL}, + {NULL, NULL, NULL, 0} +}; + +struct reloc { + /* nasm internal data */ + struct reloc *next; + + /* data that goes into the file */ + int32_t addr; /* op's offset in section */ + uint32_t snum:24, /* contains symbol index if + ** ext otherwise in-file + ** section number */ + pcrel:1, /* relative relocation */ + length:2, /* 0=byte, 1=word, 2=int32_t, 3=int64_t */ + ext:1, /* external symbol referenced */ + type:4; /* reloc type */ +}; + +#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 */ + int32_t initial_snum; /* symbol number used above in + reloc */ + int32_t snum; /* true snum for reloc */ + + /* data that goes into the file */ + uint32_t strx; /* string table index */ + uint8_t type; /* symbol type */ + uint8_t sect; /* NO_SECT or section number */ + uint16_t desc; /* for stab debugging, 0 for us */ + uint64_t 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 uint32_t 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 uint32_t ilocalsym = 0; +static uint32_t iextdefsym = 0; +static uint32_t iundefsym = 0; +static uint32_t nlocalsym; +static uint32_t nextdefsym; +static uint32_t nundefsym; +static struct symbol **extdefsyms = NULL; +static struct symbol **undefsyms = NULL; + +static struct RAA *extsyms; +static struct SAA *strs; +static uint32_t strslen; + +static FILE *machofp; +static efunc error; +static evalfunc evaluate; + +extern struct ofmt of_macho64; + +/* Global file information. This should be cleaned up into either + a structure or as function arguments. */ +uint32_t head_ncmds64 = 0; +uint32_t head_sizeofcmds64 = 0; +uint64_t seg_filesize64 = 0; +uint64_t seg_vmsize64 = 0; +uint32_t seg_nsects64 = 0; +uint64_t rel_padcnt64 = 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 alignint32_t(x) \ + align(x, sizeof(int32_t)) /* align x to int32_t boundary */ + +#define alignint64_t(x) \ + align(x, sizeof(int64_t)) /* align x to int64_t boundary */ + +static void debug_reloc (struct reloc *); +static void debug_section_relocs (struct section *) _unused; + +static int exact_log2 (uint32_t align) +{ + if (align == 0) { + return 0; + } else if (align & (align-1)) { + return -1; /* Not a power of 2 */ + } else { +#ifdef HAVE_GNUC_4 + return __builtin_ctzl (align); +#else + uint32_t result = 0; + + /* We know exactly one bit is set at this point. */ + if (align & 0xffff0000) + result |= 16; + if (align & 0xff00ff00) + result |= 8; + if (align & 0xf0f0f0f0) + result |= 4; + if (align & 0xcccccccc) + result |= 2; + if (align & 0xaaaaaaaa) + result |= 1; + + 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 int32_t index) +{ + struct section *s; + + for (s = sects; s != NULL; s = s->next) + if (index == s->index) + break; + + return s; +} + +static int32_t 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 int32_t index) +{ + struct section *s; + + for (s = sects; s != NULL; s = s->next) + if (index == s->index) + return s->sectname; + + return NULL; +} + +static uint8_t get_section_fileindex_by_index(const int32_t index) +{ + struct section *s; + uint8_t 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 struct symbol *get_closest_section_symbol_by_offset(uint8_t fileindex, int64_t offset) +{ + struct symbol *sym; + + for (sym = syms; sym != NULL; sym = sym->next) { + if ((sym->sect != NO_SECT) && + (sym->sect == fileindex) && + ((int64_t)sym->value >= offset)) + return sym; + } + + return NULL; +} + + +/* + * Special section numbers which are used to define Mach-O special + * symbols, which can be used with WRT to provide PIC relocation + * types. + */ +static int32_t macho_gotpcrel_sect; + +static void macho_init(FILE * fp, efunc errfunc, ldfunc ldef, + evalfunc eval) +{ + char zero = 0; + + maxbits = 64; + machofp = fp; + error = errfunc; + evaluate = eval; + + (void)ldef; /* placate optimizers */ + + 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; + + /* add special symbol for ..gotpcrel */ + macho_gotpcrel_sect = seg_alloc(); + macho_gotpcrel_sect ++; +// ldef("..gotpcrel", macho_gotpcrel_sect, 0L, NULL, false, false, &of_macho64, error); +} + +static int macho_setinfo(enum geninfo type, char **val) +{ + (void)type; + (void)val; + return 0; +} + +static void sect_write(struct section *sect, + const uint8_t *data, uint32_t len) +{ + saa_wbytes(sect->data, data, len); + sect->size += len; +} + +static int32_t add_reloc(struct section *sect, int32_t section, + int pcrel, int bytes, int64_t reloff) +{ + struct reloc *r; + struct symbol *sym; + int32_t fi; + int32_t adjustment = 0; + + /* 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 = 1; + r->pcrel = (pcrel ? 1 : 0); + + /* match byte count 1, 2, 4, 8 to length codes 0, 1, 2, 3 respectively */ + switch(bytes){ + case 1: + r->length = 0; + break; + case 2: + r->length = 1; + break; + case 4: + r->length = 2; + break; + case 8: + r->length = 3; + break; + default: + break; + } + + /* set default relocation values */ + r->type = 0; // X86_64_RELOC_UNSIGNED + r->snum = R_ABS; // Absolute Symbol (indicates no relocation) + + /* absolute relocation */ + if (pcrel == 0) { + + /* intra-section */ + if (section == NO_SEG) { + // r->snum = R_ABS; // Set above + + /* inter-section */ + } else { + fi = get_section_fileindex_by_index(section); + + /* external */ + if (fi == NO_SECT) { + r->snum = raa_read(extsyms, section); + + /* local */ + } else { + sym = get_closest_section_symbol_by_offset(fi, reloff); + r->snum = sym->initial_snum; + adjustment = sym->value; + } + } + + /* relative relocation */ + } else if (pcrel == 1) { + + /* intra-section */ + if (section == NO_SEG) { + r->type = 1; // X86_64_RELOC_SIGNED + + /* inter-section */ + } else { + r->type = 2; // X86_64_RELOC_BRANCH + fi = get_section_fileindex_by_index(section); + + /* external */ + if (fi == NO_SECT) { + sect->extreloc = 1; + r->snum = raa_read(extsyms, section); + + /* local */ + } else { + sym = get_closest_section_symbol_by_offset(fi, reloff); + r->snum = sym->initial_snum; + adjustment = sym->value; + } + } + + /* subtractor */ + } else if (pcrel == 2) { + r->pcrel = 0; + r->type = 5; // X86_64_RELOC_SUBTRACTOR +// r->snum = macho_gotpcrel_sect; + + /* gotpcrel */ + } else if (pcrel == 3) { + r->type = 4; // X86_64_RELOC_GOT + } else if (pcrel == 4) { + r->type = 3; // X86_64_RELOC_GOT_LOAD + } + + ++sect->nreloc; + + return adjustment; +} + +static void macho_output(int32_t secto, const void *data, + enum out_type type, uint64_t size, + int32_t section, int32_t wrt) +{ + struct section *s, *sbss; + int64_t addr; + uint8_t mydata[16], *p; + + 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 initialize memory in the" + " BSS section: ignored"); + s->size += realsize(type, size); + return; + } + + switch (type) { + case OUT_RESERVE: + if (s != sbss) { + error(ERR_WARNING, "uninitialized space declared in" + " %s section: zeroing", + get_section_name_by_index(secto)); + + sect_write(s, NULL, size); + } else + s->size += size; + + break; + + case OUT_RAWDATA: + if (section != NO_SEG) + error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG"); + + sect_write(s, data, size); + break; + + case OUT_ADDRESS: + addr = *(int64_t *)data; + if (section != NO_SEG) { + if (section % 2) { + error(ERR_NONFATAL, "Mach-O format does not support" + " section base references"); + } else { + if (wrt == NO_SEG) { + if (size < 8) { + error(ERR_NONFATAL, "Mach-O 64-bit format does not support" + " 32-bit absolute addresses"); + /* + Seemingly, Mach-O's X86_64_RELOC_SUBTRACTOR would require + pre-determined knowledge of where the image base would be, + making it impractical for use in intermediate object files + */ + } else { + addr -= add_reloc(s, section, 0, size, addr); + } + } else if (wrt == macho_gotpcrel_sect) { + addr += s->size; + add_reloc(s, section, 3, size, addr); // X86_64_RELOC_GOT + } else { + error(ERR_NONFATAL, "Mach-O format does not support" + " this use of WRT"); + } + } + } + + p = mydata; + WRITEADDR(p, addr, size); + sect_write(s, mydata, size); + break; + + case OUT_REL2ADR: + p = mydata; + WRITESHORT(p, *(int64_t *)data); + + 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 { + if (wrt == NO_SEG) { + *mydata -= add_reloc(s, section, 2, 2, (int64_t)*mydata); + *mydata -= add_reloc(s, section, 0, 2, (int64_t)*mydata); + } else { + error(ERR_NONFATAL, "Unsupported non-32-bit" + " Macho-O relocation [2]"); + } + } + + sect_write(s, mydata, 2L); + break; + + case OUT_REL4ADR: + p = mydata; + WRITELONG(p, *(int64_t *)data); + + 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 { + if (wrt == NO_SEG) { + *mydata -= add_reloc(s, section, 1, 4, (int64_t)*mydata); // X86_64_RELOC_UNSIGNED/SIGNED/BRANCH + } else if (wrt == macho_gotpcrel_sect) { + error(ERR_NONFATAL, "Mach-O format cannot produce PC-" + "relative GOT references"); + } else { + error(ERR_NONFATAL, "Mach-O format does not support" + " this use of WRT"); + wrt = NO_SEG; /* we can at least _try_ to continue */ + } + } + + sect_write(s, mydata, 4L); + break; + + default: + error(ERR_PANIC, "unknown output type?"); + break; + } +} + +static int32_t macho_section(char *name, int pass, int *bits) +{ + int32_t index, originalIndex; + char *sectionAttributes; + struct sectmap *sm; + struct section *s; + + (void)pass; + + /* Default to 64 bits. */ + if (!name) { + *bits = 64; + name = ".text"; + sectionAttributes = NULL; + } else { + sectionAttributes = name; + name = nasm_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 = -1; + + 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 = nasm_strsep(§ionAttributes, " \t"))) { + if (0 != *currentAttribute) { + if (!nasm_strnicmp("align=", currentAttribute, 6)) { + char *end; + int newAlignment, value; + + value = strtoul(currentAttribute + 6, (char**)&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) + && (s->align != -1)) { + 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 (!nasm_stricmp("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, int32_t section, int64_t 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; + + if (name[0] == '.' && name[1] == '.' && name[2] != '@') { + /* + * This is a NASM special symbol. We never allow it into + * the Macho-O symbol table, even if it's a valid one. If it + * _isn't_ a valid one, we should barf immediately. + */ + if (strcmp(name, "..gotpcrel")) + error(ERR_NONFATAL, "unrecognized special symbol `%s'", name); + return; + } + + /* 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); + + /* track the initially allocated symbol number for use in future fix-ups */ + sym->initial_snum = nsyms; + + 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); + + 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 int32_t macho_segbase(int32_t section) +{ + return section; +} + +static int macho_directive(char *directive, char *value, int pass) +{ + (void)directive; + (void)value; + (void)pass; + return 0; +} + +static void macho_filename(char *inname, char *outname, efunc error) +{ + standard_extension(inname, outname, ".o", error); +} + +extern macros_t macho_stdmac[]; + +/* 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 (uint32_t *numsyms, + uint32_t *strtabsize) +{ + struct symbol *sym, **symp; + uint32_t 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, (int32_t)(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, (int32_t)(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) { + uint64_t pad = 0; + + /* zerofill sections aren't actually written to the file */ + if ((s->flags & SECTION_TYPE) != S_ZEROFILL) + seg_filesize64 += s->size; + + /* recalculate segment address based on alignment and vm size */ + s->addr = seg_vmsize64; + /* we need section alignment to calculate final section address */ + if (s->align == -1) + s->align = DEFAULT_SECTION_ALIGNMENT; + if(s->align) { + uint64_t newaddr = align(s->addr, 1 << s->align); + pad = newaddr - s->addr; + s->addr = newaddr; + } + + seg_vmsize64 += s->size + pad; + ++seg_nsects64; + } + + /* calculate size of all headers, load commands and sections to + ** get a pointer to the start of all the raw data */ + if (seg_nsects64 > 0) { + ++head_ncmds64; + head_sizeofcmds64 += + MACHO_SEGCMD64_SIZE + seg_nsects64 * MACHO_SECTCMD64_SIZE; + } + + if (nsyms > 0) { + ++head_ncmds64; + head_sizeofcmds64 += MACHO_SYMCMD_SIZE; + } +} + +/* Write out the header information for the file. */ + +static void macho_write_header (void) +{ + fwriteint32_t(MH_MAGIC_64, machofp); /* magic */ + fwriteint32_t(CPU_TYPE_X86_64, machofp); /* CPU type */ + fwriteint32_t(CPU_SUBTYPE_I386_ALL, machofp); /* CPU subtype */ + fwriteint32_t(MH_OBJECT, machofp); /* Mach-O file type */ + fwriteint32_t(head_ncmds64, machofp); /* number of load commands */ + fwriteint32_t(head_sizeofcmds64, machofp); /* size of load commands */ + fwriteint32_t(0, machofp); /* no flags */ + fwriteint32_t(0, machofp); /* reserved for future use */ +} + +/* Write out the segment load command at offset. */ + +static uint32_t macho_write_segment (uint64_t offset) +{ + uint64_t rel_base = alignint64_t (offset + seg_filesize64); + uint32_t s_reloff = 0; + struct section *s; + + fwriteint32_t(LC_SEGMENT_64, machofp); /* cmd == LC_SEGMENT_64 */ + + /* size of load command including section load commands */ + fwriteint32_t(MACHO_SEGCMD64_SIZE + seg_nsects64 * + MACHO_SECTCMD64_SIZE, machofp); + + /* in an MH_OBJECT file all sections are in one unnamed (name + ** all zeros) segment */ + fwritezero(16, machofp); + fwriteint64_t(0, machofp); /* in-memory offset */ + fwriteint64_t(seg_vmsize64, machofp); /* in-memory size */ + fwriteint64_t(offset, machofp); /* in-file offset to data */ + fwriteint64_t(seg_filesize64, machofp); /* in-file size */ + fwriteint32_t(VM_PROT_DEFAULT, machofp); /* maximum vm protection */ + fwriteint32_t(VM_PROT_DEFAULT, machofp); /* initial vm protection */ + fwriteint32_t(seg_nsects64, machofp); /* number of sections */ + fwriteint32_t(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); + fwriteint64_t(s->addr, machofp); + fwriteint64_t(s->size, machofp); + + /* dummy data for zerofill sections or proper values */ + if ((s->flags & SECTION_TYPE) != S_ZEROFILL) { + fwriteint32_t(offset, machofp); + /* Write out section alignment, as a power of two. + e.g. 32-bit word alignment would be 2 (2^2 = 4). */ + if (s->align == -1) + s->align = DEFAULT_SECTION_ALIGNMENT; + fwriteint32_t(s->align, machofp); + /* To be compatible with cctools as we emit + a zero reloff if we have no relocations. */ + fwriteint32_t(s->nreloc ? rel_base + s_reloff : 0, machofp); + fwriteint32_t(s->nreloc, machofp); + + offset += s->size; + s_reloff += s->nreloc * MACHO_RELINFO64_SIZE; + } else { + fwriteint32_t(0, machofp); + fwriteint32_t(0, machofp); + fwriteint32_t(0, machofp); + fwriteint32_t(0, machofp); + } + + if (s->nreloc) { + s->flags |= S_ATTR_LOC_RELOC; + if (s->extreloc) + s->flags |= S_ATTR_EXT_RELOC; + } + + fwriteint32_t(s->flags, machofp); /* flags */ + fwriteint32_t(0, machofp); /* reserved */ + fwriteint32_t(0, machofp); /* reserved */ + + fwriteint32_t(0, machofp); /* align */ + } + + rel_padcnt64 = 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) { + uint32_t word2; + + fwriteint32_t(r->addr, machofp); /* reloc offset */ + + word2 = r->snum; + word2 |= r->pcrel << 24; + word2 |= r->length << 25; + word2 |= r->ext << 27; + word2 |= r->type << 28; + fwriteint32_t(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; + uint8_t fi, *p, *q, blk[8]; + int32_t len; + int64_t 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) { + len = (int32_t)r->length << 1; + if(len > 4) len = 8; + saa_fread(s->data, r->addr, blk, len); + p = q = blk; + l = *p++; + + /* get offset based on relocation type */ + if (r->length > 0) { + l += ((int64_t)*p++) << 8; + + if (r->length > 1) { + l += ((int64_t)*p++) << 16; + l += ((int64_t)*p++) << 24; + } + + if (r->length > 2) { + l += ((int64_t)*p++) << 32; + l += ((int64_t)*p++) << 40; + l += ((int64_t)*p++) << 48; + l += ((int64_t)*p++) << 56; + } + + + } + + /* 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) { + /* generate final address by section address and offset */ + for (s2 = sects, fi = 1; + s2 != NULL; s2 = s2->next, fi++) { + if (fi == r->snum) { + l += s2->addr; + break; + } + } + } + + /* write new offset back */ + if (r->length == 3) + WRITEDLONG(q, l); + else 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, len); + } + + /* dump the section data to file */ + saa_fpwrite(s->data, machofp); + } + + /* pad last section up to reloc entries on int64_t boundary */ + fwritezero(rel_padcnt64, 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; + int64_t fi; + uint64_t 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) { + fwriteint32_t(sym->strx, machofp); /* string table entry number */ + fwrite(&sym->type, 1, 1, machofp); /* symbol type */ + fwrite(&sym->sect, 1, 1, machofp); /* section */ + fwriteint16_t(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; + } + + fwriteint64_t(sym->value, machofp); /* value (i.e. offset) */ + } + } + + for (i = 0; i < nextdefsym; i++) { + sym = extdefsyms[i]; + fwriteint32_t(sym->strx, machofp); + fwrite(&sym->type, 1, 1, machofp); /* symbol type */ + fwrite(&sym->sect, 1, 1, machofp); /* section */ + fwriteint16_t(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; + } + + fwriteint64_t(sym->value, machofp); /* value (i.e. offset) */ + } + + for (i = 0; i < nundefsym; i++) { + sym = undefsyms[i]; + fwriteint32_t(sym->strx, machofp); + fwrite(&sym->type, 1, 1, machofp); /* symbol type */ + fwrite(&sym->sect, 1, 1, machofp); /* section */ + fwriteint16_t(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; + } + + fwriteint64_t(sym->value, machofp); // value (i.e. offset) + } + +} + +/* Fixup the snum in the relocation entries, we should be + doing this only for externally referenced symbols. */ +static void macho_fixup_relocs (struct reloc *r) +{ + struct symbol *sym; + + while (r != NULL) { + if (r->ext) { + for (sym = syms; sym != NULL; sym = sym->next) { + if (sym->initial_snum == r->snum) { + r->snum = sym->snum; + break; + } + } + } + r = r->next; + } +} + +/* Write out the object file. */ + +static void macho_write (void) +{ + uint64_t offset = 0; + + /* mach-o object file structure: + ** + ** mach header + ** uint32_t magic + ** int cpu type + ** int cpu subtype + ** uint32_t mach file type + ** uint32_t number of load commands + ** uint32_t size of all load commands + ** (includes section struct size of segment command) + ** uint32_t flags + ** + ** segment command + ** uint32_t command type == LC_SEGMENT_64 + ** uint32_t size of load command + ** (including section load commands) + ** char[16] segment name + ** uint64_t in-memory offset + ** uint64_t in-memory size + ** uint64_t in-file offset to data area + ** uint64_t in-file size + ** (in-memory size excluding zerofill sections) + ** int maximum vm protection + ** int initial vm protection + ** uint32_t number of sections + ** uint32_t flags + ** + ** section commands + ** char[16] section name + ** char[16] segment name + ** uint64_t in-memory offset + ** uint64_t in-memory size + ** uint32_t in-file offset + ** uint32_t alignment + ** (irrelevant in MH_OBJECT) + ** uint32_t in-file offset of relocation entires + ** uint32_t number of relocations + ** uint32_t flags + ** uint32_t reserved + ** uint32_t reserved + ** + ** symbol table command + ** uint32_t command type == LC_SYMTAB + ** uint32_t size of load command + ** uint32_t symbol table offset + ** uint32_t number of symbol table entries + ** uint32_t string table offset + ** uint32_t string table size + ** + ** raw section data + ** + ** padding to int64_t boundary + ** + ** relocation data (struct reloc) + ** int32_t offset + ** uint data (symbolnum, pcrel, length, extern, type) + ** + ** symbol table data (struct nlist) + ** int32_t string table entry number + ** uint8_t type + ** (extern, absolute, defined in section) + ** uint8_t section + ** (0 for global symbols, section number of definition (>= 1, <= + ** 254) for local symbols, size of variable for common symbols + ** [type == extern]) + ** int16_t description + ** (for stab debugging format) + ** uint64_t 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_HEADER64_SIZE + head_sizeofcmds64; + + /* emit the segment load command */ + if (seg_nsects64 > 0) + offset = macho_write_segment (offset); + else + error(ERR_WARNING, "no sections?"); + + if (nsyms > 0) { + /* write out symbol command */ + fwriteint32_t(LC_SYMTAB, machofp); /* cmd == LC_SYMTAB */ + fwriteint32_t(MACHO_SYMCMD_SIZE, machofp); /* size of load command */ + fwriteint32_t(offset, machofp); /* symbol table offset */ + fwriteint32_t(nsyms, machofp); /* number of symbol + ** table entries */ + + offset += nsyms * MACHO_NLIST64_SIZE; + fwriteint32_t(offset, machofp); /* string table offset */ + fwriteint32_t(strslen, machofp); /* string table size */ + } + + /* emit section data */ + if (seg_nsects64 > 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_NLIST64_SIZE == 16 */ + + /* 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: %"PRId32"\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_macho64 = { + "NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (x86_64) object files", + "macho64", + 0, + 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/rbtree.c b/rbtree.c new file mode 100644 index 00000000..5af6067d --- /dev/null +++ b/rbtree.c @@ -0,0 +1,119 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 1996-2009 The NASM Authors - All Rights Reserved + * See the file AUTHORS included with the NASM distribution for + * the specific copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following + * conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ----------------------------------------------------------------------- */ + +/* + * rbtree.c + * + * Simple implementation of a left-leaning red-black tree with 64-bit + * integer keys. The search operation will return the highest node <= + * the key; only search and insert are supported, but additional + * standard llrbtree operations can be coded up at will. + * + * See http://www.cs.princeton.edu/~rs/talks/LLRB/RedBlack.pdf for + * information about left-leaning red-black trees. + */ + +#include "rbtree.h" + +struct rbtree *rb_search(struct rbtree *tree, uint64_t key) +{ + struct rbtree *best = NULL; + + while (tree) { + if (tree->key == key) + return tree; + else if (tree->key > key) + tree = tree->left; + else { + best = tree; + tree = tree->right; + } + } + return best; +} + +static bool is_red(struct rbtree *h) +{ + return h && h->red; +} + +static struct rbtree *rotate_left(struct rbtree *h) +{ + struct rbtree *x = h->right; + h->right = x->left; + x->left = h; + x->red = x->left->red; + x->left->red = true; + return x; +} + +static struct rbtree *rotate_right(struct rbtree *h) +{ + struct rbtree *x = h->left; + h->left = x->right; + x->right = h; + x->red = x->right->red; + x->right->red = true; + return x; +} + +static void color_flip(struct rbtree *h) +{ + h->red = !h->red; + h->left->red = !h->left->red; + h->right->red = !h->right->red; +} + +struct rbtree *rb_insert(struct rbtree *tree, struct rbtree *node) +{ + if (!tree) { + node->red = true; + return node; + } + + if (is_red(tree->left) && is_red(tree->right)) + color_flip(tree); + + if (node->key < tree->key) + tree->left = rb_insert(tree->left, node); + else + tree->right = rb_insert(tree->right, node); + + if (is_red(tree->right)) + tree = rotate_left(tree); + + if (is_red(tree->left) && is_red(tree->left->left)) + tree = rotate_right(tree); + + return tree; +} diff --git a/rbtree.h b/rbtree.h new file mode 100644 index 00000000..ef34789f --- /dev/null +++ b/rbtree.h @@ -0,0 +1,52 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 1996-2009 The NASM Authors - All Rights Reserved + * See the file AUTHORS included with the NASM distribution for + * the specific copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following + * conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ----------------------------------------------------------------------- */ + +#ifndef NASM_RBTREE_H +#define NASM_RBTREE_H + +#include "compiler.h" +#include <inttypes.h> + +/* This structure should be embedded in a larger data structure; + the final output from rb_search() can then be converted back + to the larger data structure via container_of(). */ +struct rbtree { + uint64_t key; + struct rbtree *left, *right; + bool red; +}; + +struct rbtree *rb_insert(struct rbtree *, struct rbtree *); +struct rbtree *rb_search(struct rbtree *, uint64_t); + +#endif /* NASM_RBTREE_H */ diff --git a/rdoff/rdf2ihx.1 b/rdoff/rdf2ihx.1 new file mode 100644 index 00000000..43b33071 --- /dev/null +++ b/rdoff/rdf2ihx.1 @@ -0,0 +1 @@ +.so man1/rdf2bin.1 diff --git a/rdoff/rdf2ith.1 b/rdoff/rdf2ith.1 new file mode 100644 index 00000000..43b33071 --- /dev/null +++ b/rdoff/rdf2ith.1 @@ -0,0 +1 @@ +.so man1/rdf2bin.1 diff --git a/rdoff/rdf2srec.1 b/rdoff/rdf2srec.1 new file mode 100644 index 00000000..43b33071 --- /dev/null +++ b/rdoff/rdf2srec.1 @@ -0,0 +1 @@ +.so man1/rdf2bin.1 diff --git a/test/align13.asm b/test/align13.asm new file mode 100644 index 00000000..556373fc --- /dev/null +++ b/test/align13.asm @@ -0,0 +1,16 @@ +; Test of non-power-of-2 alignment + + bits 32 + + inc eax + inc eax + align 13 + inc eax + inc eax + align 13 + inc eax + inc eax + align 13 + align 13 ;should do nothing + inc eax + inc eax diff --git a/test/align13s.asm b/test/align13s.asm new file mode 100644 index 00000000..dab21a20 --- /dev/null +++ b/test/align13s.asm @@ -0,0 +1,16 @@ +; Test of non-power-of-2 alignment +%use smartalign + + bits 32 + + inc eax + inc eax + align 13 + inc eax + inc eax + align 13 + inc eax + inc eax + align 13 + inc eax + inc eax diff --git a/test/andbyte.asm b/test/andbyte.asm new file mode 100644 index 00000000..3d3b1c1a --- /dev/null +++ b/test/andbyte.asm @@ -0,0 +1,15 @@ +;Testname=test; Arguments=-fbin -oandbyte.bin; Files=stdout stderr andbyte.bin +;Testname=otest; Arguments=-Ox -fbin -oandbyte.bin; Files=stdout stderr andbyte.bin + + bits 16 + + add sp, byte -0x10 + add sp, -0x10 + adc sp, byte -0x10 + adc sp, -0x10 + and sp, byte -0x10 + and sp, -0x10 + sbb sp, byte -0x10 + sbb sp, -0x10 + sub sp, byte -0x10 + sub sp, -0x10 diff --git a/test/avx005.asm b/test/avx005.asm new file mode 100644 index 00000000..08765140 --- /dev/null +++ b/test/avx005.asm @@ -0,0 +1,529 @@ +;Testname=avx005; Arguments=-fbin -oavx005.bin -Ox; Files=stdout stderr avx005.bin + +%define regxmm xmm0 +%define regymm ymm0 +%define mem [0] +%define imm 3 + +%macro x 1+.nolist + %1 ; comment this line if RELAXed variants are not supported +%endmacro + + VFMADDSUB132PS regxmm,regxmm,mem ; VEX_FMA,SO + VFMADDSUB132PS regxmm,regxmm,regxmm ; VEX_FMA + VFMADDSUB132PS regymm,regymm,mem ; VEX_FMA,SY + VFMADDSUB132PS regymm,regymm,regymm ; VEX_FMA + +x VFMADDSUB312PS regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFMADDSUB312PS regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFMADDSUB312PS regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFMADDSUB312PS regymm,regymm,regymm ; VEX_FMA,RELAX + + VFMADDSUB132PD regxmm,regxmm,mem ; VEX_FMA,SO + VFMADDSUB132PD regxmm,regxmm,regxmm ; VEX_FMA + VFMADDSUB132PD regymm,regymm,mem ; VEX_FMA,SY + VFMADDSUB132PD regymm,regymm,regymm ; VEX_FMA + +x VFMADDSUB312PD regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFMADDSUB312PD regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFMADDSUB312PD regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFMADDSUB312PD regymm,regymm,regymm ; VEX_FMA,RELAX + + VFMSUBADD132PS regxmm,regxmm,mem ; VEX_FMA,SO + VFMSUBADD132PS regxmm,regxmm,regxmm ; VEX_FMA + VFMSUBADD132PS regymm,regymm,mem ; VEX_FMA,SY + VFMSUBADD132PS regymm,regymm,regymm ; VEX_FMA + +x VFMSUBADD312PS regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFMSUBADD312PS regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFMSUBADD312PS regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFMSUBADD312PS regymm,regymm,regymm ; VEX_FMA,RELAX + + VFMSUBADD132PD regxmm,regxmm,mem ; VEX_FMA,SO + VFMSUBADD132PD regxmm,regxmm,regxmm ; VEX_FMA + VFMSUBADD132PD regymm,regymm,mem ; VEX_FMA,SY + VFMSUBADD132PD regymm,regymm,regymm ; VEX_FMA + +x VFMSUBADD312PD regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFMSUBADD312PD regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFMSUBADD312PD regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFMSUBADD312PD regymm,regymm,regymm ; VEX_FMA,RELAX + + VFMADD132PS regxmm,regxmm,mem ; VEX_FMA,SO + VFMADD132PS regxmm,regxmm,regxmm ; VEX_FMA + VFMADD132PS regymm,regymm,mem ; VEX_FMA,SY + VFMADD132PS regymm,regymm,regymm ; VEX_FMA + +x VFMADD312PS regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFMADD312PS regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFMADD312PS regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFMADD312PS regymm,regymm,regymm ; VEX_FMA,RELAX + + VFMADD132PD regxmm,regxmm,mem ; VEX_FMA,SO + VFMADD132PD regxmm,regxmm,regxmm ; VEX_FMA + VFMADD132PD regymm,regymm,mem ; VEX_FMA,SY + VFMADD132PD regymm,regymm,regymm ; VEX_FMA + +x VFMADD312PD regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFMADD312PD regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFMADD312PD regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFMADD312PD regymm,regymm,regymm ; VEX_FMA,RELAX + + VFMADD132SS regxmm,regxmm,mem ; VEX_FMA,SD + VFMADD132SS regxmm,regxmm,regxmm ; VEX_FMA + +x VFMADD312SS regxmm,regxmm,mem ; VEX_FMA,RELAX,SD +x VFMADD312SS regxmm,regxmm,regxmm ; VEX_FMA,RELAX + + VFMADD132SD regxmm,regxmm,mem ; VEX_FMA,SQ + VFMADD132SD regxmm,regxmm,regxmm ; VEX_FMA + +x VFMADD312SD regxmm,regxmm,mem ; VEX_FMA,RELAX,SQ +x VFMADD312SD regxmm,regxmm,regxmm ; VEX_FMA,RELAX + + VFMSUB132PS regxmm,regxmm,mem ; VEX_FMA,SO + VFMSUB132PS regxmm,regxmm,regxmm ; VEX_FMA + VFMSUB132PS regymm,regymm,mem ; VEX_FMA,SY + VFMSUB132PS regymm,regymm,regymm ; VEX_FMA + +x VFMSUB312PS regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFMSUB312PS regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFMSUB312PS regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFMSUB312PS regymm,regymm,regymm ; VEX_FMA,RELAX + + VFMSUB132PD regxmm,regxmm,mem ; VEX_FMA,SO + VFMSUB132PD regxmm,regxmm,regxmm ; VEX_FMA + VFMSUB132PD regymm,regymm,mem ; VEX_FMA,SY + VFMSUB132PD regymm,regymm,regymm ; VEX_FMA + +x VFMSUB312PD regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFMSUB312PD regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFMSUB312PD regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFMSUB312PD regymm,regymm,regymm ; VEX_FMA,RELAX + + VFMSUB132SS regxmm,regxmm,mem ; VEX_FMA,SD + VFMSUB132SS regxmm,regxmm,regxmm ; VEX_FMA + +x VFMSUB312SS regxmm,regxmm,mem ; VEX_FMA,RELAX,SD +x VFMSUB312SS regxmm,regxmm,regxmm ; VEX_FMA,RELAX + + VFMSUB132SD regxmm,regxmm,mem ; VEX_FMA,SQ + VFMSUB132SD regxmm,regxmm,regxmm ; VEX_FMA + +x VFMSUB312SD regxmm,regxmm,mem ; VEX_FMA,RELAX,SQ +x VFMSUB312SD regxmm,regxmm,regxmm ; VEX_FMA,RELAX + + VFNMADD132PS regxmm,regxmm,mem ; VEX_FMA,SO + VFNMADD132PS regxmm,regxmm,regxmm ; VEX_FMA + VFNMADD132PS regymm,regymm,mem ; VEX_FMA,SY + VFNMADD132PS regymm,regymm,regymm ; VEX_FMA + +x VFNMADD312PS regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFNMADD312PS regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFNMADD312PS regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFNMADD312PS regymm,regymm,regymm ; VEX_FMA,RELAX + + VFNMADD132PD regxmm,regxmm,mem ; VEX_FMA,SO + VFNMADD132PD regxmm,regxmm,regxmm ; VEX_FMA + VFNMADD132PD regymm,regymm,mem ; VEX_FMA,SY + VFNMADD132PD regymm,regymm,regymm ; VEX_FMA + +x VFNMADD312PD regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFNMADD312PD regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFNMADD312PD regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFNMADD312PD regymm,regymm,regymm ; VEX_FMA,RELAX + + VFNMADD132SS regxmm,regxmm,mem ; VEX_FMA,SD + VFNMADD132SS regxmm,regxmm,regxmm ; VEX_FMA + +x VFNMADD312SS regxmm,regxmm,mem ; VEX_FMA,RELAX,SD +x VFNMADD312SS regxmm,regxmm,regxmm ; VEX_FMA,RELAX + + VFNMADD132SD regxmm,regxmm,mem ; VEX_FMA,SQ + VFNMADD132SD regxmm,regxmm,regxmm ; VEX_FMA + +x VFNMADD312SD regxmm,regxmm,mem ; VEX_FMA,RELAX,SQ +x VFNMADD312SD regxmm,regxmm,regxmm ; VEX_FMA,RELAX + + VFNMSUB132PS regxmm,regxmm,mem ; VEX_FMA,SO + VFNMSUB132PS regxmm,regxmm,regxmm ; VEX_FMA + VFNMSUB132PS regymm,regymm,mem ; VEX_FMA,SY + VFNMSUB132PS regymm,regymm,regymm ; VEX_FMA + +x VFNMSUB312PS regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFNMSUB312PS regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFNMSUB312PS regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFNMSUB312PS regymm,regymm,regymm ; VEX_FMA,RELAX + + VFNMSUB132PD regxmm,regxmm,mem ; VEX_FMA,SO + VFNMSUB132PD regxmm,regxmm,regxmm ; VEX_FMA + VFNMSUB132PD regymm,regymm,mem ; VEX_FMA,SY + VFNMSUB132PD regymm,regymm,regymm ; VEX_FMA + +x VFNMSUB312PD regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFNMSUB312PD regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFNMSUB312PD regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFNMSUB312PD regymm,regymm,regymm ; VEX_FMA,RELAX + + VFNMSUB132SS regxmm,regxmm,mem ; VEX_FMA,SD + VFNMSUB132SS regxmm,regxmm,regxmm ; VEX_FMA + +x VFNMSUB312SS regxmm,regxmm,mem ; VEX_FMA,RELAX,SD +x VFNMSUB312SS regxmm,regxmm,regxmm ; VEX_FMA,RELAX + + VFNMSUB132SD regxmm,regxmm,mem ; VEX_FMA,SQ + VFNMSUB132SD regxmm,regxmm,regxmm ; VEX_FMA + +x VFNMSUB312SD regxmm,regxmm,mem ; VEX_FMA,RELAX,SQ +x VFNMSUB312SD regxmm,regxmm,regxmm ; VEX_FMA,RELAX + + VFMADDSUB213PS regxmm,regxmm,mem ; VEX_FMA,SO + VFMADDSUB213PS regxmm,regxmm,regxmm ; VEX_FMA + VFMADDSUB213PS regymm,regymm,mem ; VEX_FMA,SY + VFMADDSUB213PS regymm,regymm,regymm ; VEX_FMA + +x VFMADDSUB123PS regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFMADDSUB123PS regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFMADDSUB123PS regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFMADDSUB123PS regymm,regymm,regymm ; VEX_FMA,RELAX + + VFMADDSUB213PD regxmm,regxmm,mem ; VEX_FMA,SO + VFMADDSUB213PD regxmm,regxmm,regxmm ; VEX_FMA + VFMADDSUB213PD regymm,regymm,mem ; VEX_FMA,SY + VFMADDSUB213PD regymm,regymm,regymm ; VEX_FMA + +x VFMADDSUB123PD regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFMADDSUB123PD regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFMADDSUB123PD regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFMADDSUB123PD regymm,regymm,regymm ; VEX_FMA,RELAX + + VFMSUBADD213PS regxmm,regxmm,mem ; VEX_FMA,SO + VFMSUBADD213PS regxmm,regxmm,regxmm ; VEX_FMA + VFMSUBADD213PS regymm,regymm,mem ; VEX_FMA,SY + VFMSUBADD213PS regymm,regymm,regymm ; VEX_FMA + +x VFMSUBADD123PS regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFMSUBADD123PS regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFMSUBADD123PS regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFMSUBADD123PS regymm,regymm,regymm ; VEX_FMA,RELAX + + VFMSUBADD213PD regxmm,regxmm,mem ; VEX_FMA,SO + VFMSUBADD213PD regxmm,regxmm,regxmm ; VEX_FMA + VFMSUBADD213PD regymm,regymm,mem ; VEX_FMA,SY + VFMSUBADD213PD regymm,regymm,regymm ; VEX_FMA + +x VFMSUBADD123PD regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFMSUBADD123PD regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFMSUBADD123PD regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFMSUBADD123PD regymm,regymm,regymm ; VEX_FMA,RELAX + + VFMADD213PS regxmm,regxmm,mem ; VEX_FMA,SO + VFMADD213PS regxmm,regxmm,regxmm ; VEX_FMA + VFMADD213PS regymm,regymm,mem ; VEX_FMA,SY + VFMADD213PS regymm,regymm,regymm ; VEX_FMA + +x VFMADD123PS regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFMADD123PS regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFMADD123PS regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFMADD123PS regymm,regymm,regymm ; VEX_FMA,RELAX + + VFMADD213PD regxmm,regxmm,mem ; VEX_FMA,SO + VFMADD213PD regxmm,regxmm,regxmm ; VEX_FMA + VFMADD213PD regymm,regymm,mem ; VEX_FMA,SY + VFMADD213PD regymm,regymm,regymm ; VEX_FMA + +x VFMADD123PD regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFMADD123PD regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFMADD123PD regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFMADD123PD regymm,regymm,regymm ; VEX_FMA,RELAX + + VFMADD213SS regxmm,regxmm,mem ; VEX_FMA,SD + VFMADD213SS regxmm,regxmm,regxmm ; VEX_FMA + +x VFMADD123SS regxmm,regxmm,mem ; VEX_FMA,RELAX,SD +x VFMADD123SS regxmm,regxmm,regxmm ; VEX_FMA,RELAX + + VFMADD213SD regxmm,regxmm,mem ; VEX_FMA,SQ + VFMADD213SD regxmm,regxmm,regxmm ; VEX_FMA + +x VFMADD123SD regxmm,regxmm,mem ; VEX_FMA,RELAX,SQ +x VFMADD123SD regxmm,regxmm,regxmm ; VEX_FMA,RELAX + + VFMSUB213PS regxmm,regxmm,mem ; VEX_FMA,SO + VFMSUB213PS regxmm,regxmm,regxmm ; VEX_FMA + VFMSUB213PS regymm,regymm,mem ; VEX_FMA,SY + VFMSUB213PS regymm,regymm,regymm ; VEX_FMA + +x VFMSUB123PS regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFMSUB123PS regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFMSUB123PS regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFMSUB123PS regymm,regymm,regymm ; VEX_FMA,RELAX + + VFMSUB213PD regxmm,regxmm,mem ; VEX_FMA,SO + VFMSUB213PD regxmm,regxmm,regxmm ; VEX_FMA + VFMSUB213PD regymm,regymm,mem ; VEX_FMA,SY + VFMSUB213PD regymm,regymm,regymm ; VEX_FMA + +x VFMSUB123PD regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFMSUB123PD regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFMSUB123PD regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFMSUB123PD regymm,regymm,regymm ; VEX_FMA,RELAX + + VFMSUB213SS regxmm,regxmm,mem ; VEX_FMA,SD + VFMSUB213SS regxmm,regxmm,regxmm ; VEX_FMA + +x VFMSUB123SS regxmm,regxmm,mem ; VEX_FMA,RELAX,SD +x VFMSUB123SS regxmm,regxmm,regxmm ; VEX_FMA,RELAX + + VFMSUB213SD regxmm,regxmm,mem ; VEX_FMA,SQ + VFMSUB213SD regxmm,regxmm,regxmm ; VEX_FMA + +x VFMSUB123SD regxmm,regxmm,mem ; VEX_FMA,RELAX,SQ +x VFMSUB123SD regxmm,regxmm,regxmm ; VEX_FMA,RELAX + + VFNMADD213PS regxmm,regxmm,mem ; VEX_FMA,SO + VFNMADD213PS regxmm,regxmm,regxmm ; VEX_FMA + VFNMADD213PS regymm,regymm,mem ; VEX_FMA,SY + VFNMADD213PS regymm,regymm,regymm ; VEX_FMA + +x VFNMADD123PS regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFNMADD123PS regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFNMADD123PS regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFNMADD123PS regymm,regymm,regymm ; VEX_FMA,RELAX + + VFNMADD213PD regxmm,regxmm,mem ; VEX_FMA,SO + VFNMADD213PD regxmm,regxmm,regxmm ; VEX_FMA + VFNMADD213PD regymm,regymm,mem ; VEX_FMA,SY + VFNMADD213PD regymm,regymm,regymm ; VEX_FMA + +x VFNMADD123PD regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFNMADD123PD regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFNMADD123PD regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFNMADD123PD regymm,regymm,regymm ; VEX_FMA,RELAX + + VFNMADD213SS regxmm,regxmm,mem ; VEX_FMA,SD + VFNMADD213SS regxmm,regxmm,regxmm ; VEX_FMA + +x VFNMADD123SS regxmm,regxmm,mem ; VEX_FMA,RELAX,SD +x VFNMADD123SS regxmm,regxmm,regxmm ; VEX_FMA,RELAX + + VFNMADD213SD regxmm,regxmm,mem ; VEX_FMA,SQ + VFNMADD213SD regxmm,regxmm,regxmm ; VEX_FMA + +x VFNMADD123SD regxmm,regxmm,mem ; VEX_FMA,RELAX,SQ +x VFNMADD123SD regxmm,regxmm,regxmm ; VEX_FMA,RELAX + + VFNMSUB213PS regxmm,regxmm,mem ; VEX_FMA,SO + VFNMSUB213PS regxmm,regxmm,regxmm ; VEX_FMA + VFNMSUB213PS regymm,regymm,mem ; VEX_FMA,SY + VFNMSUB213PS regymm,regymm,regymm ; VEX_FMA + +x VFNMSUB123PS regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFNMSUB123PS regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFNMSUB123PS regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFNMSUB123PS regymm,regymm,regymm ; VEX_FMA,RELAX + + VFNMSUB213PD regxmm,regxmm,mem ; VEX_FMA,SO + VFNMSUB213PD regxmm,regxmm,regxmm ; VEX_FMA + VFNMSUB213PD regymm,regymm,mem ; VEX_FMA,SY + VFNMSUB213PD regymm,regymm,regymm ; VEX_FMA + +x VFNMSUB123PD regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFNMSUB123PD regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFNMSUB123PD regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFNMSUB123PD regymm,regymm,regymm ; VEX_FMA,RELAX + + VFNMSUB213SS regxmm,regxmm,mem ; VEX_FMA,SD + VFNMSUB213SS regxmm,regxmm,regxmm ; VEX_FMA + +x VFNMSUB123SS regxmm,regxmm,mem ; VEX_FMA,RELAX,SD +x VFNMSUB123SS regxmm,regxmm,regxmm ; VEX_FMA,RELAX + + VFNMSUB213SD regxmm,regxmm,mem ; VEX_FMA,SQ + VFNMSUB213SD regxmm,regxmm,regxmm ; VEX_FMA + +x VFNMSUB123SD regxmm,regxmm,mem ; VEX_FMA,RELAX,SQ +x VFNMSUB123SD regxmm,regxmm,regxmm ; VEX_FMA,RELAX + + VFMADDSUB231PS regxmm,regxmm,mem ; VEX_FMA,SO + VFMADDSUB231PS regxmm,regxmm,regxmm ; VEX_FMA + VFMADDSUB231PS regymm,regymm,mem ; VEX_FMA,SY + VFMADDSUB231PS regymm,regymm,regymm ; VEX_FMA + +x VFMADDSUB321PS regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFMADDSUB321PS regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFMADDSUB321PS regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFMADDSUB321PS regymm,regymm,regymm ; VEX_FMA,RELAX + + VFMADDSUB231PD regxmm,regxmm,mem ; VEX_FMA,SO + VFMADDSUB231PD regxmm,regxmm,regxmm ; VEX_FMA + VFMADDSUB231PD regymm,regymm,mem ; VEX_FMA,SY + VFMADDSUB231PD regymm,regymm,regymm ; VEX_FMA + +x VFMADDSUB321PD regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFMADDSUB321PD regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFMADDSUB321PD regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFMADDSUB321PD regymm,regymm,regymm ; VEX_FMA,RELAX + + VFMSUBADD231PS regxmm,regxmm,mem ; VEX_FMA,SO + VFMSUBADD231PS regxmm,regxmm,regxmm ; VEX_FMA + VFMSUBADD231PS regymm,regymm,mem ; VEX_FMA,SY + VFMSUBADD231PS regymm,regymm,regymm ; VEX_FMA + +x VFMSUBADD321PS regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFMSUBADD321PS regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFMSUBADD321PS regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFMSUBADD321PS regymm,regymm,regymm ; VEX_FMA,RELAX + + VFMSUBADD231PD regxmm,regxmm,mem ; VEX_FMA,SO + VFMSUBADD231PD regxmm,regxmm,regxmm ; VEX_FMA + VFMSUBADD231PD regymm,regymm,mem ; VEX_FMA,SY + VFMSUBADD231PD regymm,regymm,regymm ; VEX_FMA + +x VFMSUBADD321PD regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFMSUBADD321PD regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFMSUBADD321PD regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFMSUBADD321PD regymm,regymm,regymm ; VEX_FMA,RELAX + + VFMADD231PS regxmm,regxmm,mem ; VEX_FMA,SO + VFMADD231PS regxmm,regxmm,regxmm ; VEX_FMA + VFMADD231PS regymm,regymm,mem ; VEX_FMA,SY + VFMADD231PS regymm,regymm,regymm ; VEX_FMA + +x VFMADD321PS regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFMADD321PS regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFMADD321PS regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFMADD321PS regymm,regymm,regymm ; VEX_FMA,RELAX + + VFMADD231PD regxmm,regxmm,mem ; VEX_FMA,SO + VFMADD231PD regxmm,regxmm,regxmm ; VEX_FMA + VFMADD231PD regymm,regymm,mem ; VEX_FMA,SY + VFMADD231PD regymm,regymm,regymm ; VEX_FMA + +x VFMADD321PD regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFMADD321PD regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFMADD321PD regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFMADD321PD regymm,regymm,regymm ; VEX_FMA,RELAX + + VFMADD231SS regxmm,regxmm,mem ; VEX_FMA,SD + VFMADD231SS regxmm,regxmm,regxmm ; VEX_FMA + +x VFMADD321SS regxmm,regxmm,mem ; VEX_FMA,RELAX,SD +x VFMADD321SS regxmm,regxmm,regxmm ; VEX_FMA,RELAX + + VFMADD231SD regxmm,regxmm,mem ; VEX_FMA,SQ + VFMADD231SD regxmm,regxmm,regxmm ; VEX_FMA + +x VFMADD321SD regxmm,regxmm,mem ; VEX_FMA,RELAX,SQ +x VFMADD321SD regxmm,regxmm,regxmm ; VEX_FMA,RELAX + + VFMSUB231PS regxmm,regxmm,mem ; VEX_FMA,SO + VFMSUB231PS regxmm,regxmm,regxmm ; VEX_FMA + VFMSUB231PS regymm,regymm,mem ; VEX_FMA,SY + VFMSUB231PS regymm,regymm,regymm ; VEX_FMA + +x VFMSUB321PS regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFMSUB321PS regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFMSUB321PS regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFMSUB321PS regymm,regymm,regymm ; VEX_FMA,RELAX + + VFMSUB231PD regxmm,regxmm,mem ; VEX_FMA,SO + VFMSUB231PD regxmm,regxmm,regxmm ; VEX_FMA + VFMSUB231PD regymm,regymm,mem ; VEX_FMA,SY + VFMSUB231PD regymm,regymm,regymm ; VEX_FMA + +x VFMSUB321PD regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFMSUB321PD regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFMSUB321PD regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFMSUB321PD regymm,regymm,regymm ; VEX_FMA,RELAX + + VFMSUB231SS regxmm,regxmm,mem ; VEX_FMA,SD + VFMSUB231SS regxmm,regxmm,regxmm ; VEX_FMA + +x VFMSUB321SS regxmm,regxmm,mem ; VEX_FMA,RELAX,SD +x VFMSUB321SS regxmm,regxmm,regxmm ; VEX_FMA,RELAX + + VFMSUB231SD regxmm,regxmm,mem ; VEX_FMA,SQ + VFMSUB231SD regxmm,regxmm,regxmm ; VEX_FMA + +x VFMSUB321SD regxmm,regxmm,mem ; VEX_FMA,RELAX,SQ +x VFMSUB321SD regxmm,regxmm,regxmm ; VEX_FMA,RELAX + + VFNMADD231PS regxmm,regxmm,mem ; VEX_FMA,SO + VFNMADD231PS regxmm,regxmm,regxmm ; VEX_FMA + VFNMADD231PS regymm,regymm,mem ; VEX_FMA,SY + VFNMADD231PS regymm,regymm,regymm ; VEX_FMA + +x VFNMADD321PS regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFNMADD321PS regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFNMADD321PS regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFNMADD321PS regymm,regymm,regymm ; VEX_FMA,RELAX + + VFNMADD231PD regxmm,regxmm,mem ; VEX_FMA,SO + VFNMADD231PD regxmm,regxmm,regxmm ; VEX_FMA + VFNMADD231PD regymm,regymm,mem ; VEX_FMA,SY + VFNMADD231PD regymm,regymm,regymm ; VEX_FMA + +x VFNMADD321PD regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFNMADD321PD regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFNMADD321PD regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFNMADD321PD regymm,regymm,regymm ; VEX_FMA,RELAX + + VFNMADD231SS regxmm,regxmm,mem ; VEX_FMA,SD + VFNMADD231SS regxmm,regxmm,regxmm ; VEX_FMA + +x VFNMADD321SS regxmm,regxmm,mem ; VEX_FMA,RELAX,SD +x VFNMADD321SS regxmm,regxmm,regxmm ; VEX_FMA,RELAX + + VFNMADD231SD regxmm,regxmm,mem ; VEX_FMA,SQ + VFNMADD231SD regxmm,regxmm,regxmm ; VEX_FMA + +x VFNMADD321SD regxmm,regxmm,mem ; VEX_FMA,RELAX,SQ +x VFNMADD321SD regxmm,regxmm,regxmm ; VEX_FMA,RELAX + + VFNMSUB231PS regxmm,regxmm,mem ; VEX_FMA,SO + VFNMSUB231PS regxmm,regxmm,regxmm ; VEX_FMA + VFNMSUB231PS regymm,regymm,mem ; VEX_FMA,SY + VFNMSUB231PS regymm,regymm,regymm ; VEX_FMA + +x VFNMSUB321PS regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFNMSUB321PS regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFNMSUB321PS regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFNMSUB321PS regymm,regymm,regymm ; VEX_FMA,RELAX + + VFNMSUB231PD regxmm,regxmm,mem ; VEX_FMA,SO + VFNMSUB231PD regxmm,regxmm,regxmm ; VEX_FMA + VFNMSUB231PD regymm,regymm,mem ; VEX_FMA,SY + VFNMSUB231PD regymm,regymm,regymm ; VEX_FMA + +x VFNMSUB321PD regxmm,regxmm,mem ; VEX_FMA,RELAX,SO +x VFNMSUB321PD regxmm,regxmm,regxmm ; VEX_FMA,RELAX +x VFNMSUB321PD regymm,regymm,mem ; VEX_FMA,RELAX,SY +x VFNMSUB321PD regymm,regymm,regymm ; VEX_FMA,RELAX + + VFNMSUB231SS regxmm,regxmm,mem ; VEX_FMA,SD + VFNMSUB231SS regxmm,regxmm,regxmm ; VEX_FMA + +x VFNMSUB321SS regxmm,regxmm,mem ; VEX_FMA,RELAX,SD +x VFNMSUB321SS regxmm,regxmm,regxmm ; VEX_FMA,RELAX + + VFNMSUB231SD regxmm,regxmm,mem ; VEX_FMA,SQ + VFNMSUB231SD regxmm,regxmm,regxmm ; VEX_FMA + +x VFNMSUB321SD regxmm,regxmm,mem ; VEX_FMA,RELAX,SQ +x VFNMSUB321SD regxmm,regxmm,regxmm ; VEX_FMA,RELAX + + VPCLMULLQLQDQ regxmm,regxmm,mem ; PCLMUL,VEX_AVX,SO + VPCLMULLQLQDQ regxmm,regxmm,regxmm ; PCLMUL,VEX_AVX + VPCLMULHQLQDQ regxmm,regxmm,mem ; PCLMUL,VEX_AVX,SO + VPCLMULHQLQDQ regxmm,regxmm,regxmm ; PCLMUL,VEX_AVX + VPCLMULLQHQDQ regxmm,regxmm,mem ; PCLMUL,VEX_AVX,SO + VPCLMULLQHQDQ regxmm,regxmm,regxmm ; PCLMUL,VEX_AVX + VPCLMULHQHQDQ regxmm,regxmm,mem ; PCLMUL,VEX_AVX,SO + VPCLMULHQHQDQ regxmm,regxmm,regxmm ; PCLMUL,VEX_AVX + VPCLMULQDQ regxmm,regxmm,mem,imm ; PCLMUL,VEX_AVX,SB3,SO + VPCLMULQDQ regxmm,regxmm,regxmm,imm ; PCLMUL,VEX_AVX,SB3 + +; EOF + + diff --git a/test/br2148476.asm b/test/br2148476.asm new file mode 100644 index 00000000..1b263c98 --- /dev/null +++ b/test/br2148476.asm @@ -0,0 +1,221 @@ +;Testname=test; Arguments=-fbin -obr2148476.bin; Files=.stdout .stderr br2148476.bin + + bits 64 + + cvtdq2pd xmm0, xmm1 + cvtdq2pd xmm0, [rdi] + cvtdq2pd xmm0, qword [rdi] + + cvtdq2ps xmm0, xmm1 + cvtdq2ps xmm0, [rdi] + cvtdq2ps xmm0, oword [rdi] + + cvtpd2dq xmm0, xmm1 + cvtpd2dq xmm0, [rdi] + cvtpd2dq xmm0, oword [rdi] + + cvtpd2pi mm0, xmm1 + cvtpd2pi mm0, [rdi] + cvtpd2pi mm0, oword [rdi] + + cvtpd2ps xmm0, xmm1 + cvtpd2ps xmm0, [rdi] + cvtpd2ps xmm0, oword [rdi] + + cvtpi2pd xmm0, mm1 + cvtpi2pd xmm0, [rdi] + cvtpi2pd xmm0, qword [rdi] + + cvtpi2ps xmm0, mm1 + cvtpi2ps xmm0, [rdi] + cvtpi2ps xmm0, qword [rdi] + + cvtps2dq xmm0, xmm1 + cvtps2dq xmm0, [rdi] + cvtps2dq xmm0, oword [rdi] + + cvtps2pd xmm0, xmm1 + cvtps2pd xmm0, [rdi] + cvtps2pd xmm0, qword [rdi] + + cvtps2pi mm0, xmm1 + cvtps2pi mm0, [rdi] + cvtps2pi mm0, qword [rdi] + + cvtsd2si eax, xmm1 + cvtsd2si eax, [rdi] + cvtsd2si eax, qword [rdi] + cvtsd2si rax, xmm1 + cvtsd2si rax, [rdi] + cvtsd2si rax, qword [rdi] + + cvtsd2ss xmm0, xmm1 + cvtsd2ss xmm0, [rdi] + cvtsd2ss xmm0, qword [rdi] + + cvtsi2sd xmm0, eax + cvtsi2sd xmm0, [rdi] ; Compatibility + cvtsi2sd xmm0, dword [rdi] + cvtsi2sd xmm0, rax + cvtsi2sd xmm0, qword [rdi] + + cvtsi2ss xmm0, eax + cvtsi2ss xmm0, [rdi] ; Compatibility + cvtsi2ss xmm0, dword [rdi] + cvtsi2ss xmm0, rax + cvtsi2ss xmm0, qword [rdi] + + cvtss2sd xmm0, xmm1 + cvtss2sd xmm0, [rdi] + cvtss2sd xmm0, dword [rdi] + + cvtss2si eax, xmm1 + cvtss2si eax, [rdi] + cvtss2si eax, dword [rdi] + cvtss2si rax, xmm1 + cvtss2si rax, [rdi] + cvtss2si rax, dword [rdi] + + cvttpd2dq xmm0, xmm1 + cvttpd2dq xmm0, [rdi] + cvttpd2dq xmm0, oword [rdi] + + cvttpd2pi mm0, xmm1 + cvttpd2pi mm0, [rdi] + cvttpd2pi mm0, oword [rdi] + + cvttps2dq xmm0, xmm1 + cvttps2dq xmm0, [rdi] + cvttps2dq xmm0, oword [rdi] + + cvttps2pi mm0, xmm1 + cvttps2pi mm0, [rdi] + cvttps2pi mm0, qword [rdi] + + cvttsd2si eax, xmm1 + cvttsd2si eax, [rdi] ; Compatibility + cvttsd2si eax, qword [rdi] + cvttsd2si rax, xmm1 + cvttsd2si rax, [rdi] + cvttsd2si rax, qword [rdi] + + cvttss2si eax, xmm1 + cvttss2si eax, [rdi] ; Compatibility + cvttss2si eax, dword [rdi] + cvttss2si rax, xmm1 + cvttss2si rax, [rdi] + cvttss2si rax, dword [rdi] + + vcvtdq2pd xmm0, xmm1 + vcvtdq2pd xmm0, [rdi] + vcvtdq2pd xmm0, qword [rdi] + vcvtdq2pd ymm0, xmm1 + vcvtdq2pd ymm0, [rdi] + vcvtdq2pd ymm0, oword [rdi] + + vcvtdq2ps xmm0, xmm1 + vcvtdq2ps xmm0, [rdi] + vcvtdq2ps xmm0, oword [rdi] + vcvtdq2ps ymm0, ymm1 + vcvtdq2ps ymm0, [rdi] + vcvtdq2ps ymm0, yword [rdi] + + vcvtpd2dq xmm0, xmm1 + vcvtpd2dq xmm0, oword [rdi] + vcvtpd2dq xmm0, ymm1 + vcvtpd2dq xmm0, yword [rdi] + + vcvtpd2ps xmm0, xmm1 + vcvtpd2ps xmm0, oword [rdi] + vcvtpd2ps xmm0, ymm1 + vcvtpd2ps xmm0, yword [rdi] + + vcvtps2dq xmm0, xmm1 + vcvtps2dq xmm0, [rdi] + vcvtps2dq xmm0, oword [rdi] + vcvtps2dq ymm0, ymm1 + vcvtps2dq ymm0, [rdi] + vcvtps2dq ymm0, yword [rdi] + + vcvtps2pd xmm0, xmm1 + vcvtps2pd xmm0, [rdi] + vcvtps2pd xmm0, qword [rdi] + vcvtps2pd ymm0, xmm1 + vcvtps2pd ymm0, [rdi] + vcvtps2pd ymm0, oword [rdi] + + vcvtsd2si eax, xmm1 + vcvtsd2si eax, [rdi] + vcvtsd2si eax, qword [rdi] + vcvtsd2si rax, xmm1 + vcvtsd2si rax, [rdi] + vcvtsd2si rax, qword [rdi] + + vcvtsd2ss xmm0, xmm1 + vcvtsd2ss xmm0, [rdi] + vcvtsd2ss xmm0, qword [rdi] + vcvtsd2ss xmm0, xmm1, xmm2 + vcvtsd2ss xmm0, xmm1, [rdi] + vcvtsd2ss xmm0, xmm1, qword [rdi] + + vcvtsi2sd xmm0, eax + vcvtsi2sd xmm0, [rdi] ; Compatibility + vcvtsi2sd xmm0, dword [rdi] + vcvtsi2sd xmm0, rax + vcvtsi2sd xmm0, qword [rdi] + vcvtsi2sd xmm0, xmm1, eax + vcvtsi2sd xmm0, xmm1, [rdi] ; Compatibility + vcvtsi2sd xmm0, xmm1, dword [rdi] + vcvtsi2sd xmm0, xmm1, rax + vcvtsi2sd xmm0, xmm1, qword [rdi] + + vcvtsi2ss xmm0, eax + vcvtsi2ss xmm0, [rdi] ; Compatibility + vcvtsi2ss xmm0, dword [rdi] + vcvtsi2ss xmm0, rax + vcvtsi2ss xmm0, qword [rdi] + vcvtsi2ss xmm0, xmm1, eax + vcvtsi2ss xmm0, xmm1, [rdi] ; Compatibility + vcvtsi2ss xmm0, xmm1, dword [rdi] + vcvtsi2ss xmm0, xmm1, rax + vcvtsi2ss xmm0, xmm1, qword [rdi] + + vcvtss2sd xmm0, xmm1 + vcvtss2sd xmm0, [rdi] + vcvtss2sd xmm0, dword [rdi] + vcvtss2sd xmm0, xmm1, xmm2 + vcvtss2sd xmm0, xmm1, [rdi] + vcvtss2sd xmm0, xmm1, dword [rdi] + + vcvtss2si eax, xmm1 + vcvtss2si eax, [rdi] + vcvtss2si eax, dword [rdi] + vcvtss2si rax, xmm1 + vcvtss2si rax, [rdi] + vcvtss2si rax, dword [rdi] + + vcvttpd2dq xmm0, xmm1 + vcvttpd2dq xmm0, oword [rdi] + vcvttpd2dq xmm0, ymm1 + vcvttpd2dq xmm0, yword [rdi] + + vcvttps2dq xmm0, xmm1 + vcvttps2dq xmm0, [rdi] + vcvttps2dq xmm0, oword [rdi] + vcvttps2dq ymm0, ymm1 + vcvttps2dq ymm0, [rdi] + vcvttps2dq ymm0, yword [rdi] + + vcvttsd2si eax, xmm1 + vcvttsd2si eax, [rdi] ; Compatibility + vcvttsd2si eax, qword [rdi] + vcvttsd2si rax, xmm1 + vcvttsd2si rax, [rdi] + vcvttsd2si rax, qword [rdi] + + vcvttss2si eax, xmm1 + vcvttss2si eax, [rdi] ; Compatibility + vcvttss2si eax, dword [rdi] + vcvttss2si rax, xmm1 + vcvttss2si rax, [rdi] + vcvttss2si rax, dword [rdi] diff --git a/test/br2222615.asm b/test/br2222615.asm new file mode 100644 index 00000000..7acef6c8 --- /dev/null +++ b/test/br2222615.asm @@ -0,0 +1,19 @@ +;Testname=noerror; Arguments=-fbin -obr2222615.bin; Files=stdout stderr br2222615.bin +;Testname=error; Arguments=-DERROR -fbin -obr2222615.bin; Files=stdout stderr br2222615.bin + +%macro bluttan 0 + nop +%endmacro + +%ifnmacro bluttan + %error "bluttan is a macro" +%endif + +%ifmacro blej + %error "blej is not a macro" +%endif + +%ifdef ERROR + %ifnmacro + %endif +%endif diff --git a/test/br890790.asm b/test/br890790.asm new file mode 100644 index 00000000..a0023825 --- /dev/null +++ b/test/br890790.asm @@ -0,0 +1,7 @@ +;Testname=test; Arguments=-fbin -obr890790.bin; Files=stdout stderr br890790.bin +%rep 5 + db 0 + %include "br890790_i.asm" +%endrep + +db 1 diff --git a/test/br890790_i.asm b/test/br890790_i.asm new file mode 100644 index 00000000..7ff797f3 --- /dev/null +++ b/test/br890790_i.asm @@ -0,0 +1 @@ +db 2 diff --git a/test/crc32.asm b/test/crc32.asm new file mode 100644 index 00000000..c1ddb296 --- /dev/null +++ b/test/crc32.asm @@ -0,0 +1,37 @@ +;Testname=test; Arguments=-fbin -ocrc32.bin; Files=stdout stderr crc32.bin + + bits 16 + + crc32 eax,cl + crc32 eax,byte [di] + crc32 eax,cx + crc32 eax,word [di] + crc32 eax,ecx + crc32 eax,dword [di] + + bits 32 + align 16 + + crc32 eax,cl + crc32 eax,byte [edi] + crc32 eax,cx + crc32 eax,word [edi] + crc32 eax,ecx + crc32 eax,dword [edi] + + bits 64 + align 16 + + crc32 eax,cl + crc32 eax,byte [rdi] + crc32 eax,r9b + crc32 eax,cx + crc32 eax,word [rdi] + crc32 eax,ecx + crc32 eax,dword [rdi] + crc32 rax,cl + crc32 rax,byte [rdi] + crc32 rax,r9b + crc32 rax,rcx + crc32 rax,qword [rdi] + crc32 rax,r9 diff --git a/test/elf64so.asm b/test/elf64so.asm new file mode 100644 index 00000000..f1b23464 --- /dev/null +++ b/test/elf64so.asm @@ -0,0 +1,118 @@ +; test source file for assembling to ELF64 shared library +; build with: +; nasm -f elf64 elf64so.asm +; ld -shared -o elf64so.so elf64so.o +; test with: +; gcc -o elf64so elftest64.c ./elf64so.so +; ./elf64so + +; This file should test the following: +; [1] Define and export a global text-section symbol +; [2] Define and export a global data-section symbol +; [3] Define and export a global BSS-section symbol +; [4] Define a non-global text-section symbol +; [5] Define a non-global data-section symbol +; [6] Define a non-global BSS-section symbol +; [7] Define a COMMON symbol +; [8] Define a NASM local label +; [9] Reference a NASM local label +; [10] Import an external symbol +; [11] Make a PC-relative call to an external symbol +; [12] Reference a text-section symbol in the text section +; [13] Reference a data-section symbol in the text section +; [14] Reference a BSS-section symbol in the text section +; [15] Reference a text-section symbol in the data section +; [16] Reference a data-section symbol in the data section +; [17] Reference a BSS-section symbol in the data section + + BITS 64 + GLOBAL lrotate:function ; [1] + GLOBAL greet_s:function ; [1] + GLOBAL greet_m:function ; [1] + GLOBAL asmstr:data asmstr.end-asmstr ; [2] + GLOBAL textptr:data 8 ; [2] + GLOBAL selfptr:data 8 ; [2] + GLOBAL useless:data 8 ; [3] + GLOBAL integer:data 8 ; [3] + EXTERN printf ; [10] + COMMON commvar 8:8 ; [7] + EXTERN _GLOBAL_OFFSET_TABLE_ + + SECTION .text + +; prototype: long lrotate(long x, int num); +lrotate: ; [1] + push rbp + mov rbp,rsp + mov rax,rdi + mov rcx,rsi +.label rol rax,1 ; [4] [8] + loop .label ; [9] [12] + mov rsp,rbp + pop rbp + ret + +;; prototype: void greet_*(void); +;; +;; Arguments are: rdi - rsi - rdx - rcx - r8 - r9 +;; Registers: rbx, rbp, r12-r15 are saved +;; greet_s() is Small PIC model, greet_m() is Medium PIC model +;; (Large model cannot be linked with other code) +;; +greet_s: + ;; This instruction is useless, this is only a test... + cmp qword [rel integer wrt ..got],0 + mov rax,[rel commvar wrt ..got] ; &commvar + mov rcx,[rax] ; commvar + mov rax,[rel integer wrt ..got] ; &integer + mov rsi,[rax] + lea rdx,[rsi+1] + mov [rel localint],rdx ; localint = integer+1 + mov rax,[rel localptr] ; localptr + mov rdx,[rax] ; *localptr = localint + lea rdi,[rel printfstr] + xor eax,eax ; No fp arguments + jmp printf wrt ..plt ; [10] + +greet_m: + push r15 ; Used by convention... + lea r15,[rel _GLOBAL_OFFSET_TABLE_] + mov rax,[rel commvar wrt ..got] ; &commvar + mov rcx,[rax] ; commvar + mov rax,[rel integer wrt ..got] ; &integer + mov rsi,[rax] + lea rdx,[rsi+1] + mov rax,localint wrt ..gotoff ; &localint - r15 + mov [rax+r15],rdx ; localint = integer+1 + mov rax,localptr wrt ..gotoff ; &localptr - r15 + mov rax,[rax+r15] ; localptr + mov rdx,[rax] ; *localptr = localint + mov rdi,printfstr wrt ..gotoff ; &printfstr - r15 + add rdi,r15 ; &printfstr + xor eax,eax ; No fp arguments + pop r15 + jmp printf wrt ..plt ; [10] + + SECTION .data + +; a string +asmstr db 'hello, world', 0 ; [2] +.end: + +; a string for Printf +printfstr db "integer=%ld, localint=%ld, commvar=%ld", 10, 0 + +; some pointers +localptr dq localint ; [5] [17] +textptr dq greet_s wrt ..sym ; [15] +selfptr dq selfptr wrt ..sym ; [16] + + SECTION .bss +; a useless symbol +useless resq 1 + +; an integer +integer resq 1 ; [3] + +; a local integer +localint resq 1 ; [6] diff --git a/test/elftest64.c b/test/elftest64.c new file mode 100644 index 00000000..1f3dec1f --- /dev/null +++ b/test/elftest64.c @@ -0,0 +1,43 @@ +/* + * build with: + * nasm -f elf64 elf64so.asm + * ld -shared -o elf64so.so elf64so.o + * test with: + * gcc -o elf64so elftest64.c ./elf64so.so + * ./elf64so + */ + +#include <stdio.h> +#include <inttypes.h> + +extern long lrotate(long, int); +extern void greet_s(void); +extern void greet_m(void); +extern int8_t asmstr[]; +extern void *selfptr; +extern void *textptr; +extern long integer; +long commvar; + +int main(void) +{ + + printf("Testing lrotate: should get 0x00400000, 0x00000001\n"); + printf("lrotate(0x00040000, 4) = 0x%08lx\n", lrotate(0x40000, 4)); + printf("lrotate(0x00040000, 46) = 0x%08lx\n", lrotate(0x40000, 46)); + + printf("This string should read `hello, world': `%s'\n", asmstr); + + printf("&integer = %p, &commvar = %p\n", &integer, &commvar); + printf("The integers here should be 1234, 1235 and 4321:\n"); + integer = 1234; + commvar = 4321; + greet_s(); + greet_m(); + + printf("These pointers should be equal: %p and %p\n", &greet_s, textptr); + + printf("So should these: %p and %p\n", selfptr, &selfptr); + + return 0; +} diff --git a/test/fwdopt.asm b/test/fwdopt.asm new file mode 100644 index 00000000..48dbc3fc --- /dev/null +++ b/test/fwdopt.asm @@ -0,0 +1,133 @@ +;Testname=test; Arguments=-fbin -ofwdopt.bin; Files=stdout stderr fwdopt.bin +n0: jmp n1 +n1: jmp n2 +n2: jmp n3 +n3: jmp n4 +n4: jmp n5 +n5: jmp n6 +n6: jmp n7 +n7: jmp n8 +n8: jmp n9 +n9: jmp n10 +n10: jmp n11 +n11: jmp n12 +n12: jmp n13 +n13: jmp n14 +n14: jmp n15 +n15: jmp n16 +n16: jmp n17 +n17: jmp n18 +n18: jmp n19 +n19: jmp n20 +n20: jmp n21 +n21: jmp n22 +n22: jmp n23 +n23: jmp n24 +n24: jmp n25 +n25: jmp n26 +n26: jmp n27 +n27: jmp n28 +n28: jmp n29 +n29: jmp n30 +n30: jmp n31 +n31: jmp n32 +n32: jmp n33 +n33: jmp n34 +n34: jmp n35 +n35: jmp n36 +n36: jmp n37 +n37: jmp n38 +n38: jmp n39 +n39: jmp n40 +n40: jmp n41 +n41: jmp n42 +n42: jmp n43 +n43: jmp n44 +n44: jmp n45 +n45: jmp n46 +n46: jmp n47 +n47: jmp n48 +n48: jmp n49 +n49: jmp n50 +n50: jmp n51 +n51: jmp n52 +n52: jmp n53 +n53: jmp n54 +n54: jmp n55 +n55: jmp n56 +n56: jmp n57 +n57: jmp n58 +n58: jmp n59 +n59: jmp n60 +n60: jmp n61 +n61: jmp n62 +n62: jmp n63 +n63: jmp n64 +n64: jmp n65 +n65: jmp n66 +n66: jmp n67 +n67: jmp n68 +n68: jmp n69 +n69: jmp n70 +n70: jmp n71 +n71: jmp n72 +n72: jmp n73 +n73: jmp n74 +n74: jmp n75 +n75: jmp n76 +n76: jmp n77 +n77: jmp n78 +n78: jmp n79 +n79: jmp n80 +n80: jmp n81 +n81: jmp n82 +n82: jmp n83 +n83: jmp n84 +n84: jmp n85 +n85: jmp n86 +n86: jmp n87 +n87: jmp n88 +n88: jmp n89 +n89: jmp n90 +n90: jmp n91 +n91: jmp n92 +n92: jmp n93 +n93: jmp n94 +n94: jmp n95 +n95: jmp n96 +n96: jmp n97 +n97: jmp n98 +n98: jmp n99 +n99: jmp n100 +n100: jmp n101 +n101: jmp n102 +n102: jmp n103 +n103: jmp n104 +n104: jmp n105 +n105: jmp n106 +n106: jmp n107 +n107: jmp n108 +n108: jmp n109 +n109: jmp n110 +n110: jmp n111 +n111: jmp n112 +n112: jmp n113 +n113: jmp n114 +n114: jmp n115 +n115: jmp n116 +n116: jmp n117 +n117: jmp n118 +n118: jmp n119 +n119: jmp n120 +n120: jmp n121 +n121: jmp n122 +n122: jmp n123 +n123: jmp n124 +n124: jmp n125 +n125: jmp n126 +n126: jmp n127 +n127: jmp n0 + + ;; This should emit exactly 3 NOP bytes + times 260-($-$$) nop + hlt diff --git a/test/fwdoptpp.asm b/test/fwdoptpp.asm new file mode 100644 index 00000000..e1f5dd63 --- /dev/null +++ b/test/fwdoptpp.asm @@ -0,0 +1,150 @@ +;Testname=error; Arguments=-fbin -DERROR -ofwdoptpp.bin; Files=stdout stderr fwdoptpp.bin +;Testname=fatal; Arguments=-fbin -DFATAL -ofwdoptpp.bin; Files=stdout stderr fwdoptpp.bin +;Testname=warning; Arguments=-fbin -DWARNING -ofwdoptpp.bin; Files=stdout stderr fwdoptpp.bin + +%ifndef ERROR + %ifndef FATAL + %ifndef WARNING + %define ERROR 1 + %endif + %endif +%endif + +n0: jmp n1 +n1: jmp n2 +n2: jmp n3 +n3: jmp n4 +n4: jmp n5 +n5: jmp n6 +n6: jmp n7 +n7: jmp n8 +n8: jmp n9 +n9: jmp n10 +n10: jmp n11 +n11: jmp n12 +n12: jmp n13 +n13: jmp n14 +n14: jmp n15 +n15: jmp n16 +n16: jmp n17 +n17: jmp n18 +n18: jmp n19 +n19: jmp n20 +n20: jmp n21 +n21: jmp n22 +n22: jmp n23 +n23: jmp n24 +n24: jmp n25 +n25: jmp n26 +n26: jmp n27 +n27: jmp n28 +n28: jmp n29 +n29: jmp n30 +n30: jmp n31 +n31: jmp n32 +n32: jmp n33 +n33: jmp n34 +n34: jmp n35 +n35: jmp n36 +n36: jmp n37 +n37: jmp n38 +n38: jmp n39 +n39: jmp n40 +n40: jmp n41 +n41: jmp n42 +n42: jmp n43 +n43: jmp n44 +n44: jmp n45 +n45: jmp n46 +n46: jmp n47 +n47: jmp n48 +n48: jmp n49 +n49: jmp n50 +n50: jmp n51 +n51: jmp n52 +n52: jmp n53 +n53: jmp n54 +n54: jmp n55 +n55: jmp n56 +n56: jmp n57 +n57: jmp n58 +n58: jmp n59 +n59: jmp n60 +n60: jmp n61 +n61: jmp n62 +n62: jmp n63 +n63: jmp n64 +n64: jmp n65 +n65: jmp n66 +n66: jmp n67 +n67: jmp n68 +n68: jmp n69 +n69: jmp n70 +n70: jmp n71 +n71: jmp n72 +n72: jmp n73 +n73: jmp n74 +n74: jmp n75 +n75: jmp n76 +n76: jmp n77 +n77: jmp n78 +n78: jmp n79 +n79: jmp n80 +n80: jmp n81 +n81: jmp n82 +n82: jmp n83 +n83: jmp n84 +n84: jmp n85 +n85: jmp n86 +n86: jmp n87 +n87: jmp n88 +n88: jmp n89 +n89: jmp n90 +n90: jmp n91 +n91: jmp n92 +n92: jmp n93 +n93: jmp n94 +n94: jmp n95 +n95: jmp n96 +n96: jmp n97 +n97: jmp n98 +n98: jmp n99 +n99: jmp n100 +n100: jmp n101 +n101: jmp n102 +n102: jmp n103 +n103: jmp n104 +n104: jmp n105 +n105: jmp n106 +n106: jmp n107 +n107: jmp n108 +n108: jmp n109 +n109: jmp n110 +n110: jmp n111 +n111: jmp n112 +n112: jmp n113 +n113: jmp n114 +n114: jmp n115 +n115: jmp n116 +n116: jmp n117 +n117: jmp n118 +n118: jmp n119 +n119: jmp n120 +n120: jmp n121 +n121: jmp n122 +n122: jmp n123 +n123: jmp n124 +n124: jmp n125 +n125: jmp n126 +n126: jmp n127 +n127: jmp n0 + +%if ($-$$) > 257 + %ifdef FATAL + %fatal "Out of space!" + %elifdef ERROR + %error "Out of space!" + %elifdef WARNING + %warning "Out of space!" + %endif +%endif diff --git a/test/gotoff64.asm b/test/gotoff64.asm new file mode 100644 index 00000000..05f5882b --- /dev/null +++ b/test/gotoff64.asm @@ -0,0 +1,25 @@ +;Testname=noerr; Arguments=-felf64 -ogotoff64.o; Files=stdout stderr gotoff64.o +;Testname=err; Arguments=-DERROR -felf64 -ogotoff64.o; Files=stdout stderr gotoff64.o + + bits 64 + default rel + + extern foo + + mov r15,[foo wrt ..got] + lea r12,[foo wrt ..got] +%ifdef ERROR + lea rax,[foo wrt ..gotoff] + mov rax,[foo wrt ..gotoff] +%endif + + default abs + + mov r15,[foo wrt ..got] + lea r12,[foo wrt ..got] + mov rax,[qword foo wrt ..got] +%ifdef ERROR + lea rax,[foo wrt ..gotoff] + mov rax,[foo wrt ..gotoff] +%endif + mov rax,[qword foo wrt ..gotoff] diff --git a/test/ifelse.asm b/test/ifelse.asm new file mode 100644 index 00000000..bbb0d796 --- /dev/null +++ b/test/ifelse.asm @@ -0,0 +1,46 @@ +;Testname=ifelse; Arguments=-fbin -oifelse.bin; Files=stdout stderr ifelse.bin + +;No problems -> db 3 +%if 0 + db 0 +%elif 0 > 0 + db 1 +%elif 1 < 1 + db 2 +%else + db 3 +%endif + +;Garbage after else, elif after else -> db 5 +%if 0 + db 4 +%else trailing garbage + db 5 +%elif 1 + db 6 +%endif + +;Garbage after endif -> +%if 0 + db 7 +%endif trailing garbage + +;else after else -> db 9 +%if 0 + db 8 +%else + db 9 +%else + db 10 +%endif + +;Problem preprocessed out, no warning -> +%if 0 + %if 1 + db 11 + %else + db 12 + %else + db 13 + %endif +%endif diff --git a/test/immwarn.asm b/test/immwarn.asm new file mode 100644 index 00000000..8bffbfae --- /dev/null +++ b/test/immwarn.asm @@ -0,0 +1,91 @@ +;Testname=onowarn; Arguments=-Ox -DOPT=1 -DWARN=0 -fbin -oimmwarn.bin; Files=stdout stderr immwarn.bin +;Testname=owarn; Arguments=-Ox -DOPT=1 -DWARN=1 -fbin -oimmwarn.bin; Files=stdout stderr immwarn.bin +;Testname=nowarn; Arguments=-O0 -DOPT=0 -DWARN=0 -fbin -oimmwarn.bin; Files=stdout stderr immwarn.bin +;Testname=warn; Arguments=-O0 -DOPT=1 -DWARN=1 -fbin -oimmwarn.bin; Files=stdout stderr immwarn.bin + +%ifndef WARN + %define WARN 1 +%endif + + bits 16 + push 1 +%if WARN + push 0ffffffffh +%endif + push -1 + push 0ffffh + push byte 0FFFFh + + add ax,0FFFFh +%if WARN + add ax,0FFFFFFFFh +%endif + add ax,-1 + add ax,byte 0FFFFh +%if WARN + add ax,byte 0FFFFFFFFh +%endif + add ax,-1 + + add cx,0FFFFh +%if WARN + add cx,0FFFFFFFFh +%endif + add cx,-1 + add cx,byte 0FFFFh +%if WARN + add cx,byte 0FFFFFFFFh +%endif + add cx,-1 + + bits 32 + push 1 + push 0ffffffffh + push -1 + push 0ffffh + + push byte 1 +%if WARN + push byte 0ffffh +%endif + push byte -1 + + push word 1 + push word 0ffffh + push word -1 + + push dword 1 + push dword 0ffffffffh + push dword -1 + + add eax,0FFFFh + add eax,0FFFFFFFFh + add eax,-1 + + add ecx,0FFFFh + add ecx,0FFFFFFFFh + add ecx,-1 + + bits 64 + mov eax,7fffffffh + mov eax,80000000h + mov rax,7fffffffh + mov rax,80000000h +%if WARN + mov rax,dword 80000000h +%endif + add rcx,0FFFFh +%if WARN + add rcx,0FFFFFFFFh +%endif + add rcx,-1 + + add ecx,0FFFFh + add ecx,0FFFFFFFFh + add ecx,-1 + + push byte 1 +%if WARN + push byte 0ffffffffh +%endif + push byte -1 diff --git a/test/imul.asm b/test/imul.asm new file mode 100644 index 00000000..b1777120 --- /dev/null +++ b/test/imul.asm @@ -0,0 +1,90 @@ +;Testname=nowarn; Arguments=-fbin -oimul.bin; Files=stdout stderr imul.bin +;Testname=warn; Arguments=-DWARN -fbin -oimul.bin; Files=stdout stderr imul.bin + +%macro test 1-2 5 + bits %1 + +%undef MEM +%if %1 == 16 + %define MEM [di] +%elif %1 == 32 + %define MEM [edi] +%elif %1 == 64 + %define MEM [rdi] +%endif + + imul al + imul byte MEM + imul ax + imul word MEM + imul eax + imul dword MEM +%if %1 == 64 + imul rdx + imul qword MEM +%endif + + imul ax,cx + imul ax,MEM + imul ax,word MEM + imul eax,ecx + imul eax,MEM + imul eax,dword MEM +%if %1 == 64 + imul rax,rcx + imul rax,MEM + imul rax,qword MEM +%endif + + imul ax,cx,%2 + imul ax,cx,byte %2 + imul ax,MEM,%2 + imul ax,word MEM,%2 + imul eax,ecx,%2 + imul eax,ecx,byte %2 + imul eax,MEM,%2 + imul eax,dword MEM,%2 +%if %1 == 64 + imul rax,rcx,%2 + imul rax,rcx,byte %2 + imul rax,MEM,%2 + imul rax,qword MEM,%2 +%endif + + imul ax,%2 + imul ax,byte %2 + imul eax,%2 + imul eax,byte %2 +%if %1 == 64 + imul rax,%2 + imul rax,byte %2 +%endif + + imul ax,cx,0x1234 + imul ax,MEM,0x1234 + imul ax,word MEM,0x1234 + imul eax,ecx,0x12345678 + imul eax,MEM,0x12345678 + imul eax,dword MEM,0x12345678 +%if %1 == 64 + imul rax,rcx,0x12345678 + imul rax,MEM,0x12345678 + imul rax,qword MEM,0x12345678 +%endif + + imul ax,0x1234 + imul eax,0x12345678 +%if %1 == 64 + imul rax,0x12345678 +%endif +%endmacro + + test 16 + test 32 + test 64 + +%ifdef WARN + test 16,0x999 + test 32,0x999999 + test 64,0x999999999 +%endif diff --git a/test/optimization.asm b/test/optimization.asm new file mode 100644 index 00000000..d78209d9 --- /dev/null +++ b/test/optimization.asm @@ -0,0 +1,104 @@ +;Testname=O0; Arguments=-O0 -fbin -ooptimization.bin; Files=stdout stderr optimization.bin +;Testname=O1; Arguments=-O1 -fbin -ooptimization.bin; Files=stdout stderr optimization.bin +;Testname=Ox; Arguments=-Ox -fbin -ooptimization.bin; Files=stdout stderr optimization.bin + +BITS 32 + +; Simple +jmp foo +times 124 nop +foo: + +; Must start short to converge optimally +jmp car +times 127 nop +car: + +; Always near +jmp cdr +times 128 nop +cdr: + + +; Simple +add eax, quux2 - quux1 +quux1: +times 127 nop +quux2: + +; Must start short +corge1: +add eax, corge2 - corge1 +times 127 - 3 nop +corge2: + + +; Simple +lea eax, [bolug2-bolug1] +bolug1: +times 127 nop +bolug2: + +; Must start short +calog1: +lea eax, [calog2-calog1] +times 127 - 3 nop +calog2: + + +; Simple +lea eax, [eax+dolug2-dolug1] +dolug1: +times 127 nop +dolug2: + +; Must start short +ealog1: +lea eax, [eax+ealog2-ealog1] +times 127 - 3 nop +ealog2: + +; Must stay long! +lea eax, [eax+folug2-folug1] +folug1: +times 128 nop +folug2: + +; Must stay long! +galog1: +lea eax, [eax+galog2-galog1] +times 128 - 3 nop +galog2: + +; Sbyte tests... +onetwentysix equ 126 +onetwentynine equ 129 + +add eax,onetwentyseven ; sbyte (forward) +add eax,onetwentyeight ; not sbyte (forward) +add eax,onetwentyseven ; sbyte (forward) +add eax,onetwentysix ; sbyte (backward) +add eax,onetwentynine ; not sbyte (backward) +add ecx,onetwentyseven ; sbyte (forward) +add ecx,onetwentyeight ; not sbyte (forward) +add ecx,onetwentyseven ; sbyte (forward) +add ecx,onetwentysix ; sbyte (backward) +add ecx,onetwentynine ; not sbyte (backward) + +onetwentyseven equ 127 +onetwentyeight equ 128 + +; Simple +add eax, holug2-holug1 +holug1: +times 127 nop +holug2: + +; Must start short +ialog1: +add eax, ialog2-ialog1 +times 127 - 3 nop +ialog2: + +; Do not confuse forward references and segmentless addresses! +jmp 12345 diff --git a/test/pinsr16.asm b/test/pinsr16.asm new file mode 100644 index 00000000..f971598c --- /dev/null +++ b/test/pinsr16.asm @@ -0,0 +1,52 @@ + bits 16 + + pinsrw mm0,eax,0 + pinsrw mm1,si,0 + pinsrw mm2,[bx],0 + pinsrw mm3,word [bx],0 + + pinsrb xmm0,eax,0 + pinsrb xmm1,sil,0 +; pinsrb xmm1,bh,0 + pinsrb xmm2,[bx],0 + pinsrb xmm3,byte [bx],0 + + pinsrw xmm0,eax,0 + pinsrw xmm1,si,0 + pinsrw xmm2,[bx],0 + pinsrw xmm3,word [bx],0 + + pinsrd xmm0,eax,0 + pinsrd xmm1,esi,0 + pinsrd xmm2,[bx],0 + pinsrd xmm3,dword [bx],0 + + vpinsrb xmm0,eax,0 + vpinsrb xmm1,bl,0 + vpinsrb xmm2,[bx],0 + vpinsrb xmm3,byte [bx],0 + + vpinsrw xmm0,eax,0 + vpinsrw xmm1,si,0 + vpinsrw xmm2,[bx],0 + vpinsrw xmm3,word [bx],0 + + vpinsrd xmm0,eax,0 + vpinsrd xmm1,esi,0 + vpinsrd xmm2,[bx],0 + vpinsrd xmm3,dword [bx],0 + + vpinsrb xmm4,xmm0,eax,0 + vpinsrb xmm5,xmm1,bl,0 + vpinsrb xmm6,xmm2,[bx],0 + vpinsrb xmm7,xmm3,byte [bx],0 + + vpinsrw xmm4,xmm0,eax,0 + vpinsrw xmm5,xmm1,si,0 + vpinsrw xmm6,xmm2,[bx],0 + vpinsrw xmm7,xmm3,word [bx],0 + + vpinsrd xmm4,xmm0,eax,0 + vpinsrd xmm5,xmm1,esi,0 + vpinsrd xmm6,xmm2,[bx],0 + vpinsrd xmm7,xmm3,dword [bx],0 diff --git a/test/pinsr32.asm b/test/pinsr32.asm new file mode 100644 index 00000000..834d1866 --- /dev/null +++ b/test/pinsr32.asm @@ -0,0 +1,52 @@ + bits 32 + + pinsrw mm0,eax,0 + pinsrw mm1,si,0 + pinsrw mm2,[ecx],0 + pinsrw mm3,word [ecx],0 + + pinsrb xmm0,eax,0 + pinsrb xmm1,sil,0 +; pinsrb xmm1,bh,0 + pinsrb xmm2,[ecx],0 + pinsrb xmm3,byte [ecx],0 + + pinsrw xmm0,eax,0 + pinsrw xmm1,si,0 + pinsrw xmm2,[ecx],0 + pinsrw xmm3,word [ecx],0 + + pinsrd xmm0,eax,0 + pinsrd xmm1,esi,0 + pinsrd xmm2,[ecx],0 + pinsrd xmm3,dword [ecx],0 + + vpinsrb xmm0,eax,0 + vpinsrb xmm1,bl,0 + vpinsrb xmm2,[ecx],0 + vpinsrb xmm3,byte [ecx],0 + + vpinsrw xmm0,eax,0 + vpinsrw xmm1,si,0 + vpinsrw xmm2,[ecx],0 + vpinsrw xmm3,word [ecx],0 + + vpinsrd xmm0,eax,0 + vpinsrd xmm1,esi,0 + vpinsrd xmm2,[ecx],0 + vpinsrd xmm3,dword [ecx],0 + + vpinsrb xmm4,xmm0,eax,0 + vpinsrb xmm5,xmm1,bl,0 + vpinsrb xmm6,xmm2,[ecx],0 + vpinsrb xmm7,xmm3,byte [ecx],0 + + vpinsrw xmm4,xmm0,eax,0 + vpinsrw xmm5,xmm1,si,0 + vpinsrw xmm6,xmm2,[ecx],0 + vpinsrw xmm7,xmm3,word [ecx],0 + + vpinsrd xmm4,xmm0,eax,0 + vpinsrd xmm5,xmm1,esi,0 + vpinsrd xmm6,xmm2,[ecx],0 + vpinsrd xmm7,xmm3,dword [ecx],0 diff --git a/test/pinsr64.asm b/test/pinsr64.asm new file mode 100644 index 00000000..bf837e9e --- /dev/null +++ b/test/pinsr64.asm @@ -0,0 +1,68 @@ + bits 64 + + pinsrw mm0,eax,0 + pinsrw mm1,si,0 + pinsrw mm2,[rcx],0 + pinsrw mm3,word [rcx],0 + + pinsrb xmm0,eax,0 + pinsrb xmm1,sil,0 +; pinsrb xmm1,bh,0 + pinsrb xmm2,[rcx],0 + pinsrb xmm3,byte [rcx],0 + + pinsrw xmm0,eax,0 + pinsrw xmm1,si,0 + pinsrw xmm2,[rcx],0 + pinsrw xmm3,word [rcx],0 + + pinsrd xmm0,eax,0 + pinsrd xmm1,esi,0 + pinsrd xmm2,[rcx],0 + pinsrd xmm3,dword [rcx],0 + + pinsrq xmm0,rax,0 + pinsrq xmm1,rsi,0 + pinsrq xmm2,[rcx],0 + pinsrq xmm3,qword [rcx],0 + + vpinsrb xmm0,eax,0 + vpinsrb xmm1,sil,0 + vpinsrb xmm2,[rcx],0 + vpinsrb xmm3,byte [rcx],0 + + vpinsrw xmm0,eax,0 + vpinsrw xmm1,si,0 + vpinsrw xmm2,[rcx],0 + vpinsrw xmm3,word [rcx],0 + + vpinsrd xmm0,eax,0 + vpinsrd xmm1,esi,0 + vpinsrd xmm2,[rcx],0 + vpinsrd xmm3,dword [rcx],0 + + vpinsrq xmm0,rax,0 + vpinsrq xmm1,rsi,0 + vpinsrq xmm2,[rcx],0 + vpinsrq xmm3,qword [rcx],0 + + vpinsrb xmm4,xmm0,eax,0 + vpinsrb xmm5,xmm1,sil,0 + vpinsrb xmm6,xmm2,[rcx],0 + vpinsrb xmm7,xmm3,byte [rcx],0 + + vpinsrw xmm4,xmm0,eax,0 + vpinsrw xmm5,xmm1,si,0 + vpinsrw xmm6,xmm2,[rcx],0 + vpinsrw xmm7,xmm3,word [rcx],0 + + vpinsrd xmm4,xmm0,eax,0 + vpinsrd xmm5,xmm1,esi,0 + vpinsrd xmm6,xmm2,[rcx],0 + vpinsrd xmm7,xmm3,dword [rcx],0 + + vpinsrq xmm4,xmm0,rax,0 + vpinsrq xmm5,xmm1,rsi,0 + vpinsrq xmm6,xmm2,[rcx],0 + vpinsrq xmm7,xmm3,qword [rdx],0 +
\ No newline at end of file diff --git a/test/popcnt.asm b/test/popcnt.asm new file mode 100644 index 00000000..00096198 --- /dev/null +++ b/test/popcnt.asm @@ -0,0 +1,32 @@ +;Testname=test; Arguments=-fbin -opopcnt.bin; Files=stdout stderr popcnt.bin + + bits 16 + + popcnt ax,cx + popcnt ax,[si] + popcnt ax,word [si] + popcnt eax,ecx + popcnt eax,[si] + popcnt eax,dword [si] + + bits 32 + + popcnt ax,cx + popcnt ax,[esi] + popcnt ax,word [esi] + popcnt eax,ecx + popcnt eax,[esi] + popcnt eax,dword [esi] + + bits 64 + + popcnt ax,cx + popcnt ax,[rsi] + popcnt ax,word [rsi] + popcnt eax,ecx + popcnt eax,[rsi] + popcnt eax,dword [rsi] + popcnt rax,rcx + popcnt rax,[rsi] + popcnt rax,qword [rsi] +
\ No newline at end of file diff --git a/test/ppindirect.asm b/test/ppindirect.asm new file mode 100644 index 00000000..0a30d075 --- /dev/null +++ b/test/ppindirect.asm @@ -0,0 +1,42 @@ +;Testname=test; Arguments=-E -o ppindirect.out; Files=ppindirect.out + +; Fun tests of the preprocessor indirection mode... + +%assign foo1 11 +%assign foo11 1111 +%assign foo2 22 +%assign foo22 2222 +%assign foo3 33 +%assign foo33 3333 +%assign n 2 +foo%[foo%[n]]*100 +foo%[n]*100 +%assign foo%[foo%[n]] foo%[foo%[n]]*100 +;%assign foo%[n] foo%[n]*100 + + foo1 + foo2 + foo3 + foo11 + foo22 + foo33 + +%define foo33bar 999999 + %[foo%[foo3]bar] + +%assign bctr 0 +%macro bluttan 0 +%assign bctr bctr+1 +%assign bluttan%[bctr] bctr +%defstr bstr bluttan%[bctr] + bluttan%[bctr] + bstr +%endmacro + +%rep 20 + bluttan +%endrep +%rep 20 + bluttan%[bctr] +%assign bctr bctr-1 +%endrep diff --git a/test/pushseg.asm b/test/pushseg.asm new file mode 100644 index 00000000..7bd7c955 --- /dev/null +++ b/test/pushseg.asm @@ -0,0 +1,17 @@ +;Testname=test; Arguments=-fbin -opushseg.bin; Files=stdout stderr pushseg.bin + + bits 16 + + push cs + push ds + push es + push ss + push fs + push gs + + pop gs + pop fs + pop ss + pop es + pop ds + pop cs ; 8086 only, does not disassemble diff --git a/test/riprel2.asm b/test/riprel2.asm new file mode 100644 index 00000000..2d13d3e4 --- /dev/null +++ b/test/riprel2.asm @@ -0,0 +1,11 @@ +;Testname=unoptimized; Arguments=-fbin -oriprel2.bin -O0; Files=stdout stderr riprel.bin +;Testname=optimized; Arguments=-fbin -oriprel2.bin -Ox; Files=stdout stderr riprel.bin + + bits 64 + + default rel + mov dword [foo],12345678h + mov qword [foo],12345678h + mov [foo],rax + mov dword [foo],12345678h +foo: diff --git a/test/smartalign16.asm b/test/smartalign16.asm new file mode 100644 index 00000000..42915de6 --- /dev/null +++ b/test/smartalign16.asm @@ -0,0 +1,36 @@ +;Testname=test; Arguments=-fbin -osmartalign16.bin; Files=stdout stderr smartalign16.bin + +%use smartalign + + bits 16 + + alignmode nop, 32 + add ax,ax + align 32 + + alignmode generic, 32 + add ax,ax + align 32 + + alignmode k7, 32 + add ax,ax + align 32 + + alignmode k8, 32 + add ax,ax + align 32 + + alignmode p6, 32 + add ax,ax + align 32 + + add ecx,ecx + align 32 + add edx,edx + align 128 + add ebx,ebx + align 256 + add esi,esi + align 512 + + add edi,edi diff --git a/test/smartalign32.asm b/test/smartalign32.asm new file mode 100644 index 00000000..64d65b0b --- /dev/null +++ b/test/smartalign32.asm @@ -0,0 +1,36 @@ +;Testname=test; Arguments=-fbin -osmartalign32.bin; Files=stdout stderr smartalign32.bin + +%use smartalign + + bits 32 + + alignmode nop, 32 + add ax,ax + align 32 + + alignmode generic, 32 + add ax,ax + align 32 + + alignmode k7, 32 + add ax,ax + align 32 + + alignmode k8, 32 + add ax,ax + align 32 + + alignmode p6, 32 + add ax,ax + align 32 + + add ecx,ecx + align 32 + add edx,edx + align 128 + add ebx,ebx + align 256 + add esi,esi + align 512 + + add edi,edi diff --git a/test/smartalign64.asm b/test/smartalign64.asm new file mode 100644 index 00000000..74454ca8 --- /dev/null +++ b/test/smartalign64.asm @@ -0,0 +1,36 @@ +;Testname=test; Arguments=-fbin -osmartalign64.bin; Files=stdout stderr smartalign64.bin + +%use smartalign + + bits 64 + + alignmode nop, 32 + add ax,ax + align 32 + + alignmode generic, 32 + add ax,ax + align 32 + + alignmode k7, 32 + add ax,ax + align 32 + + alignmode k8, 32 + add ax,ax + align 32 + + alignmode p6, 32 + add ax,ax + align 32 + + add ecx,ecx + align 32 + add edx,edx + align 128 + add ebx,ebx + align 256 + add esi,esi + align 512 + + add edi,edi diff --git a/test/struc.asm b/test/struc.asm new file mode 100644 index 00000000..3c8c1b47 --- /dev/null +++ b/test/struc.asm @@ -0,0 +1,33 @@ +;Testname=test; Arguments=-fbin -ostruc.bin; Files=stdout stderr struc.bin + +bits 32 + +; Simple struc example +struc teststruc1 + .long: resd 1 + .word: resw 1 + .byte: resb 1 + .str: resb 32 +endstruc + +; Reference with offset +mov [ebp - 40 + teststruc1.word], ax + +istruc teststruc1 + at .word, db 5 +iend + +; Struc with base offset +; should be the same as the previous stuc +struc teststruc2, -40 + .long: resd 1 + .word: resw 1 + .byte: resb 1 + .str: resb 32 +endstruc + +mov [ebp + teststruc2.word], ax + +istruc teststruc2 + at .word, db 5 +iend diff --git a/test/weirdpaste.asm b/test/weirdpaste.asm new file mode 100644 index 00000000..46bfa90a --- /dev/null +++ b/test/weirdpaste.asm @@ -0,0 +1,29 @@ +;Testname=preproc; Arguments=-E; Files=stdout stderr +;Testname=bin; Arguments=-fbin -oweirdpaste.bin; Files=stdout stderr weirdpaste.bin + + %define foo xyzzy +%define bar 1e+10 + +%define xyzzy1e 15 + +%macro dx 2 +%assign xx %1%2 + dw xx +%endmacro + + dx foo, bar + +%macro df 2 +%assign xy __float32__(%1e+%2) + dd xy + dd %1e+%2 +%endmacro + + df 1, 36 + df 33, 20 + df 0, 2 + df 1.2, 5 + + +%define N 1e%++%+ 5 + dd N, 1e+5 @@ -0,0 +1,51 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 1996-2009 The NASM Authors - All Rights Reserved + * See the file AUTHORS included with the NASM distribution for + * the specific copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following + * conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ----------------------------------------------------------------------- */ + +#include "nasm.h" +#include "version.h" + +/* This is printed when entering nasm -v */ +const char nasm_version[] = NASM_VER; +const char nasm_date[] = __DATE__; +const char nasm_compile_options[] = "" +#ifdef DEBUG + " with -DDEBUG" +#endif + ; + +/* These are used by some backends. */ +const char nasm_comment[] = + "The Netwide Assembler " NASM_VER; + +const char nasm_signature[] = + "NASM " NASM_VER; |