Get rid of obsolete dmd.{lib,scan}omf modules

This commit is contained in:
Martin Kinkelin 2024-05-25 15:49:39 +02:00
parent dd673700c0
commit d715bdc972
6 changed files with 2 additions and 997 deletions

View file

@ -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

View file

@ -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

View file

@ -22,7 +22,6 @@ import dmd.target : Target;
import dmd.libelf;
import dmd.libmach;
import dmd.libmscoff;
import dmd.libomf;
private enum LOG = false;

View file

@ -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;
}

View file

@ -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;
}

View file

@ -134,14 +134,12 @@ subPackage {
libelf,\
libmach,\
libmscoff,\
libomf,\
link,\
objc_glue,\
s2ir,\
scanelf,\
scanmach,\
scanmscoff,\
scanomf,\
tocsym,\
toctype,\
tocvdebug,\