Index: /trunk/src/emx/src/emxomf/emxomf.c
===================================================================
--- /trunk/src/emx/src/emxomf/emxomf.c	(revision 1409)
+++ /trunk/src/emx/src/emxomf/emxomf.c	(revision 1410)
@@ -351,6 +351,11 @@
 static char base_dir[256];
 
-/* This variable holds a normalized module name used with weak syms.  See get_mod_name(). */
-static char weak_mod_name[256];
+/* This variable holds the simple weak marker for the current module. See get_mod_name(). */
+static char weak_marker_simple[128];
+static int  weak_marker_simple_size;
+
+/* This variable holds the timestamped weak marker for the current module. See get_mod_name(). */
+static char weak_marker_ts[148];
+static int  weak_marker_ts_size;
 
 /* This growing array holds the file name table for generating line
@@ -777,4 +782,11 @@
   buffer_init (&sst);
   buffer_init (&sst_reloc);
+
+  /* Init weak markers */
+
+  weak_marker_simple[0] = '\0';
+  weak_marker_simple_size = 0;
+  weak_marker_ts[0] = '\0';
+  weak_marker_ts_size = 0;
 }
 
@@ -913,6 +925,6 @@
 
 
-/* Put the null-terminated string SRC into the current OMF record.  In
-   the OMF record, the string is preceded by a length byte.  The
+/* Put the null-terminated string pszName into the current OMF record.  
+   In the OMF record, the string is preceded by a length byte.  The
    string length must not exceed 255; if it is too long, display a
    warning and truncate the string.  Moreover, there must be enough
@@ -920,29 +932,38 @@
    message and abort. */
 
-static void put_str (const char *src)
-{
-  char sz[256];
-  int len;
-
-  len = strlen (src);
-  if (len > 255)
-    { /* Hash the symbol to help making it unique. */
-      const char *  psz = src;
-      unsigned      uhash = 0;
-      char          szhash[16];
-      warning ("Symbol length truncated to 255 characters for `%s'", src);
-      for (; *psz; psz++)
-        uhash = ((uhash << 3) ^ (*psz & 0x15)); /** @todo fix this rather bad hash algorithm. */
-      len = sprintf(szhash, "!_%X", 0x7fffffff & uhash);
-      memcpy(sz, src, 255);
-      memcpy(sz + 255 - len, szhash, len + 1);
-      len = 255;
-      src = &sz[0];
-    }
-  if (!fits (1+len))
-    doesn_fit ();
-  out_data[out_idx++] = (byte)len;
-  memcpy (out_data+out_idx, src, len);
-  out_idx += len;
+static void put_str(const char *pszName)
+{
+    int cch = strlen(pszName);
+    if (cch > 255)
+    {
+        /* Hash the symbol to help making it unique. 
+         * NOTE that the hash algorithm is not fixed, so is the !_%X marker too.
+         *      the weakld is parsing it!
+         */
+        char        szHash[16];
+        int         cch2;
+        const char *psz;
+        unsigned    uHash;
+        for (psz = pszName, uHash = 5381; *psz; psz++)   /* hash alg: original djb2. */
+            uHash += (uHash << 5) + *psz;
+        cch2 = sprintf(szHash, "!_%X", 0x7fffffff & uHash);
+
+        if (!fits(1+255))
+            doesn_fit();
+        out_data[out_idx++] = 255;
+        memcpy(out_data + out_idx, pszName, 255);
+        memcpy(out_data + out_idx + 255 - cch2, szHash, cch2);
+        out_idx += 255;
+
+        warning ("Symbol length truncated to 255 characters (from %d) for `%s'", cch, pszName);
+    }
+    else
+    {
+        if (!fits(1+cch))
+            doesn_fit();
+        out_data[out_idx++] = (byte)cch;
+        memcpy(out_data+out_idx, pszName, cch);
+        out_idx += cch;
+    }
 }
 
@@ -1264,4 +1285,5 @@
  *                      new name will be written.
  * @param   cchName     Size of the buffer pointed to by pachName.
+ *                      This must be at least 256, the code make this assumption!
  * @remark I'm sorry this function is written in my coding style - not!
  * @remark Weak Hack Method 2.
@@ -1287,14 +1309,83 @@
         case N_WEAKB:               /* 0x11  Weak bss symbol. */
         {
-            if (!opt_weakts)
-                snprintf(pachName, cchName, "%s$w$%s",
-                         pszOrgName, weak_mod_name);
-            else
+            int cch = strlen(pszOrgName);
+            int cch2;
+            
+            /* Init the markers if not done already. */
+            if (!weak_marker_simple[0])
             {
-                struct timeval tv = {0, 0};
+                static struct timeval   tv_prev;
+                static unsigned         iOpaque = 1;
+                struct timeval          tv = {0, 0};
+                const char             *p1;
+                char                   *p2, *p3;
+
+                /* simple */
+                memcpy(weak_marker_simple, "$w$", 4);
+                for (p1 = "\\/:", p2 = mod_name; *p1; p1++)
+                  if ((p3 = strrchr(p2, *p1)) != NULL)
+                    p2 = p3 + 1;
+                p1 = &weak_marker_simple[sizeof(weak_marker_simple) - 1];
+                for (p3 = &weak_marker_simple[3]; *p2 && p3 < p1; p2++)
+                  if (isalnum(*p2) || *p2 == '_' || *p2 == '@')
+                      *p3++ = *p2;
+                  else if (*p2 == '.')
+                      *p3++ = '_';
+                *p3 = '\0';
+                weak_marker_simple_size = p3 - &weak_marker_simple[0];
+
+                /* timestamped: $w$[1-7][1-4]#[-1-7]#[1-123] */
                 gettimeofday(&tv, NULL);
-                snprintf(pachName, cchName, "%s$w$%s%lx%lx",
-                         pszOrgName, weak_mod_name, tv.tv_sec, tv.tv_usec);
+                memcpy(&weak_marker_ts[0], "$w$", 4);
+                ltoa(tv.tv_sec, &weak_marker_ts[3], 36); 
+                cch2 = 3 + strlen(&weak_marker_ts[3]);
+                ltoa(tv.tv_usec, &weak_marker_ts[cch2], 36);
+                cch2 += strlen(&weak_marker_ts[cch2]);
+                weak_marker_ts[cch2++] = '#';
+                if (tv_prev.tv_usec == tv.tv_usec && tv_prev.tv_sec == tv.tv_sec)
+                {
+                    if (!iOpaque)   
+                    {
+                        unsigned short seed[3];
+                        seed[0] = (unsigned short)tv.tv_usec;
+                        seed[1] = (unsigned short)tv.tv_sec;
+                        seed[2] = (unsigned short)tv.tv_sec >> 16;
+                        iOpaque = nrand48(seed);
+                    }
+                    iOpaque++;
+                    ltoa(tv.tv_usec, &weak_marker_ts[cch2], 36);
+                    cch2 += strlen(&weak_marker_ts[cch2]);
+                    weak_marker_ts[cch2++] = '#';
+                }
+                tv_prev = tv;
+                memcpy(&weak_marker_ts[cch2], &weak_marker_simple[3], weak_marker_simple_size - 3 + 1);
+                weak_marker_ts_size = cch2 + weak_marker_simple_size - 3;
             }
+
+
+            /* generate the weak symbol name. */
+            if (!opt_weakts && cch + weak_marker_simple_size < 255) /* total is one byte short of full length. */
+                snprintf(pachName, cchName, "%s%s", pszOrgName, weak_marker_simple);
+            else if (cch + weak_marker_ts_size < 255)
+                snprintf(pachName, cchName, "%s%s", pszOrgName, weak_marker_ts);
+            else if (cch + 24 < 255)
+                snprintf(pachName, cchName, "%s%.16s", pszOrgName, weak_marker_ts);
+            else 
+            {   /* too long. */
+                int         cch3 = weak_marker_ts_size > 24 ? 24 : weak_marker_ts_size;
+                char        szHash[16];
+                const char *psz;
+                unsigned    uHash;   
+                for (psz = pszOrgName, uHash = 5381; *psz; psz++)   /* hash alg: original djb2. */
+                    uHash += (uHash << 5) + *psz;
+
+                cch2 = sprintf(szHash, "!_%X", 0x7fffffff & uHash);
+                memcpy(pachName, pszOrgName, cch > 255 ? 255 : cch);
+                memcpy(&pachName[255 - cch3 - cch2], szHash, cch2);
+                memcpy(&pachName[255 - cch3], weak_marker_ts, cch3);
+                pachName[255] = '\0';
+                warning ("Symbol length truncated to 255 characters (from %d) for `%s'", cch, pszOrgName);
+            }
+
             return pachName;
         }
@@ -2822,5 +2913,4 @@
   int i, len, ok;
   const char *p1, *p2;
-  char *p3;
 
   base_dir[0] = '\0';
@@ -2885,16 +2975,4 @@
       base_dir[1] = ':';
     }
-
-  /* Find the base name and length (excluding extension)
-     This is used for weak symbol handling. */
-  for (p1 = "\\/:", p2 = mod_name; *p1; p1++)
-    if ((p3 = strrchr(p2, *p1)) != NULL)
-      p2 = p3 + 1;
-  for (p3 = weak_mod_name; *p2; p2++)
-    if (isalnum(*p2) || *p2 == '$' || *p2 == '_' || *p2 == '@')
-        *p3++ = *p2;
-    else if (*p2 == '.')
-        *p3++ = '_';
-  *p3 = '\0';
 }
 
Index: /trunk/src/emx/src/emxomf/weakld.c
===================================================================
--- /trunk/src/emx/src/emxomf/weakld.c	(revision 1409)
+++ /trunk/src/emx/src/emxomf/weakld.c	(revision 1410)
@@ -54,5 +54,5 @@
 #define WLDINTERR(pWld, pMod)   wldIntErr(pWld, pMod, __FILE__, __LINE__, __FUNCTION__);
 
-/*#define WLD_ENABLED_DBG*/
+//#define WLD_ENABLED_DBG
 #ifdef WLD_ENABLED_DBG
 #define SYMDBG(pSym, pszMsg)    symDbg(pSym, pszMsg);
@@ -72,4 +72,20 @@
                                   )
 
+/** Compares a existing symbol with a new symbol. */
+#define SYM_EQUAL(pWld, pSym, _pszName, _fFlags, _uHash, _cchName) \
+    (   (pSym)->uHash == (_uHash)                                                   \
+     && ( !((_fFlags) & WLDSF_TRUNCATED) && !((pSym)->fFlags & WLDSF_TRUNCATED)     \
+         ? (pSym)->pszName == (_pszName)                                            \
+         : symCompareTrucated(pWld, pSym, _pszName, _cchName) )                     \
+      )
+      
+/** Compares a existing symbol with a potential symbol. */
+#define SYM_EQUAL2(pWld, pSym, _pszName, _fFlags, _uHash, _cchName, _pfn) \
+    (   (pSym)->uHash == (_uHash)                                                   \
+     && ( !((_fFlags) & WLDSF_TRUNCATED) && !((pSym)->fFlags & WLDSF_TRUNCATED)     \
+         ? !_pfn((pSym)->pszName, (_pszName), (_cchName)) && !(pSym)->pszName[(_cchName)] \
+         : symCompareTrucated(pWld, pSym, _pszName, _cchName) )                     \
+      )
+
 
 
@@ -81,4 +97,5 @@
 #include <stdarg.h>
 #include <string.h>
+#include <ctype.h>
 #include <sys/types.h>
 #include <sys/time.h>
@@ -170,4 +187,15 @@
 
 /**
+ * Truncated EXTDEF name.
+ */
+typedef struct wldsymtrunc
+{
+    /** Full name. */
+    const char *        pszName;
+    /** Pointer to the next symbol. */
+    struct wldsymtrunc *pNext;
+} WLDSYMTRUNC, *PWLDSYMTRUNC;
+
+/**
  * Symbol structure.
  */
@@ -178,4 +206,8 @@
     /** Weak name - for weak symbols only. */
     const char *        pszWeakName;
+    /** The full hash value. */
+    unsigned            uHash;
+    /** LIFO of truncated name variations. */
+    PWLDSYMTRUNC        pTrunc;
 
     /** Symbol flags. */
@@ -241,4 +273,9 @@
          */
         WLDSF_WEAKALIASDONE = 0x8000,
+        
+        /** Internal flag which indicates that the symbol have been
+         * truncated by emxomf. */
+        WLDSF_TRUNCATED = 0x10000,
+         
     }                   fFlags;
 
@@ -441,5 +478,6 @@
 } WLDSLEPARAM, *PWLDSLEPARAM;
 static int          symSearchLibEnum(PWLD pWld, PWLDSYM pSym, void *pvUser);
-static inline unsigned symHash(const char* pszSym, unsigned cch);
+static inline unsigned symHash(const char* pszSym, unsigned cch, unsigned fWldCaseFlag);
+static int          symCompareTrucated(PWLD pWld, PWLDSYM pSym1, const char *pszName2, unsigned cchName2);
 static const char * symGetDescr(PWLDSYM pSym);
 static void         symDumpReferers(PWLDSYM pSym);
@@ -1191,22 +1229,74 @@
  * Calculate the hash value of a symbol.
  * @returns hash value.
- * @param   pszSym  Symbol to calculate it for.
- * @param   cch     Symbol length.
+ * @param   pszSym          Symbol to calculate it for.
+ * @param   cch             Symbol length.
+ * @param   fWldCaseFlag    Case flag from the linker instance.
+ *                          Not implemented yet.
  * @todo    This ain't respecting case sensitivity.
  */
-static inline unsigned symHash(const char* pszSym, unsigned cch)
-{
-    unsigned uHash = 0;
+static inline unsigned symHash(const char* pszSym, unsigned cch, unsigned fWldCaseFlag)
+{
+    /* hash alg: original djb2. */
+    unsigned uHash = 5381;
     while (     cch
            &&   (pszSym[0] != '$' || pszSym[1] != 'w' || pszSym[2] != '$')
              )
     {
-        uHash = uHash * 63377 + *pszSym;
+        if (    pszSym[0] == '!'
+            &&  pszSym[1] == '_'
+            &&  cch > 200)
+        {
+            uHash = strtol(&pszSym[2], NULL, 16);
+            break;
+        }
+        uHash += (uHash << 5) + *pszSym;
         pszSym++;
         cch--;
     }
-    uHash %= WLDSYM_HASH_SIZE;
     return uHash;
 }
+
+
+/**
+ * Internal worker for SYM_EQUAL() 
+ *
+ * Compares truncated symbols. The hash for these symbols matches and at least
+ * one of them is truncated.
+ *
+ * @returns 1 if matches
+ * @returns 0 if not matching.
+ * @param   pWld        Linker Instance.
+ * @param   pSym1       Symbol 1.
+ * @param   pszName2    Symbol 2 name.
+ * @param   cchName2    Symbol 2 name length.
+ */
+static int symCompareTrucated(PWLD pWld, PWLDSYM pSym1, const char *pszName2, unsigned cchName2)
+{
+    /* Truncated string comparision means comparing MIN(cchName2, strlen(pSym1->pszName)) chars. */
+    const char *pszName1 = pSym1->pszName;
+    if (pWld->fFlags & WLDC_CASE_INSENSITIVE)
+    {
+        while (cchName2-- > 0 && *pszName1)
+        {
+            if (toupper(*pszName1) != toupper(*pszName2))
+                return 0;
+            pszName1++;
+            pszName2++;
+        }
+    }
+    else
+    {
+        while (cchName2-- > 0 && *pszName1)
+        {
+            if (*pszName1 != *pszName2)
+                return 0;
+            pszName1++;
+            pszName2++;
+        }
+    }
+    return 1;
+}
+
+
 
 /**
@@ -1222,9 +1312,8 @@
     const char *psz;
     unsigned    cchName;
-    unsigned    uHash;
+    unsigned    fFlags = 0;
+    unsigned    uHash = 0;
 
     /*
-     * Calculate the hash of the symbol
-     *
      * It's easier just to add it to the string table than starting to
      * check the correct case function and such. As there is a good
@@ -1233,12 +1322,33 @@
      * (if possible) and gain everywhere.
      */
-    psz = strstr(pszName, "$w$");
-    cchName = psz ? psz - pszName : strlen(pszName);
+
+    /* look for weak suffix and trucation */
+    cchName = strlen(pszName);
+    for (psz = pszName + cchName - 1; psz > pszName; psz--)
+        if (    psz[0] == '$'
+            &&  psz[1] == 'w'
+            &&  psz[2] == '$')
+        {
+            cchName = psz - pszName;
+            if (cchName > 200)
+                break;
+        }
+        else if (    psz[0] == '!'
+                 &&  psz[1] == '_'
+                 &&  psz - psz > 200)
+        {
+            uHash = strtol(&psz[2], NULL, 16);
+            fFlags |= WLDSF_TRUNCATED;
+            cchName = psz - pszName;
+            break;
+        }
+
     pszName = (pWld->fFlags & WLDC_CASE_INSENSITIVE ? strpool_addnu : strpool_addn)(pWld->pStrMisc, pszName, cchName);
-    uHash = symHash(pszName, cchName);
+    if (!fFlags)
+        uHash = symHash(pszName, cchName, pWld->fFlags & WLDC_CASE_INSENSITIVE);
 
     /* look it up */
-    for (pSym = pWld->Global.ap[uHash]; pSym; pSym = pSym->pHashNext)
-       if (pSym->pszName == pszName)
+    for (pSym = pWld->Global.ap[uHash % WLDSYM_HASH_SIZE]; pSym; pSym = pSym->pHashNext)
+       if (SYM_EQUAL(pWld, pSym, pszName, fFlags, uHash, cchName))
            return pSym;
 
@@ -1383,31 +1493,45 @@
 static int          symMatchUnDef(PWLD pWld, const unsigned char *pachPascalString, PWLDSYM pSym)
 {
-    int         cch = *pachPascalString;
-    const char *psz = pachPascalString + 1;
-    const char *pszWeak;
-    int (*pfn)(const char *, const char *, size_t) = (pWld->fFlags & WLDC_CASE_INSENSITIVE) ? strnicmp : strncmp;
-
-    /* look for weak suffix */
-    for (pszWeak = psz + cch - 1; pszWeak > psz; pszWeak--)
-        if (    pszWeak[0] == '$'
-            &&  pszWeak[1] == 'w'
-            &&  pszWeak[2] == '$')
-        {
-            cch = pszWeak - psz;
+    int         cchName = *pachPascalString;
+    const char *pszName = pachPascalString + 1;
+    const char *psz;
+    unsigned    fFlags = 0;
+    unsigned    uHash = 0;
+    int        (*pfn)(const char *, const char *, size_t) = pWld->fFlags & WLDC_CASE_INSENSITIVE ? strnicmp : strncmp;
+
+    /* look for weak suffix and trucation */
+    for (psz = pszName + cchName - 1; psz > pszName; psz--)
+        if (    psz[0] == '$'
+            &&  psz[1] == 'w'
+            &&  psz[2] == '$')
+        {
+            cchName = psz - pszName;
+            if (cchName > 200)
+                break;
+        }
+        else if (    psz[0] == '!'
+                 &&  psz[1] == '_'
+                 &&  psz - pszName > 200)
+        {
+            uHash = strtol(&psz[2], NULL, 16);
+            fFlags |= WLDSF_TRUNCATED;
+            cchName = psz - pszName;
             break;
         }
+
+    /* @todo: this isn't 100% correct when we're talking case in sensitivity. */
+    if (!fFlags)
+        uHash = symHash(pszName, cchName, pWld->fFlags & WLDC_CASE_INSENSITIVE);
 
     /* compare */
     if (pSym)
-        return !pfn(pSym->pszName, psz, cch) && !pSym->pszName[cch];
+        return SYM_EQUAL2(pWld, pSym, pszName, fFlags, uHash, cchName, pfn);
     else
     {
-        /* @todo: this isn't 100% correct when we're talking case in sensitivity. */
-        unsigned uHash = symHash(psz, cch);
-        for (pSym = pWld->Global.ap[uHash]; pSym; pSym = pSym->pHashNext)
+        for (pSym = pWld->Global.ap[uHash % WLDSYM_HASH_SIZE]; pSym; pSym = pSym->pHashNext)
         {
             if ((pSym->fFlags & (WLDSF_TYPEMASK | WLDSF_WEAK)) == WLDSF_UNDEF)
             {
-                if (!pfn(pSym->pszName, psz, cch) && !pSym->pszName[cch])
+                if (SYM_EQUAL2(pWld, pSym, pszName, fFlags, uHash, cchName, pfn))
                     return 1;
             }
@@ -1550,4 +1674,5 @@
     const char *pszName;                /* The symbol name in the string pool */
     int         cchNameWeak = 0;        /* Indicator and length of the weak name. (0 if not weak) */
+    int         cchNameTrunc = 0;       /* Full length of truncated symbol name.  */
     /* general stuff */
     const char *    pach;
@@ -1558,7 +1683,8 @@
         cchName = strlen(pachName);
 
-    /* adjust namelength / check for weak name / hash name */
+    /* adjust namelength / check for weak name and trucation / hash name */
     pach = pachName + cchName - 2;      /* "$w$" */
     while (pach-- > pachName)
+    {
         if (    pach[0] == '$'
             &&  pach[1] == 'w'
@@ -1571,23 +1697,38 @@
             if ((fFlags & WLDSF_TYPEMASK) == WLDSF_WKEXT)
                 fFlags = (fFlags & ~WLDSF_TYPEMASK) | WLDSF_UNDEF;
+            
+            if (cchName <= 200)
+                break;
+        }
+        else if (    pach[0] == '!'
+                 &&  pach[1] == '_'
+                 &&  pach - pachName > 200)
+        {
+            uHash = strtol(&pach[2], NULL, 16);
+            fFlags |= WLDSF_TRUNCATED;
+            cchNameTrunc = cchNameWeak ? cchNameWeak : cchName;
+            cchName = pach - pachName;
             break;
         }
+    }
     pszName = (pWld->fFlags & WLDC_CASE_INSENSITIVE ? strpool_addnu : strpool_addn)(pWld->pStrMisc, pachName, cchName);
-    uHash = symHash(pszName, cchName);
+    if (!(fFlags & WLDSF_TRUNCATED))
+        uHash = symHash(pszName, cchName, pWld->fFlags & WLDC_CASE_INSENSITIVE);
 
     /* search for existing symbol  */
-    pSym = pWld->Global.ap[uHash];
-    while (pSym && pSym->pszName != pszName)
-        pSym = pSym->pHashNext;
+    for (pSym = pWld->Global.ap[uHash % WLDSYM_HASH_SIZE]; pSym; pSym = pSym->pHashNext)
+        if (SYM_EQUAL(pWld, pSym, pszName, fFlags, uHash, cchName))
+            break;
 
     if (!pSym)
     {
         /*
-         * new symol - this is easy!
+         * new symbol - this is easy!
          */
         pSym = xmalloc(sizeof(*pSym));
         memset(pSym, 0, sizeof(*pSym));
-        pSym->fFlags = fFlags;
+        pSym->fFlags  = fFlags;
         pSym->pszName = pszName;
+        pSym->uHash   = uHash;
         if (cchNameWeak)
         {
@@ -1596,6 +1737,6 @@
             WLDINFO(pWld, ("Weak symbol '%s'.", pSym->pszWeakName));
         }
-        pSym->pHashNext = pWld->Global.ap[uHash];
-        pWld->Global.ap[uHash] = pSym;
+        pSym->pHashNext = pWld->Global.ap[uHash % WLDSYM_HASH_SIZE];
+        pWld->Global.ap[uHash % WLDSYM_HASH_SIZE] = pSym;
         if (peAction) *peAction = WLDSA_NEW;
         WLDDBG2(("symAdd: New symbol '%s'", pSym->pszName));
@@ -1728,5 +1869,5 @@
 
     /*
-     * Maintain the module pointer and referers.
+     * Maintain the module pointer, referers and truncation aliases.
      */
     if (pSym)
@@ -1745,4 +1886,26 @@
                     pSym->paReferers = xrealloc(pSym->paReferers, sizeof(pSym->paReferers[0]) * (pSym->cReferers + 64));
                 pSym->paReferers[pSym->cReferers++] = pMod;
+            }
+        }
+        
+        /*
+         * Maintain list of truncated aliases.
+         */
+        if (    !SYM_IS_DEFINED(fFlags) 
+            && ((fFlags & WLDSF_TRUNCATED) || (pSym->fFlags & WLDSF_TRUNCATED)))
+        {
+            PWLDSYMTRUNC    pTrunc = pSym->pTrunc;
+            const char     *pszSubName = pSym->pszWeakName;
+            if (!pszSubName)
+                pszSubName = strpool_addn(pWld->pStrMisc, pachName, cchNameTrunc);
+
+            while (pTrunc && pTrunc->pszName != pszSubName)
+                pTrunc = pTrunc->pNext;
+            if (!pTrunc)
+            {
+                pTrunc = xmalloc(sizeof(*pTrunc));
+                pTrunc->pszName = pszSubName;
+                pTrunc->pNext = pSym->pTrunc;
+                pSym->pTrunc = pTrunc;
             }
         }
@@ -3257,68 +3420,98 @@
 static int      wldGenerateObjEnum(PWLD pWld, PWLDSYM pSym, void *pvUser)
 {
+    const char     *pszSubName = pSym->pszWeakName;
+    PWLDGOEPARAM    pParam = (PWLDGOEPARAM)pvUser;
+    int             cch;
+    WLDSYMTRUNC     Trunc;
+    PWLDSYMTRUNC    pTrunc;
+
+    /*
+     * If weak, we'll make fake trunc record.
+     */
     if (pSym->pszWeakName)
     {
-        PWLDGOEPARAM    pParam = (PWLDGOEPARAM)pvUser;
-        #pragma pack(1)
-        struct omfstuff
-        {
-            OMFREC  hdr;
-            union
+        Trunc.pNext   = pSym->pTrunc;
+        Trunc.pszName = pSym->pszName;
+        pTrunc = &Trunc;
+    }
+    else
+    {
+        pTrunc = pSym->pTrunc;
+        pszSubName = pSym->pszName;
+    }
+    cch = strlen(pszSubName);
+
+    /*
+     * Walk trunc record list.
+     */
+    while (pTrunc)
+    {
+        if (pTrunc->pszName != pszSubName)
+        {
+            #pragma pack(1)
+            struct omfstuff
             {
-                char        ach[640];
-                OMFLIBHDRX  libhdr;
-            };
-        } omf;
-        #pragma pack()
-        int             cch = strlen(pSym->pszWeakName);
-        int             cchAlias = strlen(pSym->pszName);
-
-        WLDINFO(pWld, ("using weak %s for %s", pSym->pszWeakName, pSym->pszName));
-
-        /* paranoia */
-        if (cchAlias > 255)
-        {
-            wldErr(pWld, "Symbol '%s' are too long (%d).", pSym->pszName, cchAlias);
-            return -1;
-        }
-        if (cch > 255)
-        {
-            wldErr(pWld, "Symbol '%s' are too long (%d).", pSym->pszWeakName, cch);
-            return -1;
-        }
-
-        /* end the current object? */
-        if ((pWld->fFlags & WLDC_LINKER_LINK386) && pParam->cAliases >= 32)
-        {
-            int rc = wldObjEnd(pWld, pParam->phFile, 32);
-            if (rc)
-                return rc;
-            pParam->cAliases = 0;
-        }
-
-        /* make new object ? */
-        if (!pParam->cAliases)
-        {
-            sprintf(omf.ach, "wk%d.obj", pParam->iLibFile++);
-            int rc = wldObjStart(pWld, pParam->phFile, omf.ach);
-            if (rc)
-                return rc;
-        }
-
-        /* Alias record */
-        omf.hdr.chType = ALIAS;
-        omf.hdr.cb = cchAlias + cch + 3;
-        omf.ach[0] = cchAlias;
-        memcpy(&omf.ach[1], pSym->pszName, cchAlias);           /* alias */
-        omf.ach[cchAlias + 1] = cch;
-        memcpy(&omf.ach[cchAlias + 2], pSym->pszWeakName, cch); /* subtitute */
-        omf.ach[cchAlias + cch + 2] = 0; /* crc */
-        if (fwrite(&omf, omf.hdr.cb + sizeof(OMFREC), 1, pParam->phFile) != 1)
-        {
-            wldErr(pWld, "Error occured while writing weak aliases. (2)");
-            return -1;
-        }
-        pParam->cAliases++;
-    }
+                OMFREC  hdr;
+                union
+                {
+                    char        ach[640];
+                    OMFLIBHDRX  libhdr;
+                };
+            } omf;
+            #pragma pack()
+            int             cchAlias = strlen(pTrunc->pszName);
+
+            WLDINFO(pWld, ("using weak/trunc %s for %s", pszSubName, pTrunc->pszName));
+
+            /* paranoia */
+            if (cchAlias > 255)
+            {
+                wldErr(pWld, "Symbol '%s' are too long (%d).", pTrunc->pszName, cchAlias);
+                return -1;
+            }
+            if (cch > 255)
+            {
+                wldErr(pWld, "Symbol '%s' are too long (%d).", pszSubName, cch);
+                return -1;
+            }
+
+            /* end the current object? */
+            if ((pWld->fFlags & WLDC_LINKER_LINK386) && pParam->cAliases >= 32)
+            {
+                int rc = wldObjEnd(pWld, pParam->phFile, 32);
+                if (rc)
+                    return rc;
+                pParam->cAliases = 0;
+            }
+
+            /* make new object ? */
+            if (!pParam->cAliases)
+            {
+                sprintf(omf.ach, "wk%d.obj", pParam->iLibFile++);
+                int rc = wldObjStart(pWld, pParam->phFile, omf.ach);
+                if (rc)
+                    return rc;
+            }
+
+            /* Alias record */
+            omf.hdr.chType = ALIAS;
+            omf.hdr.cb = cchAlias + cch + 3;
+            omf.ach[0] = cchAlias;
+            memcpy(&omf.ach[1], pTrunc->pszName, cchAlias);           /* alias */
+            omf.ach[cchAlias + 1] = cch;
+            memcpy(&omf.ach[cchAlias + 2], pszSubName, cch); /* subtitute */
+            omf.ach[cchAlias + cch + 2] = 0; /* crc */
+            if (fwrite(&omf, omf.hdr.cb + sizeof(OMFREC), 1, pParam->phFile) != 1)
+            {
+                wldErr(pWld, "Error occured while writing weak/trunc aliases. (2)");
+                return -1;
+            }
+            pParam->cAliases++;
+        }
+
+        /* next */
+        pTrunc = pTrunc->pNext;
+    }
+
     return 0;
 }
@@ -3651,5 +3844,5 @@
                          * See defect #483 for details. Short summary: an array calculation in ilink is
                          * assuming that library objects have less EXTDEFs than the object ones. So, for
-                         * pass2 an EXTDEF array may become too short.
+                         * pass2 an EXTDEF array may become too small.
                          */
                         WLDINFO(pWld, ("cWeakAliases=%d cMaxObjExts=%d cMaxLibExts=%d",
