On Fri, 2016-02-12 at 00:51 -0700, Jeff Law wrote:
> On 02/11/2016 10:12 PM, David Malcolm wrote:
> > In r227188 I introduced driver::finalize () which resets
> > all state within gcc.c, allowing the driver code to embedded
> > inside libgccjit and run repeatedly in-process.
> > 
> > Running this on s390x revealed a bug in this cleanup:
> > I was cleaning up "specs" via:
> >                  XDELETEVEC (specs);
> > and this was crashing on s390x with:
> >    free(): invalid pointer: 0x000003fffdf30568 ***
> > 
> > Closer investigation revealed that specs == static_specs,
> > a statically allocated array.
> > 
> > What's happening is that set_specs sets "specs" to static_specs
> > the first time it's called, and any calls to set_specs () with
> > a name that isn't in static_specs cause a new spec_list node
> > to be dynamically-allocated and put at the front of the list;
> > "specs"
> > then equals that.
> > 
> > All of my testing had been on x86_64, which inserts exactly one
> > spec
> > with a name not in the static array, hence the:
> >                  XDELETEVEC (specs);
> > happened to work.
> > 
> > On s390x, the only names in the "specs" file are those in the
> > static
> > array, so specs == static_specs, and the bogus cleanup code
> > attempts
> > to free a statically-allocated array.
> > 
> > The following patch reworks this part of the cleanup, walking any
> > list
> > of specs, freeing the dynamically-allocated nodes until the
> > statically-allocated ones are reached.
> > 
> > driver::finalize is only called by libgccjit, not by the main
> > driver
> > program, so this should be relatively low-risk.
> > 
> > Verified directly by running under valgrind on x86_64 and s390x.
> > 
> > With the patch, jit.sum on s390x-ibm-linux-gnu (RHEL 7) goes from:
> >    # of expected passes            1799
> >    # of unexpected failures        61
> >    # of unresolved testcases       2
> > to:
> >    # of expected passes            8514
> > 
> > Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu.
> > 
> > OK for trunk?
> > 
> > gcc/ChangeLog:
> >     PR driver/69779
> >     * gcc.c (driver::finalize): Fix cleanup of "specs".
> Can't you just "free (specs->name) rather than messing with the cast?
> 
> OK with that twiddle, assuming it works.

Thanks.

The problem is that struct spec_list's "name" field is declared const:

  const char *name;             /* name of the spec.  */

and likewise for the "name" field within struct spec_list_1:

  const char *const name;

Some are statically allocated, others are dynamically allocated.

If I convert them to:

  char *name;           /* name of the spec.  */

and:

  char *const name;

respectively, then I run into lots of:
 warning: ISO C++ forbids converting a string constant to ‘char*’ [
-Wpedantic]

Some of these warnings are (relatively) easily fixed by adding a
  const_cast <char *> 
to gcc.c's INIT_STATIC_SPEC.  However, the other warnings are from
this:

 static const struct spec_list_1 extra_specs_1[] = { EXTRA_SPECS };

EXTRA_SPECS is defined in the config-specific subdirectories in
numerous ways, and touching those seems like too big a rathole to be
going down, especially in stage 4.

It seems simpler to keep the "const" on those string fields, and cast
it away when cleaning up the dynamically-allocated ones (as in the
candidate patch).

OK without the twiddle?

Dave

Reply via email to