Translate a gimli `.eh_frame` relocation request into the `object` crate's relocation flags for the target binary format. `eh_pe` is `None` for non-pointer relocations (rare in `.eh_frame`); in that case we treat the request as an absolute pointer of the requested width.
(
eh_pe: Option<gimli::constants::DwEhPe>,
size: u8,
format: BinaryFormat,
)
| 161 | /// `eh_pe` is `None` for non-pointer relocations (rare in `.eh_frame`); in that |
| 162 | /// case we treat the request as an absolute pointer of the requested width. |
| 163 | fn translate_eh_pe( |
| 164 | eh_pe: Option<gimli::constants::DwEhPe>, |
| 165 | size: u8, |
| 166 | format: BinaryFormat, |
| 167 | ) -> Result<RelocationFlags> { |
| 168 | use gimli::constants::*; |
| 169 | |
| 170 | let Some(pe) = eh_pe else { |
| 171 | return Ok(RelocationFlags::Generic { |
| 172 | kind: RelocationKind::Absolute, |
| 173 | encoding: RelocationEncoding::Generic, |
| 174 | size: size * 8, |
| 175 | }); |
| 176 | }; |
| 177 | |
| 178 | let application = pe.application(); |
| 179 | let kind = if application == DW_EH_PE_absptr { |
| 180 | RelocationKind::Absolute |
| 181 | } else if application == DW_EH_PE_pcrel { |
| 182 | RelocationKind::Relative |
| 183 | } else { |
| 184 | return Err(anyhow!( |
| 185 | "unsupported eh_frame pointer application {application:?}" |
| 186 | )); |
| 187 | }; |
| 188 | let format_byte = pe.format(); |
| 189 | let bit_size = if format_byte == DW_EH_PE_absptr { |
| 190 | size * 8 |
| 191 | } else if format_byte == DW_EH_PE_udata2 || format_byte == DW_EH_PE_sdata2 { |
| 192 | 16 |
| 193 | } else if format_byte == DW_EH_PE_udata4 || format_byte == DW_EH_PE_sdata4 { |
| 194 | 32 |
| 195 | } else if format_byte == DW_EH_PE_udata8 || format_byte == DW_EH_PE_sdata8 { |
| 196 | 64 |
| 197 | } else { |
| 198 | return Err(anyhow!( |
| 199 | "unsupported eh_frame pointer format {format_byte:?}" |
| 200 | )); |
| 201 | }; |
| 202 | |
| 203 | // Mach-O encodes PC-relative `.eh_frame` references as a SUBTRACTOR / |
| 204 | // UNSIGNED relocation pair, which is out of scope here. Surface a clear |
| 205 | // error rather than emitting the wrong relocation. |
| 206 | // |
| 207 | // TODO: arm64 Mach-O `__TEXT,__eh_frame` is feasible via that reloc pair; |
| 208 | // see rust-lang/rustc_codegen_cranelift#1634 for the approach. |
| 209 | if matches!(format, BinaryFormat::MachO) && kind == RelocationKind::Relative { |
| 210 | return Err(anyhow!("Mach-O .eh_frame emission is not yet supported")); |
| 211 | } |
| 212 | |
| 213 | Ok(RelocationFlags::Generic { |
| 214 | kind, |
| 215 | encoding: RelocationEncoding::Generic, |
| 216 | size: bit_size, |
| 217 | }) |
| 218 | } |
| 219 | |
| 220 | #[cfg(test)] |