home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-05-29 | 29.8 KB | 1,284 lines |
-
- #import <MachOView.h>
-
- /* $Log: MachOView.m,v $
- Revision 1.18 94/05/29 15:00:14 ediger
- zero out a memory allocation to make it clear it's unused
-
- Revision 1.17 94/05/28 16:17:55 ediger
- finally got section names to draw acceptably.
-
- Revision 1.16 94/05/26 21:21:06 ediger
- correct address bracket zooming, hi and lo address bracket checking
-
- Revision 1.15 94/05/23 20:32:13 ediger
- lot's o' stuff to do address bracket zoom-in
-
- Revision 1.14 94/05/17 23:09:48 ediger
- support for stacking of zoomed address ranges, changed types of
- some instance vars from id to pointer to that kind of object.
-
- Revision 1.13 94/05/10 22:41:07 ediger
- support for displaying a "zooming box" by mouse drag
-
- Revision 1.12 94/05/04 11:19:58 ediger
- rearrange drawSelf:: to be a bit more modular
-
- Revision 1.10 94/05/01 17:32:57 ediger
- efficiency improvements
-
- Revision 1.9 94/02/07 21:37:17 ediger
- Use of memory-mapped file object to manage file mapping,
- add display of segment names and use of matrix of buttons
- for choices of what to display.
-
- Revision 1.7 94/01/30 16:27:34 ediger
- mostly correct address spacing
-
- Revision 1.6 94/01/01 23:02:22 ediger
- broke address label spacing calcs into separate method.
-
- Revision 1.5 93/12/31 17:32:28 ediger
- better address label spacing
-
- Revision 1.3 93/12/30 19:01:37 ediger
- support for showing upper and lower addresses
- of memory mapped segments.
-
- Revision 1.2 93/12/19 14:31:43 ediger
- corrected scaling and inclusion of mapped segments of library files
-
- Revision 1.1 93/12/19 12:57:04 ediger
- Initial revision
-
- */
-
- @implementation MachOView
-
- static char rcsident[] = "$Id: MachOView.m,v 1.18 94/05/29 15:00:14 ediger Exp Locker: ediger $";
-
- #undef DEBUG
- #ifdef DEBUG
- #define D(c) c
- #define ENTER(m) fprintf(stderr, "enter %s\n", m);
- #define EXIT(m) fprintf(stderr, "exit %s\n", m);
- #else
- #define D(c)
- #define ENTER(m)
- #define EXIT(m)
- #endif
-
- //M+ -findSizes
- // PURPOSE:
- // Sort through the addresses of the mapped segments in the Mach-O file
- // to be represented, determining the high address, low address, and
- // the number of bytes used in the address space.
- //
- // EDITORIAL:
- // Should only be called after using MachOFile instance var to
- // open or re-open the Mach-O file being represented.
- //M-
- - findSizes
- {
- int iSegments, iCC;
- unsigned long ulBaseAddr, ulUpperAddr;
- char bvBuf[64];
-
- ENTER("- findSizes");
-
- loAddr = (unsigned long)-1; /* cheat */
- sumAddr = hiAddr = 0;
-
- iSegments = [theFile mappedSegments];
-
- for (iCC = 0; iCC < iSegments; ++iCC)
- { id oSegment = [theFile mappedSegment:iCC];
-
- ulBaseAddr = [oSegment getBaseAddress];
- if (loAddr > ulBaseAddr) loAddr = ulBaseAddr;
- ulUpperAddr = [oSegment getUpperAddress];
- if (hiAddr < ulUpperAddr) hiAddr = ulUpperAddr;
- sumAddr += (ulUpperAddr - ulBaseAddr);
- }
-
- sprintf(bvBuf, "0x%x", loAddr);
- [minAddress setStringValue:bvBuf];
- sprintf(bvBuf, "0x%x", hiAddr);
- [maxAddress setStringValue:bvBuf];
-
- EXIT("- findSizes");
- return self;
- }
-
- //M+ -(char *)fileType
- //M-
- - (char *)fileType
- {
- return [theFile fileType];
- }
-
- //M+ -openFileNamed:(char *)fileName
- //
- //M-
- - openFileNamed:(char *)fileName
- {
- ENTER("- openFileNamed:");
- assert(NULL != fileName);
-
- [self freeInternals];
-
- currentFileName = strcpy(malloc(strlen(fileName) + 1), fileName);
-
- mappedFile = [[[MappedFile alloc] init] filename:currentFileName];
- if (mappedFile == NULL || [mappedFile map] == FALSE)
- { [cpuType setStringValue:"Problem opening"];
- [cpuSubtype setStringValue:currentFileName];
-
- } else {
- theFile = [[[MachOFile alloc]init]
- fillFromAddress:[mappedFile address]];
- if (NULL == theFile)
- { [cpuType setStringValue:"Not a"];
- [cpuSubtype setStringValue:"Mach-O file"];
- } else {
- int iSegments = [theFile mappedSegments];
- addressMap = (struct addressMapping *)malloc(
- iSegments * sizeof(struct addressMapping));
- bzero(addressMap, iSegments * sizeof(struct addressMapping));
- [cpuType setStringValue:[theFile cpuType]];
- [cpuSubtype setStringValue:[theFile cpuSubtype]];
- [[self findSizes] display];
- }
- }
-
- EXIT("- openFileNamed:");
- return self;
- }
-
- //M+ -toggleScaling:sender
- // Action called by clicking on a button. Changes the "toScale" instance
- // variable, and calls -display, to reflect the change.
- //M-
- - toggleScaling:sender
- {
- if (toScale)
- {
- toScale = FALSE;
- showSectionNames = FALSE;
- [showSectionsButton setEnabled:NO];
- [showSectionsButton setIntValue:0];
-
- } else {
- toScale = TRUE;
- [showSectionsButton setEnabled:YES];
- [showSectionsButton setIntValue:0];
- }
-
- [self display];
-
- return self;
- }
-
-
- //M+ -toggleAddresses:sender
- // Action called by clicking on a button. Changes the "showAddresses"
- // instance variable, and calls -display, to reflect the change.
- //M-
- - toggleAddresses:sender
- {
- if (showAddresses)
- showAddresses = FALSE;
- else
- showAddresses = TRUE;
-
- [self display];
-
- return self;
- }
-
- //M+ -toggleNames:sender
- // Action called by clicking on a button. Changes the "showNames"
- // instance variable, and calls -display, to reflect the change.
- //M-
- - toggleNames:sender
- {
- if (showNames)
- showNames = FALSE;
- else
- showNames = TRUE;
-
- [self display];
-
- return self;
- }
-
- //M+ -toggleThreads:sender
- // Action called by clicking on a button. Changes the "showThreads"
- // instance variable, and calls -display, to reflect the change.
- //M-
- - toggleThreads:sender
- {
- if (showThreads)
- showThreads = FALSE;
- else
- showThreads = TRUE;
-
- [self display];
-
- return self;
- }
-
- //M+ -toggleSections:sender
- // Action called by clicking on a button. Changes the "showSectionNames"
- // instance variable, and calls -display, to reflect the change.
- //M-
- - toggleSections:sender
- {
- int iSegments, iCC;
-
- if (showSectionNames)
- showSectionNames = FALSE;
- else
- showSectionNames = TRUE;
-
- iSegments = [theFile mappedSegments];
-
- for (iCC = iSegments - 1; iCC > -1; --iCC)
- {
- int i;
- SegmentCommand *oSegment = [theFile mappedSegment:iCC];
- int iSection = [oSegment numberOfSections];
- struct section *spSection = [oSegment getSection:0];
-
- if (iSection > 0)
- {
- if (addressMap[iCC].sectionMap == NULL)
- addressMap[iCC].sectionMap =
- (struct sectionNameMapping *)malloc(
- iSection*sizeof(struct sectionNameMapping));
-
- assert(addressMap[iCC].sectionMap != NULL);
-
- for (i = 0; i < iSection; ++i)
- {
- addressMap[iCC].sectionMap[i].sectionName
- = spSection[i].sectname;
- addressMap[iCC].sectionMap[i].sectionAddress
- = spSection[i].addr;
- }
-
- } else
- addressMap[iCC].sectionMap = NULL;
- }
-
- [self display];
-
- return self;
- }
-
- //M+ -toggleLibraries:sender
- // PURPOSE:
- // Action called by clicking on a button. Changes the "showLibraries"
- // instance variable, and calls -display, to reflect the change.
- // EDITORIAL:
- // Somewhat more elaborate than the other -toggle* methods, since the
- // Mach-O file object instance variable gets completely redone. This
- // may be a case of bad design of the MachOFile object percolating up
- // to here.
- //M-
- - toggleLibraries:sender;
- {
- if (theFile != NULL)
- [theFile free];
- theFile = [[MachOFile alloc] init];
-
- if (NULL != addressMap)
- {
- int iSegments = [theFile mappedSegments];
- while (--iSegments > -1)
- if (addressMap[iSegments].sectionMap)
- free(addressMap[iSegments].sectionMap);
-
- free(addressMap);
- addressMap = NULL;
- }
-
- if (showLibraries)
- {
- showLibraries = FALSE;
- [theFile unconsiderMappedFiles];
- } else {
- showLibraries = TRUE;
- [theFile considerMappedFiles];
- }
-
- [theFile fillFromAddress:[mappedFile address]];
-
- addressMap = (struct addressMapping *)malloc(
- [theFile mappedSegments] * sizeof(struct addressMapping));
- bzero(addressMap, [theFile mappedSegments] * sizeof(struct addressMapping));
-
- // since the MachOFile object has been redone, zoom state is meaningless.
- if (NULL != zoomStack)
- {
- void *vp;
-
- while ((vp = [zoomStack pop]) != NULL)
- free(vp);
- }
- [unzoomButton setEnabled:NO];
- [zoomButton setEnabled:NO];
-
- [[self findSizes] display];
-
- return self;
- }
-
- //M+ -windowWillClose:sender
- // PURPOSE:
- // Ditch any memory-consuming instance vars when the window closes.
- // EDITORIAL:
- // one of the Window delegate methods
- //M-
- - windowWillClose:sender
- {
- ENTER("- windowWillClose:");
- [self freeInternals];
- [zoomStack free];
- EXIT("- windowWillClose:");
- return self;
- }
-
- //M+ -rescale
- // PURPOSE:
- // calculate the scaling instance vars
- //M-
- - rescale
- {
- float ht;
- ENTER("- rescale");
-
- ht = NX_HEIGHT(&bounds) - 25.0;
-
- scaleSlope = ht/(float)(hiAddr - loAddr);
- scaleYintercept = 5.0 - scaleSlope*(float)loAddr;
-
- smashedSlope = ht/(float)sumAddr;
- smashedYintercept = 0.0;
-
- EXIT("- rescale");
- return self;
- }
-
-
- //M+ -initFrame:(const NXRect *)frameRect
- // PURPOSE:
- // Set a bunch of instance variables to some sensible values.
- //
- // EDITORIAL:
- // Override of a View method
- //M-
- - initFrame:(const NXRect *)frameRect
- {
- ENTER("- initFrame:");
- [super initFrame:frameRect];
-
- toScale = TRUE;
- showLibraries = FALSE;
- showAddresses = TRUE;
- showNames = TRUE;
- showThreads = TRUE;
- showSectionNames = FALSE;
-
- currentFileName = NULL;
- addressMap = NULL;
- mappedFile = NULL;
- theFile = NULL;
- zoomStack = [[Queue alloc] init];
-
- theFont = [Font newFont:"Courier" size:(float)(LABEL_HT - LABEL_LEADING)
- matrix:NX_IDENTITYMATRIX];
-
-
- EXIT("- initFrame:");
- return self;
- }
-
- //M+ -drawSelf:(NXRect *)rects :(int)rectCount
- //
- // EDITORIAL:
- // Override of a View method.
- // This is way too complicated.
- //M-
- - drawSelf:(NXRect *)rects :(int)rectCount
- {
- int iSegments, iCC;
- float xCoord, yCoord, yLast;
- ENTER("- drawSelf::");
-
- [self rescale];
-
- // make background white and lines black
- PSsetgray(NX_WHITE);
- NXRectFill(&bounds);
- PSsetgray(NX_BLACK);
- NXFrameRect(&bounds);
- PSsetgray(NX_BLACK);
-
- PSnewpath();
- PSsetlinewidth(LINE_WDTH);
-
- [theFont set];
-
- iSegments = [theFile mappedSegments];
-
- if (iSegments == 0)
- return self;
-
- /* stagger the lines representing memory allocations */
- xCoord = NX_WIDTH(&bounds)/2.0 - ((float)iSegments/2.0)*LINE_STAGGER;
- yCoord = VERT_MARGIN;
- yLast = [[theFile mappedSegment:iSegments - 1] getBaseAddress] - 1.0;
-
- /* count down so that the "not to scale" bit works */
- for (iCC = iSegments - 1; iCC > -1; --iCC)
- {
- id oSegment = [theFile mappedSegment:iCC];
- unsigned long ulBaseAddr = [oSegment getBaseAddress];
- unsigned long ulUpperAddr = [oSegment getUpperAddress];
-
- if (ulBaseAddr > hiAddr)
- break; // don't need to check any higher
-
- if (
- (ulUpperAddr <= hiAddr && ulBaseAddr >= loAddr) ||
- (ulUpperAddr >= loAddr && ulBaseAddr < loAddr) ||
- (ulUpperAddr > hiAddr && ulBaseAddr < hiAddr)
- )
- {
-
- addressMap[iCC].baseAddress
- = (loAddr < ulBaseAddr)?ulBaseAddr:loAddr;
- addressMap[iCC].endAddress
- = (hiAddr > ulUpperAddr)?ulUpperAddr:hiAddr;
-
- if (showNames)
- addressMap[iCC].segmentName = [oSegment commandName];
-
- if (toScale)
- {
- addressMap[iCC].yCoordBase =
- (loAddr < ulBaseAddr)?
- scaleSlope*(float)ulBaseAddr + scaleYintercept
- : scaleSlope*(float)loAddr + scaleYintercept
- ;
- addressMap[iCC].yCoordTop =
- (hiAddr > ulUpperAddr) ?
- scaleSlope*(float)ulUpperAddr + scaleYintercept
- : scaleSlope*(float)hiAddr + scaleYintercept
- ;
-
- PSmoveto(xCoord, addressMap[iCC].yCoordBase);
-
- PSlineto(xCoord, addressMap[iCC].yCoordTop);
-
- } else {
-
- if (ulBaseAddr != yLast)
- PSmoveto(xCoord, yCoord + SEGMENT_GAP);
- else
- PSmoveto(xCoord, yCoord);
-
- if (ulBaseAddr != yLast)
- addressMap[iCC].yCoordBase = yCoord + SEGMENT_GAP;
- else
- addressMap[iCC].yCoordBase = yCoord;
-
- if (ulUpperAddr <= hiAddr && ulBaseAddr >= loAddr)
- yCoord += smashedSlope * (float)(ulUpperAddr - ulBaseAddr)
- + smashedYintercept;
- else if (ulUpperAddr >= loAddr && ulBaseAddr < loAddr)
- yCoord += smashedSlope * (float)(ulUpperAddr - loAddr)
- + smashedYintercept;
- else if (ulUpperAddr > hiAddr && ulBaseAddr < hiAddr)
- yCoord += smashedSlope * (float)(hiAddr - ulBaseAddr)
- + smashedYintercept;
-
- PSlineto(xCoord, yCoord);
-
- addressMap[iCC].yCoordTop = yCoord;
-
- yLast = ulUpperAddr;
- }
-
- /* stagger to the right, on the way up */
- xCoord += LINE_STAGGER;
-
- }
- }
-
- PSstroke();
-
- if (yLooping)
- {
- // draw on the box marking the zooming zone
- drawBox(sFirstMouseDown.x, sFirstMouseDown.y,
- sMouseDown.x, sMouseDown.y);
- } else {
- [zoomButton setEnabled:NO];
- }
-
- /* label the ends of each memory segment with its address */
- if (TRUE == showAddresses)
- [self drawAddresses];
-
- /* label the middle of each memory segment with its name */
- if (TRUE == showNames)
- [self drawSegmentNames];
-
- /* draw in little markers for threads program counters */
- if (showThreads)
- [self drawThreads];
-
- if (showSectionNames)
- [self drawSectionNames];
-
- EXIT("- drawSelf::");
- return self;
- }
-
- //M+ -drawThreads
- //M-
- - drawThreads
- {
- int iCC, iThreadCount = [theFile threads];
- int iSegCount = [theFile mappedSegments];
-
- PSsetlinewidth(0.50);
-
- for (iCC = 0; iCC < iThreadCount; ++iCC)
- {
- float xCoord, yCoord;
- int iSegNo = [theFile segmentOfThread:iCC];
-
- // iSegNo is -1 if there's no segment containing this thread's PC.
- // abort(2) causes just this sort of situation.
- if (iSegNo > -1)
- {
- unsigned long ulPCAddr = [[theFile thread:iCC] pc];
-
- if (ulPCAddr >= loAddr && ulPCAddr <= hiAddr)
- {
-
- xCoord = NX_WIDTH(&bounds)/2.0
- - ((float)[theFile mappedSegments]/2.0)*(LINE_STAGGER)
- + (float)(iSegCount - iSegNo) * LINE_STAGGER;
-
- yCoord = addressMap[iSegNo].yCoordBase
- + (addressMap[iSegNo].yCoordTop - addressMap[iSegNo].yCoordBase)
- * ((float)ulPCAddr - addressMap[iSegNo].baseAddress)
- / (addressMap[iSegNo].endAddress-addressMap[iSegNo].baseAddress);
-
- drawLeftArrowHead(xCoord, yCoord, 8.0);
- }
- }
- }
-
- return self;
- }
-
- //M+ -spaceLabels
- // Figure out the spacing of the address labels
- // Fills in yCoordBaseLabel and yCoordTopLabel fields such that the
- // addresses don't overlap, and don't end up out of the MachOView.
- // yCoordBaseLabel field ends up as -1.0 if it is the same number
- // as the yCoordTopLabel of the preceding (lower in memory) segment.
- //M-
- - spaceLabels
- {
- float lastY;
- float yLastAddress;
- int iCC, iSegments = [theFile mappedSegments];
-
- lastY = addressMap[iSegments - 1].baseAddress - 20.0;
- yLastAddress = addressMap[iSegments - 1].yCoordBase - LABEL_HT;
-
- for (iCC = iSegments - 1; iCC > -1; --iCC)
- {
- if (addressMap[iCC].baseAddress > hiAddr)
- break; // no need to go any higher
-
- if (
- (addressMap[iCC].endAddress <= hiAddr && addressMap[iCC].baseAddress >= loAddr)
- ||(addressMap[iCC].endAddress >= loAddr && addressMap[iCC].baseAddress < loAddr)
- ||(addressMap[iCC].endAddress > hiAddr && addressMap[iCC].baseAddress < hiAddr)
- )
- {
-
- if (addressMap[iCC].baseAddress != lastY)
- {
- if (addressMap[iCC].yCoordBase < yLastAddress + LABEL_HT)
- addressMap[iCC].yCoordBaseLabel
- = yLastAddress + (LABEL_HT + 2.0);
- else
- addressMap[iCC].yCoordBaseLabel=addressMap[iCC].yCoordBase;
-
- yLastAddress = addressMap[iCC].yCoordBaseLabel;
-
- } else {
- /* don't need to show this segment's base address */
- addressMap[iCC].yCoordBaseLabel = -1.0;
- }
-
- if (addressMap[iCC].yCoordTop < yLastAddress + LABEL_HT)
- addressMap[iCC].yCoordTopLabel = yLastAddress + (LABEL_HT+2.0);
- else
- addressMap[iCC].yCoordTopLabel = addressMap[iCC].yCoordTop;
-
- yLastAddress = addressMap[iCC].yCoordTopLabel;
- lastY = addressMap[iCC].endAddress;
-
- }
- }
-
- if (yLastAddress + LABEL_HT > NX_HEIGHT(&bounds))
- {
- yLastAddress = NX_HEIGHT(&bounds) - (LABEL_HT + 2.0);
-
- /* try to reshuffle address labels so everything fits */
- for (iCC = 0; iCC < iSegments; ++iCC)
- {
-
- if (addressMap[iCC].endAddress < loAddr)
- break; // no need to go any lower
-
- if (
- (addressMap[iCC].endAddress <= hiAddr && addressMap[iCC].baseAddress >= loAddr)
- ||(addressMap[iCC].endAddress >= loAddr && addressMap[iCC].baseAddress < loAddr)
- ||(addressMap[iCC].endAddress > hiAddr && addressMap[iCC].baseAddress < hiAddr)
- )
- {
-
- if (addressMap[iCC].yCoordTopLabel > yLastAddress)
- {
- addressMap[iCC].yCoordTopLabel = yLastAddress;
- yLastAddress -= (LABEL_HT + 2.0);
- } else if (0.0 > addressMap[iCC].yCoordTopLabel)
- continue; // this label doesn't show. go to next visible.
- else
- break; /* slipped down into a gap */
-
- if (addressMap[iCC].yCoordBaseLabel > yLastAddress)
- {
- addressMap[iCC].yCoordBaseLabel = yLastAddress;
- yLastAddress -= (LABEL_HT + 2.0);
- } else if (0.0 > addressMap[iCC].yCoordBaseLabel)
- continue;
- else
- break;
- }
- }
- }
-
- return self;
- }
-
- //M+ -spaceNames
- // Figure out the spacing of the segment name labels
- // Fills in yCoordBaseLabel field such that the
- // names don't overlap, and don't end up out of the MachOView.
- // Segment
- //M-
- - spaceNames
- {
- int iCC, iSegments = [theFile mappedSegments];
- float yLastAddress;
-
- yLastAddress = addressMap[iSegments - 1].yCoordBase - LABEL_HT;
-
- for (iCC = iSegments - 1; iCC > -1; --iCC)
- {
- if (
- (addressMap[iCC].endAddress <= hiAddr && addressMap[iCC].baseAddress >= loAddr)
- ||(addressMap[iCC].endAddress >= loAddr && addressMap[iCC].baseAddress < loAddr)
- ||(addressMap[iCC].endAddress > hiAddr && addressMap[iCC].baseAddress < hiAddr)
- )
- {
- /* space name across width of view */
- addressMap[iCC].nameXcoord = NX_WIDTH(&bounds) - LABEL_MARGIN
- - [theFont getWidthOf:addressMap[iCC].segmentName];
-
- /* put name in middle of segment vertically */
- addressMap[iCC].nameYcoord =
- (addressMap[iCC].yCoordBase + addressMap[iCC].yCoordTop)/2.0;
-
- /* handle overlaps */
- if (addressMap[iCC].nameYcoord < yLastAddress + LABEL_HT)
- addressMap[iCC].nameYcoord = yLastAddress + LABEL_HT;
-
- yLastAddress = addressMap[iCC].nameYcoord;
- }
- }
-
- if (yLastAddress + LABEL_HT > NX_HEIGHT(&bounds))
- {
- yLastAddress = NX_HEIGHT(&bounds) - (LABEL_HT + 2.0);
-
- /* try to reshuffle address labels so everything fits */
- for (iCC = 0; iCC < iSegments; ++iCC)
- {
- if (
- (addressMap[iCC].endAddress <= hiAddr && addressMap[iCC].baseAddress >= loAddr)
- ||(addressMap[iCC].endAddress >= loAddr && addressMap[iCC].baseAddress < loAddr)
- ||(addressMap[iCC].endAddress > hiAddr && addressMap[iCC].baseAddress < hiAddr)
- )
- {
- if (addressMap[iCC].nameYcoord > yLastAddress)
- {
- addressMap[iCC].nameYcoord = yLastAddress;
- yLastAddress -= (LABEL_HT + 2.0);
- } else
- break; /* slipped down into a gap */
- }
- }
- }
-
- return self;
- }
-
- //M+ -free
- //M-
- - free
- {
- ENTER("- free");
- [self freeInternals];
-
- [zoomStack free];
-
- [super free];
-
- EXIT("- free");
- return self;
- }
-
- //M+ - freeInternals
- //M-
- - freeInternals
- {
- ENTER("- freeInternals");
- if (NULL != addressMap)
- {
- int iSegments = [theFile mappedSegments];
- while (--iSegments > -1)
- if (addressMap[iSegments].sectionMap)
- free(addressMap[iSegments].sectionMap);
-
- free(addressMap);
- addressMap = NULL;
- }
-
- if (NULL != currentFileName)
- {
- free(currentFileName);
- currentFileName = NULL;
- }
-
- if (NULL != theFile)
- {
- [theFile free];
- theFile = NULL;
- }
-
- if (NULL != mappedFile)
- {
- [mappedFile free];
- mappedFile = NULL;
- }
-
- if (NULL != zoomStack)
- { // free zoomStack's contents
- void *vp;
-
- while ((vp = [zoomStack pop]) != NULL)
- free(vp);
- }
-
- EXIT("- freeInternals");
- return self;
- }
-
- //M+ -show:sender
- //M-
- - show:sender
- {
- [theWindow makeKeyAndOrderFront:self];
-
- return self;
- }
-
- //M+ -drawAddresses
- //M-
- - drawAddresses
- {
- float yCoord, xCoord;
- int iCC, iSegments;
-
- iSegments = [theFile mappedSegments];
-
- /* figure out address label spacing */
- [self spaceLabels];
-
- PSnewpath();
- PSsetlinewidth(0.50); /* thin lines to each segment */
- [theFont set];
-
- yCoord = VERT_MARGIN;
- xCoord = NX_WIDTH(&bounds)/2.0 - ((float)iSegments/2.0)*(LINE_STAGGER);
-
- for (iCC = iSegments - 1; iCC > -1; --iCC)
- {
- char bvBuffer[256];
-
- if (addressMap[iCC].baseAddress > hiAddr)
- break; // no need to go any higher
-
- if (
- (addressMap[iCC].endAddress <= hiAddr && addressMap[iCC].baseAddress >= loAddr)
- ||(addressMap[iCC].endAddress >= loAddr && addressMap[iCC].baseAddress < loAddr)
- ||(addressMap[iCC].endAddress > hiAddr && addressMap[iCC].baseAddress < hiAddr)
- )
- {
-
- if (!(addressMap[iCC].yCoordBaseLabel < 0.0))
- { sprintf(bvBuffer, "0x%x",
- (unsigned int)addressMap[iCC].baseAddress);
- drawLabel(LABEL_MARGIN, addressMap[iCC].yCoordBaseLabel,
- bvBuffer, xCoord - (LINE_STAGGER - LABEL_MARGIN),
- addressMap[iCC].yCoordBase);
- }
-
- sprintf(bvBuffer, "0x%x", (unsigned int)addressMap[iCC].endAddress);
- drawLabel(LABEL_MARGIN, addressMap[iCC].yCoordTopLabel, bvBuffer,
- xCoord - (LINE_STAGGER - LABEL_MARGIN),
- addressMap[iCC].yCoordTop);
-
- xCoord += LINE_STAGGER;
-
- }
- }
-
- PSstroke();
-
- return self;
- }
-
- //M+ -drawSegmentNames
- //M-
- - drawSegmentNames
- {
- float xCoord;
- int iCC, iSegments;
-
- if (FALSE == showAddresses)
- [self spaceLabels];
-
- [self spaceNames];
-
- PSnewpath();
- PSsetlinewidth(0.50);
- [theFont set];
-
- iSegments = [theFile mappedSegments];
-
- xCoord = NX_WIDTH(&bounds)/2.0
- - ((float)iSegments/2.0)*(LINE_STAGGER) + 5.0;
-
- for (iCC = iSegments - 1; iCC > -1; --iCC)
- {
- if (addressMap[iCC].baseAddress > hiAddr)
- break; // no need to go any higher
-
- if (
- (addressMap[iCC].endAddress <= hiAddr && addressMap[iCC].baseAddress >= loAddr)
- ||(addressMap[iCC].endAddress >= loAddr && addressMap[iCC].baseAddress < loAddr)
- ||(addressMap[iCC].endAddress > hiAddr && addressMap[iCC].baseAddress < hiAddr)
- )
- {
-
- xCoord += LINE_STAGGER;
- PSmoveto(
- xCoord,
- (addressMap[iCC].yCoordBase + addressMap[iCC].yCoordTop)/2.0);
- PSlineto(
- addressMap[iCC].nameXcoord - 10.0,
- addressMap[iCC].nameYcoord);
- PSmoveto(addressMap[iCC].nameXcoord, addressMap[iCC].nameYcoord);
- PSshow(addressMap[iCC].segmentName);
-
- }
- }
-
- PSstroke();
-
- return self;
- }
-
- //M+ -spaceSectionNames
- //M-
- - spaceSectionNames
- {
- int iCC, iSegments;
- float yLastAddress;
-
- iSegments = [theFile mappedSegments];
-
- yLastAddress = addressMap[iSegments - 1].yCoordBase - LABEL_HT;
-
- for (iCC = iSegments - 1; iCC > -1; --iCC)
- {
- if (addressMap[iCC].baseAddress > hiAddr)
- break; // no need to go any higher
-
- if (
- (addressMap[iCC].endAddress <= hiAddr && addressMap[iCC].baseAddress >= loAddr)
- ||(addressMap[iCC].endAddress >= loAddr && addressMap[iCC].baseAddress < loAddr)
- ||(addressMap[iCC].endAddress > hiAddr && addressMap[iCC].baseAddress < hiAddr)
- )
- {
- SegmentCommand *oSegment = [theFile mappedSegment:iCC];
- int iSection = [oSegment numberOfSections];
-
- if (iSection > 0 && addressMap[iCC].sectionMap != NULL)
- {
- int i;
-
- for (i = 0; i < iSection; ++i)
- {
- if(
- (addressMap[iCC].sectionMap[i].sectionAddress <= hiAddr)
- && (addressMap[iCC].sectionMap[i].sectionAddress >= loAddr)
- )
- {
-
- if (toScale)
- {
- addressMap[iCC].sectionMap[i].nameYcoord
- = scaleSlope*(float)addressMap[iCC].sectionMap[i].sectionAddress
- + scaleYintercept;
- } else {
- addressMap[iCC].sectionMap[i].nameYcoord
- = smashedSlope*(float)addressMap[iCC].sectionMap[i].sectionAddress
- + smashedYintercept;
- }
-
- if (addressMap[iCC].sectionMap[i].nameYcoord <= yLastAddress+LABEL_HT)
- addressMap[iCC].sectionMap[i].nameYcoord = yLastAddress + LABEL_HT;
-
- yLastAddress = addressMap[iCC].sectionMap[i].nameYcoord;
-
- }
-
- }
- }
- }
- }
-
- return self;
- }
-
- //M+ -drawSectionNames
- //M-
- - drawSectionNames
- {
- float xCoord;
- int iCC, iSegments;
-
- [self spaceSectionNames];
-
- PSnewpath();
- PSsetlinewidth(0.50);
- [theFont set];
-
- iSegments = [theFile mappedSegments];
-
- xCoord = NX_WIDTH(&bounds)/2.0
- - ((float)iSegments/2.0)*(LINE_STAGGER) + 5.0;
-
- for (iCC = iSegments - 1; iCC > -1; --iCC)
- {
- if (addressMap[iCC].baseAddress > hiAddr)
- break; // no need to go any higher
-
- if (
- (addressMap[iCC].endAddress <= hiAddr && addressMap[iCC].baseAddress >= loAddr)
- ||(addressMap[iCC].endAddress >= loAddr && addressMap[iCC].baseAddress < loAddr)
- ||(addressMap[iCC].endAddress > hiAddr && addressMap[iCC].baseAddress < hiAddr)
- )
- {
- SegmentCommand *oSegment = [theFile mappedSegment:iCC];
- int iSection = [oSegment numberOfSections];
-
- if (iSection > 0 && addressMap[iCC].sectionMap != NULL)
- {
- int i;
- for (i = 0; i < iSection; ++i)
- {
- if(
- (addressMap[iCC].sectionMap[i].sectionAddress <= hiAddr)
- &&(addressMap[iCC].sectionMap[i].sectionAddress >= loAddr)
- )
- {
- float yCoord;
-
- if (toScale)
- {
- yCoord
- = scaleSlope*(float)addressMap[iCC].sectionMap[i].sectionAddress
- + scaleYintercept;
- } else {
- yCoord
- = smashedSlope*(float)addressMap[iCC].sectionMap[i].sectionAddress
- + smashedYintercept;
- }
- PSmoveto(xCoord, yCoord);
- PSlineto(xCoord + 10.0,
- addressMap[iCC].sectionMap[i].nameYcoord);
- PSmoveto(xCoord + 14.0,
- addressMap[iCC].sectionMap[i].nameYcoord);
- PSshow(addressMap[iCC].sectionMap[i].sectionName);
- }
- }
- }
-
- xCoord += LINE_STAGGER;
- }
- }
-
- PSstroke();
-
- return self;
- }
-
- //M+ - mouseDown:(NXEvent *)spTheEvent
- // PURPOSE:
- // draw a box following the user's mouse drags
- //M-
- - mouseDown:(NXEvent *)spTheEvent
- {
- NXEvent *spNextEvent;
- int iOldMask, iCheckMask, iDragged = 0;
- char bvBuf[64];
-
- [self lockFocus];
-
- iOldMask = [window eventMask];
-
- iCheckMask = NX_MOUSEUPMASK | NX_MOUSEDRAGGEDMASK;
-
- [window setEventMask:(iOldMask|iCheckMask)];
-
- sFirstMouseDown = spTheEvent->location;
- [self convertPoint:&sFirstMouseDown fromView:nil];
-
- yLooping = 1;
- while (yLooping)
- {
- iDragged = 1;
- spNextEvent = [NXApp getNextEvent:iCheckMask];
-
- if ((yLooping = (spNextEvent->type != NX_MOUSEUP)))
- {
- sMouseDown = spTheEvent->location;
- [self convertPoint:&sMouseDown fromView:nil];
- [self display];
- }
- }
-
- [self unlockFocus];
-
- [window setEventMask:iOldMask];
-
- if (!iDragged)
- return self;
-
- // For sake of aesthetics, address 0x0 is not exactly at bottom of
- // view. This lets the user drag an address of less than zero,
- // which ends up as a very high address in an unsigned long.
- // The next bits use the view coords to keep user from screwing up.
- if (sFirstMouseDown.y < VERT_MARGIN)
- sFirstMouseDown.y = VERT_MARGIN;
- if (sMouseDown.y < VERT_MARGIN)
- sMouseDown.y = VERT_MARGIN;
-
- // set displayed coords for user's inspection
- if (toScale)
- {
- hiAddrZoom =
- (unsigned long)((sFirstMouseDown.y - scaleYintercept)/scaleSlope);
- loAddrZoom =
- (unsigned long)((sMouseDown.y - scaleYintercept)/scaleSlope);
-
- } else {
- int iCC;
- int iSegments = [theFile mappedSegments];
- int iLoSet = 0, iHiSet = 0;
- // find out where the addresses dragged out are
-
- for (iCC = iSegments - 1;
- iCC > -1 && (!iLoSet || !iHiSet);
- --iCC)
- {
- if (!iLoSet && addressMap[iCC].yCoordBase <= sMouseDown.y
- && addressMap[iCC].yCoordTop >= sMouseDown.y)
- {
- loAddrZoom =
- (unsigned long)((sMouseDown.y - addressMap[iCC].yCoordBase)
- /(addressMap[iCC].yCoordTop - addressMap[iCC].yCoordBase)
- *(float)(addressMap[iCC].endAddress - addressMap[iCC].baseAddress))
- + addressMap[iCC].baseAddress;
- iLoSet = 1;
-
- }
-
- if (!iHiSet && addressMap[iCC].yCoordBase <= sFirstMouseDown.y
- && addressMap[iCC].yCoordTop >= sFirstMouseDown.y)
- {
- hiAddrZoom =
- (unsigned long)((sFirstMouseDown.y - addressMap[iCC].yCoordBase)
- /(addressMap[iCC].yCoordTop - addressMap[iCC].yCoordBase)
- *(float)(addressMap[iCC].endAddress - addressMap[iCC].baseAddress))
- + addressMap[iCC].baseAddress;
- iHiSet = 1;
- }
- }
-
- if (!iLoSet)
- {
- // sMouseDown.y not in range of any segment
- if (sMouseDown.y > addressMap[0].yCoordTop)
- loAddrZoom = hiAddr;
- else
- loAddrZoom = loAddr;
- }
-
- if (!iHiSet)
- {
- // sFirstMouseDown.y not in range of any segment
- if (sFirstMouseDown.y > addressMap[0].yCoordTop)
- hiAddrZoom = hiAddr;
- else
- hiAddrZoom = loAddr;
- }
-
- }
-
- // user may have dragged from bottom to top.
- if (hiAddrZoom < loAddrZoom)
- { unsigned long ulTmp = hiAddrZoom; hiAddrZoom = loAddrZoom;
- loAddrZoom = ulTmp; }
-
- // clamp zoomed values no matter what they calculated out as
- if (hiAddrZoom > hiAddr)
- hiAddrZoom = hiAddr;
-
- if (loAddrZoom < loAddr)
- loAddrZoom = loAddr;
-
- sprintf(bvBuf, "0x%x", loAddrZoom);
- [minAddress setStringValue:bvBuf];
- sprintf(bvBuf, "0x%x", hiAddrZoom);
- [maxAddress setStringValue:bvBuf];
-
- [zoomButton setEnabled:YES];
-
- return self;
- }
-
- //M+ - zoom:sender
- // PURPOSE:
- // Do what needs to be done when user clicks on "zoom" button.
- // Essentially, it pushes the current state (high address displayed,
- // low address displayed, and amount of mapped address taked up)
- // on the zoom stack, recalcs the amount of address taken up
- // inside the new high and low addresses, then redisplays.
- //M-
- - zoom:sender
- {
- struct zoomAddress *spZoom;
- int iCC;
-
- // save current "zoom state".
- spZoom = malloc(sizeof(struct zoomAddress));
- assert(spZoom != NULL);
- spZoom->hiAddr = hiAddr;
- spZoom->loAddr = loAddr;
- spZoom->sumAddr = sumAddr;
- [zoomStack push:(void *)spZoom];
-
- hiAddr = hiAddrZoom;
- loAddr = loAddrZoom;
-
- // recalculate the amount of the address used by file's mapped segments
- sumAddr = 0;
- for (iCC = [theFile mappedSegments] - 1; iCC > -1; --iCC)
- {
- id oSegment = [theFile mappedSegment:iCC];
- unsigned long ulBaseAddr, ulUpperAddr;
-
- ulBaseAddr = [oSegment getBaseAddress];
- ulUpperAddr = [oSegment getUpperAddress];
-
- if (ulBaseAddr > hiAddr)
- break;
-
- if (
- (ulUpperAddr <= hiAddr && ulBaseAddr >= loAddr)
- ||(ulUpperAddr >= loAddr && ulBaseAddr < loAddr)
- ||(ulUpperAddr > hiAddr && ulBaseAddr < hiAddr)
- )
- {
- sumAddr +=
- (ulUpperAddr <= hiAddr ? ulUpperAddr : hiAddr)
- -
- (ulBaseAddr >= loAddr ? ulBaseAddr : loAddr);
- }
- }
-
- [unzoomButton setEnabled:YES];
-
- [self display];
-
- return self;
- }
-
- //M+ - unzoom:sender
- // PURPOSE:
- // "unzoom" a level.
- //M-
- - unzoom:sender
- {
- char bvBuf[64];
- struct zoomAddress *spZoom;
-
- spZoom = (struct zoomAddress *)[zoomStack pop];
-
- loAddr = spZoom->loAddr;
- hiAddr = spZoom->hiAddr;
- sumAddr = spZoom->sumAddr;
- free(spZoom);
-
- sprintf(bvBuf, "0x%x", loAddr);
- [minAddress setStringValue:bvBuf];
- sprintf(bvBuf, "0x%x", hiAddr);
- [maxAddress setStringValue:bvBuf];
-
- if ([zoomStack isEmpty])
- [unzoomButton setEnabled:NO];
-
- [self display];
-
- return self;
- }
-
- @end
-