exeflat: add support for response file to exeflat utility

the command line can overflow DOS max length that it fixes this issue
This commit is contained in:
Jiri Malak 2024-07-14 17:59:18 +02:00 committed by Kenneth J Davis
parent 2fb0956513
commit a5b516dd7b
3 changed files with 222 additions and 147 deletions

View File

@ -74,6 +74,7 @@ git clean -x -d -f -e test -e _output -e _downloads -e _watcom
echo set XCPU=386 echo set XCPU=386
echo set XFAT=32 echo set XFAT=32
echo set XNASM='C:\\devel\\nasm\\nasm' echo set XNASM='C:\\devel\\nasm\\nasm'
echo set XUPX=upx --8086 --best
echo set OLDPATH=%PATH% echo set OLDPATH=%PATH%
echo set PATH='%WATCOM%\\binw;C:\\bin;%OLDPATH%' echo set PATH='%WATCOM%\\binw;C:\\bin;%OLDPATH%'
} | unix2dos > config.bat } | unix2dos > config.bat

View File

@ -36,8 +36,8 @@ production: ../bin/$(TARGET).sys
# -S to avoid showing expected relocations # -S to avoid showing expected relocations
# 0x10 & 0x78 or 0x79 depending on compilation options # 0x10 & 0x78 or 0x79 depending on compilation options
kernel.sys: kernel.exe ../utils/exeflat.exe ../utils/upxentry.bin ../utils/upxdevic.bin kernel.sys: kernel.exe ../utils/exeflat.exe ../utils/upxentry.bin ../utils/upxdevic.bin exeflat.rsp
..$(DIRSEP)utils$(DIRSEP)exeflat.exe kernel.exe kernel.sys $(LOADSEG) -S0x10 -S0x78 -S0x79 -E..$(DIRSEP)utils$(DIRSEP)upxentry.bin -D..$(DIRSEP)utils$(DIRSEP)upxdevic.bin $(UPXOPT) $(XUPX) ..$(DIRSEP)utils$(DIRSEP)exeflat.exe kernel.exe kernel.sys $(LOADSEG) @exeflat.rsp
kernel.exe: $(TARGET).lnk $(OBJS) $(LIBS) kernel.exe: $(TARGET).lnk $(OBJS) $(LIBS)
$(LINK) @$(TARGET).lnk; $(LINK) @$(TARGET).lnk;
@ -46,11 +46,21 @@ clobber: clean
-$(RM) kernel.exe kernel.sys status.me -$(RM) kernel.exe kernel.sys status.me
clean: clean:
-$(RM) *.obj *.bak *.crf *.xrf *.map *.lst *.cod *.err *.lnk -$(RM) *.obj *.bak *.crf *.xrf *.map *.lst *.cod *.err *.lnk *.rsp
# XXX: This is a very ugly way of linking the kernel, forced upon us by the # XXX: This is a very ugly way of linking the kernel, forced upon us by the
# inability of Turbo `make' 2.0 to perform command line redirection. -- ror4 # inability of Turbo `make' 2.0 to perform command line redirection. -- ror4
exeflat.rsp: makefile
-$(RM) exeflat.rsp
$(ECHOTO) exeflat.rsp -S0x10
$(ECHOTO) exeflat.rsp -S0x78
$(ECHOTO) exeflat.rsp -S0x79
$(ECHOTO) exeflat.rsp -E..$(DIRSEP)utils$(DIRSEP)upxentry.bin
$(ECHOTO) exeflat.rsp -D..$(DIRSEP)utils$(DIRSEP)upxdevic.bin
$(ECHOTO) exeflat.rsp $(UPXOPT)
$(ECHOTO) exeflat.rsp $(XUPX)
$(TARGET).lnk: turboc.cfg makefile ../mkfiles/generic.mak ../mkfiles/$(COMPILER).mak $(TARGET).lnk: turboc.cfg makefile ../mkfiles/generic.mak ../mkfiles/$(COMPILER).mak
-$(RM) *.lnk -$(RM) *.lnk
$(ECHOTO) $(TARGET).lnk $(OBJS1)+ $(ECHOTO) $(TARGET).lnk $(OBJS1)+

View File

@ -90,7 +90,7 @@ static void usage(void)
static int exeflat(const char *srcfile, const char *dstfile, static int exeflat(const char *srcfile, const char *dstfile,
const char *start, short *silentSegments, short silentcount, const char *start, short *silentSegments, short silentcount,
int UPX, UWORD stubexesize, UWORD stubdevsize, int use_upx, UWORD stubexesize, UWORD stubdevsize,
UWORD entryparagraphs, exe_header *header) UWORD entryparagraphs, exe_header *header)
{ {
int i, j; int i, j;
@ -207,7 +207,7 @@ static int exeflat(const char *srcfile, const char *dstfile,
printf("\nProcessed %d relocations, %d not shown\n", printf("\nProcessed %d relocations, %d not shown\n",
header->exRelocItems, silentdone); header->exRelocItems, silentdone);
if (UPX) if (use_upx)
{ {
struct x { struct x {
char y[(KERNEL_CONFIG_LENGTH + 2) <= BUFSIZE ? 1 : -1]; char y[(KERNEL_CONFIG_LENGTH + 2) <= BUFSIZE ? 1 : -1];
@ -224,7 +224,7 @@ static int exeflat(const char *srcfile, const char *dstfile,
/* The biggest .sys file that UPX accepts seems to be 65419 bytes long. /* The biggest .sys file that UPX accepts seems to be 65419 bytes long.
Actually, UPX 3.96 appears to accept DOS/SYS files up to 65426 bytes. Actually, UPX 3.96 appears to accept DOS/SYS files up to 65426 bytes.
To avoid problems we use a slightly lower limit. */ To avoid problems we use a slightly lower limit. */
if (UPX) { if (use_upx) {
if (stubdevsize && stubexesize) if (stubdevsize && stubexesize)
compress_sys_file = (size - stubdevsize) <= /* 65426 */ 65400; compress_sys_file = (size - stubdevsize) <= /* 65426 */ 65400;
/* would need to subtract 0x10 for the device header here /* would need to subtract 0x10 for the device header here
@ -407,13 +407,59 @@ static void write_header(FILE *dest, unsigned char * code, UWORD stubsize,
} }
} }
int my_isspace( int c )
{
switch( c ) {
case ' ':
case '\n':
case '\r':
case '\f':
case '\t':
case '\v':
return( 1 );
default:
return( 0 );
}
}
char *getarg( FILE *fp )
{
static char buff[256];
char *str;
size_t len;
while( (str = fgets( buff, sizeof(buff) - 1, fp )) != NULL ) {
buff[sizeof(buff) - 1] = '\0';
len = strlen(buff);
while( len > 0 ) {
len--;
if( my_isspace( buff[len] ) ) {
buff[len] = '\0';
continue;
}
len++;
break;
}
while( len-- > 0 ) {
if( !my_isspace(*str) ) {
break;
}
}
if( *str != '\0' ) {
break;
}
}
return( str );
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
short silentSegments[20], silentcount = 0; short silentSegments[20], silentcount = 0;
static exe_header header; /* must be initialized to zero */ static exe_header header; /* must be initialized to zero */
int UPX = FALSE; int use_upx = 0;
char *upx_cmd;
int i; int i;
size_t sz, len, len2, n; size_t len;
int compress_sys_file; int compress_sys_file;
char *buffer, *tmpexe, *cmdbuf, *entryexefilename = "", *entrydevfilename = ""; char *buffer, *tmpexe, *cmdbuf, *entryexefilename = "", *entrydevfilename = "";
FILE *dest, *source; FILE *dest, *source;
@ -423,48 +469,81 @@ int main(int argc, char **argv)
FILE * entryf = NULL; FILE * entryf = NULL;
UWORD end; UWORD end;
UWORD stubexesize = 0, stubdevsize = 0; UWORD stubexesize = 0, stubdevsize = 0;
FILE *indir = NULL;
/* if no arguments provided, show usage and exit */ /* if no arguments provided, show usage and exit */
if (argc < 4) usage(); if (argc < 4) usage();
upx_cmd = malloc(1);
*upx_cmd = '\0';
i = 4;
/* do optional argument processing here */ /* do optional argument processing here */
for (i = 4; i < argc && !UPX; i++) while ( i < argc || indir != NULL )
{ {
char *argptr = argv[i]; char *argptr = NULL;
if (argptr[0] != '-' && argptr[0] != '/') if( indir != NULL ) {
usage(); argptr = getarg( indir );
if(argptr == NULL) {
argptr++; fclose( indir );
indir = NULL;
switch (toupper(argptr[0])) continue;
{ }
case 'U': }
UPX = i; if( argptr == NULL ) {
break; argptr = argv[i++];
case 'E': }
entryexefilename = &argptr[1]; if( use_upx ) {
break; len = strlen( upx_cmd );
case 'D': if( len > 0 ) len++;
entrydevfilename = &argptr[1]; upx_cmd = realloc( upx_cmd, len + strlen( argptr ) + 1 );
break; if( len > 0 ) upx_cmd[len - 1] = ' ';
case 'S': strcpy( upx_cmd + len, argptr );
if (silentcount >= LENGTH(silentSegments)) } else {
{ switch (*(unsigned char *)argptr++)
printf("can't handle more then %d silent's\n", {
(int)LENGTH(silentSegments)); case '@':
exit(1); indir = fopen( argptr, "r" );
} if( indir == NULL ) {
printf("can't open indirect file '%s'\n", argptr);
silentSegments[silentcount++] = (short)strtol(argptr + 1, NULL, 0); exit(1);
break; }
break;
default: case '-':
usage(); case '/':
switch (toupper(*(unsigned char *)argptr++))
{
case 'U':
use_upx = 1;
break;
case 'E':
entryexefilename = malloc(strlen(argptr) + 1);
strcpy(entryexefilename, argptr);
break;
case 'D':
entrydevfilename = malloc(strlen(argptr) + 1);
strcpy(entrydevfilename, argptr);
break;
case 'S':
if (silentcount >= LENGTH(silentSegments))
{
printf("can't handle more then %d silent's\n",
(int)LENGTH(silentSegments));
exit(1);
}
silentSegments[silentcount++] = (short)strtol(argptr, NULL, 0);
break;
default:
usage();
}
break;
default:
usage();
}
} }
} }
if (UPX) { if (use_upx) {
if (*entryexefilename) { if (*entryexefilename) {
entryf = fopen(entryexefilename, "rb"); entryf = fopen(entryexefilename, "rb");
if (!entryf) { if (!entryf) {
@ -510,115 +589,100 @@ int main(int argc, char **argv)
compress_sys_file = exeflat(argv[1], argv[2], argv[3], compress_sys_file = exeflat(argv[1], argv[2], argv[3],
silentSegments, silentcount, silentSegments, silentcount,
UPX, stubexesize, stubdevsize, 0, &header); use_upx, stubexesize, stubdevsize, 0, &header);
if (!UPX) if (use_upx)
exit(0);
/* move kernel.sys tmp.exe */
if (!compress_sys_file)
{ {
tmpexe = "tmp.exe"; /* move kernel.sys tmp.exe */
} else { if (!compress_sys_file)
tmpexe = "tmp.sys"; {
} tmpexe = "tmp.exe";
if (rename(argv[2], tmpexe)) } else {
{ tmpexe = "tmp.sys";
printf("Can not rename %s to %s\n", argv[2], tmpexe);
exit(1);
}
len2 = strlen(tmpexe) + 1;
sz = len2;
if (sz < 256) sz = 256;
cmdbuf = malloc(sz);
len = 0;
for (i = UPX+1; i < argc; i++)
{
n = strlen(argv[i]);
if (len + len2 + n + 2 >= sz) {
sz *= 2;
cmdbuf = realloc(cmdbuf, sz);
} }
if (i > UPX+1) if (rename(argv[2], tmpexe))
cmdbuf[len++] = ' '; {
memcpy(cmdbuf + len, argv[i], n + 1); printf("Can not rename %s to %s\n", argv[2], tmpexe);
len += n; exit(1);
} }
cmdbuf[len++] = ' ';
/* if tmpexe is tmpfile set above no quotes needed, if user needs quotes should add on cmd line */ len = strlen(upx_cmd);
memcpy(cmdbuf + len, tmpexe, len2); cmdbuf = malloc(len + 1 + strlen(tmpexe) + 1);
cmdbuf[len + len2] = '\0'; strcpy(cmdbuf, upx_cmd);
printf("%s\n", cmdbuf); cmdbuf[len] = ' ';
fflush(stdout); /* if tmpexe is tmpfile set above no quotes needed, if user needs quotes should add on cmd line */
if (system(cmdbuf)) strcpy(cmdbuf + len + 1, tmpexe);
{ printf("%s\n", cmdbuf);
printf("Problems executing %s\n", cmdbuf); fflush(stdout);
printf("Removing [%s]\n", tmpexe); if (system(cmdbuf))
{
printf("Problems executing %s\n", cmdbuf);
printf("Removing [%s]\n", tmpexe);
remove(tmpexe);
exit(1);
}
free(cmdbuf);
if (!compress_sys_file)
{
exeflat(tmpexe, "tmp.bin", argv[3],
silentSegments, silentcount,
FALSE, stubexesize, 0, stubexesize >> 4, &header);
} else {
UBYTE deviceheader[16];
FILE * devfile = fopen("tmp.sys", "rb");
if (!devfile) {
printf("Source file %s could not be opened\n", "tmp.sys");
exit(1);
}
if (fread(deviceheader, 1, sizeof deviceheader, devfile)
!= sizeof deviceheader) {
printf("Source file %s could not be read\n", "tmp.sys");
exit(1);
}
fclose(devfile);
header.exInitIP = deviceheader[6] + deviceheader[7] * 256U;
header.exInitCS = 0;
rename("tmp.sys", "tmp.bin");
}
/* tmp.bin now contains the final flattened file: just
the UPX entry header needs to be added. */
/* the compressed file may exceed 64 KiB for DOS/EXE format. */
if ((dest = fopen(argv[2], "wb")) == NULL)
{
printf("Destination file %s could not be opened\n", argv[2]);
exit(1);
}
if ((source = fopen("tmp.bin", "rb")) == NULL)
{
printf("Source file %s could not be opened\n", "tmp.bin");
exit(1);
}
buffer = malloc(32 * 1024);
if (!buffer)
{
printf("Memory allocation failure\n");
exit(1);
}
write_header(dest,
compress_sys_file ? devcode : execode,
compress_sys_file ? stubdevsize : stubexesize,
argv[3], compress_sys_file, &header);
do {
size = fread(buffer, 1, 32 * 1024, source);
if (fwrite(buffer, 1, size, dest) != size) {
printf("Write failure\n");
exit(1);
}
} while (size);
fclose(source);
remove("tmp.bin");
remove(tmpexe); remove(tmpexe);
exit(1);
} }
free(cmdbuf);
if (!compress_sys_file)
{
exeflat(tmpexe, "tmp.bin", argv[3],
silentSegments, silentcount,
FALSE, stubexesize, 0, stubexesize >> 4, &header);
} else {
UBYTE deviceheader[16];
FILE * devfile = fopen("tmp.sys", "rb");
if (!devfile) {
printf("Source file %s could not be opened\n", "tmp.sys");
exit(1);
}
if (fread(deviceheader, 1, sizeof deviceheader, devfile)
!= sizeof deviceheader) {
printf("Source file %s could not be read\n", "tmp.sys");
exit(1);
}
fclose(devfile);
header.exInitIP = deviceheader[6] + deviceheader[7] * 256U;
header.exInitCS = 0;
rename("tmp.sys", "tmp.bin");
}
/* tmp.bin now contains the final flattened file: just
the UPX entry header needs to be added. */
/* the compressed file may exceed 64 KiB for DOS/EXE format. */
if ((dest = fopen(argv[2], "wb")) == NULL)
{
printf("Destination file %s could not be opened\n", argv[2]);
exit(1);
}
if ((source = fopen("tmp.bin", "rb")) == NULL)
{
printf("Source file %s could not be opened\n", "tmp.bin");
exit(1);
}
buffer = malloc(32 * 1024);
if (!buffer)
{
printf("Memory allocation failure\n");
exit(1);
}
write_header(dest,
compress_sys_file ? devcode : execode,
compress_sys_file ? stubdevsize : stubexesize,
argv[3], compress_sys_file, &header);
do {
size = fread(buffer, 1, 32 * 1024, source);
if (fwrite(buffer, 1, size, dest) != size) {
printf("Write failure\n");
exit(1);
}
} while (size);
fclose(source);
remove("tmp.bin");
remove(tmpexe);
return 0; return 0;
} }