- Timestamp:
- Nov 13, 2005, 3:27:34 AM (20 years ago)
- Location:
- trunk/src/emx
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/emx/ChangeLog.LIBC
r2430 r2431 4 4 5 5 2005-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. 6 9 - libc: 7 10 o Fixed bug in the sigsuspend (includes pause ++) handling, -
trunk/src/emx/src/emxomf/emxomf.c
r2430 r2431 35 35 #include <sys/time.h> 36 36 #include <ar.h> 37 #include <assert.h> 37 38 38 39 /* Insert private header files. */ … … 51 52 #define SF_FAR16 0x01 /* 16:16 pointer */ 52 53 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) 53 65 /* This structure holds additional data for symbols. */ 54 66 … … 240 252 /* Remove underscores from all symbol names */ 241 253 static int opt_rmunder = FALSE; 242 243 /* Add timestamp to symbol to make it more unique. */244 static int opt_weakts = TRUE;245 254 246 255 /* This is the page size for OMF libraries. It is set by the -p … … 318 327 static char base_dir[256]; 319 328 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. */ 330 static char weak_marker[SYMBOL_WEAK_LENGTH + 1]; 327 331 328 332 /* This growing array holds the file name table for generating line … … 623 627 /* Init weak markers */ 624 628 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'; 629 630 } 630 631 … … 763 764 764 765 766 /* Calculates the hash for a string using the original djb2 aglorithm. */ 767 768 static 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 781 static 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 765 801 /* Put the string pszName into the current OMF record. 766 802 In the OMF record, the string is preceded by a length byte. The … … 772 808 static void put_nstr(const char *pszName, size_t cch) 773 809 { 774 if (cch > 255) 810 if ( cch > SYMBOL_MAX_LENGTH 811 && !strstr(pszName + SYMBOL_MAX_LENGTH - SYMBOL_WEAK_LENGTH, "$w$")) 775 812 { 776 813 /* Hash the symbol to help making it unique. … … 778 815 * the weakld is parsing it! 779 816 */ 780 char szHash[16];781 int cch2;782 c onst 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)) 789 826 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); 796 834 } 797 835 else … … 808 846 See put_nstr() for full details on string handling. */ 809 847 810 static void put_str(const char *pszName) 811 { 812 int cch = strlen(pszName); 813 put_nstr(pszName, cch); 848 static inline void put_str(const char *pszName) 849 { 850 put_nstr(pszName, strlen(pszName)); 814 851 } 815 852 … … 963 1000 static void add_extdef (int *pstarted, const char *name, int type) 964 1001 { 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 } 969 1013 } 970 1014 if (!*pstarted) 971 1015 { 972 init_rec 1016 init_rec(EXTDEF); 973 1017 *pstarted = TRUE; 974 1018 } 975 put_sym 976 put_idx (type);/* type index */1019 put_sym(name); 1020 put_idx(type); /* type index */ 977 1021 } 978 1022 … … 1096 1140 case N_WEAKB: /* 0x11 Weak bss symbol. */ 1097 1141 { 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]) 1103 1146 { 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 */ 1125 1155 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); 1150 1165 } 1151 1166 1152 1167 1153 1168 /* 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); 1160 1172 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); 1175 1181 } 1176 1182 … … 3707 3713 puts (" -I <idmdll> Name the identifier manipulation DLL"); 3708 3714 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");3711 3715 puts (" -z Remove underscores from all symbol names"); 3712 3716 puts (" -P <dbgpackdll> Name the dbgpack DLL (ilink)"); … … 4152 4156 *libreq_add = lrp; 4153 4157 libreq_add = &lrp->next; 4154 break;4155 case 'j':4156 opt_weakts = FALSE;4157 4158 break; 4158 4159 case 'I': … … 4220 4221 opt_rmunder = TRUE; 4221 4222 break; 4222 case 't':4223 opt_weakts = TRUE;4224 break;4225 4223 default: 4226 4224 usage ();
Note:
See TracChangeset
for help on using the changeset viewer.