Skip to content

Commit eaa8e85

Browse files
committed
ggc, jit: forcibly clear GTY roots in jit
As part of Antoyo's work on supporting LTO in rustc_codegen_gcc, he noticed an ICE inside libgccjit when compiling certain rust files. Debugging libgccjit showed that outdated information from a previous in-memory compile was referring to ad-hoc locations in the previous compile's line_table. The issue turned out to be the function decls in internal_fn_fnspec_array from the previous compile keeping alive the symtab nodes for these functions, and from this finding other functions in the previous compile, walking their CFGs, and finding ad-hoc data pointers in an edge with a location_t using ad-hoc data from the previous line_table instance, and thus a use-after-free ICE attempting to use this ad-hoc data. Previously in toplev::finalize we've fixed global state "piecemeal" by calling out to individual source_name_cc_finalize functions. However, it occurred to me that we have run-time information on where the GTY-marked pointers are. Hence this patch takes something of a "big hammer" approach by adding a new ggc_common_finalize that walks the GC roots, zeroing all of the pointers. I stepped through this in the debugger and observed that, in particular, this correctly zeroes the internal_fn_fnspec_array at the end of a libgccjit compile. Antoyo reports that this fixes the ICE for him. Doing so uncovered an ICE with libgccjit in dwarf2cfi.cc due to reuse of global variables from the previous compile, which this patch also fixes. I noticed that in ggc_mark_roots when clearing deletable roots we only clear the initial element in each gcc_root_tab_t. This looks like a latent bug to me, which the patch fixes. That said, there don't seem to be any deletable roots where the number of elements != 1. gcc/ChangeLog: * dwarf2cfi.cc (dwarf2cfi_cc_finalize): New. * dwarf2out.h (dwarf2cfi_cc_finalize): New decl. * ggc-common.cc (ggc_mark_roots): Multiply by rti->nelt when clearing the deletable gcc_root_tab_t. (ggc_common_finalize): New. * ggc.h (ggc_common_finalize): New decl. * toplev.cc (toplev::finalize): Call dwarf2cfi_cc_finalize and ggc_common_finalize. Signed-off-by: David Malcolm <[email protected]>
1 parent d8b4d6c commit eaa8e85

File tree

5 files changed

+37
-1
lines changed

5 files changed

+37
-1
lines changed

gcc/dwarf2cfi.cc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3822,4 +3822,13 @@ make_pass_dwarf2_frame (gcc::context *ctxt)
38223822
return new pass_dwarf2_frame (ctxt);
38233823
}
38243824

3825+
void dwarf2cfi_cc_finalize ()
3826+
{
3827+
add_cfi_insn = NULL;
3828+
add_cfi_vec = NULL;
3829+
cur_trace = NULL;
3830+
cur_row = NULL;
3831+
cur_cfa = NULL;
3832+
}
3833+
38253834
#include "gt-dwarf2cfi.h"

gcc/dwarf2out.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,7 @@ struct fixed_point_type_info
419419
} scale_factor;
420420
};
421421

422+
void dwarf2cfi_cc_finalize (void);
422423
void dwarf2out_cc_finalize (void);
423424

424425
/* Some DWARF internals are exposed for the needs of DWARF-based debug

gcc/ggc-common.cc

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ ggc_mark_roots (void)
8686

8787
for (rt = gt_ggc_deletable_rtab; *rt; rt++)
8888
for (rti = *rt; rti->base != NULL; rti++)
89-
memset (rti->base, 0, rti->stride);
89+
memset (rti->base, 0, rti->stride * rti->nelt);
9090

9191
for (rt = gt_ggc_rtab; *rt; rt++)
9292
ggc_mark_root_tab (*rt);
@@ -1293,3 +1293,24 @@ report_heap_memory_use ()
12931293
SIZE_AMOUNT (MALLINFO_FN ().arena));
12941294
#endif
12951295
}
1296+
1297+
/* Forcibly clear all GTY roots. */
1298+
1299+
void
1300+
ggc_common_finalize ()
1301+
{
1302+
const struct ggc_root_tab *const *rt;
1303+
const_ggc_root_tab_t rti;
1304+
1305+
for (rt = gt_ggc_deletable_rtab; *rt; rt++)
1306+
for (rti = *rt; rti->base != NULL; rti++)
1307+
memset (rti->base, 0, rti->stride * rti->nelt);
1308+
1309+
for (rt = gt_ggc_rtab; *rt; rt++)
1310+
for (rti = *rt; rti->base != NULL; rti++)
1311+
memset (rti->base, 0, rti->stride * rti->nelt);
1312+
1313+
for (rt = gt_pch_scalar_rtab; *rt; rt++)
1314+
for (rti = *rt; rti->base != NULL; rti++)
1315+
memset (rti->base, 0, rti->stride * rti->nelt);
1316+
}

gcc/ggc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,4 +368,6 @@ inline void gt_ggc_mx (unsigned long int) { }
368368
inline void gt_ggc_mx (long long int) { }
369369
inline void gt_ggc_mx (unsigned long long int) { }
370370

371+
extern void ggc_common_finalize ();
372+
371373
#endif

gcc/toplev.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2336,6 +2336,7 @@ toplev::finalize (void)
23362336
cgraph_cc_finalize ();
23372337
cgraphunit_cc_finalize ();
23382338
symtab_thunks_cc_finalize ();
2339+
dwarf2cfi_cc_finalize ();
23392340
dwarf2out_cc_finalize ();
23402341
gcse_cc_finalize ();
23412342
ipa_cp_cc_finalize ();
@@ -2350,6 +2351,8 @@ toplev::finalize (void)
23502351
save_decoded_options = NULL;
23512352
save_decoded_options_count = 0;
23522353

2354+
ggc_common_finalize ();
2355+
23532356
/* Clean up the context (and pass_manager etc). */
23542357
delete g;
23552358
g = NULL;

0 commit comments

Comments
 (0)