Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cranelift/jit/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,7 @@ impl Module for JITModule {
data_relocs: _,
custom_segment_section: _,
align,
used: _,
} = data;

// Make sure to allocate at least 1 byte. Allocating 0 bytes is UB. Previously a dummy
Expand Down
17 changes: 14 additions & 3 deletions cranelift/module/src/data_context.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! Defines `DataContext`.
//! Defines `DataDescription`.

use cranelift_codegen::binemit::{Addend, CodeOffset, Reloc};
use cranelift_codegen::entity::PrimaryMap;
Expand Down Expand Up @@ -62,9 +62,12 @@ pub struct DataDescription {
pub data_relocs: Vec<(CodeOffset, ir::GlobalValue, Addend)>,
/// Object file section
pub custom_segment_section: Option<(String, String)>,
/// Alignment in bytes. `None` means that the default alignment of the respective module should
/// be used.
/// Alignment in bytes. `None` means that the default alignment of the
/// respective module should be used.
pub align: Option<u64>,
/// Whether or not to request the linker to preserve this data object even
/// if not referenced.
pub used: bool,
}

impl DataDescription {
Expand All @@ -78,6 +81,7 @@ impl DataDescription {
data_relocs: vec![],
custom_segment_section: None,
align: None,
used: false,
}
}

Expand All @@ -90,6 +94,7 @@ impl DataDescription {
self.data_relocs.clear();
self.custom_segment_section = None;
self.align = None;
self.used = false;
}

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

/// Set whether or not the linker should preserve this data object even if
/// not referenced.
pub fn set_used(&mut self, used: bool) {
self.used = used;
}

/// Declare an external function import.
///
/// Users of the `Module` API generally should call
Expand Down
2 changes: 1 addition & 1 deletion cranelift/module/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -979,7 +979,7 @@ pub trait Module {
relocs: &[ModuleReloc],
) -> ModuleResult<()>;

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

Expand Down
35 changes: 32 additions & 3 deletions cranelift/object/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ use object::write::{
Object, Relocation, SectionId, StandardSection, Symbol, SymbolId, SymbolSection,
};
use object::{
RelocationEncoding, RelocationFlags, RelocationKind, SectionKind, SymbolFlags, SymbolKind,
SymbolScope,
RelocationEncoding, RelocationFlags, RelocationKind, SectionFlags, SectionKind, SymbolFlags,
SymbolKind, SymbolScope,
};
use std::collections::HashMap;
use std::collections::hash_map::Entry;
Expand Down Expand Up @@ -394,6 +394,7 @@ impl Module for ObjectModule {
data_relocs: _,
ref custom_segment_section,
align,
used,
} = data;

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

if used {
match self.object.format() {
object::BinaryFormat::Elf => {
let section = self.object.section_mut(section);
match &mut section.flags {
SectionFlags::None => {
section.flags = SectionFlags::Elf {
sh_flags: object::elf::SHF_GNU_RETAIN.into(),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should have also included elf::SHF_ALLOC | elf::SHF_WRITE (or elf::SHF_ALLOC only when the data object is neither writable nor contains relocations).

}
}
SectionFlags::Elf { sh_flags } => {
*sh_flags |= u64::from(object::elf::SHF_GNU_RETAIN)
}
_ => unreachable!(),
}
}
object::BinaryFormat::Coff => {}
object::BinaryFormat::MachO => {
let symbol = self.object.symbol_mut(symbol);
assert!(matches!(symbol.flags, SymbolFlags::None));
symbol.flags = SymbolFlags::MachO {
n_desc: object::macho::N_NO_DEAD_STRIP,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And I think this is missing N_WEAK_REF/N_WEAK_DEF for weak symbols.

}
}
_ => unreachable!(),
}
}

let align = std::cmp::max(align.unwrap_or(1), self.isa.symbol_alignment());
let offset = match *init {
Init::Uninitialized => {
Expand Down