= DevelopersFAQ = Here you can find answers to some of the most frequently asked questions about development of FM/2. If you have a question not answered on this page, you can ask it at http://tech.groups.yahoo.com/group/fm2user/ ---- [[PageOutline(2-6,,inline)]] ---- == Trouble Shooting == #trouble-shooting === How to find the source code for a trap? === The OpenWatcom maps does not provide the source line detail that the VAC maps provided, so the procedure for locating the trapping source code line changes a bit, but it's still reasonable easy. Grab the object:offset value for the failing cs:eip from popuplog.os2. Sort the memory map section of fm3dll.map. FInd the function containing the trapping object:offset value. Calculate the offset from the function start to the object:offset value. Determine the source file for the function containing the trapping function. Run wdis -l -s filename.obj where filename is the source file base name. This will create filename.lst. Find the failing function in filename.lst Find the calculated offset. This is the line that trapped. There will be labels of the form L$289. These are relative to the function start so it's easy to find the matching source code in filename.c === When the trap is in the watcom libraries, how can I trace it back to the actual call in the source? === For this you need a trap dump file. Then you can let pmdf do the work. You need my mapsymw.pl to convert the Watcom map file to something pmdf can use. To get my mapsymw.pl, you can contact me at Steven H. Levine[[BR]] steve53@earthlink.net You can also use the Watcom debugger. It can give you a call trace too. === Can a hardware breakpoint be used to detect a spurious write? === You can if the exception address shown in the popuplog P2 field is consistent. === If all the traps are in the library code, what does this possibly mean? === This is not unusual for buffer overflows. Each buffer in the heap has a header and depending on the implementation a trailer which contains counts and/or pointers. If you wipe out one of these, a trap will follow soon enough. ---- == Coding Questions == #coding-questions === Is the code below OK? Did I account for the terminating nulls correctly? === {{{ //BldFullPathName returns the fullpath of a file or Nullstr CHAR *FullPathName = BldFullPathName(CHAR *pathname, CHAR *filename) { CHAR newname[CCHMAXPATH] = Nullstr; INT c = 0; c = strlen(pathname); if (c > 0) { memcpy(newname, pathname, c + 1); if (newname[c] != '\\') newname[c++] = '\\'; } strcpy(newname + c, filename); return newname; } //BldQuotedFullPathName returns the quoted fullpath of a file or "" CHAR *FullPathName = BldQuotedFullPathName(CHAR *pathname, CHAR *filename) { CHAR newname[CCHMAXPATH] = '\"'; INT c = 0; c = strlen(pathname); if (c > 0) { memcpy(newname + 1, pathname, c + 2); if (newname[c + 1] != '\\') newname[c + 2] = '\\'; strcpy(newname + c + 3, filename); } else strcpy(newname + 1, filename) strcat(newname, '\"') return newname; } }}} Not quite. The caller must pass a pointer to the buffer. Keep in mind that local variable disappear when the function returns. {{{ PSZ BldFullPathName(PSZ fullPathName, PSZ dirname, PSZ filename); }}} {{{ CHAR newname[CCHMAXPATH] = Nullstr; }}} This will give you an error because NullStr is a pointer. {{{ CHAR newname[CCHMAXPATH]; }}} Is sufficent since you are always going to copy something. The return is {{{ return fullPathName }}} with the appropriate name changes. {{{ //BldQuotedFullPathName returns the quoted fullpath of a file or "" CHAR }}} The quotes need to be optional and the return buffer needs to be passed as above. {{{ PSZ BldQuotedFullPathName(PSZ fullPathName, PSZ pathname, PSZ filename) }}} You also need to add the calls to needs_quotes() a stuff the quotes only if needed. This is what the existing inline code does. === What is the purpose of quoting functions? === Its purpose is to replace repeated occurances of code of the form {{{ sprintf(cl, "%s %s%s%s", dcd->info->delete, (needs_quoting(dcd->arcname)) ? "\"" : NullStr, dcd->arcname, (needs_quoting(dcd->arcname)) ? "\"" : NullStr); }}} and possibly {{{ runemf2(SEPARATEKEEP | WINDOWED | MAXIMIZED, hwnd, NULL, NULL, "%s %s%s%s", ad->info->test, needs_quoting(ad->arcname) ? "\"" : NullStr, ad->arcname, needs_quoting(ad->arcname) ? "\"" : NullStr); }}} === Where is the best place to do a check for? === Since the check always needs to be done, it's generally better to do it in the function. ---- == Error Messages == #error messages === The source fails to build displaying the following error message === wcc386 -bt=os2 -mf -bd -bm -d1 -olirs -s -sg -j -wx -zfp -zgp -zq -hd arccnrs.c F:\OS2TK45\h\libc\stdarg.h(83): Warning! W138: No newline at end of file F:\OS2TK45\h\libc\stdlib.h(544): Warning! W138: No newline at end of file F:\OS2TK45\h\libc\string.h(378): Warning! W138: No newline at end of file F:\OS2TK45\h\libc\time.h(136): Warning! W138: No newline at end of file F:\OS2TK45\h\libc\direct.h(92): Warning! W138: No newline at end of file F:\OS2TK45\h\libc\share.h(49): Warning! W138: No newline at end of file F:\OS2TK45\h\libc\process.h(215): Warning! W138: No newline at end of file arccnrs.c(183): Error! E1071: Type of parameter 3 does not agree with previous definition arccnrs.c(183): Note! N2003: source conversion type is 'void *(*)(unsigned long __p1,unsigned long __p2,void *__p3,void *__p4)' arccnrs.c(183): Note! N2004: target conversion type is 'void *(_Syscall *)(unsigned long __p1,unsigned long __p2,void *__p3,void *__p4)' arccnrs.c(610): Error! E1011: Symbol 'SH_DENYWR' has not been declared arccnrs.c(610): Warning! W102: Type mismatch (warning) Since FM/2 now uses the OpenWatcom Warp Toolkit, I had to modify my config.sys statement moving the OpenWatcom entries ahead of the IBM Toolkit entries. ----