1#![cfg_attr(not(test), no_std)]
93#![deny(unsafe_op_in_unsafe_fn)]
94#![warn(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
95
96extern crate alloc;
97
98#[cfg(feature = "aarch64")]
99pub mod aarch64;
100pub(crate) mod core;
101#[cfg(feature = "riscv")]
102pub mod riscv;
103#[cfg(feature = "jit")]
104pub(crate) mod util;
105#[cfg(feature = "x86")]
106pub mod x86;
107
108#[cfg(feature = "jit")]
109pub use core::buffer::LoadedRelocatedCode;
110#[cfg(feature = "jit")]
111pub use core::jit_allocator::{JitAllocator, JitAllocatorOptions, ResetPolicy, Span};
112#[cfg(feature = "aarch64")]
113pub use core::target::AArch64Feature;
114#[cfg(feature = "riscv")]
115pub use core::target::RiscVFeature;
116#[cfg(feature = "x86")]
117pub use core::target::X86Feature;
118pub use core::{
119 arch_traits::Arch,
120 buffer::{
121 Addend, AsmReloc, CodeBuffer, CodeBufferFinalized, CodeOffset, Constant, ConstantData,
122 ExternalName, LabelUse, Reloc, RelocDistance, RelocTarget, UserExternalName,
123 },
124 builder::{Builder, InstSink, Node},
125 globals::{CondCode, InstOptions},
126 inst::Inst,
127 linker::{LinkError, Linker},
128 operand::{
129 BaseMem, BaseReg, Imm, ImmType, Label, Operand, OperandCast, OperandSignature, OperandType,
130 RegGroup, RegMask, RegTraits, RegType, Sym, imm,
131 },
132 patch::{
133 PatchBlock, PatchBlockId, PatchCatalog, PatchSite, PatchSiteId, PatchableBlock,
134 PatchableSite,
135 },
136 rwinfo::{
137 CpuRwFlags, INVALID_PHYS_ID, InstControlFlow, InstRwFlags, InstRwInfo, InstSameRegHint,
138 OpRwFlags, OpRwInfo,
139 },
140 section::{FinalizedSection, Section},
141 target::Environment,
142};
143
144use ::core::fmt;
145
146#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
152pub enum AsmError {
153 InvalidPrefix,
154 InvalidOperand,
155 InvalidImmediate,
156 InvalidInstruction,
157 OutOfMemory,
158 InvalidState,
159 TooManyHandles,
160 InvalidArgument,
161 InvalidArch,
163 NoCodeGenerated,
166 UnboundLabel,
169 FailedToOpenAnonymousMemory,
170 TooLarge,
171 Link(LinkError),
174 X86(X86Error),
175 MissingCpuFeature {
177 feature: &'static str,
178 },
179 UnsupportedInstruction {
180 reason: &'static str,
181 },
182}
183
184impl fmt::Display for AsmError {
185 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
186 match self {
187 AsmError::InvalidPrefix => write!(f, "invalid prefix"),
188 AsmError::InvalidOperand => write!(f, "invalid operand"),
189 AsmError::InvalidInstruction => write!(f, "invalid instruction"),
190 AsmError::OutOfMemory => write!(f, "out of memory"),
191 AsmError::InvalidState => write!(f, "invalid state"),
192 AsmError::TooManyHandles => write!(f, "too many handles"),
193 AsmError::InvalidArgument => write!(f, "invalid argument"),
194 AsmError::InvalidImmediate => write!(f, "invalid immediate"),
195 AsmError::InvalidArch => write!(f, "invalid or incompatible architecture"),
196 AsmError::NoCodeGenerated => write!(f, "no code generated"),
197 AsmError::UnboundLabel => write!(f, "unbound label"),
198 AsmError::FailedToOpenAnonymousMemory => {
199 write!(f, "failed to open anonymous memory")
200 }
201 AsmError::TooLarge => write!(f, "too large"),
202 AsmError::Link(error) => write!(f, "link error: {error}"),
203 AsmError::X86(e) => write!(f, "x86 error: {}", e),
204 AsmError::MissingCpuFeature { feature } => {
205 write!(f, "missing CPU feature: {}", feature)
206 }
207 AsmError::UnsupportedInstruction { reason } => {
208 write!(f, "unsupported instruction: {}", reason)
209 }
210 }
211 }
212}
213
214impl From<X86Error> for AsmError {
215 fn from(err: X86Error) -> Self {
216 AsmError::X86(err)
217 }
218}
219
220impl ::core::error::Error for AsmError {
221 fn source(&self) -> Option<&(dyn ::core::error::Error + 'static)> {
222 match self {
223 AsmError::Link(error) => Some(error),
224 AsmError::X86(error) => Some(error),
225 _ => None,
226 }
227 }
228}
229
230#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
232pub enum X86Error {
233 InvalidPrefix {
234 prefix: u64,
235 reason: &'static str,
236 },
237 InvalidOperand {
238 operand_index: usize,
239 reason: &'static str,
240 },
241 InvalidInstruction {
242 opcode: u64,
243 reason: &'static str,
244 },
245 InvalidEncoding {
246 encoding: u8,
247 reason: &'static str,
248 },
249 InvalidModRM {
250 modrm: u8,
251 reason: &'static str,
252 },
253 InvalidSIB {
254 sib: u8,
255 reason: &'static str,
256 },
257 InvalidDisplacement {
258 value: i64,
259 size: usize,
260 reason: &'static str,
261 },
262 InvalidImmediate {
263 value: i64,
264 size: usize,
265 reason: &'static str,
266 },
267 InvalidRegister {
268 reg_id: u32,
269 reg_type: &'static str,
270 reason: &'static str,
271 },
272 InvalidMemoryOperand {
273 base: Option<u32>,
274 index: Option<u32>,
275 scale: u8,
276 offset: i64,
277 reason: &'static str,
278 },
279 InvalidVSIB {
280 index_reg: u32,
281 reason: &'static str,
282 },
283 InvalidMasking {
284 mask_reg: u32,
285 reason: &'static str,
286 },
287 InvalidBroadcast {
288 reason: &'static str,
289 },
290 InvalidRoundingControl {
291 rc: u64,
292 reason: &'static str,
293 },
294 InvalidEVEX {
295 field: &'static str,
296 reason: &'static str,
297 },
298 InvalidVEX {
299 field: &'static str,
300 reason: &'static str,
301 },
302 TooLongInstruction {
303 length: usize,
304 max_length: usize,
305 },
306 SegmentOverrideNotAllowed {
307 segment: u8,
308 reason: &'static str,
309 },
310 AddressSizeMismatch {
311 expected: usize,
312 actual: usize,
313 },
314 OperandSizeMismatch {
315 expected: usize,
316 actual: usize,
317 },
318 InvalidRIPRelative {
319 offset: i64,
320 reason: &'static str,
321 },
322 InvalidLabel {
323 label_id: u32,
324 reason: &'static str,
325 },
326 InvalidSymbol {
327 symbol_id: u32,
328 reason: &'static str,
329 },
330 InvalidRelocation {
331 reloc_type: &'static str,
332 reason: &'static str,
333 },
334 InvalidOperandCombination {
335 mnemonic: &'static str,
336 },
337}
338
339impl fmt::Display for X86Error {
340 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
341 match self {
342 X86Error::InvalidPrefix { prefix, reason } => {
343 write!(f, "invalid prefix 0x{:x}: {}", prefix, reason)
344 }
345 X86Error::InvalidOperand {
346 operand_index,
347 reason,
348 } => write!(f, "invalid operand {}: {}", operand_index, reason),
349 X86Error::InvalidInstruction { opcode, reason } => {
350 write!(f, "invalid instruction 0x{:x}: {}", opcode, reason)
351 }
352 X86Error::InvalidEncoding { encoding, reason } => {
353 write!(f, "invalid encoding {}: {}", encoding, reason)
354 }
355 X86Error::InvalidModRM { modrm, reason } => {
356 write!(f, "invalid ModRM byte 0x{:02x}: {}", modrm, reason)
357 }
358 X86Error::InvalidSIB { sib, reason } => {
359 write!(f, "invalid SIB byte 0x{:02x}: {}", sib, reason)
360 }
361 X86Error::InvalidDisplacement {
362 value,
363 size,
364 reason,
365 } => write!(
366 f,
367 "invalid displacement 0x{:x} (size {}): {}",
368 value, size, reason
369 ),
370 X86Error::InvalidImmediate {
371 value,
372 size,
373 reason,
374 } => {
375 write!(
376 f,
377 "invalid immediate 0x{:x} (size {}): {}",
378 value, size, reason
379 )
380 }
381 X86Error::InvalidRegister {
382 reg_id,
383 reg_type,
384 reason,
385 } => write!(
386 f,
387 "invalid register {} (type {}): {}",
388 reg_id, reg_type, reason
389 ),
390 X86Error::InvalidMemoryOperand {
391 base,
392 index,
393 scale,
394 offset,
395 reason,
396 } => write!(
397 f,
398 "invalid memory operand [base={:?}, index={:?}, scale={}, offset={}]: {}",
399 base, index, scale, offset, reason
400 ),
401 X86Error::InvalidVSIB { index_reg, reason } => {
402 write!(f, "invalid VSIB index register {}: {}", index_reg, reason)
403 }
404 X86Error::InvalidMasking { mask_reg, reason } => {
405 write!(f, "invalid mask register {}: {}", mask_reg, reason)
406 }
407 X86Error::InvalidBroadcast { reason } => {
408 write!(f, "invalid broadcast: {}", reason)
409 }
410 X86Error::InvalidRoundingControl { rc, reason } => {
411 write!(f, "invalid rounding control 0x{:x}: {}", rc, reason)
412 }
413 X86Error::InvalidEVEX { field, reason } => {
414 write!(f, "invalid EVEX field '{}': {}", field, reason)
415 }
416 X86Error::InvalidVEX { field, reason } => {
417 write!(f, "invalid VEX field '{}': {}", field, reason)
418 }
419 X86Error::TooLongInstruction { length, max_length } => write!(
420 f,
421 "instruction too long: {} bytes (max {})",
422 length, max_length
423 ),
424 X86Error::SegmentOverrideNotAllowed { segment, reason } => {
425 write!(f, "segment override {} not allowed: {}", segment, reason)
426 }
427 X86Error::AddressSizeMismatch { expected, actual } => write!(
428 f,
429 "address size mismatch: expected {} bytes, got {}",
430 expected, actual
431 ),
432 X86Error::OperandSizeMismatch { expected, actual } => write!(
433 f,
434 "operand size mismatch: expected {} bytes, got {}",
435 expected, actual
436 ),
437 X86Error::InvalidRIPRelative { offset, reason } => {
438 write!(f, "invalid RIP-relative offset {}: {}", offset, reason)
439 }
440 X86Error::InvalidLabel { label_id, reason } => {
441 write!(f, "invalid label {}: {}", label_id, reason)
442 }
443 X86Error::InvalidSymbol { symbol_id, reason } => {
444 write!(f, "invalid symbol {}: {}", symbol_id, reason)
445 }
446 X86Error::InvalidRelocation { reloc_type, reason } => {
447 write!(f, "invalid relocation {}: {}", reloc_type, reason)
448 }
449 X86Error::InvalidOperandCombination { mnemonic } => {
450 write!(
451 f,
452 "invalid operand combination for instruction `{}`",
453 mnemonic
454 )
455 }
456 }
457 }
458}
459
460impl ::core::error::Error for X86Error {}