Path: blob/main/cranelift/object/src/backend.rs
3068 views
//! Defines `ObjectModule`.12use anyhow::anyhow;3use cranelift_codegen::binemit::{Addend, CodeOffset, Reloc};4use cranelift_codegen::entity::SecondaryMap;5use cranelift_codegen::ir;6use cranelift_codegen::isa::{OwnedTargetIsa, TargetIsa};7use cranelift_control::ControlPlane;8use cranelift_module::{9DataDescription, DataId, FuncId, Init, Linkage, Module, ModuleDeclarations, ModuleError,10ModuleReloc, ModuleRelocTarget, ModuleResult,11};12use log::info;13use object::write::{14Object, Relocation, SectionId, StandardSection, Symbol, SymbolId, SymbolSection,15};16use object::{17RelocationEncoding, RelocationFlags, RelocationKind, SectionFlags, SectionKind, SymbolFlags,18SymbolKind, SymbolScope, elf,19};20use std::collections::HashMap;21use std::collections::hash_map::Entry;22use std::mem;23use target_lexicon::PointerWidth;2425/// A builder for `ObjectModule`.26pub struct ObjectBuilder {27isa: OwnedTargetIsa,28binary_format: object::BinaryFormat,29architecture: object::Architecture,30flags: object::FileFlags,31endian: object::Endianness,32name: Vec<u8>,33libcall_names: Box<dyn Fn(ir::LibCall) -> String + Send + Sync>,34per_function_section: bool,35per_data_object_section: bool,36}3738impl ObjectBuilder {39/// Create a new `ObjectBuilder` using the given Cranelift target, that40/// can be passed to [`ObjectModule::new`].41///42/// The `libcall_names` function provides a way to translate `cranelift_codegen`'s [`ir::LibCall`]43/// enum to symbols. LibCalls are inserted in the IR as part of the legalization for certain44/// floating point instructions, and for stack probes. If you don't know what to use for this45/// argument, use [`cranelift_module::default_libcall_names`].46pub fn new<V: Into<Vec<u8>>>(47isa: OwnedTargetIsa,48name: V,49libcall_names: Box<dyn Fn(ir::LibCall) -> String + Send + Sync>,50) -> ModuleResult<Self> {51let mut file_flags = object::FileFlags::None;52let binary_format = match isa.triple().binary_format {53target_lexicon::BinaryFormat::Elf => object::BinaryFormat::Elf,54target_lexicon::BinaryFormat::Coff => object::BinaryFormat::Coff,55target_lexicon::BinaryFormat::Macho => object::BinaryFormat::MachO,56target_lexicon::BinaryFormat::Wasm => {57return Err(ModuleError::Backend(anyhow!(58"binary format wasm is unsupported",59)));60}61target_lexicon::BinaryFormat::Unknown => {62return Err(ModuleError::Backend(anyhow!("binary format is unknown")));63}64other => {65return Err(ModuleError::Backend(anyhow!(66"binary format {other} not recognized"67)));68}69};70let architecture = match isa.triple().architecture {71target_lexicon::Architecture::X86_32(_) => object::Architecture::I386,72target_lexicon::Architecture::X86_64 => object::Architecture::X86_64,73target_lexicon::Architecture::Arm(_) => object::Architecture::Arm,74target_lexicon::Architecture::Aarch64(_) => object::Architecture::Aarch64,75target_lexicon::Architecture::Riscv64(_) => {76if binary_format != object::BinaryFormat::Elf {77return Err(ModuleError::Backend(anyhow!(78"binary format {binary_format:?} is not supported for riscv64",79)));80}8182// FIXME(#4994): Get the right float ABI variant from the TargetIsa83let mut eflags = object::elf::EF_RISCV_FLOAT_ABI_DOUBLE;8485// Set the RVC eflag if we have the C extension enabled.86let has_c = isa87.isa_flags()88.iter()89.filter(|f| f.name == "has_zca" || f.name == "has_zcd")90.all(|f| f.as_bool().unwrap_or_default());91if has_c {92eflags |= object::elf::EF_RISCV_RVC;93}9495file_flags = object::FileFlags::Elf {96os_abi: object::elf::ELFOSABI_NONE,97abi_version: 0,98e_flags: eflags,99};100object::Architecture::Riscv64101}102target_lexicon::Architecture::S390x => object::Architecture::S390x,103architecture => {104return Err(ModuleError::Backend(anyhow!(105"target architecture {architecture:?} is unsupported",106)));107}108};109let endian = match isa.triple().endianness().unwrap() {110target_lexicon::Endianness::Little => object::Endianness::Little,111target_lexicon::Endianness::Big => object::Endianness::Big,112};113Ok(Self {114isa,115binary_format,116architecture,117flags: file_flags,118endian,119name: name.into(),120libcall_names,121per_function_section: false,122per_data_object_section: false,123})124}125126/// Set if every function should end up in their own section.127pub fn per_function_section(&mut self, per_function_section: bool) -> &mut Self {128self.per_function_section = per_function_section;129self130}131132/// Set if every data object should end up in their own section.133pub fn per_data_object_section(&mut self, per_data_object_section: bool) -> &mut Self {134self.per_data_object_section = per_data_object_section;135self136}137}138139/// An `ObjectModule` implements `Module` and emits ".o" files using the `object` library.140///141/// See the `ObjectBuilder` for a convenient way to construct `ObjectModule` instances.142pub struct ObjectModule {143isa: OwnedTargetIsa,144object: Object<'static>,145declarations: ModuleDeclarations,146functions: SecondaryMap<FuncId, Option<(SymbolId, bool)>>,147data_objects: SecondaryMap<DataId, Option<(SymbolId, bool)>>,148relocs: Vec<SymbolRelocs>,149libcalls: HashMap<ir::LibCall, SymbolId>,150libcall_names: Box<dyn Fn(ir::LibCall) -> String + Send + Sync>,151known_symbols: HashMap<ir::KnownSymbol, SymbolId>,152known_labels: HashMap<(FuncId, CodeOffset), SymbolId>,153per_function_section: bool,154per_data_object_section: bool,155}156157impl ObjectModule {158/// Create a new `ObjectModule` using the given Cranelift target.159pub fn new(builder: ObjectBuilder) -> Self {160let mut object = Object::new(builder.binary_format, builder.architecture, builder.endian);161object.flags = builder.flags;162object.set_subsections_via_symbols();163object.add_file_symbol(builder.name);164Self {165isa: builder.isa,166object,167declarations: ModuleDeclarations::default(),168functions: SecondaryMap::new(),169data_objects: SecondaryMap::new(),170relocs: Vec::new(),171libcalls: HashMap::new(),172libcall_names: builder.libcall_names,173known_symbols: HashMap::new(),174known_labels: HashMap::new(),175per_function_section: builder.per_function_section,176per_data_object_section: builder.per_data_object_section,177}178}179}180181fn validate_symbol(name: &str) -> ModuleResult<()> {182// null bytes are not allowed in symbol names and will cause the `object`183// crate to panic. Let's return a clean error instead.184if name.contains("\0") {185return Err(ModuleError::Backend(anyhow::anyhow!(186"Symbol {name:?} has a null byte, which is disallowed"187)));188}189Ok(())190}191192impl Module for ObjectModule {193fn isa(&self) -> &dyn TargetIsa {194&*self.isa195}196197fn declarations(&self) -> &ModuleDeclarations {198&self.declarations199}200201fn declare_function(202&mut self,203name: &str,204linkage: Linkage,205signature: &ir::Signature,206) -> ModuleResult<FuncId> {207validate_symbol(name)?;208209let (id, linkage) = self210.declarations211.declare_function(name, linkage, signature)?;212213let (scope, weak) = translate_linkage(linkage);214215if let Some((function, _defined)) = self.functions[id] {216let symbol = self.object.symbol_mut(function);217symbol.scope = scope;218symbol.weak = weak;219} else {220let symbol_id = self.object.add_symbol(Symbol {221name: name.as_bytes().to_vec(),222value: 0,223size: 0,224kind: SymbolKind::Text,225scope,226weak,227section: SymbolSection::Undefined,228flags: SymbolFlags::None,229});230self.functions[id] = Some((symbol_id, false));231}232233Ok(id)234}235236fn declare_anonymous_function(&mut self, signature: &ir::Signature) -> ModuleResult<FuncId> {237let id = self.declarations.declare_anonymous_function(signature)?;238239let symbol_id = self.object.add_symbol(Symbol {240name: self241.declarations242.get_function_decl(id)243.linkage_name(id)244.into_owned()245.into_bytes(),246value: 0,247size: 0,248kind: SymbolKind::Text,249scope: SymbolScope::Compilation,250weak: false,251section: SymbolSection::Undefined,252flags: SymbolFlags::None,253});254self.functions[id] = Some((symbol_id, false));255256Ok(id)257}258259fn declare_data(260&mut self,261name: &str,262linkage: Linkage,263writable: bool,264tls: bool,265) -> ModuleResult<DataId> {266validate_symbol(name)?;267268let (id, linkage) = self269.declarations270.declare_data(name, linkage, writable, tls)?;271272// Merging declarations with conflicting values for tls is not allowed, so it is safe to use273// the passed in tls value here.274let kind = if tls {275SymbolKind::Tls276} else {277SymbolKind::Data278};279let (scope, weak) = translate_linkage(linkage);280281if let Some((data, _defined)) = self.data_objects[id] {282let symbol = self.object.symbol_mut(data);283symbol.kind = kind;284symbol.scope = scope;285symbol.weak = weak;286} else {287let symbol_id = self.object.add_symbol(Symbol {288name: name.as_bytes().to_vec(),289value: 0,290size: 0,291kind,292scope,293weak,294section: SymbolSection::Undefined,295flags: SymbolFlags::None,296});297self.data_objects[id] = Some((symbol_id, false));298}299300Ok(id)301}302303fn declare_anonymous_data(&mut self, writable: bool, tls: bool) -> ModuleResult<DataId> {304let id = self.declarations.declare_anonymous_data(writable, tls)?;305306let kind = if tls {307SymbolKind::Tls308} else {309SymbolKind::Data310};311312let symbol_id = self.object.add_symbol(Symbol {313name: self314.declarations315.get_data_decl(id)316.linkage_name(id)317.into_owned()318.into_bytes(),319value: 0,320size: 0,321kind,322scope: SymbolScope::Compilation,323weak: false,324section: SymbolSection::Undefined,325flags: SymbolFlags::None,326});327self.data_objects[id] = Some((symbol_id, false));328329Ok(id)330}331332fn define_function_with_control_plane(333&mut self,334func_id: FuncId,335ctx: &mut cranelift_codegen::Context,336ctrl_plane: &mut ControlPlane,337) -> ModuleResult<()> {338info!("defining function {}: {}", func_id, ctx.func.display());339340let res = ctx.compile(self.isa(), ctrl_plane)?;341let alignment = res.buffer.alignment as u64;342343let buffer = &ctx.compiled_code().unwrap().buffer;344let relocs = buffer345.relocs()346.iter()347.map(|reloc| {348self.process_reloc(&ModuleReloc::from_mach_reloc(&reloc, &ctx.func, func_id))349})350.collect::<Vec<_>>();351self.define_function_inner(func_id, alignment, buffer.data(), relocs)352}353354fn define_function_bytes(355&mut self,356func_id: FuncId,357alignment: u64,358bytes: &[u8],359relocs: &[ModuleReloc],360) -> ModuleResult<()> {361let relocs = relocs362.iter()363.map(|reloc| self.process_reloc(reloc))364.collect();365self.define_function_inner(func_id, alignment, bytes, relocs)366}367368fn define_data(&mut self, data_id: DataId, data: &DataDescription) -> ModuleResult<()> {369let decl = self.declarations.get_data_decl(data_id);370if !decl.linkage.is_definable() {371return Err(ModuleError::InvalidImportDefinition(372decl.linkage_name(data_id).into_owned(),373));374}375376let &mut (symbol, ref mut defined) = self.data_objects[data_id].as_mut().unwrap();377if *defined {378return Err(ModuleError::DuplicateDefinition(379decl.linkage_name(data_id).into_owned(),380));381}382*defined = true;383384let &DataDescription {385ref init,386function_decls: _,387data_decls: _,388function_relocs: _,389data_relocs: _,390ref custom_segment_section,391align,392used,393} = data;394395let pointer_reloc = match self.isa.triple().pointer_width().unwrap() {396PointerWidth::U16 => unimplemented!("16bit pointers"),397PointerWidth::U32 => Reloc::Abs4,398PointerWidth::U64 => Reloc::Abs8,399};400let relocs = data401.all_relocs(pointer_reloc)402.map(|record| self.process_reloc(&record))403.collect::<Vec<_>>();404405let section = if custom_segment_section.is_none() {406let section_kind = if let Init::Zeros { .. } = *init {407if decl.tls {408StandardSection::UninitializedTls409} else {410StandardSection::UninitializedData411}412} else if decl.tls {413StandardSection::Tls414} else if decl.writable {415StandardSection::Data416} else if relocs.is_empty() {417StandardSection::ReadOnlyData418} else {419StandardSection::ReadOnlyDataWithRel420};421if self.per_data_object_section || used {422// FIXME pass empty symbol name once add_subsection produces `.text` as section name423// instead of `.text.` when passed an empty symbol name. (object#748) Until then424// pass `subsection` to produce `.text.subsection` as section name to reduce425// confusion.426self.object.add_subsection(section_kind, b"subsection")427} else {428self.object.section_id(section_kind)429}430} else {431if decl.tls {432return Err(cranelift_module::ModuleError::Backend(anyhow::anyhow!(433"Custom section not supported for TLS"434)));435}436let (seg, sec) = &custom_segment_section.as_ref().unwrap();437self.object.add_section(438seg.clone().into_bytes(),439sec.clone().into_bytes(),440if decl.writable {441SectionKind::Data442} else if relocs.is_empty() {443SectionKind::ReadOnlyData444} else {445SectionKind::ReadOnlyDataWithRel446},447)448};449450if used {451match self.object.format() {452object::BinaryFormat::Elf => match self.object.section_flags_mut(section) {453SectionFlags::Elf { sh_flags } => *sh_flags |= u64::from(elf::SHF_GNU_RETAIN),454_ => unreachable!(),455},456object::BinaryFormat::Coff => {}457object::BinaryFormat::MachO => match self.object.symbol_flags_mut(symbol) {458SymbolFlags::MachO { n_desc } => *n_desc |= object::macho::N_NO_DEAD_STRIP,459_ => unreachable!(),460},461_ => unreachable!(),462}463}464465let align = std::cmp::max(align.unwrap_or(1), self.isa.symbol_alignment());466let offset = match *init {467Init::Uninitialized => {468panic!("data is not initialized yet");469}470Init::Zeros { size } => self471.object472.add_symbol_bss(symbol, section, size as u64, align),473Init::Bytes { ref contents } => self474.object475.add_symbol_data(symbol, section, &contents, align),476};477if !relocs.is_empty() {478self.relocs.push(SymbolRelocs {479section,480offset,481relocs,482});483}484Ok(())485}486}487488impl ObjectModule {489fn define_function_inner(490&mut self,491func_id: FuncId,492alignment: u64,493bytes: &[u8],494relocs: Vec<ObjectRelocRecord>,495) -> Result<(), ModuleError> {496info!("defining function {func_id} with bytes");497let decl = self.declarations.get_function_decl(func_id);498let decl_name = decl.linkage_name(func_id);499if !decl.linkage.is_definable() {500return Err(ModuleError::InvalidImportDefinition(decl_name.into_owned()));501}502503let &mut (symbol, ref mut defined) = self.functions[func_id].as_mut().unwrap();504if *defined {505return Err(ModuleError::DuplicateDefinition(decl_name.into_owned()));506}507*defined = true;508509let align = alignment.max(self.isa.symbol_alignment());510let section = if self.per_function_section {511// FIXME pass empty symbol name once add_subsection produces `.text` as section name512// instead of `.text.` when passed an empty symbol name. (object#748) Until then pass513// `subsection` to produce `.text.subsection` as section name to reduce confusion.514self.object515.add_subsection(StandardSection::Text, b"subsection")516} else {517self.object.section_id(StandardSection::Text)518};519let offset = self.object.add_symbol_data(symbol, section, bytes, align);520521if !relocs.is_empty() {522self.relocs.push(SymbolRelocs {523section,524offset,525relocs,526});527}528529Ok(())530}531532/// Finalize all relocations and output an object.533pub fn finish(mut self) -> ObjectProduct {534if cfg!(debug_assertions) {535for (func_id, decl) in self.declarations.get_functions() {536if !decl.linkage.requires_definition() {537continue;538}539540assert!(541self.functions[func_id].unwrap().1,542"function \"{}\" with linkage {:?} must be defined but is not",543decl.linkage_name(func_id),544decl.linkage,545);546}547548for (data_id, decl) in self.declarations.get_data_objects() {549if !decl.linkage.requires_definition() {550continue;551}552553assert!(554self.data_objects[data_id].unwrap().1,555"data object \"{}\" with linkage {:?} must be defined but is not",556decl.linkage_name(data_id),557decl.linkage,558);559}560}561562let symbol_relocs = mem::take(&mut self.relocs);563for symbol in symbol_relocs {564for &ObjectRelocRecord {565offset,566ref name,567flags,568addend,569} in &symbol.relocs570{571let target_symbol = self.get_symbol(name);572self.object573.add_relocation(574symbol.section,575Relocation {576offset: symbol.offset + u64::from(offset),577flags,578symbol: target_symbol,579addend,580},581)582.unwrap();583}584}585586// Indicate that this object has a non-executable stack.587if self.object.format() == object::BinaryFormat::Elf {588self.object.add_section(589vec![],590".note.GNU-stack".as_bytes().to_vec(),591SectionKind::Linker,592);593}594595ObjectProduct {596object: self.object,597functions: self.functions,598data_objects: self.data_objects,599}600}601602/// This should only be called during finish because it creates603/// symbols for missing libcalls.604fn get_symbol(&mut self, name: &ModuleRelocTarget) -> SymbolId {605match *name {606ModuleRelocTarget::User { .. } => {607if ModuleDeclarations::is_function(name) {608let id = FuncId::from_name(name);609self.functions[id].unwrap().0610} else {611let id = DataId::from_name(name);612self.data_objects[id].unwrap().0613}614}615ModuleRelocTarget::LibCall(ref libcall) => {616let name = (self.libcall_names)(*libcall);617if let Some(symbol) = self.object.symbol_id(name.as_bytes()) {618symbol619} else if let Some(symbol) = self.libcalls.get(libcall) {620*symbol621} else {622let symbol = self.object.add_symbol(Symbol {623name: name.as_bytes().to_vec(),624value: 0,625size: 0,626kind: SymbolKind::Text,627scope: SymbolScope::Unknown,628weak: false,629section: SymbolSection::Undefined,630flags: SymbolFlags::None,631});632self.libcalls.insert(*libcall, symbol);633symbol634}635}636// These are "magic" names well-known to the linker.637// They require special treatment.638ModuleRelocTarget::KnownSymbol(ref known_symbol) => {639if let Some(symbol) = self.known_symbols.get(known_symbol) {640*symbol641} else {642let symbol = self.object.add_symbol(match known_symbol {643ir::KnownSymbol::ElfGlobalOffsetTable => Symbol {644name: b"_GLOBAL_OFFSET_TABLE_".to_vec(),645value: 0,646size: 0,647kind: SymbolKind::Data,648scope: SymbolScope::Unknown,649weak: false,650section: SymbolSection::Undefined,651flags: SymbolFlags::None,652},653ir::KnownSymbol::CoffTlsIndex => Symbol {654name: b"_tls_index".to_vec(),655value: 0,656size: 32,657kind: SymbolKind::Tls,658scope: SymbolScope::Unknown,659weak: false,660section: SymbolSection::Undefined,661flags: SymbolFlags::None,662},663});664self.known_symbols.insert(*known_symbol, symbol);665symbol666}667}668669ModuleRelocTarget::FunctionOffset(func_id, offset) => {670match self.known_labels.entry((func_id, offset)) {671Entry::Occupied(o) => *o.get(),672Entry::Vacant(v) => {673let func_symbol_id = self.functions[func_id].unwrap().0;674let func_symbol = self.object.symbol(func_symbol_id);675676let name = format!(".L{}_{}", func_id.as_u32(), offset);677let symbol_id = self.object.add_symbol(Symbol {678name: name.as_bytes().to_vec(),679value: func_symbol.value + offset as u64,680size: 0,681kind: SymbolKind::Label,682scope: SymbolScope::Compilation,683weak: false,684section: SymbolSection::Section(func_symbol.section.id().unwrap()),685flags: SymbolFlags::None,686});687688v.insert(symbol_id);689symbol_id690}691}692}693}694}695696fn process_reloc(&self, record: &ModuleReloc) -> ObjectRelocRecord {697let flags = match record.kind {698Reloc::Abs4 => RelocationFlags::Generic {699kind: RelocationKind::Absolute,700encoding: RelocationEncoding::Generic,701size: 32,702},703Reloc::Abs8 => RelocationFlags::Generic {704kind: RelocationKind::Absolute,705encoding: RelocationEncoding::Generic,706size: 64,707},708Reloc::X86PCRel4 => RelocationFlags::Generic {709kind: RelocationKind::Relative,710encoding: RelocationEncoding::Generic,711size: 32,712},713Reloc::X86CallPCRel4 => RelocationFlags::Generic {714kind: RelocationKind::Relative,715encoding: RelocationEncoding::X86Branch,716size: 32,717},718// TODO: Get Cranelift to tell us when we can use719// R_X86_64_GOTPCRELX/R_X86_64_REX_GOTPCRELX.720Reloc::X86CallPLTRel4 => RelocationFlags::Generic {721kind: RelocationKind::PltRelative,722encoding: RelocationEncoding::X86Branch,723size: 32,724},725Reloc::X86SecRel => RelocationFlags::Generic {726kind: RelocationKind::SectionOffset,727encoding: RelocationEncoding::Generic,728size: 32,729},730Reloc::X86GOTPCRel4 => RelocationFlags::Generic {731kind: RelocationKind::GotRelative,732encoding: RelocationEncoding::Generic,733size: 32,734},735Reloc::Arm64Call => RelocationFlags::Generic {736kind: RelocationKind::Relative,737encoding: RelocationEncoding::AArch64Call,738size: 26,739},740Reloc::ElfX86_64TlsGd => {741assert_eq!(742self.object.format(),743object::BinaryFormat::Elf,744"ElfX86_64TlsGd is not supported for this file format"745);746RelocationFlags::Elf {747r_type: object::elf::R_X86_64_TLSGD,748}749}750Reloc::MachOX86_64Tlv => {751assert_eq!(752self.object.format(),753object::BinaryFormat::MachO,754"MachOX86_64Tlv is not supported for this file format"755);756RelocationFlags::MachO {757r_type: object::macho::X86_64_RELOC_TLV,758r_pcrel: true,759r_length: 2,760}761}762Reloc::MachOAarch64TlsAdrPage21 => {763assert_eq!(764self.object.format(),765object::BinaryFormat::MachO,766"MachOAarch64TlsAdrPage21 is not supported for this file format"767);768RelocationFlags::MachO {769r_type: object::macho::ARM64_RELOC_TLVP_LOAD_PAGE21,770r_pcrel: true,771r_length: 2,772}773}774Reloc::MachOAarch64TlsAdrPageOff12 => {775assert_eq!(776self.object.format(),777object::BinaryFormat::MachO,778"MachOAarch64TlsAdrPageOff12 is not supported for this file format"779);780RelocationFlags::MachO {781r_type: object::macho::ARM64_RELOC_TLVP_LOAD_PAGEOFF12,782r_pcrel: false,783r_length: 2,784}785}786Reloc::Aarch64TlsDescAdrPage21 => {787assert_eq!(788self.object.format(),789object::BinaryFormat::Elf,790"Aarch64TlsDescAdrPage21 is not supported for this file format"791);792RelocationFlags::Elf {793r_type: object::elf::R_AARCH64_TLSDESC_ADR_PAGE21,794}795}796Reloc::Aarch64TlsDescLd64Lo12 => {797assert_eq!(798self.object.format(),799object::BinaryFormat::Elf,800"Aarch64TlsDescLd64Lo12 is not supported for this file format"801);802RelocationFlags::Elf {803r_type: object::elf::R_AARCH64_TLSDESC_LD64_LO12,804}805}806Reloc::Aarch64TlsDescAddLo12 => {807assert_eq!(808self.object.format(),809object::BinaryFormat::Elf,810"Aarch64TlsDescAddLo12 is not supported for this file format"811);812RelocationFlags::Elf {813r_type: object::elf::R_AARCH64_TLSDESC_ADD_LO12,814}815}816Reloc::Aarch64TlsDescCall => {817assert_eq!(818self.object.format(),819object::BinaryFormat::Elf,820"Aarch64TlsDescCall is not supported for this file format"821);822RelocationFlags::Elf {823r_type: object::elf::R_AARCH64_TLSDESC_CALL,824}825}826827Reloc::Aarch64AdrGotPage21 => match self.object.format() {828object::BinaryFormat::Elf => RelocationFlags::Elf {829r_type: object::elf::R_AARCH64_ADR_GOT_PAGE,830},831object::BinaryFormat::MachO => RelocationFlags::MachO {832r_type: object::macho::ARM64_RELOC_GOT_LOAD_PAGE21,833r_pcrel: true,834r_length: 2,835},836_ => unimplemented!("Aarch64AdrGotPage21 is not supported for this file format"),837},838Reloc::Aarch64Ld64GotLo12Nc => match self.object.format() {839object::BinaryFormat::Elf => RelocationFlags::Elf {840r_type: object::elf::R_AARCH64_LD64_GOT_LO12_NC,841},842object::BinaryFormat::MachO => RelocationFlags::MachO {843r_type: object::macho::ARM64_RELOC_GOT_LOAD_PAGEOFF12,844r_pcrel: false,845r_length: 2,846},847_ => unimplemented!("Aarch64Ld64GotLo12Nc is not supported for this file format"),848},849Reloc::S390xPCRel32Dbl => RelocationFlags::Generic {850kind: RelocationKind::Relative,851encoding: RelocationEncoding::S390xDbl,852size: 32,853},854Reloc::S390xPLTRel32Dbl => RelocationFlags::Generic {855kind: RelocationKind::PltRelative,856encoding: RelocationEncoding::S390xDbl,857size: 32,858},859Reloc::S390xTlsGd64 => {860assert_eq!(861self.object.format(),862object::BinaryFormat::Elf,863"S390xTlsGd64 is not supported for this file format"864);865RelocationFlags::Elf {866r_type: object::elf::R_390_TLS_GD64,867}868}869Reloc::S390xTlsGdCall => {870assert_eq!(871self.object.format(),872object::BinaryFormat::Elf,873"S390xTlsGdCall is not supported for this file format"874);875RelocationFlags::Elf {876r_type: object::elf::R_390_TLS_GDCALL,877}878}879Reloc::RiscvCallPlt => {880assert_eq!(881self.object.format(),882object::BinaryFormat::Elf,883"RiscvCallPlt is not supported for this file format"884);885RelocationFlags::Elf {886r_type: object::elf::R_RISCV_CALL_PLT,887}888}889Reloc::RiscvTlsGdHi20 => {890assert_eq!(891self.object.format(),892object::BinaryFormat::Elf,893"RiscvTlsGdHi20 is not supported for this file format"894);895RelocationFlags::Elf {896r_type: object::elf::R_RISCV_TLS_GD_HI20,897}898}899Reloc::RiscvPCRelLo12I => {900assert_eq!(901self.object.format(),902object::BinaryFormat::Elf,903"RiscvPCRelLo12I is not supported for this file format"904);905RelocationFlags::Elf {906r_type: object::elf::R_RISCV_PCREL_LO12_I,907}908}909Reloc::RiscvGotHi20 => {910assert_eq!(911self.object.format(),912object::BinaryFormat::Elf,913"RiscvGotHi20 is not supported for this file format"914);915RelocationFlags::Elf {916r_type: object::elf::R_RISCV_GOT_HI20,917}918}919// FIXME920reloc => unimplemented!("{:?}", reloc),921};922923ObjectRelocRecord {924offset: record.offset,925name: record.name.clone(),926flags,927addend: record.addend,928}929}930}931932fn translate_linkage(linkage: Linkage) -> (SymbolScope, bool) {933let scope = match linkage {934Linkage::Import => SymbolScope::Unknown,935Linkage::Local => SymbolScope::Compilation,936Linkage::Hidden => SymbolScope::Linkage,937Linkage::Export | Linkage::Preemptible => SymbolScope::Dynamic,938};939// TODO: this matches rustc_codegen_cranelift, but may be wrong.940let weak = linkage == Linkage::Preemptible;941(scope, weak)942}943944/// This is the output of `ObjectModule`'s945/// [`finish`](../struct.ObjectModule.html#method.finish) function.946/// It contains the generated `Object` and other information produced during947/// compilation.948pub struct ObjectProduct {949/// Object artifact with all functions and data from the module defined.950pub object: Object<'static>,951/// Symbol IDs for functions (both declared and defined).952pub functions: SecondaryMap<FuncId, Option<(SymbolId, bool)>>,953/// Symbol IDs for data objects (both declared and defined).954pub data_objects: SecondaryMap<DataId, Option<(SymbolId, bool)>>,955}956957impl ObjectProduct {958/// Return the `SymbolId` for the given function.959#[inline]960pub fn function_symbol(&self, id: FuncId) -> SymbolId {961self.functions[id].unwrap().0962}963964/// Return the `SymbolId` for the given data object.965#[inline]966pub fn data_symbol(&self, id: DataId) -> SymbolId {967self.data_objects[id].unwrap().0968}969970/// Write the object bytes in memory.971#[inline]972pub fn emit(self) -> Result<Vec<u8>, object::write::Error> {973self.object.write()974}975}976977#[derive(Clone)]978struct SymbolRelocs {979section: SectionId,980offset: u64,981relocs: Vec<ObjectRelocRecord>,982}983984#[derive(Clone)]985struct ObjectRelocRecord {986offset: CodeOffset,987name: ModuleRelocTarget,988flags: RelocationFlags,989addend: Addend,990}991992993