From d1faeee7710783c8342d8da527e2160d29e7060e Mon Sep 17 00:00:00 2001 From: gdr Date: Sun, 28 Sep 1997 16:41:13 +0000 Subject: [PATCH] Changes for v1.1-release - increased optimization level to -1 - added -d option - changed output format --- usr.bin/lseg/Makefile | 11 ++- usr.bin/lseg/lseg.1 | 73 ++++++++++++++++--- usr.bin/lseg/lseg.c | 165 ++++++++++++++++++++++++++---------------- usr.bin/lseg/lseg.rez | 6 +- 4 files changed, 172 insertions(+), 83 deletions(-) diff --git a/usr.bin/lseg/Makefile b/usr.bin/lseg/Makefile index 85090fa..a47ba7d 100644 --- a/usr.bin/lseg/Makefile +++ b/usr.bin/lseg/Makefile @@ -1,18 +1,23 @@ # # This makefile is intended for use with dmake(1) on Apple IIGS # -# $Id: Makefile,v 1.3 1997/09/26 06:36:22 gdr Exp $ +# $Id: Makefile,v 1.4 1997/09/28 16:41:12 gdr Exp $ # +# Created by Dave Tribby, September 1997 # Program name PROG = lseg # Default stack size and optimization (can be overridden by cmd line) +# These values have been tested and certified as working .IF $(STACK) == $(NULL) STACK = 1024 .END - +.IF $(OPTIMIZE) == $(NULL) + OPTIMIZE = -1 +.END + # Delivery directory BINDIR = /usr/bin -.INCLUDE: /src/gno/prog.mk +.INCLUDE : /src/gno/prog.mk diff --git a/usr.bin/lseg/lseg.1 b/usr.bin/lseg/lseg.1 index 8c08d8d..f9a5bc2 100644 --- a/usr.bin/lseg/lseg.1 +++ b/usr.bin/lseg/lseg.1 @@ -1,13 +1,14 @@ -.\" Man page by Dave Tribby, September 1997 .\" -.\" $Id: lseg.1,v 1.2 1997/09/21 22:05:58 gdr Exp $ +.\" $Id: lseg.1,v 1.3 1997/09/28 16:41:12 gdr Exp $ .\" .TH LSEG 1 "September 1997" "GNO" "Commands and Applications" .SH NAME .BR lseg \- list segments in an Object Module Format file .SH SYNOPSIS -.BR lseg " file ..." +.BR lseg +.RB [ -d ] +.IR file " ..." .SH DESCRIPTION .BR lseg lists segments in an OMF (object module format) file. Four kinds @@ -21,29 +22,77 @@ A full description of OMF files is provided in Appendix F of .IR "Apple IIGS GS/OS Reference" . .PP .BR lseg -prints a report that includes the type and size of each segment -of each file. Any file that is not a valid OMF file is so noted. +prints a report that includes the type, size, and name of each segment of each +.IR file . +Any file that is not a valid OMF file is so noted. .PP .BR lseg can be used on executable files in the following ways: to help discover -the location of stack segments (for later editing to smaller sizes), as an +the location of stack segments (for later editing to appropriate sizes), as an aid in determining how to segment large C files whose segments exceed the bank size, and for deciding which segments to recombine after excessive segmentation. .PP -For object and library files, .BR lseg examines each code segment and tries to figure out how many bytes of local storage are allocated from the stack at execution time. This will be determined only if the startup code matches a recognized algorithm, such as those used by ORCA/C. If it can be determined, the -value is printed at the end of the line preceeded by -string "Stack bytes:". -Note that this value does not include parameters passed into the routine, -nor does it include any other use of the stack by the routine. If a -segment has an unusually large stack allocation, examine its source code +value is printed in the column labeled "Stack". +This value does not include parameters passed into the routine, +or other use of the stack by the routine. +.PP +You can combine +.BR lseg +with other tools to ensure your program allocates the correct +amount of run-time stack space: +.RS 1 +.IP +Run +.BR lseg +on your program's object file to identify routines with significant +local storage. If a +segment has an unusually large allocation, examine its source code and see whether arrays can be made static (if the routine is not recursive) or can be allocated from standard memory by .IR malloc (3). +.IP +Add calls to the +.BR stack (3) +routines +.BR _beginStackCheck " and " _endStackCheck +to report overall run-time storage allocation. +.IP +You can also use ORCA/C's +.BR "#pragma debug" +with a parameter that sets bit 0 (a value of 1), which causes the +run-time code to check stack space at the beginning +of each function and halt the program if there is not enough. +.IP +Run +.BR lseg +on your program's linked file to determine if it has a "Direct-page/Stack" +segment. (If not, the system will allocate 4096 bytes of stack when it runs.) +You can set this value with +.BR "#pragma stacksize" +in programs compiled by ORCA/C. +.PP +If your program uses significantly less stack space at run-time than +is specified in the Direct-page/Stack segment, reduce the size so more is +available to other programs that run at the same time. +If your program uses more stack space than allocated, it can cause +serious problems such as system crashes. +.PP +Note: Be sure to remove run-time checking in the final version of you +program after you determine the appropriate stack size. +.PP +.BR lseg +returns status of 0 on success, and >0 if an error (e.g., file +not found) occurs. +.SH OPTIONS +.BR lseg +recognizes one option: +.IP \fB-d\fR +Print the segment and stack sizes in decimal rather than hexidecimal. .SH AUTHOR Jawaid Bazyar for GNO/ME 1.0; updated by Dave Tribby for GNO/ME 2.0.6. diff --git a/usr.bin/lseg/lseg.c b/usr.bin/lseg/lseg.c index bf2b7e5..a0e2f4d 100644 --- a/usr.bin/lseg/lseg.c +++ b/usr.bin/lseg/lseg.c @@ -6,17 +6,18 @@ * Version 1.1 [v1.1] updated by Dave Tribby (Sept. 1997) * - A few changes for GNO/ME 2.0.6 * - Added display of allocated stack bytes for code segments - * - Reformatted output to align names and make room for new info + * - Reformatted output to use a table format and make room for new info * - Sanity check to see whether file is an OMF file * - Use first field as block count for OMF version 1 files - * - Continue processing files even if one cannot be opened + * - Continue processing files even if one of them cannot be opened * - Use standard error reporting interfaces + * - Print values in hex unless -d (decimal) flag is set * - * $Id: lseg.c,v 1.2 1997/09/21 22:05:59 gdr Exp $ + * $Id: lseg.c,v 1.3 1997/09/28 16:41:13 gdr Exp $ */ /* Update for 2.0.6: Move optimization and stack size to Makefile -/* #pragma optimize -1 /* Doesn't work for ORCA/C 2.1 */ +/* #pragma optimize -1 /* #pragma stacksize 1024 */ @@ -29,6 +30,10 @@ #include /* GNO 2.0.6: read() and close() moved to here */ #include /* GNO 2.0.6: use standard error reporting */ +/* [v1.1] Use library routine rather than macro, so that program */ +/* code is less complicated and can be optimized by ORCA/C */ +#undef putchar + typedef struct OMFhead { longword BYTECNT; longword RESSPC; @@ -51,29 +56,32 @@ typedef struct OMFhead { longword tempOrg; } OMFhead; -char *segTypes[] = { -"Code", -"Data", -"Jump-table", -"Unknown", -"Pathname", -"Unknown", -"Unknown", -"Unknown", +char *segTypes[] = { /* [v1.1] Omit "unknown" for undefined segment types */ +"Code ", +"Data ", +"Jump-table ", +"", +"Pathname ", +"", +"", +"", "Library Dictionary", -"Unknown", -"Unknown", -"Unknown", -"Unknown", -"Unknown", -"Unknown", -"Unknown", -"Initialization", -"Unknown", -"Direct-page/Stack"}; +"", +"", +"", +"", +"", +"", +"", +"Initialization ", +"", +"Direct-page/Stack "}; -/* --- Start of new routines [v1.1] --- */ +/* --- Start of new code [v1.1] --- */ + +/* Option for decimal rather than hex output */ +int decimal_output=FALSE; /* Snippit of code to be analyzed for allocated stack size */ static char code[8]; @@ -160,7 +168,13 @@ void checkCodeStack(int fd) int value; while ( (value = readSegRec(fd)) == 0 ); - if (value > 0) printf(" Stack bytes: %d", value); + if (value > 0) + if (decimal_output) + printf("%6d ", value); + else + printf("0x%04X ", value); + else + printf(" "); } /* Is the file under consideration not an OMF file? */ @@ -179,23 +193,16 @@ int notOMF(OMFhead *headPnt) void prntAscii(char *s, int l) { - /* Pad with blanks if < 18 chars [v1.1] */ - int pad; - - pad = 18 - l; putchar('"'); while (l--) { *s &= 0x7F; if (*s < ' ') { putchar('^'); putchar(*s+'@'); - pad--; } else putchar(*s); s++; } putchar('"'); - while (pad-- > 0) - putchar(' '); } char name[256]; @@ -203,26 +210,24 @@ char name[256]; * The caller is responsible for opening the file, passing its refNum, * and closing it after we're done */ -void scanOMF(int fd) +void scanOMF(int fd, char *fname) { OMFhead header; longword off = 0l; PositionRecGS p; int kind; -int stsize = 0; +int i; p.pCount = 2; p.refNum = fd; GetEOF(&p); while (off < p.position) { - /* printf("offset: %ld\t\t",off); */ - printf(" "); lseek(fd, off, SEEK_SET); read(fd,&header,sizeof(header)); /* First time through, check validity of OMF header [v1.1] */ if (off == 0 && notOMF(&header)) { - printf("Not a recognized OMF file\n"); + printf("Note: %s is not a recognized OMF file\n", fname); return; } lseek(fd, off+header.DISPNAME+10, SEEK_SET); @@ -233,22 +238,39 @@ int stsize = 0; name[0] = header.LABLEN; read(fd, name+1, header.LABLEN); } - prntAscii(name+1,name[0]); + printf("%s",fname); + i = strlen(fname); + while (i++ < 20) putchar(' '); + kind = header.KIND & 0x1F; - if (kind < 0x13) { - printf(" %s segment (%02X) %06lX bytes", - segTypes[kind],kind,header.LENGTH); - /* Check code segment for stack allocation [v1.1] */ - if (kind == 0) { - /* Position to beginning of data */ - lseek(fd, off+header.DISPDATA, SEEK_SET); - /* Check the code */ - checkCodeStack(fd); - } + switch (kind) { + case 0x00: + if (decimal_output) + printf(" %s %8ld ", segTypes[kind],header.LENGTH); + else + printf(" %s 0x%06lX ", segTypes[kind],header.LENGTH); + /* Check code segment for stack allocation [v1.1] */ + /* Position to beginning of data */ + lseek(fd, off+header.DISPDATA, SEEK_SET); + /* Check the code */ + checkCodeStack(fd); + break; + case 0x01: + case 0x02: + case 0x04: + case 0x08: + case 0x10: + case 0x12: + if (decimal_output) + printf(" %s %8ld ", segTypes[kind],header.LENGTH); + else + printf(" %s 0x%06lX ", segTypes[kind],header.LENGTH); + break; + default: + printf(" unknown (0x%02X) ", kind); + } + prntAscii(name+1,name[0]); putchar('\n'); - } - if (kind == 0x12) /* got a stack segment */ - stsize = (word) header.LENGTH; /* In OMF version 1, the first field is a block count */ if (header.VERSION == 1) off += (header.BYTECNT * 512); @@ -257,21 +279,16 @@ int stsize = 0; /* Check for unusual case that causes infinite loop [v1.1] */ if (header.BYTECNT == 0) break; } - /* The default stack size for programs is 4096 */ - if (stsize) - printf("\tStack size: %d\n", stsize); - else - printf("\tDefault stack size: 4096\n"); } void usage(void) { - fprintf(stderr,"usage: lseg filename...\n"); + fprintf(stderr,"usage: lseg [-d] filename...\n"); exit(1); } -/* Added for 2.0.6: Check on how much stack space a C program uses. */ +/* [v1.1] Check on how much stack space a C program uses. */ #if defined(__STACK_CHECK__) #ifndef _GNO_GNO_H_ #include @@ -287,21 +304,41 @@ int main(int argc, char *argv[]) { int fd; int exit_status=0; +int ch; #if defined(__STACK_CHECK__) - _beginStackCheck(); - atexit(report_stack); + _beginStackCheck(); + atexit(report_stack); #endif - if (argc == 1) usage(); - argv++; argc--; + /* Get option, if present */ + while ((ch = getopt(argc, argv, "d")) != EOF) { + switch(ch) { + case 'd': + decimal_output = TRUE; + break; + default: + usage(); + } + } + argc -= optind; + argv = argv + optind; + + /* Make sure that at least one filename was provided */ + if (argc < 1) usage(); + + /* Print header [v1.1] */ +printf( +"File Type Size Stack Name\n"); +printf( +"-------------------- ------------------ -------- ------ ----------------\n"); + while (argc-- > 0) { if ((fd = open(*argv, O_RDONLY)) < 0) { exit_status = 1; warn("%s", *argv); } else { - printf("File: %s\n",*argv); - scanOMF(fd); + scanOMF(fd,*argv); close(fd); } ++argv; diff --git a/usr.bin/lseg/lseg.rez b/usr.bin/lseg/lseg.rez index 95c7c33..ef2d7fa 100644 --- a/usr.bin/lseg/lseg.rez +++ b/usr.bin/lseg/lseg.rez @@ -1,9 +1,7 @@ /* * Resources for version and comment - * - * $Id: lseg.rez,v 1.2 1997/09/26 06:36:01 gdr Exp $ + * $Id: lseg.rez,v 1.3 1997/09/28 16:41:13 gdr Exp $ */ - #define PROG "lseg" #define DESC "List segments of an Object Module Format file." @@ -14,7 +12,7 @@ */ resource rVersion (1, purgeable3) { { 1, 1, 0, /* Version 1.1.0 */ - beta, /* development|alpha|beta|final|release */ + release, /* development|alpha|beta|final|release */ 0 }, /* non-final release number */ verUS, /* Country */ PROG, /* Program name */