Op 21-08-2025 om 08:16 schreef Herman ten Brugge:
Op 19-08-2025 om 23:32 schreef grischka:
On 19.08.2025 11:35, Herman ten Brugge via Tinycc-devel wrote:
As to the debug problem:

I tested stabs and did 'p *s' in tcc.exe:main() to see TCCState,
nothing.  So it turned out that because TCCState is typedef'd in
libtcc.h first, it is in stabs with no members and a size of -1
and won't be added later because it already was.

Dwarf seems to have another problem though that in a case with some
mutually linked structures, it would quickly eat up 2GB -> memory full.
Which is why I added -g1dwarf switch so I can compile that project.

Seems that stabs works because the tcc_debug_remove(s1, e); doesn't
work ('e' was never added). Whereas with dwarf 't' is removed but
the code never stops.

Why should it output the same structure more than once anyway ?

I debugged this and for stabs and dwarf it is used to register anon structs
(struct with no definition):
The is for example the case in __locale_t.h on my distrubution:

struct __locale_struct
{
  struct __locale_data *__locales[13];
  ...
};

The __locale_data struct is never defined so I create a anon type for it.
If it is later defined I will replace this with the correct type in dwarf code.
I cannot do this for stabs but still need to do this because otherwise I
create illegal stabs code.

If I compile tcc with your patch the stab is only 42 lines shorter (0.03%)  (objdump -G) because no anons are output. The dwarf output is 259 lines shorter (0.03%) (objdump -W).

I fix the anons at the end of the dwarf output with dummy types. This is where the 0xffffffff
comes from when I do not do this.

I debugged the code some more and found that I did not handle file scope correctly. I created indeed multiple copies of same types if they are present inside the function code.

I created a patch (see attachment) to fix this.

    Herman

diff --git a/tccdbg.c b/tccdbg.c
index 4fd0150..27a8200 100644
--- a/tccdbg.c
+++ b/tccdbg.c
@@ -334,6 +334,8 @@ struct _tccdbg {
     struct _debug_info {
         int start;
         int end;
+        int last_debug_hash;
+        int last_debug_anon_hash;
         int n_sym;
         struct debug_sym {
             int type;
@@ -1192,6 +1194,8 @@ ST_FUNC void tcc_debug_start(TCCState *s1)
     }
 }
 
+static void fix_debug_anon_hash(TCCState *s1, int start);
+
 /* put end of translation unit info */
 ST_FUNC void tcc_debug_end(TCCState *s1)
 {
@@ -1202,31 +1206,13 @@ ST_FUNC void tcc_debug_end(TCCState *s1)
         tcc_debug_funcend(s1, 0); /* free stuff in case of errors */
 
     if (s1->dwarf) {
-       int i, j;
+       int i;
        int start_aranges;
        unsigned char *ptr;
        int text_size = text_section->data_offset;
 
        /* dwarf_info */
-       for (i = 0; i < n_debug_anon_hash; i++) {
-           Sym *t = debug_anon_hash[i].type;
-           int pos = dwarf_info_section->data_offset;
-
-           dwarf_data1(dwarf_info_section,
-                        IS_UNION (t->type.t) ? DWARF_ABBREV_UNION_EMPTY_TYPE
-                                             : 
DWARF_ABBREV_STRUCTURE_EMPTY_TYPE);
-            dwarf_strp(dwarf_info_section,
-                       (t->v & ~SYM_STRUCT) >= SYM_FIRST_ANOM
-                       ? "" : get_tok_str(t->v, NULL));
-            dwarf_uleb128(dwarf_info_section, 0);
-            dwarf_uleb128(dwarf_info_section, dwarf_line.cur_file);
-            dwarf_uleb128(dwarf_info_section, file->line_num);
-           for (j = 0; j < debug_anon_hash[i].n_debug_type; j++)
-               write32le(dwarf_info_section->data +
-                         debug_anon_hash[i].debug_type[j],
-                         pos - dwarf_info.start);
-           tcc_free (debug_anon_hash[i].debug_type);
-       }
+       fix_debug_anon_hash(s1, 0);
        tcc_free (debug_anon_hash);
        dwarf_data1(dwarf_info_section, 0);
        ptr = dwarf_info_section->data + dwarf_info.start;
@@ -1325,6 +1311,7 @@ ST_FUNC void tcc_debug_end(TCCState *s1)
     }
     else
     {
+       tcc_free (debug_anon_hash);
         put_stabs_r(s1, NULL, N_SO, 0, 0,
                     text_section->data_offset, text_section, section_sym);
     }
@@ -1473,6 +1460,33 @@ static void tcc_debug_stabs (TCCState *s1, const char 
*str, int type, unsigned l
         put_stabs (s1, str, type, 0, 0, value);
 }
 
+static void fix_debug_anon_hash(TCCState *s1, int start)
+{
+    if (s1->dwarf) {
+        int i, j;
+
+       for (i = start; i < n_debug_anon_hash; i++) {
+           Sym *t = debug_anon_hash[i].type;
+           int pos = dwarf_info_section->data_offset;
+
+           dwarf_data1(dwarf_info_section,
+                        IS_UNION (t->type.t) ? DWARF_ABBREV_UNION_EMPTY_TYPE
+                                             : 
DWARF_ABBREV_STRUCTURE_EMPTY_TYPE);
+            dwarf_strp(dwarf_info_section,
+                       (t->v & ~SYM_STRUCT) >= SYM_FIRST_ANOM
+                       ? "" : get_tok_str(t->v, NULL));
+            dwarf_uleb128(dwarf_info_section, 0);
+            dwarf_uleb128(dwarf_info_section, dwarf_line.cur_file);
+            dwarf_uleb128(dwarf_info_section, file->line_num);
+           for (j = 0; j < debug_anon_hash[i].n_debug_type; j++)
+               write32le(dwarf_info_section->data +
+                         debug_anon_hash[i].debug_type[j],
+                         pos - dwarf_info.start);
+           tcc_free (debug_anon_hash[i].debug_type);
+       }
+    }
+}
+
 ST_FUNC void tcc_debug_stabn(TCCState *s1, int type, int value)
 {
     if (!s1->do_debug)
@@ -1482,6 +1496,8 @@ ST_FUNC void tcc_debug_stabn(TCCState *s1, int type, int 
value)
             (struct _debug_info *) tcc_mallocz(sizeof (*info));
 
         info->start = value;
+        info->last_debug_hash = n_debug_hash;
+        info->last_debug_anon_hash = n_debug_anon_hash;
         info->parent = debug_info;
         if (debug_info) {
             if (debug_info->child) {
@@ -1499,6 +1515,9 @@ ST_FUNC void tcc_debug_stabn(TCCState *s1, int type, int 
value)
         debug_info = info;
     }
     else {
+       fix_debug_anon_hash(s1, debug_info->last_debug_anon_hash);
+        n_debug_hash = debug_info->last_debug_hash;
+        n_debug_anon_hash = debug_info->last_debug_anon_hash;
         debug_info->end = value;
         debug_info = debug_info->parent;
     }
@@ -1508,8 +1527,7 @@ static int tcc_debug_find(TCCState *s1, Sym *t, int dwarf)
 {
     int i;
 
-    if (!debug_info && dwarf &&
-       (t->type.t & VT_BTYPE) == VT_STRUCT && t->c == -1) {
+    if ((t->type.t & VT_BTYPE) == VT_STRUCT && t->c == -1) {
        for (i = 0; i < n_debug_anon_hash; i++)
             if (t == debug_anon_hash[i].type)
                return 0;
@@ -1533,7 +1551,7 @@ static void tcc_debug_check_anon(TCCState *s1, Sym *t, 
int debug_type)
 {
     int i;
 
-    if (!debug_info && (t->type.t & VT_BTYPE) == VT_STRUCT && t->type.ref->c 
== -1)
+    if ((t->type.t & VT_BTYPE) == VT_STRUCT && t->type.ref->c == -1)
        for (i = 0; i < n_debug_anon_hash; i++)
             if (t->type.ref == debug_anon_hash[i].type) {
                debug_anon_hash[i].debug_type =
@@ -1548,23 +1566,22 @@ ST_FUNC void tcc_debug_fix_anon(TCCState *s1, CType *t)
 {
     int i, j, debug_type;
 
-    if (!(s1->do_debug & 2) || !s1->dwarf || debug_info)
+    if (!(s1->do_debug & 2))
        return;
 
     if ((t->t & VT_BTYPE) == VT_STRUCT && t->ref->c != -1)
        for (i = 0; i < n_debug_anon_hash; i++)
            if (t->ref == debug_anon_hash[i].type) {
-               Sym sym = {0}; sym .type = *t ;
-
-               /* Trick to not hash this struct */
-               debug_info = (struct _debug_info *) t;
-               debug_type = tcc_get_dwarf_info(s1, &sym);
-               debug_info = NULL;
-               for (j = 0; j < debug_anon_hash[i].n_debug_type; j++)
-                   write32le(dwarf_info_section->data +
-                             debug_anon_hash[i].debug_type[j],
-                             debug_type - dwarf_info.start);
-               tcc_free(debug_anon_hash[i].debug_type);
+               if (s1->dwarf) {
+                   Sym sym = {0}; sym .type = *t ;
+
+                   debug_type = tcc_get_dwarf_info(s1, &sym);
+                   for (j = 0; j < debug_anon_hash[i].n_debug_type; j++)
+                       write32le(dwarf_info_section->data +
+                                 debug_anon_hash[i].debug_type[j],
+                                 debug_type - dwarf_info.start);
+                   tcc_free(debug_anon_hash[i].debug_type);
+               }
                n_debug_anon_hash--;
                for (; i < n_debug_anon_hash; i++)
                    debug_anon_hash[i] = debug_anon_hash[i + 1];
@@ -1582,18 +1599,6 @@ static int tcc_debug_add(TCCState *s1, Sym *t, int dwarf)
     return offset;
 }
 
-static void tcc_debug_remove(TCCState *s1, Sym *t)
-{
-    int i;
-
-    for (i = 0; i < n_debug_hash; i++)
-        if (t == debug_hash[i].type) {
-           n_debug_hash--;
-           for (; i < n_debug_hash; i++)
-               debug_hash[i] = debug_hash[i+1];
-       }
-}
-
 #define        STRUCT_NODEBUG(s)                              \
     (s->a.nodebug ||                           \
      ((s->v & ~SYM_FIELD) >= SYM_FIRST_ANOM && \
@@ -1621,11 +1626,9 @@ static void tcc_get_debug_info(TCCState *s1, Sym *s, 
CString *result)
             break;
     }
     if ((type & VT_BTYPE) == VT_STRUCT) {
-       Sym *e = t;
-
         t = t->type.ref;
        debug_type = tcc_debug_find(s1, t, 0);
-        if (debug_type == -1 && t->c >= 0) {
+        if (debug_type == -1) {
             debug_type = tcc_debug_add(s1, t, 0);
             cstr_new (&str);
             cstr_printf (&str, "%s:T%d=%c%d",
@@ -1656,15 +1659,13 @@ static void tcc_get_debug_info(TCCState *s1, Sym *s, 
CString *result)
             cstr_printf (&str, ";");
             tcc_debug_stabs(s1, str.data, N_LSYM, 0, NULL, 0, 0);
             cstr_free (&str);
-            if (debug_info)
-                tcc_debug_remove(s1, e);
         }
     }
     else if (IS_ENUM(type)) {
         Sym *e = t = t->type.ref;
 
        debug_type = tcc_debug_find(s1, t, 0);
-       if (debug_type == -1 && t->c >= 0) {
+       if (debug_type == -1) {
            debug_type = tcc_debug_add(s1, t, 0);
             cstr_new (&str);
             cstr_printf (&str, "%s:T%d=e",
@@ -1682,8 +1683,6 @@ static void tcc_get_debug_info(TCCState *s1, Sym *s, 
CString *result)
             cstr_printf (&str, ";");
             tcc_debug_stabs(s1, str.data, N_LSYM, 0, NULL, 0, 0);
             cstr_free (&str);
-            if (debug_info)
-                tcc_debug_remove(s1, e);
        }
     }
     else if ((type & VT_BTYPE) != VT_FUNC) {
@@ -1741,7 +1740,7 @@ static int tcc_get_dwarf_info(TCCState *s1, Sym *s)
     if ((type & VT_BTYPE) == VT_STRUCT) {
         t = t->type.ref;
        debug_type = tcc_debug_find(s1, t, 1);
-       if (debug_type == -1 && t->c >= 0) {
+       if (debug_type == -1) {
            int pos_sib = 0, i, *pos_type;
 
            debug_type = tcc_debug_add(s1, t, 1);
@@ -1812,14 +1811,12 @@ static int tcc_get_dwarf_info(TCCState *s1, Sym *s)
                          type - dwarf_info.start);
            }
            tcc_free(pos_type);
-           if (debug_info)
-               tcc_debug_remove(s1, t);
         }
     }
     else if (IS_ENUM(type)) {
         t = t->type.ref;
        debug_type = tcc_debug_find(s1, t, 1);
-       if (debug_type == -1 && t->c >= 0) {
+       if (debug_type == -1) {
            int pos_sib, pos_type;
            Sym sym = {0}; sym.type.t = VT_INT | (type & VT_UNSIGNED);
 
@@ -1854,8 +1851,6 @@ static int tcc_get_dwarf_info(TCCState *s1, Sym *s)
            dwarf_data1(dwarf_info_section, 0);
            write32le(dwarf_info_section->data + pos_sib,
                      dwarf_info_section->data_offset - dwarf_info.start);
-           if (debug_info)
-               tcc_debug_remove(s1, t);
        }
     }
     else if ((type & VT_BTYPE) != VT_FUNC) {
_______________________________________________
Tinycc-devel mailing list
Tinycc-devel@nongnu.org
https://lists.nongnu.org/mailman/listinfo/tinycc-devel

Reply via email to