Received: from isis.u-strasbg.fr ([130.79.200.1]) by nic.funet.fi with SMTP id <90548-4>; Tue, 23 May 1995 12:48:50 +0300
Received: from indi1.u-strasbg.fr (indi1.u-strasbg.fr [130.79.6.93]) by isis.u-strasbg.fr (8.6.9/8.6.9) with SMTP id LAA01697 for <vinsci@nic.funet.fi>; Tue, 23 May 1995 11:46:54 +0200
Received: by indi1.u-strasbg.fr (920330.SGI/5.6)
	id AA01383; Tue, 23 May 95 11:35:17 GMT
Date:	Tue, 23 May 95 11:35:17 GMT
From:	papier@indi1.u-strasbg.fr (Laurent Papier)
Message-Id: <9505231135.AA01383@indi1.u-strasbg.fr>
To:	vinsci@nic.funet.fi
Subject: FindHit source

>From scala!scala.com!michael.sinz@dsinc.myxa.com  Tue May 16 16:46:31 1995
Received: from dsinc.myxa.com by indi1.u-strasbg.fr (920330.SGI/5.6)
	id AA15285; Tue, 16 May 95 16:46:31 GMT
Received: from scala by dsinc.myxa.com with uucp
	(Smail3.1.28.1 #36) id m0sBNmg-00008OC; Tue, 16 May 95 10:39 EDT
Received: by scala.scala.com; Tue, 16 May 1995 10:34 EDT
Received: by fox (IBM OS/2 SENDMAIL VERSION 1.3.2)/1.0)
	  for papier@indi1.u-strasbg.fr; id AA0144; Tue, 16 May 95 10:37:51 -0400
In-Reply-To: <9505161552.AA14155@indi1.u-strasbg.fr>
Date: Tue, 16 May 95 10:31:02 EST
From: Michael Sinz                    <michael.sinz@scala.com>
Reply-To: Michael Sinz                <michael.sinz@scala.com>
To: papier@indi1.u-strasbg.fr
Subject: FindHit for amiga-dos gcc
Message-Id: <800634888.AA9754@scala.scala.com>
Content-Type: text
Content-Length: 26770
Status: R

>Hi,
>I'm looking for a FindHit clone for amiga-dos gcc executable and
>someone on the amiga-gcc mailing list tells me to contact you.
>Do you have this tool ?? If yes, this could be very nice to distribute
>it on Aminet.

The latest Enforcer has a FindHit that deals with DCC and SAS and
MANX.  The formats are basically the same for all of them.  (Dare I
say a "standard" line number debug format :-)  Anyway, I have no idea
what the format for GCC is.  If you would like to make a version of 
FindHit to support GCC, here is the source:

----
Michael Sinz -- Director, US Research & Development, Scala Inc.
michael.sinz@scala.com - Scala Computer Television

/*
******* FindHit ***************************************************************
*
*   NAME
*       FindHit - A tool that can locate the source file and line number
*                 that a SegTracker report happened at.
*
*   SYNOPSIS
*       FindHit will read the executable file and if there is debugging
*       information in it, will try to locate the source file and line
*       number that correspond to the Enforcer hit HUNK/OFFSET.
*
*   FUNCTION
*       FindHit uses the Lattice/SAS/MetaScope standard 'LINE'
*       debug hunk to locate the closest line to the hunk/offset given.
*       Note that this can only happen if the executable has the
*       LINE debugging turned on.  (The LawBreaker program has this
*       such that you can test this yourself.)
*
*       In SAS/C 6.x, you need to compile with DEBUG=LINE or better
*       and do not use the link option of NODEBUG.
*
*       In SAS/C 5.x, you need to compile with -d1 or better.
*       Note that FindHit works with the old SAS/C 5.x 'SRC '
*       debugging information too.  This is required for -d2 or
*       higher debugging support.  However, I do not have 'SRC ' hunk
*       documentation and thus FindHit may be very specific to the
*       SAS/C 5.x version of this hunk.
*
*       In DICE (2.07 registered being the one I tried) the -d1
*       debug switch also supports the 'LINE' debug hunk and
*       works with FindHit.
*
*       In HX68 and CAPE, you need to add the DEBUG directive to
*       the assembly code program.  (See LawBreaker source)
*
*       For other languages, or other versions of the above, please
*       see the documentation that comes with the language.
*
*   INPUTS
*       FILE/A      - The executable file, with debugging information.
*
*       OFFSETS/A/M - The HEX offset (with or without leading $)
*                     If a hunk number other than the default
*                     is needed, it is expressed as hunk:offset.
*                     The default hunk is that of the last argument
*                     or hunk 0 if no hunk number has been given.
*                     For example:  12 $22 $3:12 22 4:$12 32 $0:$32
*                     will find information for:
*                     hunk $0, offset $12
*                     hunk $0, offset $22
*                     hunk $3, offset $12
*                     hunk $3, offset $22
*                     hunk $4, offset $12
*                     hunk $4, offset $32
*                     hunk $0, offset $32
*
*   EXAMPLE
*       FindHit FooBar $0342 $1:4F2 3:$1A 2C
*       badcode.c : Line 184
*       No line number information for Hunk $1, Offset $4F2
*       badcode2.c : Line 12
*       badcode2.c : Line 14
*
*       See the Enforcer documentation about issues dealing with the
*       exact location of the Enforcer hit.  The line given may
*       not be exactly where the hit happened.
*
*       The way I use this is to always have line debugging turned on
*       when I compile.  This does not change the quality of the code
*       and takes only a small amount of extra disk space.  However,
*       what I do is to link the program twice:  Once to a file called
*       program.ld which contains all of the debugging information.
*       Then, I link program.ld to program, stripping debug information.
*       The command line for SLINK or BLINK is as follows:
*
*           BLINK program.ld TO program NODEBUG
*
*       I keep both of these on hand; with program being the one I
*       distribute and use.  When a hit happens, I can just use program.ld
*       with FindHit to get the line number and source file that it happened
*       in.  This way you can distribute your software without the debugging
*       information and still be able to use FindHit on the actual code.
*       (After all, that link command does nothing but strip symbol and
*       debug hunks)
*
*   NOTES
*       Note that this program does nothing when run from the Workbench
*       and thus does not have an icon.
*
*   SEE ALSO
*       "Quantum Physics:  The Dreams that Stuff is made of." - Michael Sinz
*
*   BUGS
*
*******************************************************************************
*/

/******

Line number debug information:

Looks like it is a debug hunk which look as follows:

0x000003F1
<size in long words>
<offset relative to current hunk>
0x4C494E45      'LINE'
<number of long words in the filename>
<file name, not NULL terminated if exactly the right length>
<line number>   <mask with 0x00FFFFFF since the upper byte is special>
<offset>
<line number>   <mask with 0x00FFFFFF since the upper byte is special>
<offset>
...

******/

#include <exec/types.h>
#include <exec/execbase.h>
#include <exec/tasks.h>
#include <exec/memory.h>
#include <exec/alerts.h>

#include <string.h>

#include <clib/exec_protos.h>
#include <pragmas/exec_pragmas.h>

#include <clib/dos_protos.h>
#include <pragmas/dos_pragmas.h>

#include <utility/tagitem.h>
#include <clib/utility_protos.h>
#include <pragmas/utility_pragmas.h>

#include <dos/dosextens.h>
#include <dos/datetime.h>
#include <dos/dosasl.h>
#include <dos/rdargs.h>

#define DOSLIB     "dos.library"
#define DOSVER     37L

/******************************************************************************/

#include        <exec/ports.h>
#include        <exec/libraries.h>
#include        <exec/semaphores.h>
#include        <exec/resident.h>

#include        <dos/doshunks.h>
#include        <dos/dos.h>
#include        <dos/dosextens.h>
#include        <dos/stdio.h>

#include        "findhit_rev.h"

/******************************************************************************/

#define CHECKEOF(x)     if (((ULONG)&bufferpos[x]) > ((ULONG)bufferend)) { rc=ERROR_FILE_NOT_OBJECT; goto ReadError; }
#define GETLONG getLong=*bufferpos++; CHECKEOF(0)

#define MASK_LINE       (0x00FFFFFF)

/*
 * This command finds the fine/line number of a SegTracker hit...
 */

/* This is the command template. */
#define TEMPLATE  "FILE/A,OFFSETS/A/M" VERSTAG

#define OPT_FILE        0
#define OPT_OFFSETS     1
#define OPT_COUNT       2

LONG cmd(void)
{
struct  Library *SysBase = (*((struct Library **) 4));
struct  Library *DOSBase;
struct  Process *proc;
struct  Message *msg=NULL;
        LONG    rc=RETURN_FAIL;

        proc=(struct Process *)FindTask(NULL);
        if (!(proc->pr_CLI))
        {
                WaitPort(&(proc->pr_MsgPort));
                msg=GetMsg(&(proc->pr_MsgPort));
        }
        else if (DOSBase = OpenLibrary(DOSLIB,DOSVER))
        {
        struct  RDArgs  *rdargs;
                LONG    opts[OPT_COUNT];

                memset((char *)opts, 0, sizeof(opts));
                rdargs = ReadArgs(TEMPLATE, opts, NULL);

                if (rdargs == NULL) PrintFault(IoErr(),NULL);
                else
                {
                BPTR    fh;

                        if (fh=Open((char *)opts[OPT_FILE],MODE_OLDFILE))
                        {
                        ULONG   getLong;
                        ULONG   *buffer;
                        ULONG   buffersize;

                                /*
                                 * Ok, so now we need to do the hard stuff
                                 * for each file...
                                 */
                                rc=RETURN_OK;

                                Seek(fh,0,OFFSET_END);
                                buffersize=Seek(fh,0,OFFSET_BEGINNING);
                                if (buffer=AllocVec(buffersize,MEMF_PUBLIC))
                                {
                                        if (buffersize==Read(fh,buffer,buffersize))
                                        {
                                        ULONG   hitHunk=0;
                                        char    **hex;

                                                for (hex=(char **)opts[OPT_OFFSETS];(*hex);hex++)
                                                {
                                                ULONG   *bufferpos;
                                                ULONG   *bufferend;
                                                ULONG   tableSize;
                                                ULONG   firstHunk;
                                                ULONG   lastHunk;
                                                ULONG   hunk;
                                                ULONG   hunkType;
                                                ULONG   hitOffset;
                                                ULONG   foundOffset;
                                                ULONG   foundName;
                                                ULONG   foundLine;
                                                char    *p;
                                                ULONG   c;

                                                        hitOffset=0;
                                                        p=*hex;
                                                        if (*p=='$') p++;       /* Support $hex */
                                                        while (c=(ULONG)*p)
                                                        {
                                                                if (c==':')
                                                                {
                                                                        /*
                                                                         * So this one had a hunk too, so change the hitHunk
                                                                         */
                                                                        hitHunk=hitOffset;
                                                                        hitOffset=0;
                                                                        p++;
                                                                        if (*p=='$') p++;       /* Support $hex */
                                                                }
                                                                else
                                                                {
                                                                        if ((c>='a') && (c<='f')) c-=32;
                                                                        c-='0';
                                                                        if (c>9)
                                                                        {
                                                                                c-=7;
                                                                                if (c<10) c=16;
                                                                        }

                                                                        if (c<16)
                                                                        {
                                                                                hitOffset=(hitOffset << 4) + c;
                                                                                p++;
                                                                        }
                                                                        else
                                                                        {
                                                                                hitOffset=0;
                                                                                p=&p[strlen(p)];
                                                                        }
                                                                }
                                                        }

                                                        /* Now look for the hunk/offset */
                                                        foundOffset=0x7FFFFFFF;
                                                        foundName=0;
                                                        foundLine=0;

                                                        bufferpos=buffer;
                                                        bufferend=(ULONG *)(((ULONG)buffer)+buffersize);

                                                        GETLONG;        /* Check for hunk header... */
                                                        if (getLong != HUNK_HEADER) { rc=ERROR_FILE_NOT_OBJECT; goto ReadError; }

                                                        GETLONG;        /* Check for resident lib */
                                                        if (getLong != 0) { rc=ERROR_FILE_NOT_OBJECT; goto ReadError; }

                                                        GETLONG;        /* Get table size */
                                                        tableSize=getLong;

                                                        GETLONG;        /* Get first hunk slot */
                                                        firstHunk=getLong;

                                                        GETLONG;        /* Last hunk slot */
                                                        lastHunk=getLong;

                                                        CHECKEOF(tableSize);
                                                        bufferpos=&bufferpos[tableSize];

                                                        hunk=firstHunk;
                                                        while ((!rc)&&(hunk<=lastHunk))
                                                        {
                                                                if (bufferpos != bufferend)
                                                                {
                                                                        GETLONG;
                                                                        hunkType=getLong & 0x3FFFFFFF;

                                                                        switch (hunkType)
                                                                        {
                                                                        case    HUNK_DEBUG:
                                                                                if (hunk==hitHunk)
                                                                                {
                                                                                ULONG   debugSize;
                                                                                ULONG   baseOffset;
                                                                                ULONG   checkName;
                                                                                ULONG   look=0;

                                                                                        debugSize=bufferpos[0];
                                                                                        CHECKEOF(debugSize);
                                                                                        baseOffset=bufferpos[1];
                                                                                        if (bufferpos[2]=='LINE')
                                                                                        {
                                                                                                /*
                                                                                                 * Name of source file
                                                                                                 * We play fast and loose
                                                                                                 * here with the fact that we
                                                                                                 * will be setting to 0 the upper
                                                                                                 * byte of the longword after the
                                                                                                 * file name (for other reasons) and
                                                                                                 * thus the file name will be NULL
                                                                                                 * terminated in all cases.
                                                                                                 */
                                                                                                checkName=(ULONG) &bufferpos[4];

                                                                                                /* Skip source file name, get to lines */
                                                                                                look=4+bufferpos[3];

                                                                                                /*
                                                                                                 * Kludge to work around a SAS/C 6.50+ strangeness...
                                                                                                 * We ignore LINE debug stuff with no offset and no
                                                                                                 * line offsets in the first two places.
                                                                                                 */
                                                                                                if ((!baseOffset) && (!bufferpos[look+1]) && (!bufferpos[look+3])) look=0;
                                                                                        }
                                                                                        else if ((bufferpos[2]=='SRC ') && (debugSize>16))
                                                                                        {
                                                                                                /*
                                                                                                 * Silly SAS/C 5.x did some strange stuff
                                                                                                 * It sometimes used the 'LINE' stuff and sometimes
                                                                                                 * it used the 'SRC ' stuff...
                                                                                                 */
                                                                                                checkName=(ULONG) &bufferpos[15];

                                                                                                /* Skip source file name, get to lines */
                                                                                                look=15 + ((bufferpos[14]+3) >> 2);
                                                                                                if (look==15) look=0;
                                                                                        }

                                                                                        if ((look) && (baseOffset<=hitOffset))
                                                                                        {
                                                                                                baseOffset=hitOffset-baseOffset;

                                                                                                while ((look<debugSize) && (bufferpos[look]&=MASK_LINE))
                                                                                                {
                                                                                                ULONG   junk=baseOffset-bufferpos[look+1];

                                                                                                        if (junk < foundOffset)
                                                                                                        {
                                                                                                                foundOffset=junk;
                                                                                                                foundLine=bufferpos[look];
                                                                                                                foundName=checkName;
                                                                                                        }
                                                                                                        look+=2;
                                                                                                }
                                                                                        }
                                                                                }
                                                                                /* Fall down into the skip code */

                                                                        case    HUNK_CODE:
                                                                        case    HUNK_DATA:
                                                                        case    HUNK_NAME:
                                                                                GETLONG;
                                                                                CHECKEOF(getLong);
                                                                                bufferpos=&bufferpos[getLong];
                                                                                break;

                                                                        case    HUNK_RELOC32:
                                                                        case    HUNK_SYMBOL:
                                                                                while (getLong)
                                                                                {
                                                                                        GETLONG;
                                                                                        if (getLong)
                                                                                        {
                                                                                                getLong++;
                                                                                                CHECKEOF(getLong);
                                                                                                bufferpos=&bufferpos[getLong];
                                                                                        }
                                                                                }
                                                                                break;

                                                                        case    HUNK_END:
                                                                                hunk++;
                                                                                break;

                                                                        case    HUNK_BSS:
                                                                                bufferpos++; CHECKEOF(0);
                                                                                break;

                                                                        default:        rc=ERROR_OBJECT_WRONG_TYPE; goto ReadError;
                                                                        }
                                                                }
                                                        }

                                                        if (foundName && foundLine)
                                                        {
                                                        ULONG   tmp[2];

                                                                tmp[0]=foundName;
                                                                tmp[1]=foundLine;
                                                                VPrintf("%s : Line %ld\n",(LONG *)tmp);
                                                        }
                                                        else
                                                        {
                                                        ULONG   tmp[2];

                                                                tmp[0]=hitHunk;
                                                                tmp[1]=hitOffset;
                                                                VPrintf("No line number information for Hunk $%lx, Offset $%lx.\n",(LONG *)tmp);
                                                        }
                                                }
                                        }
                                        else rc=IoErr();

ReadError:
                                        FreeVec(buffer);
                                }
                                else rc=IoErr();
                                Close(fh);

                        }
                        else rc=IoErr();

                        if (rc)
                        {
                                PrintFault(rc,NULL);
                                rc=RETURN_FAIL;
                        }

                FreeArgs(rdargs);
                }

                CloseLibrary(DOSBase);
        }
        else if (DOSBase=OpenLibrary(DOSLIB,0))
        {
                Write(Output(),"Requires Kickstart 2.04 (37.175) or later.\n",43);
                CloseLibrary(DOSBase);
        }

        if (msg)
        {
                Forbid();
                ReplyMsg(msg);
        }
        return(rc);
}


                      \|/
                      @ @
------------------oOO-(_)-OOo-----------------------------------------------
  Laurent Papier                    |  Etudiant en Doctorat
                                    |  Centre de Recherche en Informatique
  E-Mail:                           |  Universite Louis Pasteur
     papier@dpt-info.u-strasbg.fr   |  Strasbourg - FRANCE
----------------------------------------------------------------------------


