Skip to content

Commit b3ec490

Browse files
authored
Allow marking data objects as used for the linker (#11214)
1 parent 59f1af6 commit b3ec490

File tree

4 files changed

+48
-7
lines changed

4 files changed

+48
-7
lines changed

cranelift/jit/src/backend.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,7 @@ impl Module for JITModule {
611611
data_relocs: _,
612612
custom_segment_section: _,
613613
align,
614+
used: _,
614615
} = data;
615616

616617
// Make sure to allocate at least 1 byte. Allocating 0 bytes is UB. Previously a dummy

cranelift/module/src/data_context.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//! Defines `DataContext`.
1+
//! Defines `DataDescription`.
22
33
use cranelift_codegen::binemit::{Addend, CodeOffset, Reloc};
44
use cranelift_codegen::entity::PrimaryMap;
@@ -62,9 +62,12 @@ pub struct DataDescription {
6262
pub data_relocs: Vec<(CodeOffset, ir::GlobalValue, Addend)>,
6363
/// Object file section
6464
pub custom_segment_section: Option<(String, String)>,
65-
/// Alignment in bytes. `None` means that the default alignment of the respective module should
66-
/// be used.
65+
/// Alignment in bytes. `None` means that the default alignment of the
66+
/// respective module should be used.
6767
pub align: Option<u64>,
68+
/// Whether or not to request the linker to preserve this data object even
69+
/// if not referenced.
70+
pub used: bool,
6871
}
6972

7073
impl DataDescription {
@@ -78,6 +81,7 @@ impl DataDescription {
7881
data_relocs: vec![],
7982
custom_segment_section: None,
8083
align: None,
84+
used: false,
8185
}
8286
}
8387

@@ -90,6 +94,7 @@ impl DataDescription {
9094
self.data_relocs.clear();
9195
self.custom_segment_section = None;
9296
self.align = None;
97+
self.used = false;
9398
}
9499

95100
/// Define a zero-initialized object with the given size.
@@ -117,6 +122,12 @@ impl DataDescription {
117122
self.align = Some(align);
118123
}
119124

125+
/// Set whether or not the linker should preserve this data object even if
126+
/// not referenced.
127+
pub fn set_used(&mut self, used: bool) {
128+
self.used = used;
129+
}
130+
120131
/// Declare an external function import.
121132
///
122133
/// Users of the `Module` API generally should call

cranelift/module/src/module.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -979,7 +979,7 @@ pub trait Module {
979979
relocs: &[ModuleReloc],
980980
) -> ModuleResult<()>;
981981

982-
/// Define a data object, producing the data contents from the given `DataContext`.
982+
/// Define a data object, producing the data contents from the given `DataDescription`.
983983
fn define_data(&mut self, data_id: DataId, data: &DataDescription) -> ModuleResult<()>;
984984
}
985985

cranelift/object/src/backend.rs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ use object::write::{
1515
Object, Relocation, SectionId, StandardSection, Symbol, SymbolId, SymbolSection,
1616
};
1717
use object::{
18-
RelocationEncoding, RelocationFlags, RelocationKind, SectionKind, SymbolFlags, SymbolKind,
19-
SymbolScope,
18+
RelocationEncoding, RelocationFlags, RelocationKind, SectionFlags, SectionKind, SymbolFlags,
19+
SymbolKind, SymbolScope,
2020
};
2121
use std::collections::HashMap;
2222
use std::collections::hash_map::Entry;
@@ -394,6 +394,7 @@ impl Module for ObjectModule {
394394
data_relocs: _,
395395
ref custom_segment_section,
396396
align,
397+
used,
397398
} = data;
398399

399400
let pointer_reloc = match self.isa.triple().pointer_width().unwrap() {
@@ -422,7 +423,7 @@ impl Module for ObjectModule {
422423
} else {
423424
StandardSection::ReadOnlyDataWithRel
424425
};
425-
if self.per_data_object_section {
426+
if self.per_data_object_section || used {
426427
// FIXME pass empty symbol name once add_subsection produces `.text` as section name
427428
// instead of `.text.` when passed an empty symbol name. (object#748) Until then
428429
// pass `subsection` to produce `.text.subsection` as section name to reduce
@@ -451,6 +452,34 @@ impl Module for ObjectModule {
451452
)
452453
};
453454

455+
if used {
456+
match self.object.format() {
457+
object::BinaryFormat::Elf => {
458+
let section = self.object.section_mut(section);
459+
match &mut section.flags {
460+
SectionFlags::None => {
461+
section.flags = SectionFlags::Elf {
462+
sh_flags: object::elf::SHF_GNU_RETAIN.into(),
463+
}
464+
}
465+
SectionFlags::Elf { sh_flags } => {
466+
*sh_flags |= u64::from(object::elf::SHF_GNU_RETAIN)
467+
}
468+
_ => unreachable!(),
469+
}
470+
}
471+
object::BinaryFormat::Coff => {}
472+
object::BinaryFormat::MachO => {
473+
let symbol = self.object.symbol_mut(symbol);
474+
assert!(matches!(symbol.flags, SymbolFlags::None));
475+
symbol.flags = SymbolFlags::MachO {
476+
n_desc: object::macho::N_NO_DEAD_STRIP,
477+
}
478+
}
479+
_ => unreachable!(),
480+
}
481+
}
482+
454483
let align = std::cmp::max(align.unwrap_or(1), self.isa.symbol_alignment());
455484
let offset = match *init {
456485
Init::Uninitialized => {

0 commit comments

Comments
 (0)