Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

SRC/misc.c

Go to the documentation of this file.
00001 00014 #include <stdio.h> 00015 #include <stdlib.h> 00016 #include <signal.h> 00017 #include <math.h> 00018 00019 #ifdef __HIGHC__ 00020 #include <init.h> /* _mwlsl(), _msgetcs() */ 00021 #endif 00022 00023 #if defined(WIN32) || defined(_WIN32) 00024 #include <io.h> 00025 #include <fcntl.h> 00026 #include <share.h> 00027 #include <sys/stat.h> 00028 #endif 00029 00030 #include "wattcp.h" 00031 #include "wdpmi.h" 00032 #include "x32vm.h" 00033 #include "powerpak.h" 00034 #include "strings.h" 00035 #include "sock_ini.h" 00036 #include "cpumodel.h" 00037 #include "pcsed.h" 00038 #include "pcpkt.h" 00039 #include "pcconfig.h" 00040 #include "pcdbug.h" 00041 #include "bsddbug.h" 00042 #include "ioport.h" 00043 #include "btrace.h" 00044 #include "timer.h" 00045 #include "misc.h" 00046 00047 /* These arrays are used in several places (save some space) 00048 */ 00049 const char hex_chars_lower[] = "0123456789abcdef"; 00050 const char hex_chars_upper[] = "0123456789ABCDEF"; 00051 00052 BOOL win32_dos_box = FALSE; 00053 BOOL _watt_fatal_error = FALSE; 00054 WORD _watt_os_ver = 0x622; 00055 char _watt_assert_buf[256]; 00057 static int num_exit_func_inserts = 0; 00058 00059 /* 00060 * Set through macro SOCK_ERRNO() in <sys/werrno.h>. 00061 */ 00062 int _w32_errno = 0; 00063 00064 #if !defined(__DJGPP__) 00065 int __bss_count = 0; 00066 #endif 00067 00068 #if (DOSX & (PHARLAP|X32VM)) && defined(HAVE_FARPTR48) 00069 FARPTR _watt_dosFp; /* we have 48-bit far-pointers */ 00070 #endif 00071 00072 #if defined(__LCC__) 00073 static _CPUID lcc_cpuid; 00074 char cdecl x86_type = 5; /* !! */ 00075 char cdecl x86_vendor_id[13]; 00076 DWORD cdecl x86_capability; 00077 #endif 00078 00079 #if (DOSX) 00080 static void setup_dos_xfer_buf (void); 00081 static void is_in_stack_init (void); 00082 #endif 00083 00084 #define STATIC /* ease disassembly */ 00085 00086 #if defined(__BORLANDC__) 00087 #pragma inline 00088 #if defined(USE_DEBUG) && (defined(__SMALL__) || defined(__LARGE__)) 00089 STATIC int setup_stk_check (void); 00090 #endif 00091 00092 #elif defined(WATCOM386) && !defined(WIN32) 00093 extern char cdecl __begtext; /* label at TEXT start */ 00094 extern UINT cdecl _x386_stacklow; 00095 00096 #if defined(__SW_3S) /* wcc386 -3s */ 00097 void cdecl _fatal_runtime_error (UINT stk); 00098 #define FATAL_HANDLER _fatal_runtime_error 00099 #else 00100 void cdecl _fatal_runtime_error_ (UINT stk); 00101 #define FATAL_HANDLER _fatal_runtime_error_ 00102 #endif 00103 00104 00105 /* Prevent linker (with 'option eliminate') to strip our 00106 * '_fatal_runtime_error()' function from .exe-image. 00107 */ 00108 char *dummy_fatal_rte = (char*)&FATAL_HANDLER; 00109 00110 #elif defined(_MSC_VER) && defined(__LARGE__) && defined(USE_DEBUG) 00111 extern void (__cdecl *_aaltstkovr) (void); 00112 static void stk_overflow (void _far *where); 00113 #endif 00114 00115 #if (DOSX & (PHARLAP|X32VM)) || (DOSX == 0) 00116 #define CS_WRITEABLE 00117 #endif 00118 00119 #define MAKE_CS_WRITEABLE() ((void)0) 00120 #define UNDO_CS_ACCESS() ((void)0) 00123 #if defined(USE_DEBUG) && defined(__BORLANDC__) && (defined(__SMALL__) || defined(__LARGE__)) 00124 STATIC void test_stk_check (void) 00125 { 00126 char buf[1000]; 00127 sprintf (buf, "In test_stk_check(): CS:IP %04X:%04X\n", 00128 _CS, FP_OFF(test_stk_check)); 00129 puts (buf); 00130 } 00131 #endif 00132 00133 /* 00134 * Turn off stack-checking to avoid destroying assumptions 00135 * made in bswap patch code below. And also to make this run 00136 * a bit faster. 00137 */ 00138 #include "nochkstk.h" 00139 00140 #if !defined(USE_BIGENDIAN) 00141 00145 unsigned long cdecl _w32_intel (unsigned long val) 00146 { 00147 return ((val & 0x000000FFU) << 24) | 00148 ((val & 0x0000FF00U) << 8) | 00149 ((val & 0x00FF0000U) >> 8) | 00150 ((val & 0xFF000000U) >> 24); 00151 } 00152 00157 unsigned short cdecl _w32_intel16 (unsigned short val) 00158 { 00159 return ((val & 0x00FF) << 8) | ((val & 0xFF00) >> 8); 00160 } 00161 00162 #if (DOSX) && defined(CS_WRITEABLE) 00163 static const BYTE bswap32[] = { 00164 0x8B,0x44,0x24,0x04, /* mov eax,[esp+4] */ 00165 0x0F,0xC8, /* bswap eax */ 00166 0xC3 /* ret */ 00167 }; 00168 00169 static const BYTE bswap16[] = { 00170 0x8B,0x44,0x24,0x04, /* mov eax,[esp+4] */ 00171 0x0F,0xC8, /* bswap eax */ 00172 0xC1,0xE8,0x10, /* shr eax,16 */ 00173 0xC3 /* ret */ 00174 }; 00175 00176 /* 00177 * Modify functions intel/intel16 (htonl/htons) to use the 00178 * BSWAP instruction on 80486+ CPUs. We don't bother with real-mode 00179 * targets on a 80486+ CPU. Hope that size of overwritten functions 00180 * are big enough. 00181 */ 00182 static void patch_with_bswap (void) 00183 { 00184 MAKE_CS_WRITEABLE(); /* save descriptor access, make RW */ 00185 memcpy ((void*)_w32_intel, (const void*)&bswap32, sizeof(bswap32)); 00186 memcpy ((void*)_w32_intel16,(const void*)&bswap16, sizeof(bswap16)); 00187 UNDO_CS_ACCESS(); /* set old descriptor access */ 00188 } 00189 #endif /* (DOSX) && defined(CS_WRITEABLE) */ 00190 #endif /* !USE_BIGENDIAN */ 00191 00192 00198 DWORD get_day_num (void) 00199 { 00200 #if defined(WIN32) 00201 time_t now; 00202 00203 time (&now); 00204 return ((DWORD)now / (24*3600)); 00205 #else 00206 struct dosdate_t d; 00207 00208 memset (&d, 0, sizeof(d)); 00209 _dos_getdate (&d); 00210 --d.month; 00211 --d.day; 00212 return ((d.year-1970) * 365 + d.month * 31 + d.day); 00213 #endif 00214 } 00215 00216 00217 #if (DOSX) && !defined(USE_BIGENDIAN) 00218 /* 00219 * Safe check for an enabled RDTSC instruction. 00220 * Requires an "GenuineIntel" Pentium CPU to call Get_CR4() 00221 * (crashes on AMD K6-2 etc.). 00222 */ 00223 static BOOL RDTSC_enabled (void) 00224 { 00225 const char *env = getenv ("USE_RDTSC"); 00226 00227 use_rdtsc = (env && ATOI(env) > 0); 00228 00229 if (!use_rdtsc || /* Usage not enabled */ 00230 x86_type < 5) /* Not a Pentium class CPU */ 00231 return (FALSE); 00232 00233 if (!strncmp(x86_vendor_id,"AuthenticAMD",12) && 00234 (x86_capability & X86_CAPA_TSC)) /* AMD with TSC, okay? */ 00235 return (TRUE); 00236 00237 if (!strncmp(x86_vendor_id,"CentaurHauls",12)) /* Centaur/VIA is okay */ 00238 { 00239 #if 0 00240 /* The following code was originally written by 00241 * Michal Ludvig <michal@logix.cz> for VIA PadLock code 00242 * in OpenSSL. http://www.logix.cz/michal 00243 */ 00244 DWORD eax, ebx, ecx, edx; 00245 00246 get_cpuid (0xC0000000, &eax, &ebx, &ecx, &edx); 00247 centaur_eflag = (eax >= 0xC0000001); 00248 if (centaur_eflag) 00249 { 00250 get_cpuid (0xC0000001, &eax, &ebx, &ecx, &edx); 00251 use_ace = ((edx & (0x3<<6)) == (0x3<<6)); /* Advanced Cryptography Engine */ 00252 use_rng = ((edx & (0x3<<2)) == (0x3<<2)); /* Random Number Generator */ 00253 } 00254 #endif 00255 return (TRUE); 00256 } 00257 00258 if (strncmp(x86_vendor_id,"GenuineIntel",12) || /* Not Genuine Intel or */ 00259 (x86_capability & X86_CAPA_TSC) == 0) /* RDTSC not supported */ 00260 return (FALSE); 00261 00262 #if (DOSX) && !defined(__LCC__) && !defined(BORLAND_WIN32) 00263 return ((Get_CR4() & CR4_TS_DISABLE) == 0); /* True if not disabled */ 00264 #else 00265 return (TRUE); /* RDTSC never disabled in real-mode */ 00266 #endif 00267 } 00268 #endif /* DOSX && !USE_BIGENDIAN */ 00269 00270 00271 #if (DOSX == 0) && defined(USE_DEBUG) 00272 00279 #define OffsetOf(x) (unsigned)&(x) 00280 00281 static BOOL check_reg_struct (void) 00282 { 00283 #if defined(__WATCOMC__) 00284 struct IREGS *r1 = NULL; 00285 union REGPACK *r2 = NULL; 00286 00287 if ((OffsetOf(r2->w.ax) != OffsetOf(r1->r_ax)) || 00288 (OffsetOf(r2->w.bx) != OffsetOf(r1->r_bx)) || 00289 (OffsetOf(r2->w.cx) != OffsetOf(r1->r_cx)) || 00290 (OffsetOf(r2->w.dx) != OffsetOf(r1->r_dx)) || 00291 (OffsetOf(r2->w.bp) != OffsetOf(r1->r_bp)) || 00292 (OffsetOf(r2->w.si) != OffsetOf(r1->r_si)) || 00293 (OffsetOf(r2->w.di) != OffsetOf(r1->r_di)) || 00294 (OffsetOf(r2->w.ds) != OffsetOf(r1->r_ds)) || 00295 (OffsetOf(r2->w.es) != OffsetOf(r1->r_es)) || 00296 (OffsetOf(r2->x.flags) != OffsetOf(r1->r_flags))) 00297 return (FALSE); 00298 00299 #elif defined(__BORLANDC__) 00300 struct IREGS *r1 = NULL; 00301 struct REGPACK *r2 = NULL; 00302 00303 if ((OffsetOf(r2->r_ax) != OffsetOf(r1->r_ax)) || 00304 (OffsetOf(r2->r_bx) != OffsetOf(r1->r_bx)) || 00305 (OffsetOf(r2->r_cx) != OffsetOf(r1->r_cx)) || 00306 (OffsetOf(r2->r_dx) != OffsetOf(r1->r_dx)) || 00307 (OffsetOf(r2->r_bp) != OffsetOf(r1->r_bp)) || 00308 (OffsetOf(r2->r_si) != OffsetOf(r1->r_si)) || 00309 (OffsetOf(r2->r_di) != OffsetOf(r1->r_di)) || 00310 (OffsetOf(r2->r_ds) != OffsetOf(r1->r_ds)) || 00311 (OffsetOf(r2->r_es) != OffsetOf(r1->r_es)) || 00312 (OffsetOf(r2->r_flags) != OffsetOf(r1->r_flags))) 00313 return (FALSE); 00314 #endif 00315 return (TRUE); 00316 } 00317 #endif /* (DOSX == 0) && USE_DEBUG */ 00318 00322 void init_misc (void) 00323 { 00324 static BOOL init = FALSE; 00325 00326 if (init) 00327 return; 00328 00329 _watt_assert_buf[0] = '\0'; 00330 00331 #if (DOSX) 00332 is_in_stack_init(); 00333 #endif 00334 00335 #if defined(WIN32) 00336 init_winmisc(); 00337 00338 #elif defined(__DJGPP__) 00339 _watt_os_ver = _get_dos_version (1); 00340 00341 #elif defined(MSC386) 00342 _watt_os_ver = 0x500; /* Fake it for 32-bit MSVC */ 00343 00344 #else 00345 _watt_os_ver = (_osmajor << 8) + _osminor; 00346 #endif 00347 00348 #if defined(WIN32) 00349 win32_dos_box = FALSE; 00350 #else 00351 win32_dos_box = (_watt_os_ver >= 0x700 || /* DOS 7.x/8.x; Win-9x/ME */ 00352 _watt_os_ver == 0x501 || /* Borland PowerPak under Win32 */ 00353 _watt_os_ver == 0x532); /* DOS 5.50; Win-NT+ */ 00354 #endif 00355 00356 #if (DOSX & PHARLAP) && defined(HAVE_FARPTR48) 00357 /* 00358 * For 32-bit compilers with 48-bit far-pointers. 00359 * `init_misc' MUST be called before `PEEKx()' functions are used. 00360 */ 00361 FP_SET (_watt_dosFp, 0, SS_DOSMEM); 00362 00363 #elif (DOSX & X32VM) 00364 _watt_dosFp = MK_FP (_x386_zero_base_selector, 0); 00365 00366 #elif defined(HAVE_FARPTR48) /* MSVC */ 00367 UNFINISHED(); 00368 #endif 00369 00370 #if defined(__DJGPP__) || defined(__HIGHC__) 00371 /* backtrace_init(); */ 00372 #endif 00373 00374 #if (DOSX) 00375 setup_dos_xfer_buf(); /* A no-op on djgpp+Win32 */ 00376 00377 #elif defined(USE_DEBUG) /* real-mode */ 00378 if (!check_reg_struct()) 00379 { 00380 outsnl (__FILE__ ": IREGS/REGPACK size mismatch!"); 00381 exit (-1); 00382 } 00383 00384 #if defined(_MSC_VER) && defined(__LARGE__) 00385 (DWORD)_aaltstkovr = (DWORD)stk_overflow; 00386 #endif 00387 00388 #if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__LARGE__)) 00389 setup_stk_check(); 00390 #endif 00391 #endif 00392 00393 /* Check CPU type. Use RDTSC instruction if not forced off and 00394 * it's not disabled. No CPU detection of big-endian machines yet. 00395 */ 00396 #if (DOSX) && !defined(USE_BIGENDIAN) 00397 #if defined(__LCC__) 00398 if (_cpuidPresent()) 00399 { 00400 _cpuid (&lcc_cpuid); 00401 memcpy (&x86_vendor_id, &lcc_cpuid.Vendor, sizeof(x86_vendor_id)); 00402 x86_capability = X86_CAPA_TSC; /* !! this doesn't work: *(DWORD*) &lcc_cpuid.FpuPresent; */ 00403 } 00404 #elif !defined(BORLAND_WIN32) 00405 CheckCpuType(); 00406 #endif 00407 00408 if (RDTSC_enabled()) /* Try to use RDTSC */ 00409 has_rdtsc = TRUE; 00410 00411 #if defined(CS_WRITEABLE) 00412 if (x86_type >= 4) 00413 patch_with_bswap(); 00414 #endif 00415 #endif /* DOSX && !USE_BIGENDIAN */ 00416 00417 #if defined(WIN32) 00418 srand (GetTickCount()); /* should be redundant */ 00419 #else 00420 srand (PEEKW(0,0x46C)); /* initialize rand() using BIOS clock */ 00421 #endif 00422 00423 init_timers(); 00424 init = TRUE; 00425 } 00426 00430 void exit_misc (void) 00431 { 00432 num_exit_func_inserts = 0; 00433 } 00434 00441 FILE *fopen_excl (const char *file, const char *mode) 00442 { 00443 #if defined(WIN32) && !defined(__WATCOMC__) 00444 int fd, flags = _O_CREAT | _O_TRUNC | _O_WRONLY; 00445 00446 #ifdef _O_SEQUENTIAL 00447 flags += _O_SEQUENTIAL; 00448 #endif 00449 if (mode[strlen(mode)-1] == 'b') 00450 flags += O_BINARY; 00451 00452 fd = _sopen (file, flags, SH_DENYWR, S_IREAD | S_IWRITE); 00453 if (fd <= -1) 00454 return (NULL); 00455 return fdopen (fd, mode); 00456 #else 00457 return fopen (file, mode); 00458 #endif 00459 } 00460 00465 struct on_exit { 00466 void (*func)(void); 00467 const char *name; 00468 int order; 00469 }; 00470 00471 static struct on_exit exit_list [40]; 00472 00473 static int list_compare (const struct on_exit *a, const struct on_exit *b) 00474 { 00475 return (a->order - b->order); 00476 } 00477 00481 int rundown_add (void (*func)(void), const char *name, int order, 00482 const char *file, unsigned line) 00483 { 00484 int i; 00485 00486 for (i = 0; i < num_exit_func_inserts; i++) 00487 { 00488 if (!exit_list[i].func) 00489 continue; 00490 00491 if (exit_list[i].func == func) 00492 goto modify; 00493 00494 if (exit_list[i].order == order) 00495 { 00496 #if defined(USE_DEBUG) 00497 (*_printf) ("%s(%u): rundown_add (\"%s\",%d): order already " 00498 "in exit_list[]\n", file, line, name, order); 00499 exit (-1); 00500 #else 00501 return (-1); 00502 #endif 00503 } 00504 } 00505 00506 WATT_ASSERT (num_exit_func_inserts < DIM(exit_list)); 00507 i = num_exit_func_inserts++; 00508 00509 modify: 00510 exit_list[i].func = func; 00511 exit_list[i].name = name; 00512 exit_list[i].order = order; 00513 00514 qsort (&exit_list, DIM(exit_list), sizeof(exit_list[0]), 00515 (int(*)(const void *, const void *))list_compare); 00516 00517 ARGSUSED (file); 00518 ARGSUSED (line); 00519 return (num_exit_func_inserts); 00520 } 00521 00525 void rundown_run (void) 00526 { 00527 struct on_exit *oe; 00528 void (*func)(void); 00529 int i; 00530 00531 for (i = 0, oe = exit_list; i < DIM(exit_list); i++, oe++) 00532 { 00533 if (!oe->func) 00534 continue; 00535 00536 #if defined(USE_DEBUG) 00537 if (debug_on >= 3) 00538 { 00539 (*_printf) ("Calling rundown-func `%s' at order %d\n", 00540 oe->name, oe->order); 00541 fflush (stdout); 00542 } 00543 #endif 00544 func = oe->func; 00545 oe->func = NULL; /* don't call it again */ 00546 (*func)(); 00547 } 00548 } 00549 00550 #if defined(USE_DEBUG) 00551 00554 void rundown_dump (void) 00555 { 00556 const struct on_exit *oe; 00557 int i, num_active; 00558 00559 (*_printf) ("rundown_dump():\n"); 00560 for (i = num_active = 0, oe = exit_list; i < DIM(exit_list); i++, oe++) 00561 { 00562 if (!oe->func) 00563 continue; 00564 (*_printf) (" order %3d: %s\n", oe->order, oe->name); 00565 num_active++; 00566 } 00567 (*_printf) (" %s\n", num_active == i ? "possible overflow" : "okay"); 00568 } 00569 #endif 00570 00571 00572 /* 00573 * Consolidated memory debug for Fortify and MSVC CrtDbg. 00574 */ 00575 #if defined(USE_CRTDBG) /* For _MSC_VER only */ 00576 /* 00577 * If using MSVCRTD debug version, there's little point using Fortify too. 00578 * USE_CRTDBG is set only when building with cl -MDd or MTd etc (_DEBUG set). 00579 */ 00580 #if !defined(_CRT_RPTHOOK_INSTALL) && (_MSC_VER < 1300) /* SDK too old */ 00581 #define _CRT_RPTHOOK_INSTALL 0 00582 #define _CRT_RPTHOOK_REMOVE 1 00583 00584 _CRTIMP _CRT_REPORT_HOOK __cdecl 00585 _CrtSetReportHook2 (int, _CRT_REPORT_HOOK); 00586 #endif 00587 00588 static _CrtMemState last_state; 00589 static void __cdecl crtdbg_exit (void); 00590 00591 static const char *report_name (int type) 00592 { 00593 return (type == _CRT_WARN ? "Warn" : 00594 type == _CRT_ERROR ? "Error" : 00595 type == _CRT_ASSERT ? "Assert" : 00596 type == _CRT_ERRCNT ? "ErrCnt" : "??"); 00597 } 00598 00599 /* 00600 * This doesn't seem to be called (?) 00601 */ 00602 static void __cdecl crtdbg_dump (const void *buf, size_t len) 00603 { 00604 const BYTE *p = (const BYTE*) buf; 00605 size_t i; 00606 int c; 00607 00608 fprintf (stderr, "dump: buf %p, %u bytes\n", buf, len); 00609 len = min (len, 30); 00610 for (i = 0; i < len; i++) 00611 { 00612 c = *p++; 00613 fprintf (stderr, "%c", isprint(c) ? c : '.'); 00614 } 00615 } 00616 00617 static int __cdecl crtdbg_report (int type, char *message, int *ret_val) 00618 { 00619 BOOL stop; 00620 00621 fprintf (stderr, "%s: %s\n", report_name(type), message); 00622 stop = (type == _CRT_ASSERT); 00623 if (stop) 00624 { 00625 /* _CrtMemDumpAllObjectsSince (&last_state); */ 00626 crtdbg_exit(); 00627 /* StackWalk (&ret_val); */ 00628 } 00629 if (ret_val) 00630 *ret_val = stop; /* stopping forces a breakpoint (int 3) */ 00631 return (stop); 00632 } 00633 00634 static void __cdecl crtdbg_exit (void) 00635 { 00636 #if 0 00637 _CrtMemDumpStatistics (&last_state); 00638 _CrtCheckMemory(); 00639 _CrtDumpMemoryLeaks(); 00640 #endif 00641 00642 #if (_MSC_VER >= 1300) && 0 00643 _CrtSetReportHook2 (_CRT_RPTHOOK_REMOVE, crtdbg_report); 00644 #else 00645 _CrtSetReportHook (NULL); 00646 #endif 00647 } 00648 00649 void memdbg_init (void) 00650 { 00651 #if (_MSC_VER < 1500) || 1 /* !! */ 00652 _HFILE file = _CRTDBG_FILE_STDERR; 00653 int mode = _CRTDBG_MODE_FILE; 00654 int flags = _CRTDBG_LEAK_CHECK_DF | 00655 _CRTDBG_DELAY_FREE_MEM_DF | 00656 /* _CRTDBG_CHECK_CRT_DF | */ /* Don't report allocs in CRT */ 00657 _CRTDBG_CHECK_ALWAYS_DF | 00658 _CRTDBG_ALLOC_MEM_DF; 00659 00660 _CrtSetReportFile (_CRT_ASSERT, file); 00661 _CrtSetReportMode (_CRT_ASSERT, mode); 00662 _CrtSetReportFile (_CRT_ERROR, file); 00663 _CrtSetReportMode (_CRT_ERROR, mode); 00664 _CrtSetReportFile (_CRT_WARN, file); 00665 _CrtSetReportMode (_CRT_WARN, mode); 00666 00667 _CrtSetDbgFlag (flags | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)); 00668 00669 #if (_MSC_VER >= 1300) && 0 00670 _CrtSetReportHook2 (_CRT_RPTHOOK_INSTALL, crtdbg_report); 00671 #else 00672 _CrtSetReportHook (crtdbg_report); 00673 #endif 00674 00675 _CrtMemCheckpoint (&last_state); 00676 _CrtSetDumpClient (crtdbg_dump); 00677 00678 RUNDOWN_ADD (crtdbg_exit, 305); 00679 #endif 00680 } 00681 00682 #elif defined(USE_FORTIFY) 00683 00688 static void fortify_report (void) 00689 { 00690 if (debug_on >= 2) 00691 { 00692 Fortify_SetOutputFunc ((Fortify_OutputFuncPtr)printf); 00693 Fortify_OutputStatistics(); 00694 } 00695 else 00696 Fortify_SetOutputFunc (NULL); 00697 Fortify_LeaveScope(); 00698 } 00699 00700 void memdbg_init (void) 00701 { 00702 const char *env = getenv ("FORTIFY_FAIL"); 00703 00704 Fortify_EnterScope(); 00705 if (env) 00706 Fortify_SetAllocateFailRate (atoi(env)); 00707 00708 #if defined(USE_DEBUG) && defined(USE_BSD_API) 00709 Fortify_SetOutputFunc (bsd_fortify_print); 00710 #endif 00711 00712 RUNDOWN_ADD (fortify_report, 305); 00713 00714 #if defined(WIN32) 00715 LoadLibrary ("exchndl.dll"); /* Dr. MingW */ 00716 #endif 00717 } 00718 #endif /* USE_CRTDBG */ 00719 00720 00721 #if defined(USE_DEBUG) && !defined(NDEBUG) 00722 00725 void assert_fail (const char *file, unsigned line, const char *what) 00726 { 00727 #if defined(SNPRINTF) 00728 SNPRINTF (_watt_assert_buf, sizeof(_watt_assert_buf)-1, 00729 #else 00730 sprintf (_watt_assert_buf, 00731 #endif 00732 "%s (%u): Assertion `%s' failed.\n", file, line, what); 00733 00734 (*_printf) ("%s\n", _watt_assert_buf); 00735 00736 #ifdef __DJGPP__ 00737 /* 00738 * abort() doesn't call atexit() functions but makes a handy traceback. 00739 */ 00740 rundown_run(); 00741 abort(); 00742 #else 00743 exit (-1); 00744 #endif 00745 } 00746 #endif /* USE_DEBUG && !NDEBUG */ 00747 00748 00752 unsigned Random (unsigned a, unsigned b) 00753 { 00754 if (a == b) 00755 return (a); 00756 00757 if (a > b) 00758 { 00759 unsigned tmp = b; 00760 b = a; 00761 a = tmp; 00762 } 00763 return (a + (unsigned)(rand() % (b-a+1))); 00764 } 00765 00769 void RandomWait (unsigned a, unsigned b) 00770 { 00771 DWORD t = set_timeout (Random(a, b)); 00772 00773 while (!chk_timeout(t)) 00774 { 00775 #if defined(WIN32) 00776 Sleep (1); 00777 #else 00778 ENABLE(); 00779 #endif 00780 } 00781 } 00782 00786 void Wait (unsigned msec) 00787 { 00788 DWORD t = set_timeout (msec); 00789 00790 while (!chk_timeout(t)) 00791 { 00792 #if defined(WIN32) 00793 Sleep (1); 00794 #else 00795 ENABLE(); 00796 #endif 00797 } 00798 } 00799 00800 /* 00801 * Return a sensible name for running DOS-extender or subsystem. 00802 */ 00803 const char *dos_extender_name (void) 00804 { 00805 #if (DOSX & DOS4GW) 00806 return dos4gw_extender_name(); 00807 #elif (DOSX & DJGPP) 00808 return ("djgpp"); 00809 #elif (DOSX & PHARLAP) 00810 return ("PharLap"); 00811 #elif (DOSX & POWERPAK) 00812 return ("PowerPak"); 00813 #elif (DOSX & X32VM) 00814 return ("X32VM"); 00815 #elif (DOSX & WINWATT) 00816 return ("Win32"); 00817 #else 00818 return (NULL); 00819 #endif 00820 } 00821 00822 00823 void os_yield (void) 00824 { 00825 #if defined(WIN32) 00826 Sleep (1); 00827 #else 00828 static BOOL do_yield = TRUE; 00829 00830 #if defined(__DJGPP__) 00831 if (do_yield) 00832 { 00833 __dpmi_yield(); 00834 do_yield = (errno != ENOSYS); 00835 } 00836 #else 00837 if (!watt_kbhit() && do_yield) /* watt_kbhit() is to permit ^C */ 00838 { 00839 IREGS reg; 00840 memset (&reg, 0, sizeof(reg)); 00841 reg.r_ax = 0x1680; 00842 GEN_INTERRUPT (0x2F, &reg); 00843 do_yield = (loBYTE(reg.r_ax) != 0x80); 00844 } 00845 #endif 00846 #endif /* WIN32 */ 00847 } 00848 00849 00850 #if defined(NOT_USED) 00851 BOOL watt_check_break (void) 00852 { 00853 WORD head = 0x400 + PEEKW (0, 0x41A); 00854 WORD tail = 0x400 + PEEKW (0, 0x41C); 00855 int ofs, num; 00856 00857 printf ("\nwatt_check_break(): head %04X, tail %04X, keys:\n", 00858 head, tail); 00859 for (num = 0, ofs = head; ofs != tail && num < 32; num++) 00860 { 00861 printf (" ofs %04X: %02X\n", ofs, PEEKB(0,ofs)); 00862 if (++ofs > 32+0x41E) 00863 ofs = 0x41E; 00864 } 00865 puts (""); 00866 return (FALSE); 00867 } 00868 #endif 00869 00870 00874 int watt_kbhit (void) 00875 { 00876 if (_watt_cbroke) 00877 return (1); 00878 00879 #if defined(WIN32) 00880 Sleep (1); 00881 return kbhit(); 00882 00883 #else 00884 if (PEEKW(0,0x41A) == PEEKW(0,0x41C)) 00885 return (0); 00886 00887 /* RTL's kbhit() calls INT16/11 or INT21/0B which triggers INT 23 00888 * which in turn should raise SIGINT in RTL. Except for djgpp under 00889 * Windows where normal/extended BREAK checking is turned off (since 00890 * SIGINT delivery by pressing ^C is so unreliable under Windows). 00891 */ 00892 return kbhit(); 00893 #endif 00894 } 00895 00896 00897 #if defined(USE_DEBUG) 00898 00901 const char *list_lookup (DWORD type, const struct search_list *list, int num) 00902 { 00903 static char buf[15]; 00904 00905 while (num > 0 && list->name) 00906 { 00907 if (list->type == type) 00908 return (list->name); 00909 num--; 00910 list++; 00911 } 00912 sprintf (buf, "?%lu", type); 00913 return (buf); 00914 } 00915 00916 const char *list_lookupX (DWORD type, const struct search_list *list, int num) 00917 { 00918 static char buf[15]; 00919 00920 while (num > 0 && list->name) 00921 { 00922 if (list->type == type) 00923 return (list->name); 00924 num--; 00925 list++; 00926 } 00927 sprintf (buf, "?0x%lX", type); 00928 return (buf); 00929 } 00930 00935 const char *MAC_address (const void *addr) 00936 { 00937 static char buf[2][25]; 00938 static int idx = 0; 00939 char *rc = buf [idx]; 00940 char *p = rc; 00941 const char *a = (const char*)addr; 00942 00943 p += sprintf (p, "%02X:%02X:%02X:%02X:%02X:%02X", 00944 a[0] & 255, a[1] & 255, a[2] & 255, 00945 a[3] & 255, a[4] & 255, a[5] & 255); 00946 00947 /* assume '*addr' is an 7-byte AX25 address 00948 */ 00949 if (_pktdevclass == PDCLASS_AX25) 00950 sprintf (p, ":%02X", a[6] & 255); 00951 00952 idx ^= 1; 00953 return (rc); 00954 } 00955 00956 void unfinished (const char *func, const char *file, unsigned line) 00957 { 00958 if (func) 00959 fprintf (stderr, "In `%s' ", func); 00960 fprintf (stderr, "%s (%u):\7 Help! Unfinished code.\n", file, line); 00961 exit (-1); 00962 } 00963 00968 const char *dword_str (DWORD val) 00969 { 00970 static char buf[20]; 00971 char tmp[20]; 00972 00973 if (val < 1000UL) 00974 { 00975 sprintf (buf, "%lu", val); 00976 return (buf); 00977 } 00978 if (val < 1000000UL) /* 1E6 */ 00979 { 00980 sprintf (buf, "%lu,%03lu", val/1000UL, val % 1000UL); 00981 return (buf); 00982 } 00983 if (val < 1000000000UL) /* 1E9 */ 00984 { 00985 sprintf (tmp, "%9lu", val); 00986 sprintf (buf, "%.3s,%.3s,%.3s", tmp, tmp+3, tmp+6); 00987 return strltrim (buf); 00988 } 00989 sprintf (tmp, "%12lu", val); 00990 sprintf (buf, "%.3s,%.3s,%.3s,%.3s", tmp, tmp+3, tmp+6, tmp+9); 00991 return strltrim (buf); 00992 } 00993 #endif /* USE_DEBUG */ 00994 00995 00996 #if (DOSX) 00997 #if defined(BORLAND386) || defined(DMC386) || defined(MSC386) 00998 DWORD get_ds_limit (void) 00999 { 01000 DWORD res; 01001 asm mov ax, ds 01002 asm and eax, 0FFFFh 01003 asm lsl eax, eax 01004 asm mov res, eax 01005 return (res); 01006 } 01007 01008 DWORD get_cs_limit (void) 01009 { 01010 DWORD res; 01011 asm mov ax, cs 01012 asm and eax, 0FFFFh 01013 asm lsl eax, eax 01014 asm mov res, eax 01015 return (res); 01016 } 01017 01018 DWORD get_ss_limit (void) 01019 { 01020 DWORD res; 01021 asm mov ax, ss 01022 asm and eax, 0FFFFh 01023 asm lsl eax, eax 01024 asm mov res, eax 01025 return (res); 01026 } 01027 01028 #elif defined(__CCDL__) 01029 DWORD get_ds_limit (void) 01030 { 01031 asm { 01032 mov ax, ds 01033 and eax, 0xFFFF 01034 lsl eax, eax 01035 } 01036 return (_EAX); 01037 } 01038 01039 DWORD get_cs_limit (void) 01040 { 01041 asm { 01042 mov ax, cs 01043 and eax, 0xFFFF 01044 lsl eax, eax 01045 } 01046 return (_EAX); 01047 } 01048 01049 DWORD get_ss_limit (void) 01050 { 01051 asm { 01052 mov ax, ss 01053 and eax, 0xFFFF 01054 lsl eax, eax 01055 } 01056 return (_EAX); 01057 } 01058 #endif 01059 01060 /* 01061 * The is_in_stack() function is by 01062 * Jani Kajala (jani.kajala@helsinki.fi) 01063 * Feb 7, 2002, 01064 */ 01065 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 01066 #define THREADLOCAL __declspec(thread) 01067 #else 01068 #define THREADLOCAL 01069 #endif 01070 01071 THREADLOCAL static const char *stack_bottom = 0; 01072 01073 #if defined(__DJGPP__) && 0 /* not needed */ 01074 extern unsigned dj_end asm ("end"); 01075 extern unsigned _stklen, __djgpp_stack_limit; 01076 #define STK_START() (DWORD)&dj_end 01077 #endif 01078 01079 static unsigned get_frame_size (const char *x) 01080 { 01081 char y = 0; 01082 return (unsigned)(x - &y); 01083 } 01084 01085 static void is_in_stack_init (void) 01086 { 01087 char x = 0; 01088 stack_bottom = &x + get_frame_size(&x) * 2; 01089 } 01090 01091 BOOL is_in_stack (const void *ptr) 01092 { 01093 char x; 01094 char *stack_top = &x; 01095 char *p = (char*) ptr; 01096 01097 if (stack_top > stack_bottom) 01098 return (p > stack_bottom && p < stack_top); /* stack grows up */ 01099 return (p > stack_top && p < stack_bottom); /* stack grows down */ 01100 } 01101 01102 unsigned used_stack (void) 01103 { 01104 char x; 01105 char *stack_top = &x; 01106 01107 if (stack_top > stack_bottom) 01108 return (unsigned)(stack_top - stack_bottom); 01109 return (unsigned)(stack_bottom - stack_top); 01110 } 01111 01112 /* 01113 * Test for valid read/write data address. 01114 * We assume linear address 'addr' is both readable and writeable. 01115 * 01116 * \note MingW (and other Win32 compilers?) puts 'const' data in 01117 * read-only sections (.rdata). Detectible with IsBadWritePtr(). 01118 */ 01119 BOOL valid_addr (const void *addr, unsigned len) 01120 { 01121 #if defined(WIN32) 01122 if (IsBadWritePtr((void*)addr,len) && IsBadReadPtr(addr,len)) 01123 return (FALSE); 01124 01125 #else 01126 DWORD limit, addr_ = (DWORD)addr; 01127 01128 if (addr_ < 4096) /* Valid in DOS4GW, but we never uses such address */ 01129 return (FALSE); 01130 01131 /* In X32VM: DS != SS. addr may be in data or stack. 01132 */ 01133 #if defined(DMC386) && (DOSX & X32VM) && 0 /* Doesn't work :-( */ 01134 if (selector == MY_SS()) 01135 { 01136 limit = get_ss_limit(); 01137 if (addr_ < _x386_stacklow || addr_ + len >= limit) 01138 return (FALSE); 01139 if (limit > len && addr_ >= limit - len) /* Segment wrap */ 01140 return (FALSE); 01141 } 01142 else if (selector != MY_DS()) 01143 return (FALSE); 01144 #endif 01145 01146 #if defined(__DJGPP__) 01147 limit = __dpmi_get_segment_limit (_my_ds()); 01148 #elif defined(__HIGHC__) 01149 limit = _mwlsl (_mwgetcs()); /* DS & CS are aliases */ 01150 #else 01151 limit = get_ds_limit(); 01152 #endif 01153 01154 if (addr_ + len >= limit) 01155 return (FALSE); 01156 if (limit > len && addr_ >= limit - len) /* Segment wrap */ 01157 return (FALSE); 01158 #endif /* WIN32 */ 01159 01160 return (TRUE); 01161 } 01162 #endif /* DOSX */ 01163 01164 01165 /* 01166 * Pharlap/X32VM targets: Get location of (or allocate a) transfer buffer. 01167 * DOS4GW/PowerPak targets: Allocate a small (1kB) transfer buffer. 01168 * djgpp/Win32: Nothing special to do. 01169 */ 01170 #if (DOSX & (PHARLAP|X32VM)) 01171 REALPTR _watt_dosTbr; 01172 DWORD _watt_dosTbSize = 0; 01173 static WORD rm_seg = 0; 01174 01175 static void free_selector (void) 01176 { 01177 if (rm_seg) 01178 _dx_real_free (rm_seg); 01179 rm_seg = 0; 01180 _watt_dosTbr = 0; 01181 _watt_dosTbSize = 0; 01182 } 01183 01184 static void setup_dos_xfer_buf (void) 01185 { 01186 FARPTR dos_tbp; /* pmode transfer-buffer address */ 01187 REALPTR r2p_addr; /* rmode to pmode call address */ 01188 WORD temp; 01189 int len = 1024; /* min size we need */ 01190 01191 _dx_rmlink_get (&r2p_addr, &_watt_dosTbr, 01192 &_watt_dosTbSize, &dos_tbp); 01193 01194 if (_watt_dosTbSize < len && 01195 _dx_real_above(len, &rm_seg, &temp) == 0) 01196 { 01197 RP_SET (_watt_dosTbr, 0, rm_seg); 01198 _watt_dosTbSize = len; 01199 RUNDOWN_ADD (free_selector, 15); 01200 } 01201 } 01202 01203 #elif (DOSX & DOS4GW) 01204 WORD _watt_dosTbSeg = 0; /* paragraph address of xfer buffer */ 01205 WORD _watt_dosTbSel = 0; /* selector for transfer buffer */ 01206 DWORD _watt_dosTbSize = 0; /* size of transfer buffer */ 01207 01208 static void free_selector (void) 01209 { 01210 if (_watt_dosTbSel) 01211 #ifdef __CCDL__ 01212 dpmi_free_selector (_watt_dosTbSel); 01213 #else 01214 dpmi_real_free (_watt_dosTbSel); 01215 #endif 01216 _watt_dosTbSel = 0; 01217 } 01218 01219 static void setup_dos_xfer_buf (void) 01220 { 01221 _watt_dosTbSize = 1024; 01222 #ifdef __CCDL__ 01223 if (dpmi_alloc_real_memory (&_watt_dosTbSel, &_watt_dosTbSeg, _watt_dosTbSize) >= 0) 01224 _watt_dosTbSeg = 0; 01225 #else 01226 _watt_dosTbSeg = dpmi_real_malloc (_watt_dosTbSize, &_watt_dosTbSel); 01227 #endif 01228 01229 if (!_watt_dosTbSeg) 01230 _watt_dosTbSize = 0; 01231 else RUNDOWN_ADD (free_selector, 15); 01232 } 01233 01234 #elif (DOSX & POWERPAK) 01235 WORD _watt_dos_ds; 01236 WORD _watt_dosTbSeg = 0; 01237 WORD _watt_dosTbSel = 0; 01238 DWORD _watt_dosTbr = 0; 01239 DWORD _watt_dosTbSize = 0; 01240 01241 static void free_selector (void) 01242 { 01243 if (_watt_dosTbSel) 01244 dpmi_real_free (_watt_dosTbSel); 01245 _watt_dosTbSel = 0; 01246 if (_watt_dos_ds) 01247 dpmi_free_dos_selector (_watt_dos_ds); 01248 _watt_dos_ds = 0; 01249 _watt_dosTbr = 0; 01250 } 01251 01252 static void setup_dos_xfer_buf (void) 01253 { 01254 _watt_dos_ds = dpmi_create_dos_selector(); 01255 if (!_watt_dos_ds) 01256 { 01257 fprintf (stderr, "Fatal: Failed to create DOS selector. " 01258 "DPMI error 0x%04X.\n", __dpmi_errno); 01259 exit (-1); 01260 } 01261 _watt_dosTbSize = 1024; 01262 _watt_dosTbSeg = dpmi_real_malloc (_watt_dosTbSize, &_watt_dosTbSel); 01263 if (!_watt_dosTbSeg) 01264 _watt_dosTbSize = 0; 01265 else 01266 { 01267 RUNDOWN_ADD (free_selector, 15); 01268 _watt_dosTbr = (_watt_dosTbSeg << 16); 01269 } 01270 } 01271 01272 #elif (DOSX) 01273 static void setup_dos_xfer_buf (void) 01274 { 01275 /* no-op */ 01276 } 01277 #endif 01278 01279 01280 #if defined(USE_BSD_API) 01281 /* 01282 * ffs() isn't needed yet, but could be used in select_s() 01283 * 01284 * Copyright (C) 1991, 1992 Free Software Foundation, Inc. 01285 * Contributed by Torbjorn Granlund (tege@sics.se). 01286 * 01287 * The GNU C Library is free software; you can redistribute it and/or 01288 * modify it under the terms of the GNU Library General Public License as 01289 * published by the Free Software Foundation; either version 2 of the 01290 * License, or (at your option) any later version. 01291 * 01292 * The GNU C Library is distributed in the hope that it will be useful, 01293 * but WITHOUT ANY WARRANTY; without even the implied warranty of 01294 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 01295 * Library General Public License for more details. 01296 * 01297 * You should have received a copy of the GNU Library General Public 01298 * License along with the GNU C Library; see the file COPYING.LIB. If 01299 * not, write to the Free Software Foundation, Inc., 675 Mass Ave, 01300 * Cambridge, MA 02139, USA. 01301 */ 01302 01303 /* 01304 * Returns the index of first bit set in 'i'. Counting from 1 at 01305 * "right side". Returns 0 if 'i' is 0. 01306 */ 01307 int _w32_ffs (int i) 01308 { 01309 static const BYTE table[] = { 01310 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 01311 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 01312 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 01313 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 01314 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 01315 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 01316 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 01317 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 01318 }; 01319 DWORD a, x; 01320 01321 #if (DOSX) && !defined(__LCC__) && !defined(BORLAND_WIN32) 01322 if (x86_type >= 3) 01323 return asm_ffs (i); /* BSF requires 386+ */ 01324 #endif 01325 01326 x = i & -i; 01327 a = x <= 0xFFFFUL ? (x <= 0xFF ? 0 : 8) : (x <= 0xFFFFFF ? 16 : 24); 01328 return (table[x >> a] + a); 01329 } 01330 #endif /* USE_BSD_API */ 01331 01332 01333 /* 01334 * Checks for bugs when compiling in large model C compiler 01335 * 01336 * Borland C uses a 4K stack by default. In all memory models the 01337 * stack grows down toward the heap. 01338 * 01339 * If you accidentally place _tcp_Socket onto the stack, then you 01340 * will have already used up that whole 4K and then some! 01341 * 01342 * In large model, this will mess up the data space in a major way 01343 * because the stack starts at SS:_stklen, or SS:1000, so you will 01344 * wrap the SP pointer back around to FFFE and start writing over 01345 * the far heap. Yuck. 01346 * 01347 * In small model it usually doesn't kill your application because 01348 * you would have to be down to your last 4K of memory and this is 01349 * not as common. 01350 * 01351 * The solutions: declare your sockets as static, or put them on the 01352 * heap, or bump up your stack size by using the global special variable: 01353 * 01354 * unsigned _stklen = 16536; 01355 */ 01356 01357 #if defined(__LARGE__) 01358 void watt_large_check (const void *sock, int size, 01359 const char *file, unsigned line) 01360 { 01361 if ((unsigned)(FP_OFF(sock)) > (unsigned)(-size)) 01362 { 01363 #if defined(USE_DEBUG) 01364 fprintf (stderr, "%s (%d): user stack size error", file, line); 01365 #else 01366 outsnl ("user stack size error"); 01367 ARGSUSED (file); 01368 ARGSUSED (line); 01369 #endif 01370 exit (3); 01371 } 01372 } 01373 #endif /* __LARGE__ */ 01374 01375 01376 #if defined(USE_DEBUG) 01377 #if defined(NOT_USED) 01378 BOOL is_big_endian (void) 01379 { 01380 /* From Harbison & Steele. 01381 */ 01382 union { 01383 long l; 01384 char c[sizeof(long)]; 01385 } u; 01386 01387 u.l = 1; 01388 return (u.c[sizeof(long)-1] == 1); 01389 } 01390 01394 #include <sys/pack_on.h> 01395 01396 struct cmd_block { 01397 BYTE len; 01398 char buf[256]; 01399 }; 01400 01401 #include <sys/pack_off.h> 01402 01403 BOOL shell_exec (const char *cmd) 01404 { 01405 struct cmd_block blk; 01406 size_t i = sizeof(blk.buf)-1; 01407 IREGS regs; 01408 01409 StrLcpy (blk.buf, cmd, i); 01410 i = min (i, strlen(blk.buf)); 01411 blk.len = i; 01412 blk.buf[i] = '\r'; 01413 01414 #if (DOSX & DJGPP) 01415 regs.r_ds = __tb / 16; 01416 regs.r_si = __tb & 15; 01417 dosmemput (&blk, sizeof(blk), __tb); 01418 01419 #elif (DOSX == 0) 01420 regs.r_ds = FP_SEG (&blk); 01421 regs.r_si = FP_OFF (&blk); 01422 #endif 01423 01424 GEN_INTERRUPT (0x2E, &regs); 01425 return (regs.r_ax != 0xFFFF); 01426 } 01427 #endif /* NOT_USED */ 01428 01429 01433 #if (defined(_MSC_VER) || defined(__DMC__)) && (DOSX == 0) 01434 #undef intr 01435 void _w32_intr (int int_no, IREGS *reg) 01436 { 01437 union REGS r; 01438 struct SREGS s; 01439 01440 r.x.ax = reg->r_ax; 01441 r.x.bx = reg->r_bx; 01442 r.x.cx = reg->r_cx; 01443 r.x.dx = reg->r_dx; 01444 r.x.si = reg->r_si; 01445 r.x.di = reg->r_di; 01446 s.ds = reg->r_ds; 01447 s.es = reg->r_es; 01448 int86x (int_no, &r, &r, &s); 01449 reg->r_flags = r.x.cflag; 01450 reg->r_ax = r.x.ax; 01451 reg->r_bx = r.x.bx; 01452 reg->r_cx = r.x.cx; 01453 reg->r_dx = r.x.dx; 01454 reg->r_si = r.x.si; 01455 reg->r_di = r.x.di; 01456 reg->r_ds = s.ds; 01457 reg->r_es = s.es; 01458 } 01459 #endif 01460 01461 01462 #if defined(__BORLANDC__) && defined(__LARGE__) 01463 /* 01464 * Large model with option '-N' generates code like: 01465 * < .. standard prologue ...> 01466 * 39 26 00 00 cmp DGROUP:__stklen,sp 01467 * 77 05 ja Lxx 01468 * 9A 00 00 00 00 call F_OVERFLOW@ 01469 * Lxx: 01470 * 01471 * We need to find the address of F_OVERFLOW@ (it cannot be addressed 01472 * from C). 01473 */ 01474 STATIC void stk_overflow (WORD ret_addr) 01475 { 01476 static WORD cs, ip; 01477 static WORD stk[128]; 01478 01479 cs = *(WORD*) (&ret_addr-1); 01480 ip = *(WORD*) (&ret_addr-2); 01481 01482 _SS = FP_SEG (stk); 01483 _SP = (WORD) &stk [DIM(stk)-1]; 01484 _stklen = 0x7FFF; 01485 _watt_fatal_error = TRUE; 01486 fprintf (stderr, "\nStack overflow at %04X:%04X!\n", cs, ip); 01487 _eth_release(); 01488 _exit (-1); 01489 } 01490 01491 STATIC int setup_stk_check (void) 01492 { 01493 BYTE sign[] = { 0x39, 0x26, 0,0, 0x77, 5, 0x9A }; 01494 BYTE *p = (BYTE*) _eth_arrived; 01495 int i; 01496 01497 *(WORD*)&sign[2] = FP_OFF (&_stklen); 01498 for (i = 0; i < 10; i++, p++) 01499 if (!memcmp(p, sign, sizeof(sign))) 01500 { 01501 DWORD addr = *(DWORD*) (p + sizeof(sign)); 01502 BYTE *patch; 01503 01504 /* printf ("F_OVERFLOW@ at %04X:%04X\n", (WORD)(addr >> 16), (WORD)addr); */ 01505 patch = (BYTE*) addr; 01506 *patch++ = 0x2E; 01507 *patch++ = 0xFF; 01508 *patch++ = 0x2E; 01509 *(WORD*)patch = 6 - 1 + (WORD)addr; /* relocation of [where] */ 01510 patch += 2; 01511 *(WORD*)patch = FP_OFF (stk_overflow); 01512 patch += 2; 01513 *(WORD*)patch = FP_SEG (stk_overflow); 01514 01515 /* 01516 * 0001 F_OVERFLOW@: 01517 * 0001 2E: FF 2E 0006r jmp dword ptr cs:[where] 01518 * 0006 ???????? where dd ? 01519 */ 01520 #if 0 01521 printf ("test_stk_check() at CS:IP %04X:%04X\n", 01522 _CS, FP_OFF(test_stk_check)); 01523 _stklen = 10; 01524 test_stk_check(); 01525 #endif 01526 return (1); 01527 } 01528 return (0); 01529 } 01530 01531 #elif defined(__BORLANDC__) && defined(__SMALL__) 01532 /* 01533 * Small model with option '-N' generates code like: 01534 * < .. standard prologue ...> 01535 * 39 26 00 00 cmp ___brklvl,sp 01536 * 72 03 jb L$1 01537 * E8 00 00 call N_OVERFLOW@ 01538 * L$1: 01539 * 01540 * We need to find the address of N_OVERFLOW@ (it cannot be addressed 01541 * from C). It should be the same code as in large model. 01542 */ 01543 extern int __brklvl; 01544 01545 static void stk_overflow (UINT ret_addr) 01546 { 01547 static WORD cs, ip; 01548 static WORD stk[128]; 01549 01550 cs = _CS; 01551 ip = *(WORD*) (&ret_addr-1); 01552 01553 _SS = FP_SEG (stk); 01554 _SP = (WORD) &stk [DIM(stk)-1]; 01555 01556 _stklen = 0x7FFF; 01557 _watt_fatal_error = TRUE; 01558 fprintf (stderr, "\nStack overflow at %04X:%04X!\n", cs, ip); 01559 _eth_release(); 01560 _exit (1); /* do minimal work, no rundown_run() */ 01561 } 01562 01563 static int stk_check_setup (void) 01564 { 01565 BYTE sign[] = { 0x39, 0x26, 0,0, 0x72, 3, 0xE8 }; 01566 BYTE *p = (BYTE*) _eth_arrived; 01567 int i; 01568 01569 *(WORD*)&sign[2] = FP_OFF (&__brklvl); 01570 for (i = 0; i < 10; i++, p++) 01571 if (!memcmp(p, sign, sizeof(sign))) 01572 { 01573 BYTE *addr = *(BYTE*)(++p); 01574 *addr = (BYTE*) stk_overflow; 01575 return (1); 01576 } 01577 return (0); 01578 } 01579 01580 #elif defined(WATCOM386) && !defined(WIN32) 01581 /* 01582 * For tracking down stack overflow bugs. 01583 * Stack checker __CHK is pascal-style with stack-size at [esp+4]. 01584 * __CHK calls __STK which in turn may call _fatal_runtime_error() 01585 * 01586 * Compiling with stack-checking on, this prologue is in every function: 01587 * (*) push <stack size needed> <- 68h, dword size at EIP-9 01588 * call __CHK <- 5 bytes 01589 * ... <- extracted EIP of return 01590 */ 01591 static void stk_overflow (WORD cs, UINT eip) 01592 { 01593 UINT size = *(UINT*)(eip-9); 01594 01595 eip -= (UINT)&__begtext - 9; /* print .map-file address of (*) */ 01596 01597 _watt_fatal_error = TRUE; 01598 fprintf (stderr, "Stack overflow (%u bytes needed) detected at %X:%08lXh\n", 01599 size, cs, (DWORD)eip); 01600 _eth_release(); 01601 _exit (1); /* do minimal work, no rundown_run() */ 01602 } 01603 01604 void FATAL_HANDLER (UINT stk) 01605 { 01606 #if defined(__SMALL__) 01607 _x386_stacklow = stk + 2; 01608 stk_overflow (MY_CS(), *(DWORD*)(&stk+1)); 01609 01610 #elif defined(__LARGE__) 01611 _x386_stacklow = stk + 4; 01612 stk_overflow (*(WORD*)(&stk+1), *(WORD*)(&stk+2)); /* far-call */ 01613 01614 #else /* wcc386/DOS */ 01615 _x386_stacklow = stk + 4; 01616 stk_overflow (MY_CS(), *(WORD*)(&stk+1)); 01617 #endif 01618 } 01619 01620 #elif defined(_MSC_VER) && defined(__LARGE__) 01621 static void stk_overflow (void _far *where) 01622 { 01623 fprintf (stderr, "Stack overflow detected at %04X:%04Xh\n", 01624 FP_SEG(where), FP_OFF(where)); 01625 _eth_release(); 01626 _exit (1); 01627 } 01628 #endif 01629 #endif /* USE_DEBUG */ 01630 01631 /* 01632 * Functions needed for "gcc -O0". These are inlined on -O1 or above. 01633 */ 01634 #if defined(__GNUC__) 01635 #undef __SYS_SWAP_BYTES_H 01636 #undef _w32_SYS_SWAP_BYTES_H 01637 #undef _w32_CPUMODEL_H 01638 #undef _w32_MISC_H 01639 #undef _w32_IOPORT_H 01640 #undef BEEP 01641 #undef WIN_ASSERT 01642 01643 #define extern 01644 #define __inline__ 01645 #define __inline 01646 01647 #if defined(__MINGW32__) || defined(__CYGWIN__) 01648 #undef intel 01649 #undef intel16 01650 #define __NO_INLINE__ /* emulate -O0 */ 01651 #endif 01652 01653 #include <sys/swap.h> 01654 #include "misc.h" 01655 #include "cpumodel.h" 01656 01657 #if defined(__EMX__) 01658 #include "ioport.h" 01659 #endif 01660 01661 #endif /* __GNUC__ */ 01662 01663 01664 #if defined(TEST_PROG) 01665 /* 01666 * Get/set DOS' memory allocation strategy. 01667 */ 01668 BOOL get_mem_strat (BYTE *strat) 01669 { 01670 IREGS reg; 01671 01672 memset (&reg, 0, sizeof(reg)); 01673 reg.r_ax = 0x5800; 01674 GEN_INTERRUPT (0x21, &reg); 01675 if (reg.r_flags & CARRY_BIT) 01676 return (FALSE); 01677 *strat = loBYTE (reg.r_ax); 01678 return (TRUE); 01679 } 01680 01681 BOOL set_mem_strat (BYTE strat) 01682 { 01683 IREGS reg; 01684 01685 memset (&reg, 0, sizeof(reg)); 01686 reg.r_ax = 0x5801; 01687 reg.r_bx = strat; 01688 GEN_INTERRUPT (0x21, &reg); 01689 if (reg.r_flags & CARRY_BIT) 01690 return (FALSE); 01691 return (TRUE); 01692 } 01693 01694 void foo_10 (void) { puts ("I'm foo_10()"); } 01695 void foo_20 (void) { puts ("I'm foo_20()"); } 01696 void foo_30 (void) { puts ("I'm foo_30()"); } 01697 void foo_40 (void) { puts ("I'm foo_40()"); } 01698 void foo_50 (void) { puts ("I'm foo_50()"); } 01699 void foo_60 (void) { puts ("I'm foo_60()"); } 01700 void foo_70 (void) { puts ("I'm foo_70()"); } 01701 01702 int main (void) 01703 { 01704 BYTE strat; 01705 01706 printf ("DOS memory allocation strategy: "); 01707 if (!get_mem_strat(&strat)) 01708 puts ("failed"); 01709 else printf ("0x%02X\n", strat); 01710 01711 printf ("Setting \"low memory best fit\" "); 01712 if (!set_mem_strat(1)) 01713 puts ("failed"); 01714 else puts ("okay"); 01715 01716 set_mem_strat (strat); 01717 01718 RUNDOWN_ADD (foo_40, 40); 01719 RUNDOWN_ADD (foo_10, 10); 01720 RUNDOWN_ADD (foo_60, 60); 01721 RUNDOWN_ADD (foo_30, 30); 01722 RUNDOWN_ADD (foo_20, 20); 01723 RUNDOWN_ADD (foo_50, 50); 01724 RUNDOWN_ADD (foo_70, 70); 01725 debug_on = 2; 01726 rundown_run(); 01727 return (0); 01728 } 01729 #endif 01730

Generated on Wed Aug 4 08:55:48 2010 for Watt-32 tcp/ip by doxygen 1.3.8