diff --git a/compiler/src/build.d b/compiler/src/build.d index d7949970ec..a9cbbe7458 100755 --- a/compiler/src/build.d +++ b/compiler/src/build.d @@ -1562,8 +1562,8 @@ auto sourceFiles() dmsc.d e2ir.d iasmdmd.d glue.d objc_glue.d s2ir.d tocsym.d toctype.d tocvdebug.d todt.d toir.d toobj.d "), - driver: fileArray(env["D"], "dinifile.d dmdparams.d gluelayer.d lib.d libelf.d libmach.d libmscoff.d libomf.d - link.d mars.d main.d scanelf.d scanmach.d scanmscoff.d scanomf.d vsoptions.d + driver: fileArray(env["D"], "dinifile.d dmdparams.d gluelayer.d lib.d libelf.d libmach.d libmscoff.d + link.d mars.d main.d scanelf.d scanmach.d scanmscoff.d vsoptions.d "), frontend: fileArray(env["D"], " access.d aggregate.d aliasthis.d argtypes_x86.d argtypes_sysv_x64.d argtypes_aarch64.d arrayop.d diff --git a/compiler/src/dmd/README.md b/compiler/src/dmd/README.md index d784d07df2..baac0d79b3 100644 --- a/compiler/src/dmd/README.md +++ b/compiler/src/dmd/README.md @@ -201,11 +201,9 @@ Note that these groups have no strict meaning, the category assignments are a bi | [libelf.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/libelf.d) | Library in ELF format (Unix) | | [libmach.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/libmach.d) | Library in Mach-O format (macOS) | | [libmscoff.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/libmscoff.d) | Library in COFF format (32/64-bit Windows) | -| [libomf.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/libomf.d) | Library in OMF format (legacy 32-bit Windows) | | [scanelf.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/scanelf.d) | Extract symbol names from a library in ELF format | | [scanmach.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/scanmach.d) | Extract symbol names from a library in Mach-O format | | [scanmscoff.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/scanmscoff.d) | Extract symbol names from a library in COFF format | -| [scanomf.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/scanomf.d) | Extract symbol names from a library in OMF format | ### Code generation / back-end interfacing diff --git a/compiler/src/dmd/lib.d b/compiler/src/dmd/lib.d index 5302fa9264..05569f0bca 100644 --- a/compiler/src/dmd/lib.d +++ b/compiler/src/dmd/lib.d @@ -22,7 +22,6 @@ import dmd.target : Target; import dmd.libelf; import dmd.libmach; import dmd.libmscoff; -import dmd.libomf; private enum LOG = false; diff --git a/compiler/src/dmd/libomf.d b/compiler/src/dmd/libomf.d deleted file mode 100644 index 57669c66ae..0000000000 --- a/compiler/src/dmd/libomf.d +++ /dev/null @@ -1,596 +0,0 @@ -/** - * A library in the OMF format, a legacy format for 32-bit Windows. - * - * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved - * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) - * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/libomf.d, _libomf.d) - * Documentation: https://dlang.org/phobos/dmd_libomf.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/libomf.d - */ - -module dmd.libomf; - -import core.stdc.stdio; -import core.stdc.string; -import core.stdc.stdlib; -import core.bitop; - -import dmd.errors : fatal; -import dmd.utils; -import dmd.lib; -import dmd.location; - -import dmd.root.array; -import dmd.root.file; -import dmd.root.filename; -import dmd.root.rmem; -import dmd.common.outbuffer; -import dmd.root.string; -import dmd.root.stringtable; - -import dmd.scanomf; - -// Entry point (only public symbol in this module). -Library LibOMF_factory() -{ - return new LibOMF(); -} - -private: // for the remainder of this module -nothrow: - -enum LOG = false; - -struct OmfObjSymbol -{ - char* name; - OmfObjModule* om; - - /// Predicate for `Array.sort`for name comparison - static int name_pred (scope const OmfObjSymbol** ppe1, scope const OmfObjSymbol** ppe2) nothrow @nogc pure - { - return strcmp((**ppe1).name, (**ppe2).name); - } -} - -alias OmfObjModules = Array!(OmfObjModule*); -alias OmfObjSymbols = Array!(OmfObjSymbol*); - -final class LibOMF : Library -{ - OmfObjModules objmodules; // OmfObjModule[] - OmfObjSymbols objsymbols; // OmfObjSymbol[] - StringTable!(OmfObjSymbol*) tab; - - extern (D) this() - { - tab._init(14_000); - } - - /*************************************** - * Add object module or library to the library. - * Examine the buffer to see which it is. - * If the buffer is NULL, use module_name as the file name - * and load the file. - */ - override void addObject(const(char)[] module_name, const(ubyte)[] buffer) - { - static if (LOG) - { - printf("LibOMF::addObject(%.*s)\n", cast(int)module_name.length, - module_name.ptr); - } - - void corrupt(int reason) - { - eSink.error(loc, "corrupt OMF object module %.*s %d", - cast(int)module_name.length, module_name.ptr, reason); - } - - if (!buffer.length) - { - assert(module_name.length, "No module nor buffer provided to `addObject`"); - // read file and take buffer ownership - OutBuffer b; - if (readFile(Loc.initial, module_name, b)) - fatal(); - buffer = cast(ubyte[])b.extractSlice(); - } - uint g_page_size; - ubyte* pstart = cast(ubyte*)buffer.ptr; - bool islibrary = false; - /* See if it's an OMF library. - * Don't go by file extension. - */ - struct LibHeader - { - align(1): - ubyte recTyp; // 0xF0 - ushort pagesize; - uint lSymSeek; - ushort ndicpages; - } - - /* Determine if it is an OMF library, an OMF object module, - * or something else. - */ - if (buffer.length < (LibHeader).sizeof) - return corrupt(__LINE__); - const lh = cast(const(LibHeader)*)buffer.ptr; - if (lh.recTyp == 0xF0) - { - /* OMF library - * The modules are all at buffer.ptr[g_page_size .. lh.lSymSeek] - */ - islibrary = 1; - g_page_size = lh.pagesize + 3; - if (lh.lSymSeek > buffer.length || g_page_size > buffer.length) - return corrupt(__LINE__); - buffer = (cast(ubyte*)pstart)[g_page_size .. lh.lSymSeek]; - } - else if (lh.recTyp == '!' && memcmp(lh, "!\n".ptr, 8) == 0) - { - eSink.error(loc, "COFF libraries not supported"); - return; - } - else - { - // Not a library, assume OMF object module - g_page_size = 16; - } - bool firstmodule = true; - - void addOmfObjModule(char* name, void* base, size_t length) - { - auto om = new OmfObjModule(); - om.base = cast(ubyte*)base; - om.page = cast(ushort)((om.base - pstart) / g_page_size); - om.length = cast(uint)length; - /* Determine the name of the module - */ - const(char)[] n; - if (firstmodule && module_name && !islibrary) - { - // Remove path and extension - n = FileName.sansExt(FileName.name(module_name)); - } - else - { - /* Use THEADR name as module name, - * removing path and extension. - */ - n = FileName.sansExt(FileName.name(name.toDString())); - } - om.name = toCString(n)[0 .. n.length]; - firstmodule = false; - this.objmodules.push(om); - } - - if (scanOmfLib(&addOmfObjModule, cast(void*)buffer.ptr, buffer.length, g_page_size)) - return corrupt(__LINE__); - } - - /*****************************************************************************/ - - void addSymbol(OmfObjModule* om, const(char)[] name, int pickAny = 0) nothrow - { - assert(name.length == strlen(name.ptr)); - static if (LOG) - { - printf("LibOMF::addSymbol(%.*s, %.*s, %d)\n", - cast(int)om.name.length, om.name.ptr, - cast(int)name.length, name.ptr, pickAny); - } - if (auto s = tab.insert(name, null)) - { - auto os = new OmfObjSymbol(); - os.name = cast(char*)Mem.check(strdup(name.ptr)); - os.om = om; - s.value = os; - objsymbols.push(os); - } - else - { - // already in table - if (!pickAny) - { - const s2 = tab.lookup(name); - assert(s2); - const os = s2.value; - eSink.error(loc, "multiple definition of %.*s: %.*s and %.*s: %s", - cast(int)om.name.length, om.name.ptr, - cast(int)name.length, name.ptr, - cast(int)os.om.name.length, os.om.name.ptr, os.name); - } - } - } - -private: - /************************************ - * Scan single object module for dictionary symbols. - * Send those symbols to LibOMF::addSymbol(). - */ - void scanObjModule(OmfObjModule* om) - { - static if (LOG) - { - printf("LibMSCoff::scanObjModule(%s)\n", om.name.ptr); - } - - extern (D) void addSymbol(const(char)[] name, int pickAny) nothrow - { - this.addSymbol(om, name, pickAny); - } - - scanOmfObjModule(&addSymbol, om.base[0 .. om.length], om.name.ptr, loc, eSink); - } - - /*********************************** - * Calculates number of pages needed for dictionary - * Returns: - * number of pages - */ - ushort numDictPages(uint padding) - { - ushort ndicpages; - ushort bucksForHash; - ushort bucksForSize; - uint symSize = 0; - foreach (s; objsymbols) - { - symSize += (strlen(s.name) + 4) & ~1; - } - foreach (om; objmodules) - { - size_t len = om.name.length; - if (len > 0xFF) - len += 2; // Digital Mars long name extension - symSize += (len + 4 + 1) & ~1; - } - bucksForHash = cast(ushort)((objsymbols.length + objmodules.length + HASHMOD - 3) / (HASHMOD - 2)); - bucksForSize = cast(ushort)((symSize + BUCKETSIZE - padding - padding - 1) / (BUCKETSIZE - padding)); - ndicpages = (bucksForHash > bucksForSize) ? bucksForHash : bucksForSize; - //printf("ndicpages = %u\n",ndicpages); - // Find prime number greater than ndicpages - __gshared uint* primes = - [ - 1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, - 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, - 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, - 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, - 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, - 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, - 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, - 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, - 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, - //521,523,541,547, - 0 - ]; - for (size_t i = 0; 1; i++) - { - if (primes[i] == 0) - { - // Quick and easy way is out. - // Now try and find first prime number > ndicpages - uint prime; - for (prime = (ndicpages + 1) | 1; 1; prime += 2) - { - // Determine if prime is prime - for (uint u = 3; u < prime / 2; u += 2) - { - if ((prime / u) * u == prime) - goto L1; - } - break; - L1: - } - ndicpages = cast(ushort)prime; - break; - } - if (primes[i] > ndicpages) - { - ndicpages = cast(ushort)primes[i]; - break; - } - } - return ndicpages; - } - - /******************************************* - * Write the module and symbol names to the dictionary. - * Returns: - * false failure - */ - bool FillDict(ubyte* bucketsP, ushort ndicpages) - { - // max size that will fit in dictionary - enum LIBIDMAX = (512 - 0x25 - 3 - 4); - ubyte[4 + LIBIDMAX + 2 + 1] entry; - //printf("FillDict()\n"); - // Add each of the module names - foreach (om; objmodules) - { - ushort n = cast(ushort)om.name.length; - if (n > 255) - { - entry[0] = 0xFF; - entry[1] = 0; - *cast(ushort*)(entry.ptr + 2) = cast(ushort)(n + 1); - memcpy(entry.ptr + 4, om.name.ptr, n); - n += 3; - } - else - { - entry[0] = cast(ubyte)(1 + n); - memcpy(entry.ptr + 1, om.name.ptr, n); - } - entry[n + 1] = '!'; - *(cast(ushort*)(n + 2 + entry.ptr)) = om.page; - if (n & 1) - entry[n + 2 + 2] = 0; - if (!EnterDict(bucketsP, ndicpages, entry.ptr, n + 1)) - return false; - } - // Sort the symbols - objsymbols.sort!(OmfObjSymbol.name_pred); - // Add each of the symbols - foreach (os; objsymbols) - { - ushort n = cast(ushort)strlen(os.name); - if (n > 255) - { - entry[0] = 0xFF; - entry[1] = 0; - *cast(ushort*)(entry.ptr + 2) = n; - memcpy(entry.ptr + 4, os.name, n); - n += 3; - } - else - { - entry[0] = cast(ubyte)n; - memcpy(entry.ptr + 1, os.name, n); - } - *(cast(ushort*)(n + 1 + entry.ptr)) = os.om.page; - if ((n & 1) == 0) - entry[n + 3] = 0; - if (!EnterDict(bucketsP, ndicpages, entry.ptr, n)) - { - return false; - } - } - return true; - } - - /********************************************** - * Create and write library to libbuf. - * The library consists of: - * library header - * object modules... - * dictionary header - * dictionary pages... - */ - protected override void writeLibToBuffer(ref OutBuffer libbuf) - { - /* Scan each of the object modules for symbols - * to go into the dictionary - */ - foreach (om; objmodules) - { - scanObjModule(om); - } - uint g_page_size = 16; - /* Calculate page size so that the number of pages - * fits in 16 bits. This is because object modules - * are indexed by page number, stored as an unsigned short. - */ - while (1) - { - Lagain: - static if (LOG) - { - printf("g_page_size = %d\n", g_page_size); - } - uint offset = g_page_size; - foreach (om; objmodules) - { - uint page = offset / g_page_size; - if (page > 0xFFFF) - { - // Page size is too small, double it and try again - g_page_size *= 2; - goto Lagain; - } - offset += OMFObjSize(om.base, om.length, om.name.ptr); - // Round the size of the file up to the next page size - // by filling with 0s - uint n = (g_page_size - 1) & offset; - if (n) - offset += g_page_size - n; - } - break; - } - /* Leave one page of 0s at start as a dummy library header. - * Fill it in later with the real data. - */ - libbuf.fill0(g_page_size); - /* Write each object module into the library - */ - foreach (om; objmodules) - { - uint page = cast(uint)(libbuf.length / g_page_size); - assert(page <= 0xFFFF); - om.page = cast(ushort)page; - // Write out the object module om - writeOMFObj(libbuf, om.base, om.length, om.name.ptr); - // Round the size of the file up to the next page size - // by filling with 0s - uint n = (g_page_size - 1) & libbuf.length; - if (n) - libbuf.fill0(g_page_size - n); - } - // File offset of start of dictionary - uint offset = cast(uint)libbuf.length; - // Write dictionary header, then round it to a BUCKETPAGE boundary - ushort size = (BUCKETPAGE - (cast(short)offset + 3)) & (BUCKETPAGE - 1); - libbuf.writeByte(0xF1); - libbuf.writeword(size); - libbuf.fill0(size); - // Create dictionary - ubyte* bucketsP = null; - ushort ndicpages; - ushort padding = 32; - for (;;) - { - ndicpages = numDictPages(padding); - static if (LOG) - { - printf("ndicpages = %d\n", ndicpages); - } - // Allocate dictionary - if (bucketsP) - bucketsP = cast(ubyte*)Mem.check(realloc(bucketsP, ndicpages * BUCKETPAGE)); - else - bucketsP = cast(ubyte*)Mem.check(malloc(ndicpages * BUCKETPAGE)); - memset(bucketsP, 0, ndicpages * BUCKETPAGE); - for (uint u = 0; u < ndicpages; u++) - { - // 'next available' slot - bucketsP[u * BUCKETPAGE + HASHMOD] = (HASHMOD + 1) >> 1; - } - if (FillDict(bucketsP, ndicpages)) - break; - padding += 16; // try again with more margins - } - // Write dictionary - libbuf.write(bucketsP[0 .. ndicpages * BUCKETPAGE]); - if (bucketsP) - free(bucketsP); - // Create library header - struct Libheader - { - align(1): - ubyte recTyp; - ushort recLen; - uint trailerPosn; - ushort ndicpages; - ubyte flags; - uint filler; - } - - Libheader libHeader; - memset(&libHeader, 0, (Libheader).sizeof); - libHeader.recTyp = 0xF0; - libHeader.recLen = 0x0D; - libHeader.trailerPosn = offset + (3 + size); - libHeader.recLen = cast(ushort)(g_page_size - 3); - libHeader.ndicpages = ndicpages; - libHeader.flags = 1; // always case sensitive - // Write library header at start of buffer - memcpy(cast(void*)libbuf[].ptr, &libHeader, (libHeader).sizeof); - } -} - -/*****************************************************************************/ -/*****************************************************************************/ -struct OmfObjModule -{ - ubyte* base; // where are we holding it in memory - uint length; // in bytes - ushort page; // page module starts in output file - const(char)[] name; // module name, with terminating 0 -} - -enum HASHMOD = 0x25; -enum BUCKETPAGE = 512; -enum BUCKETSIZE = (BUCKETPAGE - HASHMOD - 1); - -/******************************************* - * Write a single entry into dictionary. - * Returns: - * false failure - */ -bool EnterDict(ubyte* bucketsP, ushort ndicpages, ubyte* entry, uint entrylen) -{ - ushort uStartIndex; - ushort uStep; - ushort uStartPage; - ushort uPageStep; - ushort uIndex; - ushort uPage; - ushort n; - uint u; - uint nbytes; - ubyte* aP; - ubyte* zP; - aP = entry; - zP = aP + entrylen; // point at last char in identifier - uStartPage = 0; - uPageStep = 0; - uStartIndex = 0; - uStep = 0; - u = entrylen; - while (u--) - { - uStartPage = rol!(ushort)(uStartPage, 2) ^ (*aP | 0x20); - uStep = ror!(ushort)(uStep, 2) ^ (*aP++ | 0x20); - uStartIndex = ror!(ushort)(uStartIndex, 2) ^ (*zP | 0x20); - uPageStep = rol!(ushort)(uPageStep, 2) ^ (*zP-- | 0x20); - } - uStartPage %= ndicpages; - uPageStep %= ndicpages; - if (uPageStep == 0) - uPageStep++; - uStartIndex %= HASHMOD; - uStep %= HASHMOD; - if (uStep == 0) - uStep++; - uPage = uStartPage; - uIndex = uStartIndex; - // number of bytes in entry - nbytes = 1 + entrylen + 2; - if (entrylen > 255) - nbytes += 2; - while (1) - { - aP = &bucketsP[uPage * BUCKETPAGE]; - uStartIndex = uIndex; - while (1) - { - if (0 == aP[uIndex]) - { - // n = next available position in this page - n = aP[HASHMOD] << 1; - assert(n > HASHMOD); - // if off end of this page - if (n + nbytes > BUCKETPAGE) - { - aP[HASHMOD] = 0xFF; - break; - // next page - } - else - { - aP[uIndex] = cast(ubyte)(n >> 1); - memcpy((aP + n), entry, nbytes); - aP[HASHMOD] += (nbytes + 1) >> 1; - if (aP[HASHMOD] == 0) - aP[HASHMOD] = 0xFF; - return true; - } - } - uIndex += uStep; - uIndex %= 0x25; - /*if (uIndex > 0x25) - uIndex -= 0x25;*/ - if (uIndex == uStartIndex) - break; - } - uPage += uPageStep; - if (uPage >= ndicpages) - uPage -= ndicpages; - if (uPage == uStartPage) - break; - } - return false; -} diff --git a/compiler/src/dmd/scanomf.d b/compiler/src/dmd/scanomf.d deleted file mode 100644 index 0a9006eb3d..0000000000 --- a/compiler/src/dmd/scanomf.d +++ /dev/null @@ -1,394 +0,0 @@ -/** - * Extract symbols from an OMF object file. - * - * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved - * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) - * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/scanomf.d, _scanomf.d) - * Documentation: https://dlang.org/phobos/dmd_scanomf.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/scanomf.d - */ - -module dmd.scanomf; - -import core.stdc.string; -import core.stdc.stdlib; - -import dmd.arraytypes; -import dmd.common.outbuffer; -import dmd.errorsink; -import dmd.location; -import dmd.root.rmem; -import dmd.root.string; - -nothrow: - -private enum LOG = false; - -/***************************************** - * Reads an object module from base[] and passes the names - * of any exported symbols to (*pAddSymbol)(). - * Params: - * pAddSymbol = function to pass the names to - * base = array of contents of object module - * module_name = name of the object module (used for error messages) - * loc = location to use for error printing - * eSink = where the error messages go - */ -void scanOmfObjModule(void delegate(const(char)[] name, int pickAny) nothrow pAddSymbol, - scope const ubyte[] base, scope const char* module_name, Loc loc, ErrorSink eSink) -{ - static if (LOG) - { - printf("scanOmfObjModule(%s)\n", module_name); - } - char[LIBIDMAX + 1] name = void; - Strings names; - scope(exit) - for (size_t u = 1; u < names.length; u++) - free(cast(void*)names[u]); - names.push(null); // don't use index 0 - bool easyomf = false; // assume not EASY-OMF - const pend = base.ptr + base.length; - const(ubyte)* pnext; - for (auto p = base.ptr; 1; p = pnext) - { - assert(p < pend); - ubyte recTyp = *p++; - ushort recLen = *cast(ushort*)p; - p += 2; - pnext = p + recLen; - recLen--; // forget the checksum - switch (recTyp) - { - case LNAMES: - case LLNAMES: - while (p + 1 < pnext) - { - parseName(p, name.ptr); - char* copy = cast(char*)Mem.check(strdup(name.ptr)); - names.push(copy); - } - break; - case PUBDEF: - if (easyomf) - recTyp = PUB386; // convert to MS format - goto case; - case PUB386: - if (!(parseIdx(p) | parseIdx(p))) - p += 2; // skip seg, grp, frame - while (p + 1 < pnext) - { - parseName(p, name.ptr); - p += (recTyp == PUBDEF) ? 2 : 4; // skip offset - parseIdx(p); // skip type index - pAddSymbol(name[0 .. strlen(name.ptr)], 0); - } - break; - case COMDAT: - if (easyomf) - recTyp = COMDAT + 1; // convert to MS format - goto case; - case COMDAT + 1: - { - int pickAny = 0; - if (*p++ & 5) // if continuation or local comdat - break; - ubyte attr = *p++; - if (attr & 0xF0) // attr: if multiple instances allowed - pickAny = 1; - p++; // align - p += 2; // enum data offset - if (recTyp == COMDAT + 1) - p += 2; // enum data offset - parseIdx(p); // type index - if ((attr & 0x0F) == 0) // if explicit allocation - { - parseIdx(p); // base group - parseIdx(p); // base segment - } - uint idx = parseIdx(p); // public name index - if (idx == 0 || idx >= names.length) - { - //debug(printf("[s] name idx=%d, uCntNames=%d\n", idx, uCntNames)); - eSink.error(loc, "corrupt COMDAT"); - return; - } - //printf("[s] name='%s'\n",name); - const(char)* n = names[idx]; - pAddSymbol(n.toDString(), pickAny); - break; - } - case COMDEF: - { - while (p + 1 < pnext) - { - parseName(p, name.ptr); - parseIdx(p); // type index - skipDataType(p); // data type - pAddSymbol(name[0 .. strlen(name.ptr)], 1); - } - break; - } - case ALIAS: - while (p + 1 < pnext) - { - parseName(p, name.ptr); - pAddSymbol(name[0 .. strlen(name.ptr)], 0); - parseName(p, name.ptr); - } - break; - case MODEND: - case M386END: - return; - case COMENT: - // Recognize Phar Lap EASY-OMF format - { - __gshared ubyte* omfstr1 = [0x80, 0xAA, '8', '0', '3', '8', '6']; - if (recLen == (omfstr1).sizeof) - { - for (uint i = 0; i < (omfstr1).sizeof; i++) - if (*p++ != omfstr1[i]) - goto L1; - easyomf = true; - break; - L1: - } - } - // Recognize .IMPDEF Import Definition Records - { - __gshared ubyte* omfstr2 = [0, 0xA0, 1]; - if (recLen >= 7) - { - p++; - for (uint i = 1; i < (omfstr2).sizeof; i++) - if (*p++ != omfstr2[i]) - goto L2; - p++; // skip OrdFlag field - parseName(p, name.ptr); - pAddSymbol(name[0 .. strlen(name.ptr)], 0); - break; - L2: - } - } - break; - default: - // ignore - } - } -} - -/************************************************* - * Scan a block of memory buf[0..buflen], pulling out each - * OMF object module in it and sending the info in it to (*pAddObjModule). - * Returns: - * true for corrupt OMF data - */ -bool scanOmfLib(void delegate(char* name, void* base, size_t length) nothrow pAddObjModule, scope void* buf, size_t buflen, uint pagesize) -{ - /* Split up the buffer buf[0..buflen] into multiple object modules, - * each aligned on a pagesize boundary. - */ - const(ubyte)* base = null; - char[LIBIDMAX + 1] name = void; - auto p = cast(const(ubyte)*)buf; - auto pend = p + buflen; - const(ubyte)* pnext; - for (; p < pend; p = pnext) // for each OMF record - { - if (p + 3 >= pend) - return true; // corrupt - ubyte recTyp = *p; - ushort recLen = *cast(const(ushort)*)(p + 1); - pnext = p + 3 + recLen; - if (pnext > pend) - return true; // corrupt - recLen--; // forget the checksum - switch (recTyp) - { - case LHEADR: - case THEADR: - if (!base) - { - base = p; - p += 3; - parseName(p, name.ptr); - if (name[0] == 'C' && name[1] == 0) // old C compilers did this - base = pnext; // skip past THEADR - } - break; - case MODEND: - case M386END: - { - if (base) - { - pAddObjModule(name.ptr, cast(ubyte*)base, pnext - base); - base = null; - } - // Round up to next page - uint t = cast(uint)(pnext - cast(const(ubyte)*)buf); - t = (t + pagesize - 1) & ~cast(uint)(pagesize - 1); - pnext = cast(const(ubyte)*)buf + t; - break; - } - default: - // ignore - } - } - return (base !is null); // missing MODEND record -} - -uint OMFObjSize(scope const void* base, size_t length, scope const char* name) -{ - ubyte c = *cast(const(ubyte)*)base; - if (c != THEADR && c != LHEADR) - { - size_t len = strlen(name); - assert(len <= LIBIDMAX); - length += len + 5; - } - return cast(uint)length; -} - -void writeOMFObj(ref OutBuffer buf, scope const void* base, size_t length, scope const char* name) -{ - ubyte c = *cast(const(ubyte)*)base; - if (c != THEADR && c != LHEADR) - { - const len = strlen(name); - assert(len <= LIBIDMAX); - ubyte[4 + LIBIDMAX + 1] header = void; - header[0] = THEADR; - header[1] = cast(ubyte)(2 + len); - header[2] = 0; - header[3] = cast(ubyte)len; - assert(len <= 0xFF - 2); - memcpy(4 + header.ptr, name, len); - // Compute and store record checksum - uint n = cast(uint)(len + 4); - ubyte checksum = 0; - ubyte* p = header.ptr; - while (n--) - { - checksum -= *p; - p++; - } - *p = checksum; - buf.write(header.ptr[0 .. len + 5]); - } - buf.write(base[0 .. length]); -} - -private: // for the remainder of this module - -/************************** - * Record types: - */ -enum RHEADR = 0x6E; -enum REGINT = 0x70; -enum REDATA = 0x72; -enum RIDATA = 0x74; -enum OVLDEF = 0x76; -enum ENDREC = 0x78; -enum BLKDEF = 0x7A; -enum BLKEND = 0x7C; -enum DEBSYM = 0x7E; -enum THEADR = 0x80; -enum LHEADR = 0x82; -enum PEDATA = 0x84; -enum PIDATA = 0x86; -enum COMENT = 0x88; -enum MODEND = 0x8A; -enum M386END = 0x8B; /* 32 bit module end record */ -enum EXTDEF = 0x8C; -enum TYPDEF = 0x8E; -enum PUBDEF = 0x90; -enum PUB386 = 0x91; -enum LOCSYM = 0x92; -enum LINNUM = 0x94; -enum LNAMES = 0x96; -enum SEGDEF = 0x98; -enum GRPDEF = 0x9A; -enum FIXUPP = 0x9C; -/*#define (none) 0x9E */ -enum LEDATA = 0xA0; -enum LIDATA = 0xA2; -enum LIBHED = 0xA4; -enum LIBNAM = 0xA6; -enum LIBLOC = 0xA8; -enum LIBDIC = 0xAA; -enum COMDEF = 0xB0; -enum LEXTDEF = 0xB4; -enum LPUBDEF = 0xB6; -enum LCOMDEF = 0xB8; -enum CEXTDEF = 0xBC; -enum COMDAT = 0xC2; -enum LINSYM = 0xC4; -enum ALIAS = 0xC6; -enum LLNAMES = 0xCA; -enum LIBIDMAX = (512 - 0x25 - 3 - 4); - -// max size that will fit in dictionary -void parseName(ref scope const(ubyte)* pp, char* name) -{ - auto p = pp; - uint len = *p++; - if (len == 0xFF && *p == 0) // if long name - { - len = p[1] & 0xFF; - len |= cast(uint)p[2] << 8; - p += 3; - assert(len <= LIBIDMAX); - } - memcpy(name, p, len); - name[len] = 0; - pp = p + len; -} - -ushort parseIdx(ref scope const(ubyte)* pp) -{ - auto p = pp; - const c = *p++; - ushort idx = (0x80 & c) ? ((0x7F & c) << 8) + *p++ : c; - pp = p; - return idx; -} - -// skip numeric field of a data type of a COMDEF record -void skipNumericField(ref scope const(ubyte)* pp) -{ - const(ubyte)* p = pp; - const c = *p++; - if (c == 0x81) - p += 2; - else if (c == 0x84) - p += 3; - else if (c == 0x88) - p += 4; - else - assert(c <= 0x80); - pp = p; -} - -// skip data type of a COMDEF record -void skipDataType(ref scope const(ubyte)* pp) -{ - auto p = pp; - const c = *p++; - if (c == 0x61) - { - // FAR data - skipNumericField(p); - skipNumericField(p); - } - else if (c == 0x62) - { - // NEAR data - skipNumericField(p); - } - else - { - assert(1 <= c && c <= 0x5f); // Borland segment indices - } - pp = p; -} diff --git a/dub.sdl b/dub.sdl index d6a1282d12..67aaa41558 100644 --- a/dub.sdl +++ b/dub.sdl @@ -134,14 +134,12 @@ subPackage { libelf,\ libmach,\ libmscoff,\ - libomf,\ link,\ objc_glue,\ s2ir,\ scanelf,\ scanmach,\ scanmscoff,\ - scanomf,\ tocsym,\ toctype,\ tocvdebug,\