Changes for v1.1-release

- increased optimization level to -1
	- added -d option
	- changed output format
This commit is contained in:
gdr 1997-09-28 16:41:13 +00:00
parent e62ed561aa
commit d1faeee771
4 changed files with 172 additions and 83 deletions

View File

@ -1,18 +1,23 @@
# #
# This makefile is intended for use with dmake(1) on Apple IIGS # 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 # Program name
PROG = lseg PROG = lseg
# Default stack size and optimization (can be overridden by cmd line) # Default stack size and optimization (can be overridden by cmd line)
# These values have been tested and certified as working
.IF $(STACK) == $(NULL) .IF $(STACK) == $(NULL)
STACK = 1024 STACK = 1024
.END .END
.IF $(OPTIMIZE) == $(NULL)
OPTIMIZE = -1
.END
# Delivery directory # Delivery directory
BINDIR = /usr/bin BINDIR = /usr/bin
.INCLUDE: /src/gno/prog.mk .INCLUDE : /src/gno/prog.mk

View File

@ -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" .TH LSEG 1 "September 1997" "GNO" "Commands and Applications"
.SH NAME .SH NAME
.BR lseg .BR lseg
\- list segments in an Object Module Format file \- list segments in an Object Module Format file
.SH SYNOPSIS .SH SYNOPSIS
.BR lseg " file ..." .BR lseg
.RB [ -d ]
.IR file " ..."
.SH DESCRIPTION .SH DESCRIPTION
.BR lseg .BR lseg
lists segments in an OMF (object module format) file. Four kinds 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" . .IR "Apple IIGS GS/OS Reference" .
.PP .PP
.BR lseg .BR lseg
prints a report that includes the type and size of each segment prints a report that includes the type, size, and name of each segment of each
of each file. Any file that is not a valid OMF file is so noted. .IR file .
Any file that is not a valid OMF file is so noted.
.PP .PP
.BR lseg .BR lseg
can be used on executable files in the following ways: to help discover 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 aid in determining how to segment large C files whose segments
exceed the bank size, and for deciding which segments to recombine exceed the bank size, and for deciding which segments to recombine
after excessive segmentation. after excessive segmentation.
.PP .PP
For object and library files,
.BR lseg .BR lseg
examines each code segment and tries to figure out how examines each code segment and tries to figure out how
many bytes of local storage are allocated from the stack at execution 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 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 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 value is printed in the column labeled "Stack".
string "Stack bytes:". This value does not include parameters passed into the routine,
Note that this value does not include parameters passed into the routine, or other use of the stack by the routine.
nor does it include any other use of the stack by the routine. If a .PP
segment has an unusually large stack allocation, examine its source code 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 and see whether arrays can be made static (if the routine is not
recursive) or can be allocated from standard memory by recursive) or can be allocated from standard memory by
.IR malloc (3). .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 .SH AUTHOR
Jawaid Bazyar for GNO/ME 1.0; updated by Dave Tribby for GNO/ME 2.0.6. Jawaid Bazyar for GNO/ME 1.0; updated by Dave Tribby for GNO/ME 2.0.6.

View File

@ -6,17 +6,18 @@
* Version 1.1 [v1.1] updated by Dave Tribby (Sept. 1997) * Version 1.1 [v1.1] updated by Dave Tribby (Sept. 1997)
* - A few changes for GNO/ME 2.0.6 * - A few changes for GNO/ME 2.0.6
* - Added display of allocated stack bytes for code segments * - 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 * - Sanity check to see whether file is an OMF file
* - Use first field as block count for OMF version 1 files * - 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 * - 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 /* 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 /* #pragma stacksize 1024
*/ */
@ -29,6 +30,10 @@
#include <unistd.h> /* GNO 2.0.6: read() and close() moved to here */ #include <unistd.h> /* GNO 2.0.6: read() and close() moved to here */
#include <err.h> /* GNO 2.0.6: use standard error reporting */ #include <err.h> /* 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 { typedef struct OMFhead {
longword BYTECNT; longword BYTECNT;
longword RESSPC; longword RESSPC;
@ -51,29 +56,32 @@ typedef struct OMFhead {
longword tempOrg; longword tempOrg;
} OMFhead; } OMFhead;
char *segTypes[] = { char *segTypes[] = { /* [v1.1] Omit "unknown" for undefined segment types */
"Code", "Code ",
"Data", "Data ",
"Jump-table", "Jump-table ",
"Unknown", "",
"Pathname", "Pathname ",
"Unknown", "",
"Unknown", "",
"Unknown", "",
"Library Dictionary", "Library Dictionary",
"Unknown", "",
"Unknown", "",
"Unknown", "",
"Unknown", "",
"Unknown", "",
"Unknown", "",
"Unknown", "",
"Initialization", "Initialization ",
"Unknown", "",
"Direct-page/Stack"}; "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 */ /* Snippit of code to be analyzed for allocated stack size */
static char code[8]; static char code[8];
@ -160,7 +168,13 @@ void checkCodeStack(int fd)
int value; int value;
while ( (value = readSegRec(fd)) == 0 ); 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? */ /* Is the file under consideration not an OMF file? */
@ -179,23 +193,16 @@ int notOMF(OMFhead *headPnt)
void prntAscii(char *s, int l) void prntAscii(char *s, int l)
{ {
/* Pad with blanks if < 18 chars [v1.1] */
int pad;
pad = 18 - l;
putchar('"'); putchar('"');
while (l--) { while (l--) {
*s &= 0x7F; *s &= 0x7F;
if (*s < ' ') { if (*s < ' ') {
putchar('^'); putchar('^');
putchar(*s+'@'); putchar(*s+'@');
pad--;
} else putchar(*s); } else putchar(*s);
s++; s++;
} }
putchar('"'); putchar('"');
while (pad-- > 0)
putchar(' ');
} }
char name[256]; char name[256];
@ -203,26 +210,24 @@ char name[256];
* The caller is responsible for opening the file, passing its refNum, * The caller is responsible for opening the file, passing its refNum,
* and closing it after we're done * and closing it after we're done
*/ */
void scanOMF(int fd) void scanOMF(int fd, char *fname)
{ {
OMFhead header; OMFhead header;
longword off = 0l; longword off = 0l;
PositionRecGS p; PositionRecGS p;
int kind; int kind;
int stsize = 0; int i;
p.pCount = 2; p.pCount = 2;
p.refNum = fd; p.refNum = fd;
GetEOF(&p); GetEOF(&p);
while (off < p.position) { while (off < p.position) {
/* printf("offset: %ld\t\t",off); */
printf(" ");
lseek(fd, off, SEEK_SET); lseek(fd, off, SEEK_SET);
read(fd,&header,sizeof(header)); read(fd,&header,sizeof(header));
/* First time through, check validity of OMF header [v1.1] */ /* First time through, check validity of OMF header [v1.1] */
if (off == 0 && notOMF(&header)) { if (off == 0 && notOMF(&header)) {
printf("Not a recognized OMF file\n"); printf("Note: %s is not a recognized OMF file\n", fname);
return; return;
} }
lseek(fd, off+header.DISPNAME+10, SEEK_SET); lseek(fd, off+header.DISPNAME+10, SEEK_SET);
@ -233,22 +238,39 @@ int stsize = 0;
name[0] = header.LABLEN; name[0] = header.LABLEN;
read(fd, name+1, 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; kind = header.KIND & 0x1F;
if (kind < 0x13) { switch (kind) {
printf(" %s segment (%02X) %06lX bytes", case 0x00:
segTypes[kind],kind,header.LENGTH); if (decimal_output)
/* Check code segment for stack allocation [v1.1] */ printf(" %s %8ld ", segTypes[kind],header.LENGTH);
if (kind == 0) { else
/* Position to beginning of data */ printf(" %s 0x%06lX ", segTypes[kind],header.LENGTH);
lseek(fd, off+header.DISPDATA, SEEK_SET); /* Check code segment for stack allocation [v1.1] */
/* Check the code */ /* Position to beginning of data */
checkCodeStack(fd); 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'); putchar('\n');
}
if (kind == 0x12) /* got a stack segment */
stsize = (word) header.LENGTH;
/* In OMF version 1, the first field is a block count */ /* In OMF version 1, the first field is a block count */
if (header.VERSION == 1) if (header.VERSION == 1)
off += (header.BYTECNT * 512); off += (header.BYTECNT * 512);
@ -257,21 +279,16 @@ int stsize = 0;
/* Check for unusual case that causes infinite loop [v1.1] */ /* Check for unusual case that causes infinite loop [v1.1] */
if (header.BYTECNT == 0) break; 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) void usage(void)
{ {
fprintf(stderr,"usage: lseg filename...\n"); fprintf(stderr,"usage: lseg [-d] filename...\n");
exit(1); 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__) #if defined(__STACK_CHECK__)
#ifndef _GNO_GNO_H_ #ifndef _GNO_GNO_H_
#include <gno/gno.h> #include <gno/gno.h>
@ -287,21 +304,41 @@ int main(int argc, char *argv[])
{ {
int fd; int fd;
int exit_status=0; int exit_status=0;
int ch;
#if defined(__STACK_CHECK__) #if defined(__STACK_CHECK__)
_beginStackCheck(); _beginStackCheck();
atexit(report_stack); atexit(report_stack);
#endif #endif
if (argc == 1) usage(); /* Get option, if present */
argv++; argc--; 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) { while (argc-- > 0) {
if ((fd = open(*argv, O_RDONLY)) < 0) { if ((fd = open(*argv, O_RDONLY)) < 0) {
exit_status = 1; exit_status = 1;
warn("%s", *argv); warn("%s", *argv);
} else { } else {
printf("File: %s\n",*argv); scanOMF(fd,*argv);
scanOMF(fd);
close(fd); close(fd);
} }
++argv; ++argv;

View File

@ -1,9 +1,7 @@
/* /*
* Resources for version and comment * Resources for version and comment
* * $Id: lseg.rez,v 1.3 1997/09/28 16:41:13 gdr Exp $
* $Id: lseg.rez,v 1.2 1997/09/26 06:36:01 gdr Exp $
*/ */
#define PROG "lseg" #define PROG "lseg"
#define DESC "List segments of an Object Module Format file." #define DESC "List segments of an Object Module Format file."
@ -14,7 +12,7 @@
*/ */
resource rVersion (1, purgeable3) { resource rVersion (1, purgeable3) {
{ 1, 1, 0, /* Version 1.1.0 */ { 1, 1, 0, /* Version 1.1.0 */
beta, /* development|alpha|beta|final|release */ release, /* development|alpha|beta|final|release */
0 }, /* non-final release number */ 0 }, /* non-final release number */
verUS, /* Country */ verUS, /* Country */
PROG, /* Program name */ PROG, /* Program name */