Re: [RFA] Runtime Dwarf2 CFI engine cleanup

Elena Zannoni
2003-02-03T16:23:43Z

Michal Ludvig writes:
> Hi all,
> the attached is a fix for the problem described here:
> http://sources.redhat.com/ml/gdb/2002-12/msg00246.html
>
> I've created a new function cleanup_cfi() in dwarf2cfi.c that deletes
> all CIEs and FDEs of objfiles removed later by objfile_purge_solibs().
> So far it works fine but I don't know how should I correctly call it.

I have tried your function, and it does fixes some weird errors which occur
on rerun.

I just tried by using the hack of defining GDB_TARGET_IS_X86_64, which
is definitely a bad thing.

I think that the best way is to define a gdbarch method, just like it
was done for gdbarch_dwarf2_build_frame_info.

In the patch below, you cannot use printf's. Use printf_filtered. But
maybe, better yet, using a warning here would be more appropriate.

Watch out for the non-GNU indentation and spacing.

elena

> For now I put the call directly to run_command():
>
> static void
> run_command (char *args, int from_tty)
> {
> [...]
> clear_breakpoint_hit_counts ();
>
> cleanup_cfi (); /* <=== HERE */
>
> objfile_purge_solibs ();
>
> do_run_cleanups (NULL);
>
> reopen_exec_file ();
> reread_symbols ();
> [...]
> }
>
> I know it isn't the right solution because it would require linking of
> dwarf2cfi.o to all targets. If I would wrap it by #ifdef X86_64 ...
> #endif it still isn't perfect, because other archs will hopefully use
> CFI in the future as well.
>
> I was thinking about defining something like USE_DWARF2CFI for each
> target that use it in their config/whatever file...? Is it a way to go?
>
> I can't attach this function to run_cleanup_chain, because I need to
> call cleanup_cfi() before objfile_purge_solibs() and also because
> do_run_cleanups() finally destroys the contents of run_cleanup_chain and
> finally because I don't know how (when/where) to attach cleanup_cfi() to
> run_cleanup_chain.
>
> Could someone please tell me what is the cleanest way to call
> cleanup_cfi()? Thanks.
>
> Michal Ludvig
> --
> * SuSE CR, s.r.o * mludvig@suse.cz
> * (+420) 296.545.373 * http://www.suse.cz
> Index: dwarf2cfi.h
> ===================================================================
> RCS file: /cvs/src/src/gdb/dwarf2cfi.c,v
> retrieving revision 1.16
> diff -u -p -r1.16 dwarf2cfi.h
> --- dwarf2cfi.h 19 Jul 2002 09:40:51 -0000 1.16
> +++ dwarf2cfi.h 20 Dec 2002 15:14:21 -0000
> @@ -64,6 +64,12 @@ struct cie_unit
>
> /* Next in chain. */
> struct cie_unit *next;
> +
> + /* Keep or destroy this CIE on a new run? */
> + int keep;
> +
> + /* How many FDEs refer to this CIE? */
> + int refs;
> };
>
> /* Frame Description Entry. */
> Index: dwarf2cfi.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/dwarf2cfi.c,v
> retrieving revision 1.16
> diff -u -p -r1.16 dwarf2cfi.c
> --- dwarf2cfi.c 19 Jul 2002 09:40:51 -0000 1.16
> +++ dwarf2cfi.c 20 Dec 2002 15:14:21 -0000
> @@ -317,6 +326,86 @@ frame_state_alloc (void)
> (struct frame_state_reg *) obstack_alloc (&unwind_tmp_obstack, regs_size);
> memset (fs->regs.reg, 0, regs_size);
> return fs;
> +}
> +
> +void
> +cleanup_cfi (void *name)
> +{
> + struct objfile *ofp;
> + struct cie_unit *cie, *cie_prev;
> + int fde_index=0, fde_free=0;
> +
> + cie = cie_chunks;
> + while (cie)
> + {
> + cie->refs = 0;
> + cie->keep = 0;
> + cie = cie->next;
> + }
> +
> + /* Mark all unwanted CIEs. */
> + ALL_OBJFILES (ofp)
> + {
> + if (!(ofp->flags & OBJF_USERLOADED) && (ofp->flags & OBJF_SHARED))
> + printf ("\tRemoving %s...\n", ofp->name);
> + else
> + {
> + printf ("\tKeeping %s...\n", ofp->name);
> + cie = cie_chunks;
> + while(cie)
> + {
> + if (cie->objfile == ofp)
> + cie->keep = 1;
> + cie = cie->next;
> + }
> + }
> + }
> +
> + /* Remove all FDEs pointing to unwanted CIEs. */
> + for (fde_index = 0, fde_free=0;
> + fde_index < fde_chunks.elems;
> + fde_index++, fde_free++)
> + {
> + if (!fde_chunks.array[fde_index]->cie_ptr->keep)
> + {
> + fde_free--;
> + continue;
> + }
> + else if (fde_free < fde_index)
> + fde_chunks.array[fde_free] = fde_chunks.array[fde_index];
> + fde_chunks.array[fde_free]->cie_ptr->refs++;
> + }
> + fde_chunks.elems = fde_free;
> +
> + /* Remove all unwanted CIEs. */
> + cie = cie_chunks;
> + cie_prev = NULL;
> + while (cie)
> + {
> + struct cie_unit *cie_tmp;
> +
> + if (! cie->keep || !cie->refs)
> + {
> + cie_tmp = cie;
> + if (cie_prev == NULL)
> + {
> + cie_chunks = cie->next;
> + cie = cie_chunks;
> + }
> + else
> + {
> + cie_prev->next = cie->next;
> + cie = cie->next;
> + }
> + /* cie_prev must remain unchanged. */
> + xfree (cie_tmp);
> + }
> + else
> + {
> + cie_prev = cie;
> + cie = cie->next;
> + }
> + }
> }
>
> static void