]> git.sur5r.net Git - cc65/commitdiff
First support for symbols - mostly untested.
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Mon, 9 Aug 2010 22:05:44 +0000 (22:05 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Mon, 9 Aug 2010 22:05:44 +0000 (22:05 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@4805 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/dbginfo/dbginfo.c
src/dbginfo/dbginfo.h
src/dbginfo/dbgtest.c

index 41da640c1316dff9ebf21373772f094949637e17..c8b4c788601f43dd8dcbef0f90d6e5dbd883b1b5 100644 (file)
@@ -90,6 +90,7 @@ struct DbgInfo {
     Collection  FileInfoByName;         /* File infos sorted by name */
     Collection  FileInfoById;           /* File infos sorted by id */
     Collection  LineInfoByAddr;         /* Line information sorted by address */
+    Collection  SymInfoByName;          /* Symbol information sorted by name */
 };
 
 /* Input tokens */
@@ -196,6 +197,14 @@ struct LineInfo {
     } Seg;
 };
 
+/* Internally used symbol info struct */
+typedef struct SymInfo SymInfo;
+struct SymInfo {
+    cc65_symbol_type    Type;           /* Type of symbol */
+    long                Value;          /* Value of symbol */
+    char                SymName[1];     /* Name of symbol */
+};
+
 
 
 /*****************************************************************************/
@@ -837,6 +846,47 @@ static int CompareFileInfoById (const void* L, const void* R)
 
 
 
+/*****************************************************************************/
+/*                                Symbol info                                */
+/*****************************************************************************/
+
+
+
+static SymInfo* NewSymInfo (const StrBuf* Name, long Val, cc65_symbol_type Type)
+/* Create a new SymInfo struct, intialize and return it */
+{
+    /* Allocate memory */
+    SymInfo* S = xmalloc (sizeof (SymInfo) + SB_GetLen (Name));
+
+    /* Initialize it */
+    S->Value = Val;
+    S->Type  = Type;
+    memcpy (S->SymName, SB_GetConstBuf (Name), SB_GetLen (Name) + 1);
+
+    /* Return it */
+    return S;
+}
+
+
+
+static void FreeSymInfo (SymInfo* S)
+/* Free a SymInfo struct */
+{
+    xfree (S);
+}
+
+
+
+static int CompareSymInfoByName (const void* L, const void* R)
+/* Helper function to sort symbol infos in a collection by name */
+{
+    /* Sort by file name */
+    return strcmp (((const SymInfo*) L)->SymName,
+                   ((const SymInfo*) R)->SymName);
+}
+
+
+
 /*****************************************************************************/
 /*                                Debug info                                 */
 /*****************************************************************************/
@@ -855,6 +905,7 @@ static DbgInfo* NewDbgInfo (void)
     InitCollection (&Info->FileInfoByName);
     InitCollection (&Info->FileInfoById);
     InitCollection (&Info->LineInfoByAddr);
+    InitCollection (&Info->SymInfoByName);
 
     /* Return it */
     return Info;
@@ -884,6 +935,12 @@ static void FreeDbgInfo (DbgInfo* Info)
     /* Free line info */
     DoneCollection (&Info->LineInfoByAddr);
 
+    /* Free symbol info */
+    for (I = 0; I < CollCount (&Info->SymInfoByName); ++I) {
+        FreeSymInfo (CollAt (&Info->SymInfoByName, I));
+    }
+    DoneCollection (&Info->SymInfoByName);
+
     /* Free the structure itself */
     xfree (Info);
 }
@@ -1704,6 +1761,7 @@ static void ParseSym (InputData* D)
     cc65_symbol_type    Type;
     long                Value;
     StrBuf              SymName = STRBUF_INITIALIZER;
+    SymInfo*            S;
     enum {
         ibNone          = 0x00,
         ibSymName       = 0x01,
@@ -1814,10 +1872,8 @@ static void ParseSym (InputData* D)
     }
 
     /* Create the symbol info and remember it */
-#if 0
-    S = NewSegInfo (&SegName, Id, Start, Size, &OutputName, OutputOffs);
-    CollAppend (&D->Info->SegInfoByName, S);
-#endif
+    S = NewSymInfo (&SymName, Value, Type);
+    CollAppend (&D->Info->SymInfoByName, S);
 
 ErrorExit:
     /* Entry point in case of errors */
@@ -2287,6 +2343,61 @@ static LineInfo* FindLineInfoByLine (FileInfo* F, cc65_line Line)
 
 
 
+static void ProcessSymInfo (InputData* D)
+/* Postprocess symbol infos */
+{
+    /* Get pointers to the symbol info collections */
+    Collection* SymInfoByName = &D->Info->SymInfoByName;
+
+    /* Sort the symbol infos by name */
+    CollSort (SymInfoByName, CompareSymInfoByName);
+}
+
+
+
+static int FindSymInfoByName (Collection* SymInfos, const char* SymName, int* Index)
+/* Find the SymInfo for a given file name. The function returns true if the
+ * name was found. In this case, Index contains the index of the first item
+ * that matches. If the item wasn't found, the function returns false and
+ * Index contains the insert position for SymName.
+ */
+{
+    /* Do a binary search */
+    int Lo = 0;
+    int Hi = (int) CollCount (SymInfos) - 1;
+    int Found = 0;
+    while (Lo <= Hi) {
+
+        /* Mid of range */
+        int Cur = (Lo + Hi) / 2;
+
+        /* Get item */
+        SymInfo* CurItem = CollAt (SymInfos, Cur);
+
+        /* Compare */
+        int Res = strcmp (CurItem->SymName, SymName);
+
+        /* Found? */
+        if (Res < 0) {
+            Lo = Cur + 1;
+        } else {
+            Hi = Cur - 1;
+            /* Since we may have duplicates, repeat the search until we've
+             * the first item that has a match.
+             */
+            if (Res == 0) {
+                Found = 1;
+            }
+        }
+    }
+
+    /* Pass back the index. This is also the insert position */
+    *Index = Lo;
+    return Found;
+}
+
+
+
 /*****************************************************************************/
 /*                                          Code                                    */
 /*****************************************************************************/
@@ -2424,6 +2535,7 @@ cc65_dbginfo cc65_read_dbginfo (const char* FileName, cc65_errorfunc ErrFunc)
     ProcessSegInfo (&D);
     ProcessFileInfo (&D);
     ProcessLineInfo (&D);
+    ProcessSymInfo (&D);
 
     /* Return the debug info struct that was created */
     return D.Info;
@@ -2570,7 +2682,7 @@ cc65_sourceinfo* cc65_get_sourcelist (cc65_dbginfo Handle)
     for (I = 0; I < CollCount (FileInfoByName); ++I) {
 
         /* Get this item */
-        FileInfo* F = CollAt (FileInfoByName, I);
+        const FileInfo* F = CollAt (FileInfoByName, I);
 
         /* Copy the data */
         D->data[I].source_name  = F->FileName;
@@ -2610,7 +2722,7 @@ cc65_segmentinfo* cc65_get_segmentlist (cc65_dbginfo Handle)
     /* The handle is actually a pointer to a debug info struct */
     Info = (DbgInfo*) Handle;
 
-    /* Get a pointer to the file list */
+    /* Get a pointer to the segment list */
     SegInfoByName = &Info->SegInfoByName;
 
     /* Allocate memory for the data structure returned to the caller */
@@ -2622,7 +2734,7 @@ cc65_segmentinfo* cc65_get_segmentlist (cc65_dbginfo Handle)
     for (I = 0; I < CollCount (SegInfoByName); ++I) {
 
         /* Get this item */
-        SegInfo* S = CollAt (SegInfoByName, I);
+        const SegInfo* S = CollAt (SegInfoByName, I);
 
         /* Copy the data */
         D->data[I].segment_name  = S->SegName;
@@ -2650,3 +2762,76 @@ void cc65_free_segmentinfo (cc65_dbginfo Handle, cc65_segmentinfo* Info)
 
 
 
+cc65_symbolinfo* cc65_symbol_byname (cc65_dbginfo Handle, const char* Name)
+/* Return a list of symbols with a given name. The function returns NULL if
+ * no symbol with this name was found.
+ */
+{
+    DbgInfo*            Info;
+    Collection*         SymInfoByName;
+    cc65_symbolinfo*    D;
+    unsigned            I;
+    int                 Index;
+    unsigned            Count;
+
+    /* Check the parameter */
+    assert (Handle != 0);
+
+    /* The handle is actually a pointer to a debug info struct */
+    Info = (DbgInfo*) Handle;
+
+    /* Get a pointer to the symbol list */
+    SymInfoByName = &Info->SymInfoByName;
+
+    /* Search for the symbol */
+    if (!FindSymInfoByName (SymInfoByName, Name, &Index)) {
+        /* Not found */
+        return 0;
+    }
+
+    /* Index contains the position. Count how many symbols with this name
+     * we have. Skip the first one, since we have at least one.
+     */
+    Count = 1;
+    while ((unsigned) Index + Count < CollCount (SymInfoByName)) {
+        const SymInfo* S = CollAt (SymInfoByName, (unsigned) Index + Count);
+        if (strcmp (S->SymName, Name) != 0) {
+            break;
+        }
+        ++Count;
+    }
+
+    /* Allocate memory for the data structure returned to the caller */
+    D = xmalloc (sizeof (*D) + (Count - 1) * sizeof (D->data[0]));
+
+    /* Fill in the data */
+    D->count = Count;
+    while (Count--) {
+
+        /* Get this item */
+        const SymInfo* S = CollAt (SymInfoByName, Index);
+
+        /* Copy the data */
+        D->data[I].symbol_name  = S->SymName;
+        D->data[I].symbol_type  = S->Type;
+        D->data[I].symbol_value = S->Value;
+    }
+
+    /* Return the result */
+    return D;
+}
+
+
+
+void cc65_free_symbolinfo (cc65_dbginfo Handle, cc65_symbolinfo* Info)
+/* Free a symbol info record */
+{
+    /* Just for completeness, check the handle */
+    assert (Handle != 0);
+
+    /* Free the memory */
+    xfree (Info);
+}
+
+
+
index f1348fcd5e949ef4921e999c81de6f9bb94238d9..699091385f38cf29455dcc225ab04ef74a6e3d3a 100644 (file)
@@ -207,6 +207,14 @@ cc65_segmentinfo* cc65_get_segmentlist (cc65_dbginfo handle);
 void cc65_free_segmentinfo (cc65_dbginfo handle, cc65_segmentinfo* info);
 /* Free a segment info record */
 
+cc65_symbolinfo* cc65_symbol_byname (cc65_dbginfo Handle, const char* Name);
+/* Return a list of symbols with a given name. The function returns NULL if
+ * no symbol with this name was found.
+ */
+                                                                            
+void cc65_free_symbolinfo (cc65_dbginfo Handle, cc65_symbolinfo* Info);
+/* Free a symbol info record */
+
 
 
 /* Allow usage from C++ */
index f83a749a5c07898c9c765aa9f90c9ffc123a2727..82b5cced039caded1c18d75cc2131ca66e032184 100644 (file)
@@ -67,7 +67,8 @@ int main (int argc, char** argv)
     cc65_dbginfo        Info;
     cc65_sourceinfo*    Sources;
     cc65_segmentinfo*   Segments;
-    cc65_lineinfo*      L;
+    cc65_lineinfo*      Lines;
+    cc65_symbolinfo*    Symbols;
     unsigned            I;
     unsigned long       Addr;
 
@@ -113,14 +114,14 @@ int main (int argc, char** argv)
 
     /* Check one line */
     printf ("Requesting line info for crt0.s(59):\n");
-    L = cc65_lineinfo_byname (Info, "crt0.s", 59);
-    if (L == 0) {
+    Lines = cc65_lineinfo_byname (Info, "crt0.s", 59);
+    if (Lines == 0) {
         printf ("  Not found\n");
     } else {
         printf ("  Code range is $%04X-$%04X\n",
-                L->data[0].line_start,
-                L->data[0].line_end);
-        cc65_free_lineinfo (Info, L);
+                Lines->data[0].line_start,
+                Lines->data[0].line_end);
+        cc65_free_lineinfo (Info, Lines);
     }
 
     /* Output debug information for all addresses in the complete 6502 address
@@ -128,29 +129,45 @@ int main (int argc, char** argv)
      */
     printf ("Line info:\n");
     for (Addr = 0; Addr < 0x10000; ++Addr) {
-        L = cc65_lineinfo_byaddr (Info, Addr);
-        if (L) {
+        Lines = cc65_lineinfo_byaddr (Info, Addr);
+        if (Lines) {
             unsigned I;
             printf ("  $%04lX: ", Addr);
-            for (I = 0; I < L->count; ++I) {
+            for (I = 0; I < Lines->count; ++I) {
                 if (I > 0) {
                     printf (", ");
                 }
-                printf ("%s(%lu)", 
-                        L->data[I].source_name,
-                        (unsigned long) L->data[I].source_line);
-                if (L->data[I].output_name) {
+                printf ("%s(%lu)",
+                        Lines->data[I].source_name,
+                        (unsigned long) Lines->data[I].source_line);
+                if (Lines->data[I].output_name) {
                     printf ("  %s($%06lX)",
-                            L->data[I].output_name,
-                            L->data[I].output_offs);
+                            Lines->data[I].output_name,
+                            Lines->data[I].output_offs);
 
                 }
             }
             printf ("\n");
-            cc65_free_lineinfo (Info, L);
+            cc65_free_lineinfo (Info, Lines);
         }
     }
 
+    /* Check for address of main */
+    printf ("Requesting address of _main:\n");
+    Symbols = cc65_symbol_byname (Info, "_main");
+    if (Symbols == 0) {
+        printf ("  Not found\n");
+    } else {                             
+        unsigned I;
+        for (I = 0; I < Symbols->count; ++I) {
+            printf ("  %-20s = %04lX\n", 
+                    Symbols->data[I].symbol_name,
+                    Symbols->data[I].symbol_value);
+        }
+        cc65_free_symbolinfo (Info, Symbols);
+    }
+
+
     /* Free the debug info */
     cc65_free_dbginfo (Info);