INF: How to Remove CodeView Symbolic Data from an .EXE or DLL

ID Number: Q74951

2.x 3.00 3.10 3.11 3.14 | 2.x 3.00 3.11 3.12 3.50

MS-DOS | OS/2

Summary:

The standard method for removing CodeView symbolic debugging

information from an .EXE or dynamic-link library (DLL) file is to

relink the .OBJ files without specifying the /CO (CODEVIEW) option,

but in some cases it may be desirable to remove the CodeView data

without relinking.

As demonstrated below, this can be done by writing a small program to

"strip off" the CodeView debug information, since this information is

appended to the end of a file and does not interfere in any way with

the preceding .EXE or DLL file contents.

More Information:

Any file that contains CodeView information can be identified by a

special signature and a file offset in the last 8 bytes of the file.

The signature is the first 4 of these 8 bytes and consists of "NB"

followed by a 2-digit ASCII number corresponding to the .EXE format

produced by the version of the LINK that was used.

The next 4 bytes after the signature contain a long value representing

the negative offset from the end of the file where the CodeView

symbols actually start. The signature at the end of the file is also

repeated at the beginning of the appended CodeView data in order to

provide verification that the file does indeed contain CodeView

symbolic information.

The sample program below removes CodeView symbolic data from an .EXE

by executing the following steps. If any step is unsuccessful, the

program errs out with an appropriate message.

1. Check for the CodeView signature 8 bytes from the end of the file.

2. Extract the offset value for the symbolic information from the last

4 bytes of the file and compute the offset of the symbolic data.

3. Move to that file location and check for a matching CodeView

signature.

4. Truncate the file at that point.

For further information on the format and signatures used for CodeView

debugging information, see Section 3.3 on page 44 of the "Microsoft C

Developer's Toolkit Reference," which is included in the Microsoft

Developer's Toolkit (product number 048-044-060).

Sample Code

-----------

/* Compile options needed: none

*/

#include <stdio.h>

#include <io.h>

#include <errno.h>

#include <string.h>

int main(int argc, char *argv[])

{

FILE *fptr;

unsigned long cvsize = 0L, filesize;

int fhandle;

char cv_sig1[5], cv_sig2[5];

/* get filename argument from command line and open it */

if ( argc < 2 ) {

printf("\nUsage: %s <filename>\n\n", argv[0]);

return 1;

}

if ( (fptr = fopen(argv[1], "rb+")) == NULL ) {

printf("\nUnable to open file: %s\n\n", argv[1]);

return 1;

}

/* get handle to the file and determine file size */

fhandle = fileno(fptr);

filesize = filelength(fhandle);

/* go to the last 8 bytes in the file and read the signature */

fseek(fptr, (long)(filesize - 8), SEEK_SET);

fread(cv_sig1, sizeof(char), 4, fptr);

cv_sig1[4] = '\0';

/* verify that the signature is valid */

if ( !(cv_sig1[0] == 'N' && cv_sig1[1] == 'B') ) {

printf("\n%s contains no CodeView symbols\n\n", argv[1]);

return 1;

}

/* read the symbol table offset */

fread(&cvsize, sizeof(long), 1, fptr);

/* go to the start of the symbol table and read the signature */

fseek(fptr, (long)(filesize - cvsize), SEEK_SET);

fread(cv_sig2, sizeof(char), 4, fptr);

cv_sig2[4] = '\0';

/* compare the two signatures */

if ( strcmp(cv_sig1, cv_sig2) != 0 ) {

printf("\nSignature Cross Match Failed on %s!\n\n", argv[1]);

return 1;

}

/* truncate the file, since all tests have been successful */

chsize(fhandle, (long)(filesize - cvsize));

fclose(fptr);

printf("\nCodeView Information Successfully Stripped from %s!\n\n",

argv[1]);

return 0;

}

Additional reference words: 2.0 2.00 2.1 2.10 2.2 2.20 2.3 2.30 2.35

3.0 3.00 3.1 3.10 3.11 3.12 3.14 3.5 3.50