Changeset 2431 for trunk


Ignore:
Timestamp:
Nov 13, 2005, 3:27:34 AM (20 years ago)
Author:
bird
Message:

Fixed problems with symbol truncation.
Kudos to Yuri for tracking down the places which required attention.

Location:
trunk/src/emx
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/emx/ChangeLog.LIBC

    r2430 r2431  
    44
    552005-11-12: knut st. osmundsen <bird-gccos2-spam@anduin.net>
     6    - emxomf:
     7        o Fixed problems with symbol truncation.
     8          Kudos to Yuri for tracking down the places which required attention.
    69    - libc:
    710        o Fixed bug in the sigsuspend (includes pause ++) handling,
  • trunk/src/emx/src/emxomf/emxomf.c

    r2430 r2431  
    3535#include <sys/time.h>
    3636#include <ar.h>
     37#include <assert.h>
    3738
    3839/* Insert private header files. */
     
    5152#define SF_FAR16        0x01    /* 16:16 pointer */
    5253
     54/* Length of the weak marker. */
     55
     56#define SYMBOL_WEAK_LENGTH  (3 + 11 + 6)
     57
     58/* Length of the OMF symbol hash */
     59
     60#define SYMBOL_HASH_LENGTH  (2 + 6)
     61
     62/* Max OMF symbol length */
     63
     64#define SYMBOL_MAX_LENGTH   (255 - SYMBOL_HASH_LENGTH - SYMBOL_WEAK_LENGTH)
    5365/* This structure holds additional data for symbols. */
    5466
     
    240252/* Remove underscores from all symbol names */
    241253static int opt_rmunder = FALSE;
    242 
    243 /* Add timestamp to symbol to make it more unique. */
    244 static int opt_weakts = TRUE;
    245254
    246255/* This is the page size for OMF libraries.  It is set by the -p
     
    318327static char base_dir[256];
    319328
    320 /* This variable holds the simple weak marker for the current module. See get_mod_name(). */
    321 static char weak_marker_simple[128];
    322 static int  weak_marker_simple_size;
    323 
    324 /* This variable holds the timestamped weak marker for the current module. See get_mod_name(). */
    325 static char weak_marker_ts[148];
    326 static int  weak_marker_ts_size;
     329/* This variable holds the timestamped weak marker for the current module. */
     330static char weak_marker[SYMBOL_WEAK_LENGTH + 1];
    327331
    328332/* This growing array holds the file name table for generating line
     
    623627  /* Init weak markers */
    624628
    625   weak_marker_simple[0] = '\0';
    626   weak_marker_simple_size = 0;
    627   weak_marker_ts[0] = '\0';
    628   weak_marker_ts_size = 0;
     629  weak_marker[0] = '\0';
    629630}
    630631
     
    763764
    764765
     766/* Calculates the hash for a string using the original djb2 aglorithm. */
     767 
     768static unsigned hash_string(const char *pch, size_t cch)
     769{
     770    unsigned uHash;
     771    for (uHash = 5381; cch > 0; pch++, cch--)
     772        uHash += (uHash << 5) + *pch;
     773    return uHash;
     774}
     775
     776/* Formats a 64-bit number with a fixed with. The purpose is to encode
     777   a unique number as tiny as possible while keeping within what any
     778   linker should accept. The width is fixed, and the string is clipped
     779   or padded with zeros to satisfy that. The return value is psz + cchWidth. */
     780
     781static char *format_u64(uint64_t u64, char *psz, unsigned uRadix, int cchWidth)
     782{
     783    static const char       s_achDigits[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
     784    static const unsigned   s_cchDigits = sizeof(s_achDigits) / sizeof(s_achDigits[0]) - 1;
     785    assert(uRadix <= s_cchDigits);
     786    while (cchWidth-- > 0)
     787    {
     788        unsigned i = u64 % uRadix;
     789        *psz++ = s_achDigits[i];
     790        u64 /= uRadix;
     791    }
     792    assert(!u64);
     793    *psz = '\0';
     794    return psz;
     795}
     796
     797
     798
     799
     800
    765801/* Put the string pszName into the current OMF record.
    766802   In the OMF record, the string is preceded by a length byte.  The
     
    772808static void put_nstr(const char *pszName, size_t cch)
    773809{
    774     if (cch > 255)
     810    if (    cch > SYMBOL_MAX_LENGTH
     811        &&  !strstr(pszName + SYMBOL_MAX_LENGTH - SYMBOL_WEAK_LENGTH, "$w$"))
    775812    {
    776813        /* Hash the symbol to help making it unique.
     
    778815         *      the weakld is parsing it!
    779816         */
    780         char        szHash[16];
    781         int         cch2;
    782         const char *psz;
    783         unsigned    uHash;
    784         for (psz = pszName, uHash = 5381, cch2 = cch; cch > 0; psz++, cch--) /* hash alg: original djb2. */
    785             uHash += (uHash << 5) + *psz;
    786         cch2 = sprintf(szHash, "!_%X", 0x7fffffff & uHash);
    787 
    788         if (!fits(1+255))
     817        unsigned    uHash = hash_string(pszName, cch);
     818        char        szHash[SYMBOL_HASH_LENGTH + 1];
     819        char      *psz;
     820        szHash[0] = '!';
     821        szHash[1] = '_';
     822        psz = format_u64((uint32_t)uHash, &szHash[2], 62, 6);
     823        assert(psz - &szHash[0] == SYMBOL_HASH_LENGTH);
     824
     825        if (!fits(1 + SYMBOL_MAX_LENGTH + SYMBOL_HASH_LENGTH))
    789826            doesn_fit();
    790         out_data[out_idx++] = 255;
    791         memcpy(out_data + out_idx, pszName, 255);
    792         memcpy(out_data + out_idx + 255 - cch2, szHash, cch2);
    793         out_idx += 255;
    794 
    795         warning ("Symbol length truncated to 255 characters (from %d) for `%s'", cch, pszName);
     827        out_data[out_idx++] = SYMBOL_MAX_LENGTH + SYMBOL_HASH_LENGTH;
     828        memcpy(out_data + out_idx, pszName, SYMBOL_MAX_LENGTH);
     829        out_idx += SYMBOL_MAX_LENGTH;
     830        memcpy(out_data + out_idx, szHash, SYMBOL_HASH_LENGTH);
     831        out_idx += SYMBOL_HASH_LENGTH;
     832
     833        warning ("Truncated symbol '%.*s' to '%.*s%s'", cch, pszName, SYMBOL_MAX_LENGTH, pszName, szHash);
    796834    }
    797835    else
     
    808846   See put_nstr() for full details on string handling. */
    809847
    810 static void put_str(const char *pszName)
    811 {
    812     int cch = strlen(pszName);
    813     put_nstr(pszName, cch);
     848static inline void put_str(const char *pszName)
     849{
     850    put_nstr(pszName, strlen(pszName));
    814851}
    815852
     
    9631000static void add_extdef (int *pstarted, const char *name, int type)
    9641001{
    965   if (*pstarted && !fits (strlen (name) + 3 + (type > 127)))
    966     {
    967       write_rec ();
    968       *pstarted = FALSE;
     1002  if (*pstarted)
     1003    {
     1004      size_t cchEncodedName = strlen(name);
     1005      if (   cchEncodedName > SYMBOL_MAX_LENGTH
     1006          && !strstr(name + SYMBOL_MAX_LENGTH - SYMBOL_WEAK_LENGTH, "$w$"))
     1007        cchEncodedName = SYMBOL_MAX_LENGTH + SYMBOL_HASH_LENGTH;
     1008      if (!fits(cchEncodedName + 3 + (type > 127)))
     1009        {
     1010           write_rec();
     1011           *pstarted = FALSE;
     1012        }
    9691013    }
    9701014  if (!*pstarted)
    9711015    {
    972       init_rec (EXTDEF);
     1016      init_rec(EXTDEF);
    9731017      *pstarted = TRUE;
    9741018    }
    975   put_sym (name);
    976   put_idx (type);                       /* type index */
     1019  put_sym(name);
     1020  put_idx(type);                        /* type index */
    9771021}
    9781022
     
    10961140        case N_WEAKB:               /* 0x11  Weak bss symbol. */
    10971141        {
    1098             int cch = strlen(pszOrgName);
    1099             int cch2;
    1100 
    1101             /* Init the markers if not done already. */
    1102             if (!weak_marker_simple[0])
     1142            int cch;
     1143
     1144            /* Init the weak marker if it hasn't already been done for this module. */
     1145            if (!weak_marker[0])
    11031146            {
    1104                 static struct timeval   tv_prev;
    1105                 static unsigned         iOpaque = 1;
    1106                 struct timeval          tv = {0, 0};
    1107                 const char             *p1;
    1108                 char                   *p2, *p3;
    1109 
    1110                 /* simple */
    1111                 memcpy(weak_marker_simple, "$w$", 4);
    1112                 for (p1 = "\\/:", p2 = mod_name; *p1; p1++)
    1113                   if ((p3 = strrchr(p2, *p1)) != NULL)
    1114                     p2 = p3 + 1;
    1115                 p1 = &weak_marker_simple[sizeof(weak_marker_simple) - 1];
    1116                 for (p3 = &weak_marker_simple[3]; *p2 && p3 < p1; p2++)
    1117                   if (isalnum(*p2) || *p2 == '_' || *p2 == '@')
    1118                       *p3++ = *p2;
    1119                   else if (*p2 == '.')
    1120                       *p3++ = '_';
    1121                 *p3 = '\0';
    1122                 weak_marker_simple_size = p3 - &weak_marker_simple[0];
    1123 
    1124                 /* timestamped: $w$[1-7][1-4]#[-1-7]#[1-123] */
     1147                struct timeval  tv = {0, 0};
     1148                uint64_t        u64;
     1149                char           *psz;
     1150
     1151                /* prefix */
     1152                psz = (char *)memcpy(&weak_marker[0], "$w$", sizeof("$w$")) + sizeof("$w$") - 1;
     1153
     1154                /* use time-of-day + 4 random bits for the 11 char value */
    11251155                gettimeofday(&tv, NULL);
    1126                 memcpy(&weak_marker_ts[0], "$w$", 4);
    1127                 ltoa(tv.tv_sec, &weak_marker_ts[3], 36);
    1128                 cch2 = 3 + strlen(&weak_marker_ts[3]);
    1129                 ltoa(tv.tv_usec, &weak_marker_ts[cch2], 36);
    1130                 cch2 += strlen(&weak_marker_ts[cch2]);
    1131                 weak_marker_ts[cch2++] = '#';
    1132                 if (tv_prev.tv_usec == tv.tv_usec && tv_prev.tv_sec == tv.tv_sec)
    1133                 {
    1134                     if (!iOpaque)
    1135                     {
    1136                         unsigned short seed[3];
    1137                         seed[0] = (unsigned short)tv.tv_usec;
    1138                         seed[1] = (unsigned short)tv.tv_sec;
    1139                         seed[2] = (unsigned short)tv.tv_sec >> 16;
    1140                         iOpaque = nrand48(seed);
    1141                     }
    1142                     iOpaque++;
    1143                     ltoa(tv.tv_usec, &weak_marker_ts[cch2], 36);
    1144                     cch2 += strlen(&weak_marker_ts[cch2]);
    1145                     weak_marker_ts[cch2++] = '#';
    1146                 }
    1147                 tv_prev = tv;
    1148                 memcpy(&weak_marker_ts[cch2], &weak_marker_simple[3], weak_marker_simple_size - 3 + 1);
    1149                 weak_marker_ts_size = cch2 + weak_marker_simple_size - 3;
     1156                u64 = (uint64_t)tv.tv_sec * 1000000 + tv.tv_usec;
     1157                u64 <<= 12;
     1158                u64 |= rand() & 0xfff;
     1159                psz = format_u64(u64, psz, 62, 11);
     1160
     1161                /* simply hash the current filename for the next 6 chars value. */
     1162                u64 = hash_string(mod_name, strlen(mod_name));
     1163                psz = format_u64((uint32_t)u64, psz, 62, 6);
     1164                assert((psz - &weak_marker[0]) == SYMBOL_WEAK_LENGTH);
    11501165            }
    11511166
    11521167
    11531168            /* generate the weak symbol name. */
    1154             if (!opt_weakts && cch + weak_marker_simple_size < 255) /* total is one byte short of full length. */
    1155                 snprintf(pachName, cchName, "%s%s", pszOrgName, weak_marker_simple);
    1156             else if (cch + weak_marker_ts_size < 255)
    1157                 snprintf(pachName, cchName, "%s%s", pszOrgName, weak_marker_ts);
    1158             else if (cch + 24 < 255)
    1159                 snprintf(pachName, cchName, "%s%.16s", pszOrgName, weak_marker_ts);
     1169            cch = strlen(pszOrgName);
     1170            if (cch <= SYMBOL_MAX_LENGTH)           /* Must cut exactly where add_nstr cuts. */
     1171                snprintf(pachName, cchName, "%s%s", pszOrgName, weak_marker);
    11601172            else
    1161             {   /* too long. */
    1162                 int         cch3 = weak_marker_ts_size > 24 ? 24 : weak_marker_ts_size;
    1163                 char        szHash[16];
    1164                 const char *psz;
    1165                 unsigned    uHash;
    1166                 for (psz = pszOrgName, uHash = 5381; *psz; psz++)   /* hash alg: original djb2. */
    1167                     uHash += (uHash << 5) + *psz;
    1168 
    1169                 cch2 = sprintf(szHash, "!_%X", 0x7fffffff & uHash);
    1170                 memcpy(pachName, pszOrgName, cch > 255 ? 255 : cch);
    1171                 memcpy(&pachName[255 - cch3 - cch2], szHash, cch2);
    1172                 memcpy(&pachName[255 - cch3], weak_marker_ts, cch3);
    1173                 pachName[255] = '\0';
    1174                 warning ("Symbol length truncated to 255 characters (from %d) for `%s'", cch, pszOrgName);
     1173            {   /* too long. truncate to: name+!_[hash]$w$[weakmarker] */
     1174                uint32_t u32Hash = hash_string(pszOrgName, cch);
     1175                memcpy(pachName, pszOrgName, SYMBOL_MAX_LENGTH);
     1176                pachName[SYMBOL_MAX_LENGTH + 0] = '!';
     1177                pachName[SYMBOL_MAX_LENGTH + 1] = '_';
     1178                format_u64(u32Hash, &pachName[SYMBOL_MAX_LENGTH + 2], 62, 6);
     1179                memcpy(&pachName[SYMBOL_MAX_LENGTH + SYMBOL_HASH_LENGTH], weak_marker, SYMBOL_WEAK_LENGTH + 1);
     1180                warning("Truncated symbol '%s' to '%s' (weak)", pszOrgName, pachName);
    11751181            }
    11761182
     
    37073713  puts ("  -I <idmdll>        Name the identifier manipulation DLL");
    37083714  puts ("  -O <directory>     Extract files to <directory>");
    3709   puts ("  -t                 Add timestamping to the weak symbol mangling (def)");
    3710   puts ("  -j                 Do not add timestamping to the weak symbol mangling");
    37113715  puts ("  -z                 Remove underscores from all symbol names");
    37123716  puts ("  -P <dbgpackdll>    Name the dbgpack DLL (ilink)");
     
    41524156        *libreq_add = lrp;
    41534157        libreq_add = &lrp->next;
    4154         break;
    4155       case 'j':
    4156         opt_weakts = FALSE;
    41574158        break;
    41584159      case 'I':
     
    42204221        opt_rmunder = TRUE;
    42214222        break;
    4222       case 't':
    4223         opt_weakts = TRUE;
    4224         break;
    42254223      default:
    42264224        usage ();
Note: See TracChangeset for help on using the changeset viewer.