Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

start on coff support

  • Loading branch information...
commit 2511126cd7a234797e8b32515e419ce4f84ca928 1 parent 51280f3
Walter Bright authored June 24, 2012
239  src/backend/mscoff.h
... ...
@@ -0,0 +1,239 @@
  1
+/* Microsoft COFF object file format */
  2
+
  3
+#pragma ZTC align 1
  4
+
  5
+/***********************************************/
  6
+
  7
+struct filehdr
  8
+{
  9
+        unsigned short f_magic; // identifies type of target machine
  10
+#define IMAGE_FILE_MACHINE_UNKNOWN 0            // applies to any machine type
  11
+#define IMAGE_FILE_MACHINE_AMD64   0x8664       // x86_64
  12
+        unsigned short f_nscns; // number of sections (96 is max)
  13
+        long f_timdat;          // creation date, number of seconds since 1970
  14
+        long f_symptr;          // file offset of symbol table
  15
+        long f_nsyms;           // number of entried in the symbol table
  16
+        unsigned short f_opthdr; // optional header size (0)
  17
+        unsigned short f_flags;
  18
+#define IMAGE_FILE_RELOCS_STRIPPED              1
  19
+#define IMAGE_FILE_EXECUTABLE_IMAGE             2
  20
+#define IMAGE_FILE_LINE_NUMS_STRIPPED           4
  21
+#define IMAGE_FILE_LOCAL_SYMS_STRIPPED          8
  22
+#define IMAGE_FILE_AGGRESSIVE_WS_TRIM           0x10
  23
+#define IMAGE_FILE_LARGE_ADDRESS_AWARE          0x20
  24
+#define IMAGE_FILE_BYTES_REVERSED_LO            0x80
  25
+#define IMAGE_FILE_32BIT_MACHINE                0x100
  26
+#define IMAGE_FILE_DEBUG_STRIPPED               0x200
  27
+#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP      0x400
  28
+#define IMAGE_FILE_NET_RUN_FROM_SWAP            0x800
  29
+#define IMAGE_FILE_SYSTEM                       0x1000
  30
+#define IMAGE_FILE_DLL                          0x2000
  31
+#define IMAGE_FILE_UP_SYSTEM_ONLY               0x4000
  32
+#define IMAGE_FILE_BYTES_REVERSED_HI            0x8000
  33
+};
  34
+
  35
+/***********************************************/
  36
+
  37
+// size should be 40 bytes
  38
+struct scnhdr
  39
+{
  40
+        char s_name[8];         // name or /nnnn, where nnnn is offset in string table
  41
+        long s_paddr;           // virtual size, 0 for obj files
  42
+        long s_vaddr;           // virtual address, 0 for obj files
  43
+        long s_size;            // size of raw data on disk
  44
+        long s_scnptr;          // file offset of raw data on disk, should be aligned by 4
  45
+        long s_relptr;          // file offset of relocation data
  46
+        long s_lnnoptr;         // file offset of line numbers, should be 0
  47
+        unsigned short s_nreloc;        // number of relocations
  48
+        unsigned short s_nlnno;         // number of line number entries, should be 0
  49
+        unsigned long s_flags;
  50
+#define IMAGE_SCN_TYPE_NO_PAD           8       // obsolete
  51
+#define IMAGE_SCN_CNT_CODE              0x20    // code section
  52
+#define IMAGE_SCN_CNT_INITIALIZED_DATA  0x40
  53
+#define IMAGE_SCN_CNT_UNINITIALIZED_DATA        0x80
  54
+#define IMAGE_SCN_LNK_OTHER             0x100
  55
+#define IMAGE_SCN_LNK_INFO              0x200   // comments; for .drectve section
  56
+#define IMAGE_SCN_LNK_REMOVE            0x800   // do not put in image file
  57
+#define IMAGE_SCN_LNK_COMDAT            0x1000  // COMDAT section
  58
+#define IMAGE_SCN_GPREL                 0x8000  // data referenced through global pointer GP
  59
+#define IMAGE_SCN_MEM_PURGEABLE         0x20000
  60
+#define IMAGE_SCN_MEM_16BIT             0x20000
  61
+#define IMAGE_SCN_MEM_LOCKED            0x40000
  62
+#define IMAGE_SCN_MEM_PRELOAD           0x80000
  63
+#define IMAGE_SCN_ALIGN_1BYTES          0x100000
  64
+#define IMAGE_SCN_ALIGN_2BYTES          0x200000
  65
+#define IMAGE_SCN_ALIGN_4BYTES          0x300000
  66
+#define IMAGE_SCN_ALIGN_8BYTES          0x400000
  67
+#define IMAGE_SCN_ALIGN_16BYTES         0x500000
  68
+#define IMAGE_SCN_ALIGN_32BYTES         0x600000
  69
+#define IMAGE_SCN_ALIGN_64BYTES         0x700000
  70
+#define IMAGE_SCN_ALIGN_128BYTES        0x800000
  71
+#define IMAGE_SCN_ALIGN_256BYTES        0x900000
  72
+#define IMAGE_SCN_ALIGN_512BYTES        0xA00000
  73
+#define IMAGE_SCN_ALIGN_1024BYTES       0xB00000
  74
+#define IMAGE_SCN_ALIGN_2048BYTES       0xC00000
  75
+#define IMAGE_SCN_ALIGN_4096BYTES       0xD00000
  76
+#define IMAGE_SCN_ALIGN_8192BYTES       0xE00000
  77
+#define IMAGE_SCN_LNK_NRELOC_OVFL       0x1000000       // more than 0xFFFF relocations
  78
+#define IMAGE_SCN_MEM_DISCARDABLE       0x2000000       // can be discarded
  79
+#define IMAGE_SCN_MEM_NOT_CACHED        0x4000000       // cannot be cached
  80
+#define IMAGE_SCN_MEM_NOT_PAGED         0x8000000       // cannot be paged
  81
+#define IMAGE_SCN_MEM_SHARED            0x10000000      // can be shared
  82
+#define IMAGE_SCN_MEM_EXECUTE           0x20000000      // executable code
  83
+#define IMAGE_SCN_MEM_READ              0x40000000      // readable
  84
+#define IMAGE_SCN_MEM_WRITE             0x80000000      // writeable
  85
+};
  86
+
  87
+/***********************************************/
  88
+
  89
+struct syment
  90
+{
  91
+    union
  92
+    {
  93
+#define SYMNMLEN        8
  94
+        char _n_name[SYMNMLEN];
  95
+        struct
  96
+        {   long _n_zeroes;
  97
+            long _n_offset;
  98
+        } _n_n;
  99
+        char *_n_nptr[2];
  100
+    } _n;
  101
+#define n_name          _n._n_name
  102
+#define n_zeroes        _n._n_n._n_zeroes
  103
+#define n_offset        _n._n_n._n_offset
  104
+#define n_nptr          _n._n_nptr[1]
  105
+
  106
+    unsigned n_value;
  107
+    short n_scnum;
  108
+#define IMAGE_SYM_DEBUG                 -2
  109
+#define IMAGE_SYM_ABSOLUTE              -1
  110
+#define IMAGE_SYM_UNDEFINED             0
  111
+
  112
+    unsigned short n_type;      // 0x20 function; 0x00 not a function
  113
+
  114
+    unsigned char n_sclass;
  115
+/* Values for n_sclass  */
  116
+#define IMAGE_SYM_CLASS_EXTERNAL        2
  117
+#define IMAGE_SYM_CLASS_STATIC          3
  118
+#define IMAGE_SYM_CLASS_FUNCTION        101
  119
+#define IMAGE_SYM_CLASS_FILE            103
  120
+
  121
+    unsigned char n_numaux;
  122
+};
  123
+
  124
+
  125
+/***********************************************/
  126
+
  127
+struct reloc
  128
+{   unsigned r_vaddr;           // file offset of relocation
  129
+    unsigned r_symndx;          // symbol table index
  130
+    unsigned short r_type;
  131
+
  132
+#define IMAGE_REL_AMD64_ABSOLUTE        0
  133
+#define IMAGE_REL_AMD64_ADDR64          1
  134
+#define IMAGE_REL_AMD64_ADDR32          2
  135
+#define IMAGE_REL_AMD64_ADDR32NB        3
  136
+#define IMAGE_REL_AMD64_REL32           4
  137
+#define IMAGE_REL_AMD64_REL32_1         5
  138
+#define IMAGE_REL_AMD64_REL32_2         6
  139
+#define IMAGE_REL_AMD64_REL32_3         7
  140
+#define IMAGE_REL_AMD64_REL32_4         8
  141
+#define IMAGE_REL_AMD64_REL32_5         9
  142
+#define IMAGE_REL_AMD64_SECTION         0xA
  143
+#define IMAGE_REL_AMD64_SECREL          0xB
  144
+#define IMAGE_REL_AMD64_SECREL7         0xC
  145
+#define IMAGE_REL_AMD64_TOKEN           0xD
  146
+#define IMAGE_REL_AMD64_SREL32          0xE
  147
+#define IMAGE_REL_AMD64_PAIR            0xF
  148
+#define IMAGE_REL_AMD64_SSPAN32         0x10
  149
+
  150
+#define IMAGE_REL_I386_ABSOLUTE         0
  151
+#define IMAGE_REL_I386_DIR16            1
  152
+#define IMAGE_REL_I386_REL16            2
  153
+#define IMAGE_REL_I386_DIR32            6
  154
+#define IMAGE_REL_I386_DIR32NB          7
  155
+#define IMAGE_REL_I386_SEG12            9
  156
+#define IMAGE_REL_I386_SECTION          0xA
  157
+#define IMAGE_REL_I386_SECREL           0xB
  158
+#define IMAGE_REL_I386_TOKEN            0xC
  159
+#define IMAGE_REL_I386_SECREL7          0xD
  160
+#define IMAGE_REL_I386_REL32            0x14
  161
+};
  162
+
  163
+
  164
+/***********************************************/
  165
+
  166
+struct lineno
  167
+{
  168
+    union
  169
+    {
  170
+        unsigned l_symndx;
  171
+        unsigned l_paddr;
  172
+    } l_addr;
  173
+    unsigned short l_lnno;
  174
+};
  175
+
  176
+
  177
+/***********************************************/
  178
+
  179
+union auxent
  180
+{
  181
+    // Function definitions
  182
+    struct
  183
+    {   unsigned TagIndex;
  184
+        unsigned TotalSize;
  185
+        unsigned PointerToLinenumber;
  186
+        unsigned PointerToNextFunction;
  187
+    } x_fd;
  188
+
  189
+    // .bf symbols
  190
+    struct
  191
+    {   unsigned Unused;
  192
+        unsigned short Linenumber;
  193
+        char filler[6];
  194
+        unsigned PointerToNextFunction;
  195
+    } x_bf;
  196
+
  197
+    // .ef symbols
  198
+    struct
  199
+    {   unsigned Unused;
  200
+        unsigned short Linenumber;
  201
+    } x_ef;
  202
+
  203
+    // Weak externals
  204
+    struct
  205
+    {   unsigned TagIndex;
  206
+        unsigned Characteristics;
  207
+#define IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY
  208
+#define IMAGE_WEAK_EXTERN_SEARCH_LIBRARY
  209
+#define IMAGE_WEAK_EXTERN_SEARCH_ALIAS
  210
+    } x_weak;
  211
+
  212
+    // Files
  213
+    struct
  214
+    {   char FileName[18];
  215
+    } x_filename;
  216
+
  217
+    // Section definitions
  218
+    struct
  219
+    {   unsigned length;
  220
+        unsigned short NumberOfRelocations;
  221
+        unsigned short NumberOfLinenumbers;
  222
+        unsigned CheckSum;
  223
+        unsigned short Number;
  224
+        unsigned char Selection;
  225
+#define IMAGE_COMDAT_SELECT_NODUPLICATES        1
  226
+#define IMAGE_COMDAT_SELECT_ANY                 2
  227
+#define IMAGE_COMDAT_SELECT_SAME_SIZE           3
  228
+#define IMAGE_COMDAT_SELECT_EXACT_MATCH         4
  229
+#define IMAGE_COMDAT_SELECT_ASSOCIATIVE         5
  230
+#define IMAGE_COMDAT_SELECT_LARGEST             6
  231
+    } x_section;
  232
+
  233
+    char filler[18];
  234
+};
  235
+
  236
+
  237
+/***********************************************/
  238
+
  239
+#pragma ZTC align
2  src/backend/mscoffobj.c
... ...
@@ -0,0 +1,2 @@
  1
+
  2
+#include "mscoff.h"
815  src/libmscoff.c
... ...
@@ -0,0 +1,815 @@
  1
+
  2
+// Compiler implementation of the D programming language
  3
+// Copyright (c) 1999-2012 by Digital Mars
  4
+// All Rights Reserved
  5
+// written by Walter Bright
  6
+// http://www.digitalmars.com
  7
+// License for redistribution is by either the Artistic License
  8
+// in artistic.txt, or the GNU General Public License in gnu.txt.
  9
+// See the included readme.txt for details.
  10
+
  11
+/* Implements object library reading and writing in the MS-COFF object
  12
+ * module format.
  13
+ * This format is described in the Microsoft document
  14
+ * "Microsoft Portable Executable and Common Object File Format Specification"
  15
+ * Revision 8.2 September 21, 2010
  16
+ * chapter 6 "Archive (Library) File Format"
  17
+ */
  18
+
  19
+#include <stdio.h>
  20
+#include <string.h>
  21
+#include <stdlib.h>
  22
+#include <assert.h>
  23
+#include <time.h>
  24
+//#include <unistd.h>
  25
+#include <sys/types.h>
  26
+#include <sys/stat.h>
  27
+
  28
+#include "rmem.h"
  29
+#include "root.h"
  30
+#include "stringtable.h"
  31
+
  32
+#include "mars.h"
  33
+#include "lib.h"
  34
+
  35
+#define LOG 0
  36
+
  37
+struct ObjModule;
  38
+
  39
+struct ObjSymbol
  40
+{
  41
+    char *name;
  42
+    ObjModule *om;
  43
+};
  44
+
  45
+/*********
  46
+ * Do lexical comparison of ObjSymbol's for qsort()
  47
+ */
  48
+int ObjSymbol_cmp(const void *p, const void *q)
  49
+{
  50
+    ObjSymbol *s1 = (ObjSymbol *)p;
  51
+    ObjSymbol *s2 = (ObjSymbol *)q;
  52
+    return strcmp(s1->name, s2->name);
  53
+}
  54
+
  55
+#include "arraytypes.h"
  56
+
  57
+typedef ArrayBase<ObjModule> ObjModules;
  58
+typedef ArrayBase<ObjSymbol> ObjSymbols;
  59
+
  60
+class LibMSCoff : public Library
  61
+{
  62
+  public:
  63
+    File *libfile;
  64
+    ObjModules objmodules;   // ObjModule[]
  65
+    ObjSymbols objsymbols;   // ObjSymbol[]
  66
+
  67
+    StringTable tab;
  68
+
  69
+    LibMSCoff();
  70
+    void setFilename(char *dir, char *filename);
  71
+    void addObject(const char *module_name, void *buf, size_t buflen);
  72
+    void addLibrary(void *buf, size_t buflen);
  73
+    void write();
  74
+
  75
+    void addSymbol(ObjModule *om, char *name, int pickAny = 0);
  76
+  private:
  77
+    void scanObjModule(ObjModule *om);
  78
+    void WriteLibToBuffer(OutBuffer *libbuf);
  79
+
  80
+    void error(const char *format, ...)
  81
+    {
  82
+        va_list ap;
  83
+        va_start(ap, format);
  84
+        ::verror(loc, format, ap);
  85
+        va_end(ap);
  86
+    }
  87
+
  88
+    Loc loc;
  89
+};
  90
+
  91
+#if 0 // TODO: figure out how to initialize
  92
+Library *Library::factory()
  93
+{
  94
+    return new LibMSCoff();
  95
+}
  96
+#endif
  97
+
  98
+LibMSCoff::LibMSCoff()
  99
+{
  100
+    libfile = NULL;
  101
+    tab.init();
  102
+}
  103
+
  104
+/***********************************
  105
+ * Set the library file name based on the output directory
  106
+ * and the filename.
  107
+ * Add default library file name extension.
  108
+ */
  109
+
  110
+void LibMSCoff::setFilename(char *dir, char *filename)
  111
+{
  112
+#if LOG
  113
+    printf("LibMSCoff::setFilename(dir = '%s', filename = '%s')\n",
  114
+        dir ? dir : "", filename ? filename : "");
  115
+#endif
  116
+    char *arg = filename;
  117
+    if (!arg || !*arg)
  118
+    {   // Generate lib file name from first obj name
  119
+        char *n = (*global.params.objfiles)[0];
  120
+
  121
+        n = FileName::name(n);
  122
+        FileName *fn = FileName::forceExt(n, global.lib_ext);
  123
+        arg = fn->toChars();
  124
+    }
  125
+    if (!FileName::absolute(arg))
  126
+        arg = FileName::combine(dir, arg);
  127
+    FileName *libfilename = FileName::defaultExt(arg, global.lib_ext);
  128
+
  129
+    libfile = new File(libfilename);
  130
+
  131
+    loc.filename = libfile->name->toChars();
  132
+    loc.linnum = 0;
  133
+}
  134
+
  135
+void LibMSCoff::write()
  136
+{
  137
+    if (global.params.verbose)
  138
+        printf("library   %s\n", libfile->name->toChars());
  139
+
  140
+    OutBuffer libbuf;
  141
+    WriteLibToBuffer(&libbuf);
  142
+
  143
+    // Transfer image to file
  144
+    libfile->setbuffer(libbuf.data, libbuf.offset);
  145
+    libbuf.extractData();
  146
+
  147
+
  148
+    char *p = FileName::path(libfile->name->toChars());
  149
+    FileName::ensurePathExists(p);
  150
+    //mem.free(p);
  151
+
  152
+    libfile->writev();
  153
+}
  154
+
  155
+/*****************************************************************************/
  156
+
  157
+void LibMSCoff::addLibrary(void *buf, size_t buflen)
  158
+{
  159
+    addObject(NULL, buf, buflen);
  160
+}
  161
+
  162
+
  163
+/*****************************************************************************/
  164
+/*****************************************************************************/
  165
+
  166
+void sputl(int value, void* buffer)
  167
+{
  168
+    unsigned char *p = (unsigned char*)buffer;
  169
+    p[3] = (unsigned char)(value >> 24);
  170
+    p[2] = (unsigned char)(value >> 16);
  171
+    p[1] = (unsigned char)(value >> 8);
  172
+    p[0] = (unsigned char)(value);
  173
+}
  174
+
  175
+int sgetl(void* buffer)
  176
+{
  177
+    unsigned char *p = (unsigned char*)buffer;
  178
+    return (((((p[3] << 8) | p[2]) << 8) | p[1]) << 8) | p[0];
  179
+}
  180
+
  181
+
  182
+struct ObjModule
  183
+{
  184
+    unsigned char *base;        // where are we holding it in memory
  185
+    unsigned length;            // in bytes
  186
+    unsigned offset;            // offset from start of library
  187
+    unsigned short index;       // index in Second Linker Member
  188
+    char *name;                 // module name (file name)
  189
+    int name_offset;            // if not -1, offset into string table of name
  190
+    long file_time;             // file time
  191
+    unsigned user_id;
  192
+    unsigned group_id;
  193
+    unsigned file_mode;
  194
+    int scan;                   // 1 means scan for symbols
  195
+};
  196
+
  197
+struct Header
  198
+{
  199
+    #define OBJECT_NAME_SIZE 16
  200
+    char object_name[OBJECT_NAME_SIZE];
  201
+    char file_time[12];
  202
+    char user_id[6];
  203
+    char group_id[6];
  204
+    char file_mode[8];          // in octal
  205
+    char file_size[10];
  206
+    char trailer[2];
  207
+};
  208
+
  209
+void OmToHeader(Header *h, ObjModule *om)
  210
+{
  211
+    size_t len;
  212
+    if (om->name_offset == -1)
  213
+    {
  214
+        len = strlen(om->name);
  215
+        memcpy(h->object_name, om->name, len);
  216
+        h->object_name[len] = '/';
  217
+    }
  218
+    else
  219
+    {
  220
+        len = sprintf(h->object_name, "/%d", om->name_offset);
  221
+        h->object_name[len] = ' ';
  222
+    }
  223
+    assert(len < OBJECT_NAME_SIZE);
  224
+    memset(h->object_name + len + 1, ' ', OBJECT_NAME_SIZE - (len + 1));
  225
+
  226
+    /* In the following sprintf's, don't worry if the trailing 0
  227
+     * that sprintf writes goes off the end of the field. It will
  228
+     * write into the next field, which we will promptly overwrite
  229
+     * anyway. (So make sure to write the fields in ascending order.)
  230
+     */
  231
+
  232
+    len = sprintf(h->file_time, "%lu", om->file_time);
  233
+    assert(len <= 12);
  234
+    memset(h->file_time + len, ' ', 12 - len);
  235
+
  236
+    if (om->user_id > 999999)
  237
+        om->user_id = 0;
  238
+    len = sprintf(h->user_id, "%u", om->user_id);
  239
+    assert(len <= 6);
  240
+    memset(h->user_id + len, ' ', 6 - len);
  241
+
  242
+    len = sprintf(h->group_id, "%u", om->group_id);
  243
+    assert(len <= 6);
  244
+    memset(h->group_id + len, ' ', 6 - len);
  245
+
  246
+    len = sprintf(h->file_mode, "%o", om->file_mode);
  247
+    assert(len <= 8);
  248
+    memset(h->file_mode + len, ' ', 8 - len);
  249
+
  250
+    len = sprintf(h->file_size, "%u", om->length);
  251
+    assert(len <= 10);
  252
+    memset(h->file_size + len, ' ', 10 - len);
  253
+
  254
+    h->trailer[0] = '`';
  255
+    h->trailer[1] = '\n';
  256
+}
  257
+
  258
+void LibMSCoff::addSymbol(ObjModule *om, char *name, int pickAny)
  259
+{
  260
+#if LOG
  261
+    printf("LibMSCoff::addSymbol(%s, %s, %d)\n", om->name, name, pickAny);
  262
+#endif
  263
+    ObjSymbol *os = new ObjSymbol();
  264
+    os->name = strdup(name);
  265
+    os->om = om;
  266
+    objsymbols.push(os);
  267
+}
  268
+
  269
+/************************************
  270
+ * Scan single object module for dictionary symbols.
  271
+ * Send those symbols to LibMSCoff::addSymbol().
  272
+ */
  273
+
  274
+void LibMSCoff::scanObjModule(ObjModule *om)
  275
+{
  276
+#if LOG
  277
+    printf("LibMSCoff::scanObjModule(%s)\n", om->name);
  278
+#endif
  279
+
  280
+    struct Context
  281
+    {
  282
+        LibMSCoff *lib;
  283
+        ObjModule *om;
  284
+
  285
+        Context(LibMSCoff *lib, ObjModule *om)
  286
+        {
  287
+            this->lib = lib;
  288
+            this->om = om;
  289
+        }
  290
+
  291
+        static void addSymbol(void *pctx, char *name, int pickAny)
  292
+        {
  293
+            ((Context *)pctx)->lib->addSymbol(((Context *)pctx)->om, name, pickAny);
  294
+        }
  295
+    };
  296
+
  297
+    Context ctx(this, om);
  298
+
  299
+    extern void scanMSCoffObjModule(void*, void (*pAddSymbol)(void*, char*, int), void *, size_t, char *, Loc loc);
  300
+    scanMSCoffObjModule(&ctx, &Context::addSymbol, om->base, om->length, om->name, loc);
  301
+}
  302
+
  303
+/***************************************
  304
+ * Add object module or library to the library.
  305
+ * Examine the buffer to see which it is.
  306
+ * If the buffer is NULL, use module_name as the file name
  307
+ * and load the file.
  308
+ */
  309
+
  310
+void LibMSCoff::addObject(const char *module_name, void *buf, size_t buflen)
  311
+{
  312
+    if (!module_name)
  313
+        module_name = "";
  314
+#if LOG
  315
+    printf("LibMSCoff::addObject(%s)\n", module_name);
  316
+#endif
  317
+    int fromfile = 0;
  318
+    if (!buf)
  319
+    {   assert(module_name[0]);
  320
+        FileName f((char *)module_name, 0);
  321
+        File file(&f);
  322
+        file.readv();
  323
+        buf = file.buffer;
  324
+        buflen = file.len;
  325
+        file.ref = 1;
  326
+        fromfile = 1;
  327
+    }
  328
+    int reason = 0;
  329
+
  330
+    if (buflen < 16)
  331
+    {
  332
+#if LOG
  333
+        printf("buf = %p, buflen = %d\n", buf, buflen);
  334
+#endif
  335
+      Lcorrupt:
  336
+        error("corrupt object module %s %d", module_name, reason);
  337
+        return;
  338
+    }
  339
+
  340
+    if (memcmp(buf, "!<arch>\n", 8) == 0)
  341
+    {   /* Library file.
  342
+         * Pull each object module out of the library and add it
  343
+         * to the object module array.
  344
+         */
  345
+#if LOG
  346
+        printf("archive, buf = %p, buflen = %d\n", buf, buflen);
  347
+#endif
  348
+        Header *amh = NULL;
  349
+        Header *flm = NULL;     // first linker member
  350
+
  351
+        Header *slm = NULL;     // second linker member
  352
+        unsigned long number_of_members = 0;
  353
+        unsigned long *member_file_offsets = NULL;
  354
+        unsigned long number_of_symbols = 0;
  355
+        unsigned short *indices = NULL;
  356
+        char *string_table = NULL;
  357
+        unsigned long string_table_length = 0;
  358
+
  359
+        Header *lnm = NULL;     // longname member
  360
+        char *longnames = NULL;
  361
+        size_t longnames_length = 0;
  362
+
  363
+        unsigned offset = 8;
  364
+        char *symtab = NULL;
  365
+        unsigned symtab_size = 0;
  366
+        unsigned mstart = objmodules.dim;
  367
+        while (offset < buflen)
  368
+        {
  369
+            offset = (offset + 1) & ~1;         // round to even boundary
  370
+            if (offset + sizeof(Header) >= buflen)
  371
+            {   reason = 1;
  372
+                goto Lcorrupt;
  373
+            }
  374
+            Header *header = (Header *)((unsigned char *)buf + offset);
  375
+            offset += sizeof(Header);
  376
+            char *endptr = NULL;
  377
+            unsigned long size = strtoul(header->file_size, &endptr, 10);
  378
+            if (endptr >= &header->file_size[10] || *endptr != ' ')
  379
+            {   reason = 2;
  380
+                goto Lcorrupt;
  381
+            }
  382
+            if (offset + size > buflen)
  383
+            {   reason = 3;
  384
+                goto Lcorrupt;
  385
+            }
  386
+
  387
+            if (!amh)
  388
+                amh = header;
  389
+            else if (memcmp(header->object_name, "/               ", OBJECT_NAME_SIZE) == 0)
  390
+            {
  391
+                if (!flm)
  392
+                {   // First Linker Member, which is ignored
  393
+                    flm = header;
  394
+                }
  395
+                else if (!slm)
  396
+                {   // Second Linker Member, which we require even though the format doesn't require it
  397
+                    slm = header;
  398
+                    if (size < 4 + 4)
  399
+                    {   reason = __LINE__;
  400
+                        goto Lcorrupt;
  401
+                    }
  402
+                    number_of_members = sgetl((char *)buf + offset);
  403
+                    member_file_offsets = (unsigned long *)((char *)buf + offset + 4);
  404
+                    if (size < 4 + number_of_members * 4 + 4)
  405
+                    {   reason = __LINE__;
  406
+                        goto Lcorrupt;
  407
+                    }
  408
+                    number_of_symbols = sgetl((char *)buf + offset + 4 + number_of_members * 4);
  409
+                    indices = (unsigned short *)((char *)buf + offset + 4 + number_of_members * 4 + 4);
  410
+                    string_table = (char *)((char *)buf + offset + 4 + number_of_members * 4 + 4 + number_of_symbols * 2);
  411
+                    if (size <= (4 + number_of_members * 4 + 4 + number_of_symbols * 2))
  412
+                    {   reason = __LINE__;
  413
+                        goto Lcorrupt;
  414
+                    }
  415
+                    string_table_length = size - (4 + number_of_members * 4 + 4 + number_of_symbols * 2);
  416
+
  417
+                    /* The number of strings in the string_table must be number_of_symbols; check it
  418
+                     * The strings must also be in ascending lexical order; not checked.
  419
+                     */
  420
+                    unsigned long i = 0;
  421
+                    for (unsigned n = 0; n < number_of_symbols; n++)
  422
+                    {
  423
+                        while (1)
  424
+                        {
  425
+                            if (i >= string_table_length)
  426
+                            {   reason = __LINE__;
  427
+                                goto Lcorrupt;
  428
+                            }
  429
+                            if (!string_table[i++])
  430
+                                break;
  431
+                        }
  432
+                    }
  433
+                    if (i != string_table_length)
  434
+                    {   reason = __LINE__;
  435
+                        goto Lcorrupt;
  436
+                    }
  437
+                }
  438
+            }
  439
+            else if (memcmp(header->object_name, "//              ", OBJECT_NAME_SIZE) == 0)
  440
+            {
  441
+                if (!lnm)
  442
+                {   lnm = header;
  443
+                    longnames = (char *)buf + offset;
  444
+                    longnames_length = size;
  445
+                }
  446
+            }
  447
+            else
  448
+            {
  449
+                if (!slm)
  450
+                {   reason = __LINE__;
  451
+                    goto Lcorrupt;
  452
+                }
  453
+                if (!lnm)
  454
+                {   reason = __LINE__;
  455
+                    goto Lcorrupt;
  456
+                }
  457
+
  458
+                ObjModule *om = new ObjModule();
  459
+                // Include Header in base[0..length], so we don't have to repro it
  460
+                om->base = (unsigned char *)buf + offset - sizeof(Header);
  461
+                om->length = size + sizeof(Header);
  462
+                om->offset = 0;
  463
+                if (header->object_name[0] == '/')
  464
+                {   /* Pick long name out of longnames[]
  465
+                     */
  466
+                    unsigned foff = strtoul(header->object_name + 1, &endptr, 10);
  467
+                    unsigned i;
  468
+                    for (i = 0; 1; i++)
  469
+                    {   if (foff + i >= longnames_length)
  470
+                        {   reason = 7;
  471
+                            goto Lcorrupt;
  472
+                        }
  473
+                        char c = longnames[foff + i];
  474
+                        if (c == '/')
  475
+                            break;
  476
+                    }
  477
+                    om->name = (char *)malloc(i + 1);
  478
+                    assert(om->name);
  479
+                    memcpy(om->name, longnames + foff, i);
  480
+                    om->name[i] = 0;
  481
+                }
  482
+                else
  483
+                {   /* Pick short name out of header
  484
+                     */
  485
+                    om->name = (char *)malloc(OBJECT_NAME_SIZE);
  486
+                    assert(om->name);
  487
+                    for (int i = 0; 1; i++)
  488
+                    {   if (i == OBJECT_NAME_SIZE)
  489
+                        {   reason = __LINE__;
  490
+                            goto Lcorrupt;
  491
+                        }
  492
+                        char c = header->object_name[i];
  493
+                        if (c == '/')
  494
+                        {   om->name[i] = 0;
  495
+                            break;
  496
+                        }
  497
+                        om->name[i] = c;
  498
+                    }
  499
+                }
  500
+                om->file_time = strtoul(header->file_time, &endptr, 10);
  501
+                om->user_id   = strtoul(header->user_id, &endptr, 10);
  502
+                om->group_id  = strtoul(header->group_id, &endptr, 10);
  503
+                om->file_mode = strtoul(header->file_mode, &endptr, 8);
  504
+                om->scan = 0;                   // don't scan object module for symbols
  505
+                objmodules.push(om);
  506
+            }
  507
+            offset += (size + 1) & ~1;
  508
+        }
  509
+        if (offset != buflen)
  510
+        {   reason = __LINE__;
  511
+            goto Lcorrupt;
  512
+        }
  513
+
  514
+        /* Scan the library's symbol table, and insert it into our own.
  515
+         * We use this instead of rescanning the object module, because
  516
+         * the library's creator may have a different idea of what symbols
  517
+         * go into the symbol table than we do.
  518
+         * This is also probably faster.
  519
+         */
  520
+        if (!slm)
  521
+        {   reason = __LINE__;
  522
+            goto Lcorrupt;
  523
+        }
  524
+
  525
+        char *s = string_table;
  526
+        for (unsigned i = 0; i < number_of_symbols; i++)
  527
+        {
  528
+            char *name = s;
  529
+            s += strlen(s) + 1;
  530
+
  531
+            unsigned memi = indices[i] - 1;
  532
+            if (memi >= number_of_members)
  533
+            {   reason = __LINE__;
  534
+                goto Lcorrupt;
  535
+            }
  536
+            unsigned long moff = member_file_offsets[memi];
  537
+            for (unsigned m = mstart; 1; m++)
  538
+            {   if (m == objmodules.dim)
  539
+                {   reason = __LINE__;
  540
+                    goto Lcorrupt;              // didn't find it
  541
+                }
  542
+                ObjModule *om = objmodules[m];
  543
+                //printf("\tom offset = x%x\n", (char *)om->base - (char *)buf);
  544
+                if (moff == (char *)om->base - (char *)buf)
  545
+                {
  546
+                    addSymbol(om, name, 1);
  547
+//                  if (mstart == m)
  548
+//                      mstart++;
  549
+                    break;
  550
+                }
  551
+            }
  552
+        }
  553
+
  554
+        return;
  555
+    }
  556
+
  557
+    /* It's an object module
  558
+     */
  559
+    ObjModule *om = new ObjModule();
  560
+    om->base = (unsigned char *)buf;
  561
+    om->length = buflen;
  562
+    om->offset = 0;
  563
+    om->name = FileName::name(module_name);     // remove path, but not extension
  564
+    om->scan = 1;
  565
+    if (fromfile)
  566
+    {   struct stat statbuf;
  567
+        int i = stat(module_name, &statbuf);
  568
+        if (i == -1)            // error, errno is set
  569
+        {   reason = 14;
  570
+            goto Lcorrupt;
  571
+        }
  572
+        om->file_time = statbuf.st_ctime;
  573
+        om->user_id   = statbuf.st_uid;
  574
+        om->group_id  = statbuf.st_gid;
  575
+        om->file_mode = statbuf.st_mode;
  576
+    }
  577
+    else
  578
+    {   /* Mock things up for the object module file that never was
  579
+         * actually written out.
  580
+         */
  581
+#if 0
  582
+        static uid_t uid;
  583
+        static gid_t gid;
  584
+        static int init;
  585
+        if (!init)
  586
+        {   init = 1;
  587
+            uid = getuid();
  588
+            gid = getgid();
  589
+        }
  590
+        time(&om->file_time);
  591
+        om->user_id = uid;
  592
+        om->group_id = gid;
  593
+        om->file_mode = 0100644;
  594
+#endif
  595
+    }
  596
+    objmodules.push(om);
  597
+}
  598
+
  599
+
  600
+/*****************************************************************************/
  601
+/*****************************************************************************/
  602
+
  603
+/**********************************************
  604
+ * Create and write library to libbuf.
  605
+ * The library consists of:
  606
+ *      !<arch>\n
  607
+ *      header
  608
+ *      1st Linker Member
  609
+ *      Header
  610
+ *      2nd Linker Member
  611
+ *      Header
  612
+ *      Longnames Member
  613
+ *      object modules...
  614
+ */
  615
+
  616
+void LibMSCoff::WriteLibToBuffer(OutBuffer *libbuf)
  617
+{
  618
+#if LOG
  619
+    printf("LibElf::WriteLibToBuffer()\n");
  620
+#endif
  621
+
  622
+    /************* Scan Object Modules for Symbols ******************/
  623
+
  624
+    for (size_t i = 0; i < objmodules.dim; i++)
  625
+    {   ObjModule *om = objmodules[i];
  626
+        if (om->scan)
  627
+        {
  628
+            scanObjModule(om);
  629
+        }
  630
+    }
  631
+
  632
+    /************* Determine longnames size ******************/
  633
+
  634
+    /* The longnames section is where we store long file names.
  635
+     */
  636
+    unsigned noffset = 0;
  637
+    for (size_t i = 0; i < objmodules.dim; i++)
  638
+    {   ObjModule *om = objmodules[i];
  639
+        size_t len = strlen(om->name);
  640
+        if (len >= OBJECT_NAME_SIZE)
  641
+        {
  642
+            om->name_offset = noffset;
  643
+            noffset += len + 1;
  644
+        }
  645
+        else
  646
+            om->name_offset = -1;
  647
+    }
  648
+
  649
+#if LOG
  650
+    printf("\tnoffset = x%x\n", noffset);
  651
+#endif
  652
+
  653
+    /************* Determine string table length ******************/
  654
+
  655
+    unsigned slength = 0;
  656
+
  657
+    for (size_t i = 0; i < objsymbols.dim; i++)
  658
+    {   ObjSymbol *os = objsymbols[i];
  659
+
  660
+        slength += strlen(os->name) + 1;
  661
+    }
  662
+
  663
+    /************* Offset of first module ***********************/
  664
+
  665
+    unsigned moffset = 8;       // signature
  666
+    moffset += sizeof(Header) + 4 + objsymbols.dim * 4 + slength;       // 1st Linker Member
  667
+    moffset += moffset & 1;
  668
+    moffset += sizeof(Header) + 4 + objmodules.dim * 4 + 4 + objsymbols.dim * 4 + slength;
  669
+    moffset += moffset & 1;
  670
+
  671
+#if LOG
  672
+    printf("\tmoffset = x%x\n", moffset);
  673
+#endif
  674
+
  675
+    /************* Offset of each module *************************/
  676
+
  677
+    for (size_t i = 0; i < objmodules.dim; i++)
  678
+    {   ObjModule *om = objmodules[i];
  679
+
  680
+        moffset += moffset & 1;
  681
+        om->offset = moffset;
  682
+        moffset += sizeof(Header) + om->length;
  683
+    }
  684
+
  685
+    libbuf->reserve(moffset);
  686
+
  687
+    /************* Write the library ******************/
  688
+    libbuf->write("!<arch>\n", 8);
  689
+
  690
+    ObjModule om;
  691
+    om.name_offset = -1;
  692
+    om.base = NULL;
  693
+    om.length = 4 + objsymbols.dim * 4 + slength;
  694
+    om.offset = 8;
  695
+    om.name = (char*)"";
  696
+    ::time(&om.file_time);
  697
+    om.user_id = 0;
  698
+    om.group_id = 0;
  699
+    om.file_mode = 0;
  700
+
  701
+    /*** Write out First Linker Member ***/
  702
+
  703
+    Header h;
  704
+    OmToHeader(&h, &om);
  705
+    libbuf->write(&h, sizeof(h));
  706
+
  707
+    char buf[4];
  708
+    sputl(objsymbols.dim, buf);
  709
+    libbuf->write(buf, 4);
  710
+
  711
+    unsigned long lastoffset;
  712
+    for (size_t i = 0; i < objsymbols.dim; i++)
  713
+    {   ObjSymbol *os = objsymbols[i];
  714
+
  715
+        if (i)
  716
+            // Should be sorted in module order
  717
+            assert(lastoffset <= os->om->offset);
  718
+        lastoffset = os->om->offset;
  719
+        sputl(lastoffset, buf);
  720
+        libbuf->write(buf, 4);
  721
+    }
  722
+
  723
+    for (size_t i = 0; i < objsymbols.dim; i++)
  724
+    {   ObjSymbol *os = objsymbols[i];
  725
+
  726
+        libbuf->writestring(os->name);
  727
+        libbuf->writeByte(0);
  728
+    }
  729
+
  730
+    /*** Write out Second Linker Member ***/
  731
+
  732
+    if (libbuf->offset & 1)
  733
+        libbuf->writeByte('\n');
  734
+
  735
+    om.length = 4 + objmodules.dim * 4 + 4 + objsymbols.dim * 2 + slength;
  736
+    OmToHeader(&h, &om);
  737
+    libbuf->write(&h, sizeof(h));
  738
+
  739
+    sputl(objmodules.dim, buf);
  740
+    libbuf->write(buf, 4);
  741
+
  742
+    for (size_t i = 0; i < objmodules.dim; i++)
  743
+    {   ObjModule *om = objmodules[i];
  744
+
  745
+        om->index = i;
  746
+        sputl(om->offset, buf);
  747
+        libbuf->write(buf, 4);
  748
+    }
  749
+
  750
+    sputl(objsymbols.dim, buf);
  751
+    libbuf->write(buf, 4);
  752
+
  753
+    // Sort objsymbols[] in lexical order
  754
+    qsort(objsymbols.data, objsymbols.dim, sizeof(objsymbols.data[0]), &ObjSymbol_cmp);
  755
+
  756
+    for (size_t i = 0; i < objsymbols.dim; i++)
  757
+    {   ObjSymbol *os = objsymbols[i];
  758
+
  759
+        sputl(os->om->index + 1, buf);
  760
+        libbuf->write(buf, 2);
  761
+    }
  762
+
  763
+    for (size_t i = 0; i < objsymbols.dim; i++)
  764
+    {   ObjSymbol *os = objsymbols[i];
  765
+
  766
+        libbuf->writestring(os->name);
  767
+        libbuf->writeByte(0);
  768
+    }
  769
+
  770
+    /*** Write out longnames Member ***/
  771
+
  772
+    if (libbuf->offset & 1)
  773
+        libbuf->writeByte('\n');
  774
+
  775
+    // header
  776
+    memset(&h, ' ', sizeof(Header));
  777
+    h.object_name[0] = '/';
  778
+    h.object_name[1] = '/';
  779
+    size_t len = sprintf(h.file_size, "%u", noffset);
  780
+    assert(len < 10);
  781
+    h.file_size[len] = ' ';
  782
+    h.trailer[0] = '`';
  783
+    h.trailer[1] = '\n';
  784
+    libbuf->write(&h, sizeof(h));
  785
+
  786
+    for (size_t i = 0; i < objmodules.dim; i++)
  787
+    {   ObjModule *om = objmodules[i];
  788
+        if (om->name_offset >= 0)
  789
+        {   libbuf->writestring(om->name);
  790
+            libbuf->writeByte(0);
  791
+        }
  792
+    }
  793
+
  794
+    /* Write out each of the object modules
  795
+     */
  796
+    for (size_t i = 0; i < objmodules.dim; i++)
  797
+    {   ObjModule *om = objmodules[i];
  798
+
  799
+        if (libbuf->offset & 1)
  800
+            libbuf->writeByte('\n');    // module alignment
  801
+
  802
+        assert(libbuf->offset == om->offset);
  803
+
  804
+        OmToHeader(&h, om);
  805
+        libbuf->write(&h, sizeof(h));   // module header
  806
+
  807
+        libbuf->write(om->base, om->length);    // module contents
  808
+    }
  809
+
  810
+#if LOG
  811
+    printf("moffset = x%x, libbuf->offset = x%x\n", moffset, libbuf->offset);
  812
+#endif
  813
+    assert(libbuf->offset == moffset);
  814
+}
  815
+
11  src/posix.mak
@@ -114,6 +114,7 @@ SRC = win32.mak posix.mak \
114 114
 	builtin.c clone.c lib.h libomf.c libelf.c libmach.c arrayop.c \
115 115
 	aliasthis.h aliasthis.c json.h json.c unittests.c imphint.c \
116 116
 	argtypes.c intrange.c apply.c canthrow.c sideeffect.c \
  117
+	scanmscoff.c \
117 118
 	$C/cdef.h $C/cc.h $C/oper.h $C/ty.h $C/optabgen.c \
118 119
 	$C/global.h $C/code.h $C/type.h $C/dt.h $C/cgcv.h \
119 120
 	$C/el.h $C/iasm.h $C/rtlsym.h $C/html.h \
@@ -125,12 +126,12 @@ SRC = win32.mak posix.mak \
125 126
 	$C/evalu8.c $C/go.c $C/gflow.c $C/gdag.c \
126 127
 	$C/gother.c $C/glocal.c $C/gloop.c $C/html.c $C/newman.c \
127 128
 	$C/nteh.c $C/os.c $C/out.c $C/outbuf.c $C/ptrntab.c $C/rtlsym.c \
128  
-	$C/type.c $C/melf.h $C/mach.h $C/bcomplex.h \
  129
+	$C/type.c $C/melf.h $C/mach.h $C/mscoff.h $C/bcomplex.h \
129 130
 	$C/cdeflnx.h $C/outbuf.h $C/token.h $C/tassert.h \
130 131
 	$C/elfobj.c $C/cv4.h $C/dwarf2.h $C/exh.h $C/go.h \
131 132
 	$C/dwarf.c $C/dwarf.h $C/aa.h $C/aa.c $C/tinfo.h $C/ti_achar.c \
132 133
 	$C/ti_pvoid.c \
133  
-	$C/machobj.c \
  134
+	$C/machobj.c $C/mscoffobj.c \
134 135
 	$C/xmm.h \
135 136
 	$(TK)/filespec.h $(TK)/mem.h $(TK)/list.h $(TK)/vec.h \
136 137
 	$(TK)/filespec.c $(TK)/mem.c $(TK)/vec.c $(TK)/list.c \
@@ -435,6 +436,9 @@ libelf.o: libelf.c $C/melf.h
435 436
 libmach.o: libmach.c $C/mach.h
436 437
 	$(CC) -c $(CFLAGS) -I$C $<
437 438
 
  439
+libmscoff.o: libmscoff.c $C/mscoff.h
  440
+	$(CC) -c $(CFLAGS) -I$C $<
  441
+
438 442
 link.o: link.c
439 443
 	$(CC) -c $(CFLAGS) $<
440 444
 
@@ -459,6 +463,9 @@ rmem.o: $(ROOT)/rmem.c
459 463
 module.o: module.c $C/html.h
460 464
 	$(CC) -c $(CFLAGS) -I$C $<
461 465
 
  466
+mscoffobj.o: $C/mscoffobj.c $C/mscoff.h
  467
+	$(CC) -c $(MFLAGS) $<
  468
+
462 469
 msc.o: msc.c $(CH) mars.h
463 470
 	$(CC) -c $(MFLAGS) $<
464 471
 
238  src/scanmscoff.c
... ...
@@ -0,0 +1,238 @@
  1
+
  2
+// Compiler implementation of the D programming language
  3
+// Copyright (c) 1999-2012 by Digital Mars
  4
+// All Rights Reserved
  5
+// written by Walter Bright
  6
+// http://www.digitalmars.com
  7
+// License for redistribution is by either the Artistic License
  8
+// in artistic.txt, or the GNU General Public License in gnu.txt.
  9
+// See the included readme.txt for details.
  10
+
  11
+/* Implements scanning an object module for names to go in the library table of contents.
  12
+ * The object module format is MS-COFF.
  13
+ * This format is described in the Microsoft document
  14
+ * "Microsoft Portable Executable and Common Object File Format Specification"
  15
+ * Revision 8.2 September 21, 2010
  16
+ */
  17
+
  18
+#include <stdio.h>
  19
+#include <string.h>
  20
+#include <stdlib.h>
  21
+#include <assert.h>
  22
+
  23
+#include "mscoff.h"
  24
+
  25
+#include "root.h"
  26
+#include "mars.h"
  27
+
  28
+#define LOG 0
  29
+
  30
+
  31
+/*****************************************
  32
+ * Reads an object module from base[0..buflen] and passes the names
  33
+ * of any exported symbols to (*pAddSymbol)().
  34
+ * Input:
  35
+ *      pctx            context pointer, pass to *pAddSymbol
  36
+ *      pAddSymbol      function to pass the names to
  37
+ *      base[0..buflen] contains contents of object module
  38
+ *      module_name     name of the object module (used for error messages)
  39
+ *      loc             location to use for error printing
  40
+ */
  41
+
  42
+void scanMSCoffObjModule(void* pctx, void (*pAddSymbol)(void* pctx, char* name, int pickAny), void *base, size_t buflen, char *module_name, Loc loc)
  43
+{
  44
+#if LOG
  45
+    printf("scanMSCoffObjModule(%s)\n", name);
  46
+#endif
  47
+
  48
+#if 0
  49
+    unsigned char *buf = (unsigned char *)base;
  50
+    int reason = 0;
  51
+    uint32_t ncmds;
  52
+
  53
+    struct mach_header *header = (struct mach_header *)buf;
  54
+    struct mach_header_64 *header64 = NULL;
  55
+
  56
+    /* First do sanity checks on object file
  57
+     */
  58
+    if (buflen < sizeof(struct mach_header))
  59
+    {
  60
+      Lcorrupt:
  61
+        error(loc, "MS-Coff object module %s corrupt, %d", module_name, reason);
  62
+        return;
  63
+    }
  64
+
  65
+    if (header->magic == MH_MAGIC)
  66
+    {
  67
+        if (header->cputype != CPU_TYPE_I386)
  68
+        {
  69
+            error(loc, "MS-Coff object module %s has cputype = %d, should be %d",
  70
+                    module_name, header->cputype, CPU_TYPE_I386);
  71
+            return;
  72
+        }
  73
+        if (header->filetype != MH_OBJECT)
  74
+        {
  75
+            error(loc, "MS-Coff object module %s has file type = %d, should be %d",
  76
+                    module_name, header->filetype, MH_OBJECT);
  77
+            return;
  78
+        }
  79
+        if (buflen < sizeof(struct mach_header) + header->sizeofcmds)
  80
+        {   reason = 2;
  81
+            goto Lcorrupt;
  82
+        }
  83
+        ncmds = header->ncmds;
  84
+    }
  85
+    else if (header->magic == MH_MAGIC_64)
  86
+    {
  87
+        header64 = (struct mach_header_64 *)buf;
  88
+        if (buflen < sizeof(struct mach_header_64))
  89
+            goto Lcorrupt;
  90
+        if (header64->cputype != CPU_TYPE_X86_64)
  91
+        {
  92
+            error(loc, "MS-Coff object module %s has cputype = %d, should be %d",
  93
+                    module_name, header64->cputype, CPU_TYPE_X86_64);