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
#
# $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

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"
.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.

View File

@ -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 <unistd.h> /* GNO 2.0.6: read() and close() moved to here */
#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 {
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 <gno/gno.h>
@ -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;

View File

@ -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 */