Reorganize exeflat.c, part 1, no functional changes.

git-svn-id: https://svn.code.sf.net/p/freedos/svn/kernel/trunk@1351 6ac86273-5f31-0410-b378-82cca8765d1b
This commit is contained in:
Bart Oldeman 2007-08-29 06:34:54 +00:00
parent 266398c247
commit d6232e9cd5

View File

@ -59,7 +59,7 @@ typedef struct {
UWORD off, seg; UWORD off, seg;
} farptr; } farptr;
int compReloc(const void *p1, const void *p2) static int compReloc(const void *p1, const void *p2)
{ {
farptr *r1 = (farptr *) p1; farptr *r1 = (farptr *) p1;
farptr *r2 = (farptr *) p2; farptr *r2 = (farptr *) p2;
@ -74,7 +74,7 @@ int compReloc(const void *p1, const void *p2)
return 0; return 0;
} }
void usage(void) static void usage(void)
{ {
printf("usage: exeflat (src.exe) (dest.sys) (relocation-factor)\n"); printf("usage: exeflat (src.exe) (dest.sys) (relocation-factor)\n");
printf printf
@ -83,7 +83,13 @@ void usage(void)
exit(1); exit(1);
} }
int main(int argc, char **argv) static void write_header(FILE *dest, size_t size);
static void write_trailer(FILE *dest, size_t size, int compress_sys_file,
exe_header *header);
static int exeflat(int UPX, const char *srcfile, const char *dstfile,
const char *start, short *silentSegments, short silentcount,
int flat_exe)
{ {
static exe_header header; /* must be initialized to zero */ static exe_header header; /* must be initialized to zero */
int i, j; int i, j;
@ -94,57 +100,17 @@ int main(int argc, char **argv)
UBYTE **buffers; UBYTE **buffers;
UBYTE **curbuf; UBYTE **curbuf;
FILE *src, *dest; FILE *src, *dest;
short silentSegments[20], silentcount = 0, silentdone = 0; short silentdone = 0;
int UPX = FALSE, flat_exe = FALSE, compress_sys_file = FALSE; int compress_sys_file = FALSE;
/* if no arguments provided, show usage and exit */ if ((src = fopen(srcfile, "rb")) == NULL)
if (argc < 4) usage();
/* do optional argument processing here */
for (i = 4; i < argc; i++)
{ {
char *argptr = argv[i]; if (UPX && strlen(srcfile) > 3)
if (argptr[0] != '-' && argptr[0] != '/')
usage();
argptr++;
switch (toupper(argptr[0]))
{ {
case 'U': strcpy((char *)srcfile + strlen(srcfile) - 3, "sys");
UPX = TRUE; if ((src = fopen(srcfile, "rb")) == NULL)
break;
case 'E':
flat_exe = TRUE;
break;
case 'S':
if (silentcount >= LENGTH(silentSegments))
{ {
printf("can't handle more then %d silent's\n", printf("Source file %s could not be opened\n", srcfile);
LENGTH(silentSegments));
exit(1);
}
silentSegments[silentcount++] = (short)strtol(argptr + 1, NULL, 0);
break;
default:
usage();
}
}
/* arguments left :
infile outfile relocation offset */
if ((src = fopen(argv[1], "rb")) == NULL)
{
if (UPX && strlen(argv[1]) > 3)
{
strcpy(argv[1] + strlen(argv[1]) - 3, "sys");
if ((src = fopen(argv[1], "rb")) == NULL)
{
printf("Source file %s could not be opened\n", argv[1]);
return 1; return 1;
} }
compress_sys_file = TRUE; compress_sys_file = TRUE;
@ -156,17 +122,17 @@ int main(int argc, char **argv)
} else { } else {
if (fread(&header, sizeof(header), 1, src) != 1) if (fread(&header, sizeof(header), 1, src) != 1)
{ {
printf("Error reading header from %s\n", argv[1]); printf("Error reading header from %s\n", srcfile);
fclose(src); fclose(src);
return 1; return 1;
} }
if (header.exSignature != MAGIC) if (header.exSignature != MAGIC)
{ {
printf("Source file %s is not a valid .EXE\n", argv[1]); printf("Source file %s is not a valid .EXE\n", srcfile);
fclose(src); fclose(src);
return 1; return 1;
} }
start_seg = (UWORD)strtol(argv[3], NULL, 0); start_seg = (UWORD)strtol(start, NULL, 0);
if (header.exExtraBytes == 0) if (header.exExtraBytes == 0)
header.exExtraBytes = 0x200; header.exExtraBytes = 0x200;
printf("header len = %lu = 0x%lx\n", header.exHeaderSize * 16UL, printf("header len = %lu = 0x%lx\n", header.exHeaderSize * 16UL,
@ -250,48 +216,18 @@ int main(int argc, char **argv)
if (flat_exe) { if (flat_exe) {
/* 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 */
compress_sys_file = size < 65420; compress_sys_file = size < 65420;
if (compress_sys_file && strlen(argv[2]) > 3) if (compress_sys_file && strlen(dstfile) > 3)
strcpy(argv[2] + strlen(argv[2]) - 3, "sys"); strcpy((char *)dstfile + strlen(dstfile) - 3, "sys");
} }
if ((dest = fopen(argv[2], "wb+")) == NULL) if ((dest = fopen(dstfile, "wb+")) == NULL)
{ {
printf("Destination file %s could not be created\n", argv[2]); printf("Destination file %s could not be created\n", dstfile);
return 1; return 1;
} }
if (UPX) if (UPX)
{ {
/* UPX HEADER jump $+2+size */ write_header(dest, (size_t)size);
static char JumpBehindCode[] = {
/* kernel config header - 32 bytes */
0xeb, 0x1b, /* jmp short realentry */
'C', 'O', 'N', 'F', 'I', 'G', 32 - 2 - 6 - 2 - 3, 0, /* WORD */
0, /* DLASortByDriveNo db 0 */
1, /* InitDiskShowDriveAssignment db 1 */
2, /* SkipConfigSeconds db 2 */
0, /* ForceLBA db 0 */
1, /* GlobalEnableLBAsupport db 1 */
0, /* BootHarddiskSeconds */
'n', 'u', 's', 'e', 'd', /* unused filler bytes */
8, 7, 6, 5, 4, 3, 2, 1,
/* real-entry: jump over the 'real' image do the trailer */
0xe9, 0, 0 /* 100: jmp 103 */
};
struct x {
char y[sizeof(JumpBehindCode) == 0x20 ? 1 : -1];
};
if (size >= 0xfe00u)
{
printf("kernel; size too large - must be <= 0xfe00\n");
exit(1);
}
/* this assumes <= 0xfe00 code in kernel */
*(short *)&JumpBehindCode[0x1e] += (short)size;
fwrite(JumpBehindCode, 1, 0x20, dest);
} }
if (flat_exe && !compress_sys_file) { if (flat_exe && !compress_sys_file) {
@ -327,9 +263,66 @@ int main(int argc, char **argv)
} }
if (UPX) if (UPX)
{
write_trailer(dest, (size_t)size, compress_sys_file, &header);
}
if (flat_exe && compress_sys_file) {
/* overwrite first 8 bytes with SYS header */
UWORD dhdr[4];
fseek(dest, 0, SEEK_SET);
for (i = 0; i < 3; i++)
dhdr[i] = 0xffff;
/* strategy will jump to us, interrupt never called */
dhdr[3] = KERNEL_START;
fwrite(dhdr, sizeof(dhdr), 1, dest);
}
fclose(dest);
printf("\nProcessed %d relocations, %d not shown\n",
header.exRelocItems, silentdone);
return 0;
}
static void write_header(FILE *dest, size_t size)
{
/* UPX HEADER jump $+2+size */
static char JumpBehindCode[] = {
/* kernel config header - 32 bytes */
0xeb, 0x1b, /* jmp short realentry */
'C', 'O', 'N', 'F', 'I', 'G', 32 - 2 - 6 - 2 - 3, 0, /* WORD */
0, /* DLASortByDriveNo db 0 */
1, /* InitDiskShowDriveAssignment db 1 */
2, /* SkipConfigSeconds db 2 */
0, /* ForceLBA db 0 */
1, /* GlobalEnableLBAsupport db 1 */
0, /* BootHarddiskSeconds */
'n', 'u', 's', 'e', 'd', /* unused filler bytes */
8, 7, 6, 5, 4, 3, 2, 1,
/* real-entry: jump over the 'real' image do the trailer */
0xe9, 0, 0 /* 100: jmp 103 */
};
struct x {
char y[sizeof(JumpBehindCode) == 0x20 ? 1 : -1];
};
if (size >= 0xfe00u)
{
printf("kernel; size too large - must be <= 0xfe00\n");
exit(1);
}
/* this assumes <= 0xfe00 code in kernel */
*(short *)&JumpBehindCode[0x1e] += (short)size;
fwrite(JumpBehindCode, 1, 0x20, dest);
}
static void write_trailer(FILE *dest, size_t size, int compress_sys_file,
exe_header *header)
{ {
/* UPX trailer */ /* UPX trailer */
/* hand assembled - so this remains ANSI C ;-) */ /* hand assembled - so this remains ANSI C ;-) */
/* well almost: we still need packing and assume little endian ... */
/* move kernel down to place CONFIG-block, which added above, /* move kernel down to place CONFIG-block, which added above,
at start_seg-2:0 (e.g. 0x5e:0) instead of at start_seg-2:0 (e.g. 0x5e:0) instead of
start_seg:0 (e.g. 0x60:0) and store there boot drive number start_seg:0 (e.g. 0x60:0) and store there boot drive number
@ -359,8 +352,8 @@ int main(int argc, char **argv)
}; };
*(short *)&trailer[1] = (short)size + 0x20; *(short *)&trailer[1] = (short)size + 0x20;
*(short *)&trailer[23] = header.exInitSS; *(short *)&trailer[23] = header->exInitSS;
*(short *)&trailer[28] = header.exInitSP; *(short *)&trailer[28] = header->exInitSP;
if (compress_sys_file) { if (compress_sys_file) {
/* replace by jmp word ptr [6]: ff 26 06 00 /* replace by jmp word ptr [6]: ff 26 06 00
(the .SYS strategy handler which will unpack) */ (the .SYS strategy handler which will unpack) */
@ -371,18 +364,53 @@ int main(int argc, char **argv)
} }
fwrite(trailer, 1, sizeof trailer, dest); fwrite(trailer, 1, sizeof trailer, dest);
} }
if (flat_exe && compress_sys_file) {
/* overwrite first 8 bytes with SYS header */ int main(int argc, char **argv)
UWORD dhdr[4]; {
fseek(dest, 0, SEEK_SET); short silentSegments[20], silentcount = 0;
for (i = 0; i < 3; i++) int UPX = FALSE, flat_exe = FALSE;
dhdr[i] = 0xffff; int i;
/* strategy will jump to us, interrupt never called */
dhdr[3] = KERNEL_START; /* if no arguments provided, show usage and exit */
fwrite(dhdr, sizeof(dhdr), 1, dest); if (argc < 4) usage();
/* do optional argument processing here */
for (i = 4; i < argc; i++)
{
char *argptr = argv[i];
if (argptr[0] != '-' && argptr[0] != '/')
usage();
argptr++;
switch (toupper(argptr[0]))
{
case 'U':
UPX = TRUE;
break;
case 'E':
flat_exe = TRUE;
break;
case 'S':
if (silentcount >= LENGTH(silentSegments))
{
printf("can't handle more then %d silent's\n",
LENGTH(silentSegments));
exit(1);
} }
fclose(dest);
printf("\nProcessed %d relocations, %d not shown\n", silentSegments[silentcount++] = (short)strtol(argptr + 1, NULL, 0);
header.exRelocItems, silentdone); break;
return 0;
default:
usage();
}
}
/* arguments left :
infile outfile relocation offset */
return exeflat(UPX, argv[1], argv[2], argv[3], silentSegments, silentcount,
flat_exe);
} }