Skip to content

Commit a68b894

Browse files
Fix stack overflow in llvm::Verifier::visitMDNode()
This code is a proof-of-concept more than anything else. It is not ready to be merged in its current state. Any version of this fix must somehow measure the depth of the metadata nodes (or a rough upper bound), and it must somehow send that depth to the LLVM codegen entry point. There is likely a tradeoff to be made between performance and readability here.
1 parent b347aa5 commit a68b894

File tree

12 files changed

+219
-104
lines changed

12 files changed

+219
-104
lines changed

compiler/rustc_codegen_llvm/src/back/write.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use rustc_codegen_ssa::traits::*;
1919
use rustc_codegen_ssa::{CompiledModule, ModuleCodegen};
2020
use rustc_data_structures::profiling::SelfProfilerRef;
2121
use rustc_data_structures::small_c_str::SmallCStr;
22+
use rustc_data_structures::stack::ensure_recursive_stack;
2223
use rustc_errors::{FatalError, Handler, Level};
2324
use rustc_fs_util::{link_or_copy, path_to_c_string};
2425
use rustc_middle::bug;
@@ -757,6 +758,13 @@ pub(crate) unsafe fn codegen(
757758
create_msvc_imps(cgcx, llcx, llmod);
758759
}
759760

761+
let stack_size = crate::debuginfo::LLMOD_DEPTHS
762+
.lock()
763+
.unwrap()
764+
.get(&(llmod as *const _ as usize))
765+
.unwrap_or(&0)
766+
* 256;
767+
760768
// A codegen-specific pass manager is used to generate object
761769
// files for an LLVM module.
762770
//
@@ -769,6 +777,7 @@ pub(crate) unsafe fn codegen(
769777
tm: &'ll llvm::TargetMachine,
770778
llmod: &'ll llvm::Module,
771779
no_builtins: bool,
780+
stack_size: usize,
772781
f: F,
773782
) -> R
774783
where
@@ -777,7 +786,7 @@ pub(crate) unsafe fn codegen(
777786
let cpm = llvm::LLVMCreatePassManager();
778787
llvm::LLVMAddAnalysisPasses(tm, cpm);
779788
llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
780-
f(cpm)
789+
ensure_recursive_stack(stack_size, || f(cpm))
781790
}
782791

783792
// Two things to note:
@@ -881,7 +890,7 @@ pub(crate) unsafe fn codegen(
881890
} else {
882891
llmod
883892
};
884-
with_codegen(tm, llmod, config.no_builtins, |cpm| {
893+
with_codegen(tm, llmod, config.no_builtins, stack_size, |cpm| {
885894
write_output_file(
886895
diag_handler,
887896
tm,
@@ -916,7 +925,7 @@ pub(crate) unsafe fn codegen(
916925
(_, SplitDwarfKind::Split) => Some(dwo_out.as_path()),
917926
};
918927

919-
with_codegen(tm, llmod, config.no_builtins, |cpm| {
928+
with_codegen(tm, llmod, config.no_builtins, stack_size, |cpm| {
920929
write_output_file(
921930
diag_handler,
922931
tm,

compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs

+14-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::metadata::file_metadata;
2-
use super::utils::DIB;
2+
use super::utils::{self, DIB};
33
use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext};
44
use rustc_codegen_ssa::traits::*;
55

@@ -97,15 +97,19 @@ fn make_mir_scope<'ll, 'tcx>(
9797
let callee_fn_abi = cx.fn_abi_of_instance(callee, ty::List::empty());
9898
cx.dbg_scope_fn(callee, callee_fn_abi, None)
9999
}
100-
None => unsafe {
101-
llvm::LLVMRustDIBuilderCreateLexicalBlock(
102-
DIB(cx),
103-
parent_scope.dbg_scope.unwrap(),
104-
file_metadata,
105-
loc.line,
106-
loc.col,
107-
)
108-
},
100+
None => {
101+
let dbg_scope = unsafe {
102+
llvm::LLVMRustDIBuilderCreateLexicalBlock(
103+
DIB(cx),
104+
parent_scope.dbg_scope.unwrap(),
105+
file_metadata,
106+
loc.line,
107+
loc.col,
108+
)
109+
};
110+
utils::debug_context(cx).add_di_node(dbg_scope);
111+
dbg_scope
112+
}
109113
};
110114

111115
let inlined_at = scope_data.inlined.map(|(_, callsite_span)| {

compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs

+50-29
Original file line numberDiff line numberDiff line change
@@ -136,10 +136,10 @@ fn build_fixed_size_array_di_node<'ll, 'tcx>(
136136

137137
let upper_bound = len.eval_usize(cx.tcx, ty::ParamEnv::reveal_all()) as c_longlong;
138138

139-
let subrange =
140-
unsafe { Some(llvm::LLVMRustDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound)) };
139+
let subrange = unsafe { llvm::LLVMRustDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound) };
140+
debug_context(cx).add_di_node(subrange);
141141

142-
let subscripts = create_DIArray(DIB(cx), &[subrange]);
142+
let subscripts = create_DIArray(cx, &[Some(subrange)]);
143143
let di_node = unsafe {
144144
llvm::LLVMRustDIBuilderCreateArrayType(
145145
DIB(cx),
@@ -149,6 +149,7 @@ fn build_fixed_size_array_di_node<'ll, 'tcx>(
149149
subscripts,
150150
)
151151
};
152+
debug_context(cx).add_di_node(di_node);
152153

153154
DINodeCreationResult::new(di_node, false)
154155
}
@@ -204,6 +205,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
204205
ptr_type_debuginfo_name.len(),
205206
)
206207
};
208+
debug_context(cx).add_di_node(di_node);
207209

208210
DINodeCreationResult { di_node, already_stored_in_typemap: false }
209211
}
@@ -255,6 +257,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
255257
0,
256258
)
257259
};
260+
debug_context(cx).add_di_node(data_ptr_type_di_node);
258261

259262
smallvec![
260263
build_field_di_node(
@@ -332,9 +335,10 @@ fn build_subroutine_type_di_node<'ll, 'tcx>(
332335
let fn_di_node = unsafe {
333336
llvm::LLVMRustDIBuilderCreateSubroutineType(
334337
DIB(cx),
335-
create_DIArray(DIB(cx), &signature_di_nodes[..]),
338+
create_DIArray(cx, &signature_di_nodes[..]),
336339
)
337340
};
341+
debug_context(cx).add_nested_di_node(fn_di_node, &[3]);
338342

339343
// This is actually a function pointer, so wrap it in pointer DI.
340344
let name = compute_debuginfo_type_name(cx.tcx, fn_ty, false);
@@ -349,6 +353,7 @@ fn build_subroutine_type_di_node<'ll, 'tcx>(
349353
name.len(),
350354
)
351355
};
356+
debug_context(cx).add_di_node(di_node);
352357

353358
DINodeCreationResult::new(di_node, false)
354359
}
@@ -498,7 +503,7 @@ pub fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll D
498503
// FIXME(mw): Cache this via a regular UniqueTypeId instead of an extra field in the debug context.
499504
fn recursion_marker_type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> &'ll DIType {
500505
*debug_context(cx).recursion_marker_type.get_or_init(move || {
501-
unsafe {
506+
let di_node = unsafe {
502507
// The choice of type here is pretty arbitrary -
503508
// anything reading the debuginfo for a recursive
504509
// type is going to see *something* weird - the only
@@ -517,7 +522,9 @@ fn recursion_marker_type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> &'ll D
517522
cx.tcx.data_layout.pointer_size.bits(),
518523
DW_ATE_unsigned,
519524
)
520-
}
525+
};
526+
debug_context(cx).add_di_node(di_node);
527+
di_node
521528
})
522529
}
523530

@@ -595,6 +602,7 @@ fn file_metadata_raw<'ll>(
595602
hash_value.len(),
596603
)
597604
};
605+
debug_context(cx).add_di_node(file_metadata);
598606

599607
v.insert(file_metadata);
600608
file_metadata
@@ -680,6 +688,7 @@ fn build_basic_type_di_node<'ll, 'tcx>(
680688
encoding,
681689
)
682690
};
691+
debug_context(cx).add_di_node(ty_di_node);
683692

684693
if !cpp_like_debuginfo {
685694
return DINodeCreationResult::new(ty_di_node, false);
@@ -703,6 +712,7 @@ fn build_basic_type_di_node<'ll, 'tcx>(
703712
None,
704713
)
705714
};
715+
debug_context(cx).add_di_node(typedef_di_node);
706716

707717
DINodeCreationResult::new(typedef_di_node, false)
708718
}
@@ -740,18 +750,17 @@ fn build_param_type_di_node<'ll, 'tcx>(
740750
) -> DINodeCreationResult<'ll> {
741751
debug!("build_param_type_di_node: {:?}", t);
742752
let name = format!("{:?}", t);
743-
DINodeCreationResult {
744-
di_node: unsafe {
745-
llvm::LLVMRustDIBuilderCreateBasicType(
746-
DIB(cx),
747-
name.as_ptr().cast(),
748-
name.len(),
749-
Size::ZERO.bits(),
750-
DW_ATE_unsigned,
751-
)
752-
},
753-
already_stored_in_typemap: false,
754-
}
753+
let di_node = unsafe {
754+
llvm::LLVMRustDIBuilderCreateBasicType(
755+
DIB(cx),
756+
name.as_ptr().cast(),
757+
name.len(),
758+
Size::ZERO.bits(),
759+
DW_ATE_unsigned,
760+
)
761+
};
762+
debug_context(cx).add_di_node(di_node);
763+
DINodeCreationResult { di_node, already_stored_in_typemap: false }
755764
}
756765

757766
pub fn build_compile_unit_di_node<'ll, 'tcx>(
@@ -838,6 +847,7 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>(
838847
ptr::null(),
839848
0,
840849
);
850+
debug_context.add_di_node(compile_unit_file);
841851

842852
let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit(
843853
debug_context.builder,
@@ -857,6 +867,7 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>(
857867
0,
858868
tcx.sess.opts.debugging_opts.split_dwarf_inlining,
859869
);
870+
debug_context.add_di_node(unit_metadata);
860871

861872
if tcx.sess.opts.debugging_opts.profile {
862873
let cu_desc_metadata =
@@ -924,7 +935,7 @@ fn build_field_di_node<'ll, 'tcx>(
924935
flags: DIFlags,
925936
type_di_node: &'ll DIType,
926937
) -> &'ll DIType {
927-
unsafe {
938+
let di_node = unsafe {
928939
llvm::LLVMRustDIBuilderCreateMemberType(
929940
DIB(cx),
930941
owner,
@@ -938,7 +949,9 @@ fn build_field_di_node<'ll, 'tcx>(
938949
flags,
939950
type_di_node,
940951
)
941-
}
952+
};
953+
debug_context(cx).add_di_node(di_node);
954+
di_node
942955
}
943956

944957
/// Creates the debuginfo node for a Rust struct type. Maybe be a regular struct or a tuple-struct.
@@ -1257,15 +1270,17 @@ fn build_generic_type_param_di_nodes<'ll, 'tcx>(
12571270
cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
12581271
let actual_type_di_node = type_di_node(cx, actual_type);
12591272
let name = name.as_str();
1260-
Some(unsafe {
1273+
let template_param = unsafe {
12611274
llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
12621275
DIB(cx),
12631276
None,
12641277
name.as_ptr().cast(),
12651278
name.len(),
12661279
actual_type_di_node,
12671280
)
1268-
})
1281+
};
1282+
debug_context(cx).add_di_node(template_param);
1283+
Some(template_param)
12691284
} else {
12701285
None
12711286
}
@@ -1326,7 +1341,7 @@ pub fn build_global_var_di_node<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId, glo
13261341

13271342
let global_align = cx.align_of(variable_type);
13281343

1329-
unsafe {
1344+
let di_node = unsafe {
13301345
llvm::LLVMRustDIBuilderCreateStaticVariable(
13311346
DIB(cx),
13321347
Some(var_scope),
@@ -1341,8 +1356,9 @@ pub fn build_global_var_di_node<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId, glo
13411356
global,
13421357
None,
13431358
global_align.bytes() as u32,
1344-
);
1345-
}
1359+
)
1360+
};
1361+
debug_context(cx).add_nested_di_node(di_node, &[0, 1]);
13461362
}
13471363

13481364
/// Generates LLVM debuginfo for a vtable.
@@ -1467,7 +1483,7 @@ pub fn create_vtable_di_node<'ll, 'tcx>(
14671483
let vtable_type_di_node = build_vtable_type_di_node(cx, ty, poly_trait_ref);
14681484
let linkage_name = "";
14691485

1470-
unsafe {
1486+
let di_node = unsafe {
14711487
llvm::LLVMRustDIBuilderCreateStaticVariable(
14721488
DIB(cx),
14731489
NO_SCOPE_METADATA,
@@ -1482,8 +1498,9 @@ pub fn create_vtable_di_node<'ll, 'tcx>(
14821498
vtable,
14831499
None,
14841500
0,
1485-
);
1486-
}
1501+
)
1502+
};
1503+
debug_context(cx).add_nested_di_node(di_node, &[0, 1]);
14871504
}
14881505

14891506
/// Creates an "extension" of an existing `DIScope` into another file.
@@ -1493,7 +1510,11 @@ pub fn extend_scope_to_file<'ll>(
14931510
file: &SourceFile,
14941511
) -> &'ll DILexicalBlock {
14951512
let file_metadata = file_metadata(cx, file);
1496-
unsafe { llvm::LLVMRustDIBuilderCreateLexicalBlockFile(DIB(cx), scope_metadata, file_metadata) }
1513+
let di_node = unsafe {
1514+
llvm::LLVMRustDIBuilderCreateLexicalBlockFile(DIB(cx), scope_metadata, file_metadata)
1515+
};
1516+
debug_context(cx).add_di_node(di_node);
1517+
di_node
14971518
}
14981519

14991520
pub fn tuple_field_name(field_index: usize) -> Cow<'static, str> {

compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use crate::{
2727
unknown_file_metadata, DINodeCreationResult, SmallVec, NO_GENERICS, NO_SCOPE_METADATA,
2828
UNKNOWN_LINE_NUMBER,
2929
},
30-
utils::DIB,
30+
utils::{debug_context, DIB},
3131
},
3232
llvm::{
3333
self,
@@ -441,7 +441,7 @@ fn build_union_fields_for_direct_tag_enum_or_generator<'ll, 'tcx>(
441441
// We use LLVMRustDIBuilderCreateMemberType() member type directly because
442442
// the build_field_di_node() function does not support specifying a source location,
443443
// which is something that we don't do anywhere else.
444-
unsafe {
444+
let member_type_di_node = unsafe {
445445
llvm::LLVMRustDIBuilderCreateMemberType(
446446
DIB(cx),
447447
enum_type_di_node,
@@ -458,7 +458,9 @@ fn build_union_fields_for_direct_tag_enum_or_generator<'ll, 'tcx>(
458458
DIFlags::FlagZero,
459459
variant_member_info.variant_struct_type_di_node,
460460
)
461-
}
461+
};
462+
debug_context(cx).add_di_node(member_type_di_node);
463+
member_type_di_node
462464
}));
463465

464466
debug_assert_eq!(

0 commit comments

Comments
 (0)