Path: blob/main/cranelift/object/src/backend.rs
1691 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 {} not recognized",67other68)));69}70};71let architecture = match isa.triple().architecture {72target_lexicon::Architecture::X86_32(_) => object::Architecture::I386,73target_lexicon::Architecture::X86_64 => object::Architecture::X86_64,74target_lexicon::Architecture::Arm(_) => object::Architecture::Arm,75target_lexicon::Architecture::Aarch64(_) => object::Architecture::Aarch64,76target_lexicon::Architecture::Riscv64(_) => {77if binary_format != object::BinaryFormat::Elf {78return Err(ModuleError::Backend(anyhow!(79"binary format {:?} is not supported for riscv64",80binary_format,81)));82}8384// FIXME(#4994): Get the right float ABI variant from the TargetIsa85let mut eflags = object::elf::EF_RISCV_FLOAT_ABI_DOUBLE;8687// Set the RVC eflag if we have the C extension enabled.88let has_c = isa89.isa_flags()90.iter()91.filter(|f| f.name == "has_zca" || f.name == "has_zcd")92.all(|f| f.as_bool().unwrap_or_default());93if has_c {94eflags |= object::elf::EF_RISCV_RVC;95}9697file_flags = object::FileFlags::Elf {98os_abi: object::elf::ELFOSABI_NONE,99abi_version: 0,100e_flags: eflags,101};102object::Architecture::Riscv64103}104target_lexicon::Architecture::S390x => object::Architecture::S390x,105architecture => {106return Err(ModuleError::Backend(anyhow!(107"target architecture {:?} is unsupported",108architecture,109)));110}111};112let endian = match isa.triple().endianness().unwrap() {113target_lexicon::Endianness::Little => object::Endianness::Little,114target_lexicon::Endianness::Big => object::Endianness::Big,115};116Ok(Self {117isa,118binary_format,119architecture,120flags: file_flags,121endian,122name: name.into(),123libcall_names,124per_function_section: false,125per_data_object_section: false,126})127}128129/// Set if every function should end up in their own section.130pub fn per_function_section(&mut self, per_function_section: bool) -> &mut Self {131self.per_function_section = per_function_section;132self133}134135/// Set if every data object should end up in their own section.136pub fn per_data_object_section(&mut self, per_data_object_section: bool) -> &mut Self {137self.per_data_object_section = per_data_object_section;138self139}140}141142/// An `ObjectModule` implements `Module` and emits ".o" files using the `object` library.143///144/// See the `ObjectBuilder` for a convenient way to construct `ObjectModule` instances.145pub struct ObjectModule {146isa: OwnedTargetIsa,147object: Object<'static>,148declarations: ModuleDeclarations,149functions: SecondaryMap<FuncId, Option<(SymbolId, bool)>>,150data_objects: SecondaryMap<DataId, Option<(SymbolId, bool)>>,151relocs: Vec<SymbolRelocs>,152libcalls: HashMap<ir::LibCall, SymbolId>,153libcall_names: Box<dyn Fn(ir::LibCall) -> String + Send + Sync>,154known_symbols: HashMap<ir::KnownSymbol, SymbolId>,155known_labels: HashMap<(FuncId, CodeOffset), SymbolId>,156per_function_section: bool,157per_data_object_section: bool,158}159160impl ObjectModule {161/// Create a new `ObjectModule` using the given Cranelift target.162pub fn new(builder: ObjectBuilder) -> Self {163let mut object = Object::new(builder.binary_format, builder.architecture, builder.endian);164object.flags = builder.flags;165object.set_subsections_via_symbols();166object.add_file_symbol(builder.name);167Self {168isa: builder.isa,169object,170declarations: ModuleDeclarations::default(),171functions: SecondaryMap::new(),172data_objects: SecondaryMap::new(),173relocs: Vec::new(),174libcalls: HashMap::new(),175libcall_names: builder.libcall_names,176known_symbols: HashMap::new(),177known_labels: HashMap::new(),178per_function_section: builder.per_function_section,179per_data_object_section: builder.per_data_object_section,180}181}182}183184fn validate_symbol(name: &str) -> ModuleResult<()> {185// null bytes are not allowed in symbol names and will cause the `object`186// crate to panic. Let's return a clean error instead.187if name.contains("\0") {188return Err(ModuleError::Backend(anyhow::anyhow!(189"Symbol {:?} has a null byte, which is disallowed",190name191)));192}193Ok(())194}195196impl Module for ObjectModule {197fn isa(&self) -> &dyn TargetIsa {198&*self.isa199}200201fn declarations(&self) -> &ModuleDeclarations {202&self.declarations203}204205fn declare_function(206&mut self,207name: &str,208linkage: Linkage,209signature: &ir::Signature,210) -> ModuleResult<FuncId> {211validate_symbol(name)?;212213let (id, linkage) = self214.declarations215.declare_function(name, linkage, signature)?;216217let (scope, weak) = translate_linkage(linkage);218219if let Some((function, _defined)) = self.functions[id] {220let symbol = self.object.symbol_mut(function);221symbol.scope = scope;222symbol.weak = weak;223} else {224let symbol_id = self.object.add_symbol(Symbol {225name: name.as_bytes().to_vec(),226value: 0,227size: 0,228kind: SymbolKind::Text,229scope,230weak,231section: SymbolSection::Undefined,232flags: SymbolFlags::None,233});234self.functions[id] = Some((symbol_id, false));235}236237Ok(id)238}239240fn declare_anonymous_function(&mut self, signature: &ir::Signature) -> ModuleResult<FuncId> {241let id = self.declarations.declare_anonymous_function(signature)?;242243let symbol_id = self.object.add_symbol(Symbol {244name: self245.declarations246.get_function_decl(id)247.linkage_name(id)248.into_owned()249.into_bytes(),250value: 0,251size: 0,252kind: SymbolKind::Text,253scope: SymbolScope::Compilation,254weak: false,255section: SymbolSection::Undefined,256flags: SymbolFlags::None,257});258self.functions[id] = Some((symbol_id, false));259260Ok(id)261}262263fn declare_data(264&mut self,265name: &str,266linkage: Linkage,267writable: bool,268tls: bool,269) -> ModuleResult<DataId> {270validate_symbol(name)?;271272let (id, linkage) = self273.declarations274.declare_data(name, linkage, writable, tls)?;275276// Merging declarations with conflicting values for tls is not allowed, so it is safe to use277// the passed in tls value here.278let kind = if tls {279SymbolKind::Tls280} else {281SymbolKind::Data282};283let (scope, weak) = translate_linkage(linkage);284285if let Some((data, _defined)) = self.data_objects[id] {286let symbol = self.object.symbol_mut(data);287symbol.kind = kind;288symbol.scope = scope;289symbol.weak = weak;290} else {291let symbol_id = self.object.add_symbol(Symbol {292name: name.as_bytes().to_vec(),293value: 0,294size: 0,295kind,296scope,297weak,298section: SymbolSection::Undefined,299flags: SymbolFlags::None,300});301self.data_objects[id] = Some((symbol_id, false));302}303304Ok(id)305}306307fn declare_anonymous_data(&mut self, writable: bool, tls: bool) -> ModuleResult<DataId> {308let id = self.declarations.declare_anonymous_data(writable, tls)?;309310let kind = if tls {311SymbolKind::Tls312} else {313SymbolKind::Data314};315316let symbol_id = self.object.add_symbol(Symbol {317name: self318.declarations319.get_data_decl(id)320.linkage_name(id)321.into_owned()322.into_bytes(),323value: 0,324size: 0,325kind,326scope: SymbolScope::Compilation,327weak: false,328section: SymbolSection::Undefined,329flags: SymbolFlags::None,330});331self.data_objects[id] = Some((symbol_id, false));332333Ok(id)334}335336fn define_function_with_control_plane(337&mut self,338func_id: FuncId,339ctx: &mut cranelift_codegen::Context,340ctrl_plane: &mut ControlPlane,341) -> ModuleResult<()> {342info!("defining function {}: {}", func_id, ctx.func.display());343344let res = ctx.compile(self.isa(), ctrl_plane)?;345let alignment = res.buffer.alignment as u64;346347let buffer = &ctx.compiled_code().unwrap().buffer;348let relocs = buffer349.relocs()350.iter()351.map(|reloc| {352self.process_reloc(&ModuleReloc::from_mach_reloc(&reloc, &ctx.func, func_id))353})354.collect::<Vec<_>>();355self.define_function_inner(func_id, alignment, buffer.data(), relocs)356}357358fn define_function_bytes(359&mut self,360func_id: FuncId,361alignment: u64,362bytes: &[u8],363relocs: &[ModuleReloc],364) -> ModuleResult<()> {365let relocs = relocs366.iter()367.map(|reloc| self.process_reloc(reloc))368.collect();369self.define_function_inner(func_id, alignment, bytes, relocs)370}371372fn define_data(&mut self, data_id: DataId, data: &DataDescription) -> ModuleResult<()> {373let decl = self.declarations.get_data_decl(data_id);374if !decl.linkage.is_definable() {375return Err(ModuleError::InvalidImportDefinition(376decl.linkage_name(data_id).into_owned(),377));378}379380let &mut (symbol, ref mut defined) = self.data_objects[data_id].as_mut().unwrap();381if *defined {382return Err(ModuleError::DuplicateDefinition(383decl.linkage_name(data_id).into_owned(),384));385}386*defined = true;387388let &DataDescription {389ref init,390function_decls: _,391data_decls: _,392function_relocs: _,393data_relocs: _,394ref custom_segment_section,395align,396used,397} = data;398399let pointer_reloc = match self.isa.triple().pointer_width().unwrap() {400PointerWidth::U16 => unimplemented!("16bit pointers"),401PointerWidth::U32 => Reloc::Abs4,402PointerWidth::U64 => Reloc::Abs8,403};404let relocs = data405.all_relocs(pointer_reloc)406.map(|record| self.process_reloc(&record))407.collect::<Vec<_>>();408409let section = if custom_segment_section.is_none() {410let section_kind = if let Init::Zeros { .. } = *init {411if decl.tls {412StandardSection::UninitializedTls413} else {414StandardSection::UninitializedData415}416} else if decl.tls {417StandardSection::Tls418} else if decl.writable {419StandardSection::Data420} else if relocs.is_empty() {421StandardSection::ReadOnlyData422} else {423StandardSection::ReadOnlyDataWithRel424};425if self.per_data_object_section || used {426// FIXME pass empty symbol name once add_subsection produces `.text` as section name427// instead of `.text.` when passed an empty symbol name. (object#748) Until then428// pass `subsection` to produce `.text.subsection` as section name to reduce429// confusion.430self.object.add_subsection(section_kind, b"subsection")431} else {432self.object.section_id(section_kind)433}434} else {435if decl.tls {436return Err(cranelift_module::ModuleError::Backend(anyhow::anyhow!(437"Custom section not supported for TLS"438)));439}440let (seg, sec) = &custom_segment_section.as_ref().unwrap();441self.object.add_section(442seg.clone().into_bytes(),443sec.clone().into_bytes(),444if decl.writable {445SectionKind::Data446} else if relocs.is_empty() {447SectionKind::ReadOnlyData448} else {449SectionKind::ReadOnlyDataWithRel450},451)452};453454if used {455match self.object.format() {456object::BinaryFormat::Elf => match self.object.section_flags_mut(section) {457SectionFlags::Elf { sh_flags } => *sh_flags |= u64::from(elf::SHF_GNU_RETAIN),458_ => unreachable!(),459},460object::BinaryFormat::Coff => {}461object::BinaryFormat::MachO => match self.object.symbol_flags_mut(symbol) {462SymbolFlags::MachO { n_desc } => *n_desc |= object::macho::N_NO_DEAD_STRIP,463_ => unreachable!(),464},465_ => unreachable!(),466}467}468469let align = std::cmp::max(align.unwrap_or(1), self.isa.symbol_alignment());470let offset = match *init {471Init::Uninitialized => {472panic!("data is not initialized yet");473}474Init::Zeros { size } => self475.object476.add_symbol_bss(symbol, section, size as u64, align),477Init::Bytes { ref contents } => self478.object479.add_symbol_data(symbol, section, &contents, align),480};481if !relocs.is_empty() {482self.relocs.push(SymbolRelocs {483section,484offset,485relocs,486});487}488Ok(())489}490}491492impl ObjectModule {493fn define_function_inner(494&mut self,495func_id: FuncId,496alignment: u64,497bytes: &[u8],498relocs: Vec<ObjectRelocRecord>,499) -> Result<(), ModuleError> {500info!("defining function {func_id} with bytes");501let decl = self.declarations.get_function_decl(func_id);502let decl_name = decl.linkage_name(func_id);503if !decl.linkage.is_definable() {504return Err(ModuleError::InvalidImportDefinition(decl_name.into_owned()));505}506507let &mut (symbol, ref mut defined) = self.functions[func_id].as_mut().unwrap();508if *defined {509return Err(ModuleError::DuplicateDefinition(decl_name.into_owned()));510}511*defined = true;512513let align = alignment.max(self.isa.symbol_alignment());514let section = if self.per_function_section {515// FIXME pass empty symbol name once add_subsection produces `.text` as section name516// instead of `.text.` when passed an empty symbol name. (object#748) Until then pass517// `subsection` to produce `.text.subsection` as section name to reduce confusion.518self.object519.add_subsection(StandardSection::Text, b"subsection")520} else {521self.object.section_id(StandardSection::Text)522};523let offset = self.object.add_symbol_data(symbol, section, bytes, align);524525if !relocs.is_empty() {526self.relocs.push(SymbolRelocs {527section,528offset,529relocs,530});531}532533Ok(())534}535536/// Finalize all relocations and output an object.537pub fn finish(mut self) -> ObjectProduct {538let symbol_relocs = mem::take(&mut self.relocs);539for symbol in symbol_relocs {540for &ObjectRelocRecord {541offset,542ref name,543flags,544addend,545} in &symbol.relocs546{547let target_symbol = self.get_symbol(name);548self.object549.add_relocation(550symbol.section,551Relocation {552offset: symbol.offset + u64::from(offset),553flags,554symbol: target_symbol,555addend,556},557)558.unwrap();559}560}561562// Indicate that this object has a non-executable stack.563if self.object.format() == object::BinaryFormat::Elf {564self.object.add_section(565vec![],566".note.GNU-stack".as_bytes().to_vec(),567SectionKind::Linker,568);569}570571ObjectProduct {572object: self.object,573functions: self.functions,574data_objects: self.data_objects,575}576}577578/// This should only be called during finish because it creates579/// symbols for missing libcalls.580fn get_symbol(&mut self, name: &ModuleRelocTarget) -> SymbolId {581match *name {582ModuleRelocTarget::User { .. } => {583if ModuleDeclarations::is_function(name) {584let id = FuncId::from_name(name);585self.functions[id].unwrap().0586} else {587let id = DataId::from_name(name);588self.data_objects[id].unwrap().0589}590}591ModuleRelocTarget::LibCall(ref libcall) => {592let name = (self.libcall_names)(*libcall);593if let Some(symbol) = self.object.symbol_id(name.as_bytes()) {594symbol595} else if let Some(symbol) = self.libcalls.get(libcall) {596*symbol597} else {598let symbol = self.object.add_symbol(Symbol {599name: name.as_bytes().to_vec(),600value: 0,601size: 0,602kind: SymbolKind::Text,603scope: SymbolScope::Unknown,604weak: false,605section: SymbolSection::Undefined,606flags: SymbolFlags::None,607});608self.libcalls.insert(*libcall, symbol);609symbol610}611}612// These are "magic" names well-known to the linker.613// They require special treatment.614ModuleRelocTarget::KnownSymbol(ref known_symbol) => {615if let Some(symbol) = self.known_symbols.get(known_symbol) {616*symbol617} else {618let symbol = self.object.add_symbol(match known_symbol {619ir::KnownSymbol::ElfGlobalOffsetTable => Symbol {620name: b"_GLOBAL_OFFSET_TABLE_".to_vec(),621value: 0,622size: 0,623kind: SymbolKind::Data,624scope: SymbolScope::Unknown,625weak: false,626section: SymbolSection::Undefined,627flags: SymbolFlags::None,628},629ir::KnownSymbol::CoffTlsIndex => Symbol {630name: b"_tls_index".to_vec(),631value: 0,632size: 32,633kind: SymbolKind::Tls,634scope: SymbolScope::Unknown,635weak: false,636section: SymbolSection::Undefined,637flags: SymbolFlags::None,638},639});640self.known_symbols.insert(*known_symbol, symbol);641symbol642}643}644645ModuleRelocTarget::FunctionOffset(func_id, offset) => {646match self.known_labels.entry((func_id, offset)) {647Entry::Occupied(o) => *o.get(),648Entry::Vacant(v) => {649let func_symbol_id = self.functions[func_id].unwrap().0;650let func_symbol = self.object.symbol(func_symbol_id);651652let name = format!(".L{}_{}", func_id.as_u32(), offset);653let symbol_id = self.object.add_symbol(Symbol {654name: name.as_bytes().to_vec(),655value: func_symbol.value + offset as u64,656size: 0,657kind: SymbolKind::Label,658scope: SymbolScope::Compilation,659weak: false,660section: SymbolSection::Section(func_symbol.section.id().unwrap()),661flags: SymbolFlags::None,662});663664v.insert(symbol_id);665symbol_id666}667}668}669}670}671672fn process_reloc(&self, record: &ModuleReloc) -> ObjectRelocRecord {673let flags = match record.kind {674Reloc::Abs4 => RelocationFlags::Generic {675kind: RelocationKind::Absolute,676encoding: RelocationEncoding::Generic,677size: 32,678},679Reloc::Abs8 => RelocationFlags::Generic {680kind: RelocationKind::Absolute,681encoding: RelocationEncoding::Generic,682size: 64,683},684Reloc::X86PCRel4 => RelocationFlags::Generic {685kind: RelocationKind::Relative,686encoding: RelocationEncoding::Generic,687size: 32,688},689Reloc::X86CallPCRel4 => RelocationFlags::Generic {690kind: RelocationKind::Relative,691encoding: RelocationEncoding::X86Branch,692size: 32,693},694// TODO: Get Cranelift to tell us when we can use695// R_X86_64_GOTPCRELX/R_X86_64_REX_GOTPCRELX.696Reloc::X86CallPLTRel4 => RelocationFlags::Generic {697kind: RelocationKind::PltRelative,698encoding: RelocationEncoding::X86Branch,699size: 32,700},701Reloc::X86SecRel => RelocationFlags::Generic {702kind: RelocationKind::SectionOffset,703encoding: RelocationEncoding::Generic,704size: 32,705},706Reloc::X86GOTPCRel4 => RelocationFlags::Generic {707kind: RelocationKind::GotRelative,708encoding: RelocationEncoding::Generic,709size: 32,710},711Reloc::Arm64Call => RelocationFlags::Generic {712kind: RelocationKind::Relative,713encoding: RelocationEncoding::AArch64Call,714size: 26,715},716Reloc::ElfX86_64TlsGd => {717assert_eq!(718self.object.format(),719object::BinaryFormat::Elf,720"ElfX86_64TlsGd is not supported for this file format"721);722RelocationFlags::Elf {723r_type: object::elf::R_X86_64_TLSGD,724}725}726Reloc::MachOX86_64Tlv => {727assert_eq!(728self.object.format(),729object::BinaryFormat::MachO,730"MachOX86_64Tlv is not supported for this file format"731);732RelocationFlags::MachO {733r_type: object::macho::X86_64_RELOC_TLV,734r_pcrel: true,735r_length: 2,736}737}738Reloc::MachOAarch64TlsAdrPage21 => {739assert_eq!(740self.object.format(),741object::BinaryFormat::MachO,742"MachOAarch64TlsAdrPage21 is not supported for this file format"743);744RelocationFlags::MachO {745r_type: object::macho::ARM64_RELOC_TLVP_LOAD_PAGE21,746r_pcrel: true,747r_length: 2,748}749}750Reloc::MachOAarch64TlsAdrPageOff12 => {751assert_eq!(752self.object.format(),753object::BinaryFormat::MachO,754"MachOAarch64TlsAdrPageOff12 is not supported for this file format"755);756RelocationFlags::MachO {757r_type: object::macho::ARM64_RELOC_TLVP_LOAD_PAGEOFF12,758r_pcrel: false,759r_length: 2,760}761}762Reloc::Aarch64TlsDescAdrPage21 => {763assert_eq!(764self.object.format(),765object::BinaryFormat::Elf,766"Aarch64TlsDescAdrPage21 is not supported for this file format"767);768RelocationFlags::Elf {769r_type: object::elf::R_AARCH64_TLSDESC_ADR_PAGE21,770}771}772Reloc::Aarch64TlsDescLd64Lo12 => {773assert_eq!(774self.object.format(),775object::BinaryFormat::Elf,776"Aarch64TlsDescLd64Lo12 is not supported for this file format"777);778RelocationFlags::Elf {779r_type: object::elf::R_AARCH64_TLSDESC_LD64_LO12,780}781}782Reloc::Aarch64TlsDescAddLo12 => {783assert_eq!(784self.object.format(),785object::BinaryFormat::Elf,786"Aarch64TlsDescAddLo12 is not supported for this file format"787);788RelocationFlags::Elf {789r_type: object::elf::R_AARCH64_TLSDESC_ADD_LO12,790}791}792Reloc::Aarch64TlsDescCall => {793assert_eq!(794self.object.format(),795object::BinaryFormat::Elf,796"Aarch64TlsDescCall is not supported for this file format"797);798RelocationFlags::Elf {799r_type: object::elf::R_AARCH64_TLSDESC_CALL,800}801}802803Reloc::Aarch64AdrGotPage21 => match self.object.format() {804object::BinaryFormat::Elf => RelocationFlags::Elf {805r_type: object::elf::R_AARCH64_ADR_GOT_PAGE,806},807object::BinaryFormat::MachO => RelocationFlags::MachO {808r_type: object::macho::ARM64_RELOC_GOT_LOAD_PAGE21,809r_pcrel: true,810r_length: 2,811},812_ => unimplemented!("Aarch64AdrGotPage21 is not supported for this file format"),813},814Reloc::Aarch64Ld64GotLo12Nc => match self.object.format() {815object::BinaryFormat::Elf => RelocationFlags::Elf {816r_type: object::elf::R_AARCH64_LD64_GOT_LO12_NC,817},818object::BinaryFormat::MachO => RelocationFlags::MachO {819r_type: object::macho::ARM64_RELOC_GOT_LOAD_PAGEOFF12,820r_pcrel: false,821r_length: 2,822},823_ => unimplemented!("Aarch64Ld64GotLo12Nc is not supported for this file format"),824},825Reloc::S390xPCRel32Dbl => RelocationFlags::Generic {826kind: RelocationKind::Relative,827encoding: RelocationEncoding::S390xDbl,828size: 32,829},830Reloc::S390xPLTRel32Dbl => RelocationFlags::Generic {831kind: RelocationKind::PltRelative,832encoding: RelocationEncoding::S390xDbl,833size: 32,834},835Reloc::S390xTlsGd64 => {836assert_eq!(837self.object.format(),838object::BinaryFormat::Elf,839"S390xTlsGd64 is not supported for this file format"840);841RelocationFlags::Elf {842r_type: object::elf::R_390_TLS_GD64,843}844}845Reloc::S390xTlsGdCall => {846assert_eq!(847self.object.format(),848object::BinaryFormat::Elf,849"S390xTlsGdCall is not supported for this file format"850);851RelocationFlags::Elf {852r_type: object::elf::R_390_TLS_GDCALL,853}854}855Reloc::RiscvCallPlt => {856assert_eq!(857self.object.format(),858object::BinaryFormat::Elf,859"RiscvCallPlt is not supported for this file format"860);861RelocationFlags::Elf {862r_type: object::elf::R_RISCV_CALL_PLT,863}864}865Reloc::RiscvTlsGdHi20 => {866assert_eq!(867self.object.format(),868object::BinaryFormat::Elf,869"RiscvTlsGdHi20 is not supported for this file format"870);871RelocationFlags::Elf {872r_type: object::elf::R_RISCV_TLS_GD_HI20,873}874}875Reloc::RiscvPCRelLo12I => {876assert_eq!(877self.object.format(),878object::BinaryFormat::Elf,879"RiscvPCRelLo12I is not supported for this file format"880);881RelocationFlags::Elf {882r_type: object::elf::R_RISCV_PCREL_LO12_I,883}884}885Reloc::RiscvGotHi20 => {886assert_eq!(887self.object.format(),888object::BinaryFormat::Elf,889"RiscvGotHi20 is not supported for this file format"890);891RelocationFlags::Elf {892r_type: object::elf::R_RISCV_GOT_HI20,893}894}895// FIXME896reloc => unimplemented!("{:?}", reloc),897};898899ObjectRelocRecord {900offset: record.offset,901name: record.name.clone(),902flags,903addend: record.addend,904}905}906}907908fn translate_linkage(linkage: Linkage) -> (SymbolScope, bool) {909let scope = match linkage {910Linkage::Import => SymbolScope::Unknown,911Linkage::Local => SymbolScope::Compilation,912Linkage::Hidden => SymbolScope::Linkage,913Linkage::Export | Linkage::Preemptible => SymbolScope::Dynamic,914};915// TODO: this matches rustc_codegen_cranelift, but may be wrong.916let weak = linkage == Linkage::Preemptible;917(scope, weak)918}919920/// This is the output of `ObjectModule`'s921/// [`finish`](../struct.ObjectModule.html#method.finish) function.922/// It contains the generated `Object` and other information produced during923/// compilation.924pub struct ObjectProduct {925/// Object artifact with all functions and data from the module defined.926pub object: Object<'static>,927/// Symbol IDs for functions (both declared and defined).928pub functions: SecondaryMap<FuncId, Option<(SymbolId, bool)>>,929/// Symbol IDs for data objects (both declared and defined).930pub data_objects: SecondaryMap<DataId, Option<(SymbolId, bool)>>,931}932933impl ObjectProduct {934/// Return the `SymbolId` for the given function.935#[inline]936pub fn function_symbol(&self, id: FuncId) -> SymbolId {937self.functions[id].unwrap().0938}939940/// Return the `SymbolId` for the given data object.941#[inline]942pub fn data_symbol(&self, id: DataId) -> SymbolId {943self.data_objects[id].unwrap().0944}945946/// Write the object bytes in memory.947#[inline]948pub fn emit(self) -> Result<Vec<u8>, object::write::Error> {949self.object.write()950}951}952953#[derive(Clone)]954struct SymbolRelocs {955section: SectionId,956offset: u64,957relocs: Vec<ObjectRelocRecord>,958}959960#[derive(Clone)]961struct ObjectRelocRecord {962offset: CodeOffset,963name: ModuleRelocTarget,964flags: RelocationFlags,965addend: Addend,966}967968969