mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 21:21:48 +03:00
Get rid of obsolete dmd.{lib,scan}omf modules
This commit is contained in:
parent
dd673700c0
commit
d715bdc972
6 changed files with 2 additions and 997 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@ import dmd.target : Target;
|
|||
import dmd.libelf;
|
||||
import dmd.libmach;
|
||||
import dmd.libmscoff;
|
||||
import dmd.libomf;
|
||||
|
||||
private enum LOG = false;
|
||||
|
||||
|
|
|
@ -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, "!<arch>\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;
|
||||
}
|
|
@ -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;
|
||||
}
|
2
dub.sdl
2
dub.sdl
|
@ -134,14 +134,12 @@ subPackage {
|
|||
libelf,\
|
||||
libmach,\
|
||||
libmscoff,\
|
||||
libomf,\
|
||||
link,\
|
||||
objc_glue,\
|
||||
s2ir,\
|
||||
scanelf,\
|
||||
scanmach,\
|
||||
scanmscoff,\
|
||||
scanomf,\
|
||||
tocsym,\
|
||||
toctype,\
|
||||
tocvdebug,\
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue