On Fri, Nov 5, 2021 at 5:37 PM Iain Sandoe <i...@sandoe.co.uk> wrote: > > > > > On 5 Nov 2021, at 15:25, Jakub Jelinek <ja...@redhat.com> wrote: > > > > On Fri, Nov 05, 2021 at 11:31:58AM +0100, Richard Biener wrote: > >> On Fri, Nov 5, 2021 at 10:54 AM Jakub Jelinek <ja...@redhat.com> wrote: > >>> > >>> On Fri, Nov 05, 2021 at 10:42:05AM +0100, Richard Biener via Gcc-patches > >>> wrote: > >>>> I had the impression we have support for PCH file relocation to deal > >>>> with ASLR > >>>> at least on some platforms. > >>> > >>> Unfortunately we do not, e.g. if you build cc1/cc1plus as PIE on > >>> x86_64-linux, PCH will stop working unless one always invokes it with > >>> disabled ASLR through personality. > >>> > >>> I think this is related to function pointers and pointers to .rodata/.data > >>> etc. variables in GC memory, we currently do not relocate that. > >>> > >>> What we perhaps could do is (at least assuming all the ELF PT_LOAD > >>> segments > >>> are adjacent with a single load base for them - I think at least ia64 > >>> non-PIE binaries were violating this by having .text and .data PT_LOAD > >>> segments many terrabytes appart with a whole in between not protected in > >>> any > >>> way, but dunno if that is for PIEs too), perhaps try in a host > >>> specific way remember the address range in which the function pointers and > >>> .rodata/.data can exist, remember the extent start and end from PCH > >>> generation > >>> and on PCH load query those addresses for the current compiler and > >>> relocate > >>> everything in that extent by the load bias from the last run. > >>> But, the assumption for this is that those function and data/rodata > >>> pointers > >>> in GC memory are actually marked at least as pointers... > >> > >> If any such pointers exist they must be marked GTY((skip)) since they do > >> not > >> point to GC memory... So we'd need to invent special-handling for those. > >> > >>> Do we e.g. have objects with virtual classes in GC memory and if so, do we > >>> catch their virtual table pointers? > >> > >> Who knows, but then I don't remember adding stuff that should end in a PCH. > > > > So, I've investigated a little bit. > > Apparently all the relocation we currently do for PCH is done at PCH write > > time, we choose some address range in the address space we think will be > > likely > > mmappable each time successfully, relocate all pointers pointing to GC > > memory to point in there and then write that to file, together with the > > scalar GTY global vars values and GTY pointers in global vars. > > On PCH load, we just try to mmap memory in the right range, fail PCH load if > > unsuccessful, and read the GC memory into that range and update scalar and > > pointer GTY global vars from what we've recorded. > > Patch that made PCH load to fail for PIEs etc. was > > https://gcc.gnu.org/legacy-ml/gcc-patches/2003-10/msg01994.html > > If we wanted to relocate pointers to functions and .data/.rodata etc., > > ideally we'd create a relocation list of addresses that should be > > incremented by the bias and quickly relocate those. > > It is hard to judge the relative effort in the two immediately visible > solutions: > > 1. relocatable PCH > 2. taking the tree streamer from the modules implementation, moving its home > to c-family and adding hooks so that each FE can stream its own special > trees. > > ISTM, that part of the reason people dislike PCH is because the > implementation is > mixed up with the GC solution - the rendering is non-transparent etc.
Yes. In particular it stands in the way of even thinking of doing sth different than GC for trees. > So, in some ways, (2) above would be a better investment - the process of PCH > is: > generate: > “get to the end of parsing a TU” .. stream the AST > consume: > .. see a header .. stream the PCH AST in if there is one available for the > header. > > There is no reason for this to be mixed into the GC solution - the read in > (currently) > happens to an empty TU and there should be nothing in the AST that carries any > reference to the compiler’s executable. It makes the PCH read-in "cheap" - IIRC Google invested quite some work in evaluating different PC* approaches but none in the end made a big enough difference. Given we now have a standards backed PCH-like thing for C++ with modules and given that for C (besides on Darwin...) PCH never made much sense I doubt investing into generalizing the C++ module support or making PCH relocatable is worth the trouble. Richard. > > just 0.02 GBP. > Iain > > > > > > I wrote following ugly hack: > > > > --- ggc-common.c.jj 2021-08-19 11:42:27.365422400 +0200 > > +++ ggc-common.c 2021-11-05 15:37:51.447222544 +0100 > > @@ -404,6 +404,9 @@ struct mmap_info > > > > /* Write out the state of the compiler to F. */ > > > > +char *exestart = (char *) 2; > > +char *exeend = (char *) 2; > > + > > void > > gt_pch_save (FILE *f) > > { > > @@ -458,6 +461,14 @@ gt_pch_save (FILE *f) > > for (rti = *rt; rti->base != NULL; rti++) > > if (fwrite (rti->base, rti->stride, 1, f) != 1) > > fatal_error (input_location, "cannot write PCH file: %m"); > > + else if ((((uintptr_t) rti->base) & (sizeof (void *) - 1)) == 0) > > + { > > + char *const *p = (char *const *) rti->base; > > + char *const *q = (char *const *) ((uintptr_t) rti->base + > > (rti->stride & ~(sizeof (void *) - 1))); > > + for (; p < q; p++) > > + if (*p >= exestart && *p < exeend) > > + fprintf (stderr, "scalar at %p points to executable %p\n", > > (void *) p, (void *) *p); > > + } > > > > /* Write out all the global pointers, after translation. */ > > write_pch_globals (gt_ggc_rtab, &state); > > @@ -546,6 +557,15 @@ gt_pch_save (FILE *f) > > state.ptrs[i]->note_ptr_fn (state.ptrs[i]->obj, > > state.ptrs[i]->note_ptr_cookie, > > relocate_ptrs, &state); > > + if ((((uintptr_t) state.ptrs[i]->obj) & (sizeof (void *) - 1)) == 0) > > + { > > + char *const *p = (char *const *) (state.ptrs[i]->obj); > > + char *const *q = (char *const *) ((uintptr_t) > > (state.ptrs[i]->obj) + (state.ptrs[i]->size & ~(sizeof (void *) - 1))); > > + for (; p < q; p++) > > + if (*p >= exestart && *p < exeend) > > + fprintf (stderr, "object %p at %p points to executable %p\n", > > (void *) (state.ptrs[i]->obj), (void *) p, (void *) *p); > > + } > > + > > ggc_pch_write_object (state.d, state.f, state.ptrs[i]->obj, > > state.ptrs[i]->new_addr, state.ptrs[i]->size, > > state.ptrs[i]->note_ptr_fn == gt_pch_p_S); > > > > and under debugger set exestart and exeend from /proc/*/maps of the cc1plus > > process being debugged (the extent of cc1plus mappings). > > This resulted in something like: > > scalar at 0x3d869a8 points to executable 0x2dd85e0 > > scalar at 0x3d869b0 points to executable 0x2dd85e4 > > scalar at 0x3d869c8 points to executable 0x2dd85e7 > > ... > > object 0x7fffea007e70 at 0x7fffea007e70 points to executable 0x11e48c2 > > object 0x7fffe953dcc0 at 0x7fffe953dcc0 points to executable 0x201e222 > > object 0x7fffe401d260 at 0x7fffe401d260 points to executable 0x4b0a27 > > object 0x7fffea02fce0 at 0x7fffea02fce0 points to executable 0x18bb2b0 > > object 0x7fffe7034ca0 at 0x7fffe7034ca0 points to executable 0x2f81537 > > object 0x7fffe700f8a0 at 0x7fffe700f8a0 points to executable 0x2c36a32 > > on stderr. Unfortunately, I didn't try to rebuild the compiler as PIE, so > > unfortunately the range was 0x400000 .. 0x3d9b000 so I'm not really sure > > if all it dumped were actually addresses or some nice numbers like 0x1000000 > > etc. Much better would be to have the compiler as PIE, run it twice and > > only look at values that actually changed, or link the compiler at some very > > unlikely virtual address offset so that addresses into it would be easy to > > spot. > > All the "scalar at " messages are for offsets in the ovl_op_info > > array. > > struct GTY(()) ovl_op_info_t { > > /* The IDENTIFIER_NODE for the operator. */ > > tree identifier; > > /* The name of the operator. */ > > const char *name; > > /* The mangled name of the operator. */ > > const char *mangled_name; > > /* The (regular) tree code. */ > > enum tree_code tree_code : 16; > > /* The (compressed) operator code. */ > > enum ovl_op_code ovl_op_code : 8; > > /* The ovl_op_flags of the operator */ > > unsigned flags : 8; > > }; > > For that particular case gengtype emits: > > { > > &ovl_op_info[0][0].identifier, > > 1 * (2) * (OVL_OP_MAX), > > sizeof (ovl_op_info[0][0]), > > >_ggc_mx_tree_node, > > >_pch_nx_tree_node > > }, > > { > > &ovl_op_info[0][0].name, > > 1 * (2) * (OVL_OP_MAX), > > sizeof (ovl_op_info[0][0]), > > (gt_pointer_walker) >_ggc_m_S, > > (gt_pointer_walker) >_pch_n_S > > }, > > { > > &ovl_op_info[0][0].mangled_name, > > 1 * (2) * (OVL_OP_MAX), > > sizeof (ovl_op_info[0][0]), > > (gt_pointer_walker) >_ggc_m_S, > > (gt_pointer_walker) >_pch_n_S > > }, > > so I believe we treat the identifier as always a GC memory object pointer, > > and name and mangled_name are const char * pointers which I vaguely remember > > we allow to be either NULL, or 1 or GC memory pointers or string literals > > (but can't find how it deals with that last category in the source). > > From the source: > > ovl_op_info_t ovl_op_info[2][OVL_OP_MAX] = > > { > > { > > {NULL_TREE, NULL, NULL, ERROR_MARK, OVL_OP_ERROR_MARK, 0}, > > {NULL_TREE, NULL, NULL, NOP_EXPR, OVL_OP_NOP_EXPR, 0}, > > #define DEF_OPERATOR(NAME, CODE, MANGLING, FLAGS) \ > > {NULL_TREE, NAME, MANGLING, CODE, OVL_OP_##CODE, FLAGS}, > > #define OPERATOR_TRANSITION }, { \ > > {NULL_TREE, NULL, NULL, ERROR_MARK, OVL_OP_ERROR_MARK, 0}, > > #include "operators.def" > > } > > }; > > where operators.def has e.g.: > > DEF_OPERATOR ("new", NEW_EXPR, "nw", OVL_OP_FLAG_ALLOC) > > in this particular array the strings are always string literals. > > I guess to get ovl_op_info out of the picture we could mark > > name and mangled_name as GTY((skip)). > > But that is just 178 records, the remaining 52520 are in GC memory > > objects. Figuring out what exactly it is in will be harder... > > From the addresses it printed in the last column, the following point > > to the start of some cc1plus symbol: > > 3310: 0000000000c121d2 831 FUNC LOCAL DEFAULT 14 > > _ZL9min_vis_rPP9tree_nodePiPv > > 134773: 0000000000fa67a9 47 FUNC GLOBAL DEFAULT 14 > > _Z20ggc_round_alloc_sizem > > 6151: 0000000000fa67a9 47 FUNC GLOBAL DEFAULT 14 > > _Z20ggc_round_alloc_sizem > > 188594: 000000000102d0a0 26 FUNC WEAK DEFAULT 14 > > _Z4is_aIP7gswitch6gimpleEbPT0_ > > 37908: 000000000102d0a0 26 FUNC WEAK DEFAULT 14 > > _Z4is_aIP7gswitch6gimpleEbPT0_ > > 50655: 0000000001707c85 37 FUNC LOCAL DEFAULT 14 > > _ZL20realloc_for_line_mapPvm > > 131570: 000000000178d3e0 66 FUNC WEAK DEFAULT 14 > > _ZNK3vecI13numbered_tree7va_heap6vl_ptrE5spaceEi > > 1653: 000000000178d3e0 66 FUNC WEAK DEFAULT 14 > > _ZNK3vecI13numbered_tree7va_heap6vl_ptrE5spaceEi > > 129108: 000000000178e520 43 FUNC WEAK DEFAULT 14 > > _ZNK3vecI12loc_map_pair7va_heap8vl_embedE5spaceEj > > 51650: 000000000178e520 43 FUNC WEAK DEFAULT 14 > > _ZNK3vecI12loc_map_pair7va_heap8vl_embedE5spaceEj > > 77141: 0000000001b6cb5a 159 FUNC LOCAL DEFAULT 14 > > _ZL10emit_localP9tree_nodePKcmm > > 77142: 0000000001b6cbf9 75 FUNC LOCAL DEFAULT 14 > > _ZL8emit_bssP9tree_nodePKcmm > > 77143: 0000000001b6cc44 75 FUNC LOCAL DEFAULT 14 > > _ZL11emit_commonP9tree_nodePKcmm > > 77144: 0000000001b6cc8f 231 FUNC LOCAL DEFAULT 14 > > _ZL15emit_tls_commonP9tree_nodePKcmm > > 181390: 0000000001b7e3d0 44 FUNC GLOBAL DEFAULT 14 > > _Z21output_section_asm_opPKv > > 25347: 0000000001b7e3d0 44 FUNC GLOBAL DEFAULT 14 > > _Z21output_section_asm_opPKv > > 160243: 0000000001fbc260 27 FUNC WEAK DEFAULT 14 > > _ZN11code_helperC2E11combined_fn > > 163230: 0000000001fbc260 27 FUNC WEAK DEFAULT 14 > > _ZN11code_helperC1E11combined_fn > > 26343: 0000000001fbc260 27 FUNC WEAK DEFAULT 14 > > _ZN11code_helperC1E11combined_fn > > 40584: 0000000001fbc260 27 FUNC WEAK DEFAULT 14 > > _ZN11code_helperC2E11combined_fn > > 12547: 00000000029516e0 68 FUNC WEAK DEFAULT 14 > > _ZNSt4pairIPSt18_Rb_tree_node_baseS1_EC2IRPSt13_Rb_tree_nodeIP15basic_block_defERS1_Lb1EEEOT_OT0_ > > 165150: 00000000029516e0 68 FUNC WEAK DEFAULT 14 > > _ZNSt4pairIPSt18_Rb_tree_node_baseS1_EC2IRPSt13_Rb_tree_nodeIP15basic_block_defERS1_Lb1EEEOT_OT0_ > > 181147: 00000000029516e0 68 FUNC WEAK DEFAULT 14 > > _ZNSt4pairIPSt18_Rb_tree_node_baseS1_EC1IRPSt13_Rb_tree_nodeIP15basic_block_defERS1_Lb1EEEOT_OT0_ > > 26558: 00000000029516e0 68 FUNC WEAK DEFAULT 14 > > _ZNSt4pairIPSt18_Rb_tree_node_baseS1_EC1IRPSt13_Rb_tree_nodeIP15basic_block_defERS1_Lb1EEEOT_OT0_ > > 8400: 0000000002e13f60 16 OBJECT LOCAL DEFAULT 16 _ZL10PTA_SSE4_1 > > 8448: 0000000002e14260 16 OBJECT LOCAL DEFAULT 16 _ZL12PTA_WBNOINVD > > 10166: 0000000002e444a0 4 OBJECT LOCAL DEFAULT 16 > > _ZN15zero_regs_flagsL11ALL_GPR_ARGE > > 11568: 0000000002e51420 16 OBJECT LOCAL DEFAULT 16 > > _ZL14PTA_AVX512FP16 > > 11735: 0000000002e52f60 16 OBJECT LOCAL DEFAULT 16 > > _ZL14PTA_VPCLMULQDQ > > 12575: 0000000002e5f560 16 OBJECT LOCAL DEFAULT 16 > > _ZL14PTA_ROCKETLAKE > > 165019: 0000000002e605a0 20 OBJECT GLOBAL DEFAULT 16 > > class_narrowest_mode > > 9991: 0000000002e605a0 20 OBJECT GLOBAL DEFAULT 16 > > class_narrowest_mode > > 12749: 0000000002e60f60 160 OBJECT LOCAL DEFAULT 16 > > _ZL22extra_order_size_table > > 14715: 0000000002e7e340 16 OBJECT LOCAL DEFAULT 16 > > _ZL18PTA_SKYLAKE_AVX512 > > 15895: 0000000002e84480 16 OBJECT LOCAL DEFAULT 16 _ZL9PTA_UINTR > > 17084: 0000000002e8c160 16 OBJECT LOCAL DEFAULT 16 > > _ZL18PTA_SAPPHIRERAPIDS > > 18397: 0000000002e946a0 16 OBJECT LOCAL DEFAULT 16 _ZL10PTA_SSE4_2 > > 18986: 0000000002e97580 16 OBJECT LOCAL DEFAULT 16 _ZL7PTA_KNL > > 18990: 0000000002e975c0 16 OBJECT LOCAL DEFAULT 16 > > _ZL17PTA_GOLDMONT_PLUS > > 22195: 0000000002eb1640 16 OBJECT LOCAL DEFAULT 16 _ZL7PTA_FMA > > 30065: 0000000002eed6e0 16 OBJECT LOCAL DEFAULT 16 > > _ZL14PTA_AVX512BF16 > > 31474: 0000000002ef3560 1 OBJECT LOCAL DEFAULT 16 > > _ZStL19piecewise_construct > > 34906: 0000000002f02580 16 OBJECT LOCAL DEFAULT 16 _ZL12PTA_AVX512BW > > 37696: 0000000002f0e420 1 OBJECT LOCAL DEFAULT 16 > > _ZStL19piecewise_construct > > 37701: 0000000002f0e484 4 OBJECT LOCAL DEFAULT 16 > > _ZL40LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES > > 38868: 0000000002f13420 16 OBJECT LOCAL DEFAULT 16 _ZL7PTA_KNL > > 39129: 0000000002f143c0 16 OBJECT LOCAL DEFAULT 16 _ZL10PTA_XSAVES > > 40610: 0000000002f1e7c0 1 OBJECT LOCAL DEFAULT 16 > > _ZStL19piecewise_construct > > 42157: 0000000002f293c0 16 OBJECT LOCAL DEFAULT 16 > > _ZL16PTA_AVX5124VNNIW > > 42201: 0000000002f29680 16 OBJECT LOCAL DEFAULT 16 > > _ZL18PTA_SKYLAKE_AVX512 > > 42207: 0000000002f296e0 16 OBJECT LOCAL DEFAULT 16 > > _ZL18PTA_ICELAKE_SERVER > > 49618: 0000000002f556e0 4 OBJECT LOCAL DEFAULT 16 > > _ZN15zero_regs_flagsL8USED_ARGE > > 50904: 0000000002f5d4e0 16 OBJECT LOCAL DEFAULT 16 _ZL7PTA_AVX > > 51188: 0000000002f5e6e0 48 OBJECT LOCAL DEFAULT 16 > > _ZN12_GLOBAL__N_1L17pass_data_tm_initE > > 56440: 0000000002f7d440 16 OBJECT LOCAL DEFAULT 16 > > _ZL14PTA_SILVERMONT > > 57404: 0000000002f81640 4 OBJECT LOCAL DEFAULT 16 > > _ZL14MAX_LOCATION_T > > 57424: 0000000002f816a0 16 OBJECT LOCAL DEFAULT 16 _ZL9PTA_64BIT > > 60100: 0000000002f903a0 16 OBJECT LOCAL DEFAULT 16 _ZL12PTA_AMX_TILE > > 67672: 0000000002fae460 16 OBJECT LOCAL DEFAULT 16 > > _ZL14PTA_COOPERLAKE > > 68780: 0000000002fb37c0 16 OBJECT LOCAL DEFAULT 16 _ZL12PTA_AVX512CD > > 70316: 0000000002fbb4e0 16 OBJECT LOCAL DEFAULT 16 _ZL7PTA_LWP > > 70637: 0000000002fbc7a0 16 OBJECT LOCAL DEFAULT 16 _ZL11PTA_PTWRITE > > 70837: 0000000002fbd4e0 16 OBJECT LOCAL DEFAULT 16 _ZL8PTA_SSE3 > > 73878: 0000000002fcb960 16 OBJECT LOCAL DEFAULT 16 _ZL10PTA_HRESET > > 79867: 00000000030435c0 16 OBJECT LOCAL DEFAULT 16 > > _ZL14PTA_SILVERMONT > > 81991: 0000000003053520 16 OBJECT LOCAL DEFAULT 16 _ZL8PTA_F16C > > 82244: 0000000003054500 16 OBJECT LOCAL DEFAULT 16 _ZL12PTA_CLDEMOTE > > 86070: 00000000033ec560 99 OBJECT LOCAL DEFAULT 16 > > _ZL26znver1_agu_min_issue_delay > > 86071: 00000000033ec5e0 1334 OBJECT LOCAL DEFAULT 16 > > _ZL15geode_translate > > 86228: 00000000034419c0 16 OBJECT LOCAL DEFAULT 16 _ZL12PTA_NO_80387 > > 94224: 0000000003849420 16 OBJECT LOCAL DEFAULT 16 _ZL8PTA_SSE3 > > 94230: 0000000003849480 16 OBJECT LOCAL DEFAULT 16 _ZL7PTA_XOP > > 94647: 000000000384aa40 16 OBJECT LOCAL DEFAULT 16 _ZL7PTA_SGX > > 95488: 000000000384e4c0 16 OBJECT LOCAL DEFAULT 16 _ZL7PTA_KNM > > 95820: 000000000384f6a0 16 OBJECT LOCAL DEFAULT 16 _ZL12PTA_WBNOINVD > > 95822: 000000000384f6c0 16 OBJECT LOCAL DEFAULT 16 _ZL11PTA_PTWRITE > > 95824: 000000000384f6e0 16 OBJECT LOCAL DEFAULT 16 _ZL11PTA_WAITPKG > > 96072: 0000000003850640 16 OBJECT LOCAL DEFAULT 16 _ZL9PTA_LZCNT > > 96074: 0000000003850660 16 OBJECT LOCAL DEFAULT 16 _ZL9PTA_MOVBE > > 96080: 00000000038506c0 16 OBJECT LOCAL DEFAULT 16 _ZL7PTA_SSE > > 98344: 000000000385a4c0 16 OBJECT LOCAL DEFAULT 16 _ZL10PTA_ENQCMD > > 99309: 000000000385da40 16 OBJECT LOCAL DEFAULT 16 _ZL10PTA_POPCNT > > 103332: 000000000386f2c0 16 OBJECT LOCAL DEFAULT 16 > > _ZL14PTA_CLFLUSHOPT > > 103344: 000000000386f380 16 OBJECT LOCAL DEFAULT 16 _ZL7PTA_PKU > > 103352: 000000000386f400 16 OBJECT LOCAL DEFAULT 16 > > _ZL15PTA_AVX512VBMI2 > > 103709: 0000000003870a40 16 OBJECT LOCAL DEFAULT 16 _ZL8PTA_SSE3 > > 104337: 0000000003873660 16 OBJECT LOCAL DEFAULT 16 _ZL10PTA_HRESET > > 106315: 000000000387d260 16 OBJECT LOCAL DEFAULT 16 _ZL11PTA_NO_TUNE > > 109183: 000000000388c160 16 OBJECT LOCAL DEFAULT 16 > > _ZL16PTA_AVX5124VNNIW > > 111159: 0000000003894a40 16 OBJECT LOCAL DEFAULT 16 > > _ZL14PTA_CANNONLAKE > > 112043: 00000000038994c0 16 OBJECT LOCAL DEFAULT 16 _ZL11PTA_PTWRITE > > 112049: 0000000003899520 16 OBJECT LOCAL DEFAULT 16 _ZL12PTA_CLDEMOTE > > 113040: 000000000389d6c0 16 OBJECT LOCAL DEFAULT 16 _ZL12PTA_AMX_BF16 > > 21876: 0000000003d8d5c0 56 OBJECT LOCAL DEFAULT 28 > > _ZL22mem_alloc_origin_names > > 31109: 0000000003d8e100 40 OBJECT LOCAL DEFAULT 28 > > _ZL30unspecified_modref_access_node > > 78193: 0000000003d932e0 56 OBJECT LOCAL DEFAULT 28 > > _ZL22mem_alloc_origin_names > > 78366: 0000000003d93320 56 OBJECT LOCAL DEFAULT 28 > > _ZL22mem_alloc_origin_names > > > > Jakub >