llvm_mapper/record/
alias.rs

1//! Functionality for mapping the `MODULE_CODE_ALIAS` record.
2
3use std::convert::TryFrom;
4
5use llvm_support::{
6    DllStorageClass, Linkage, RuntimePreemption, ThreadLocalMode, Type, UnnamedAddr, Visibility,
7};
8use num_enum::TryFromPrimitiveError;
9use thiserror::Error;
10
11use crate::map::{CtxMappable, MapCtx};
12use crate::record::StrtabError;
13use crate::unroll::UnrolledRecord;
14
15/// Errors that can occur while mapping an alias record.
16#[derive(Debug, Error)]
17pub enum AliasError {
18    /// The alias record is too short to be well-formed.
19    #[error("alias record too short: {0} < 5 fields")]
20    TooShort(usize),
21
22    /// The alias record is in an old unsupported format.
23    #[error("unsupported alias record format (v1)")]
24    V1Unsupported,
25
26    /// Retrieving a string from a string table failed.
27    #[error("error while accessing string table")]
28    Strtab(#[from] StrtabError),
29
30    /// The alias has a bad or unknown type.
31    #[error("invalid type table index: {0}")]
32    Type(u64),
33
34    /// The alias has an invalid visibility.
35    #[error("invalid visibility")]
36    Visibility(#[from] TryFromPrimitiveError<Visibility>),
37
38    /// The alias has an invalid DLL storage class.
39    #[error("invalid storage class")]
40    DllStorageClass(#[from] TryFromPrimitiveError<DllStorageClass>),
41}
42
43/// Models the `MODULE_CODE_ALIAS` record.
44#[derive(Debug)]
45pub struct Alias<'ctx> {
46    /// The alias's name.
47    pub name: &'ctx str,
48
49    /// The alias's type.
50    pub ty: &'ctx Type,
51
52    /// The aliasee value index.
53    pub value_index: u64,
54
55    /// The alias's linkage.
56    pub linkage: Linkage,
57
58    /// The alias's visibility.
59    pub visibility: Visibility,
60
61    /// The alias's storage class.
62    pub storage_class: DllStorageClass,
63
64    /// The alias's thread local storage mode.
65    pub tls_mode: ThreadLocalMode,
66
67    /// The alias's `unnamed_addr` specifier.
68    pub unnamed_addr: UnnamedAddr,
69
70    /// The alias's preemption specifier.
71    pub preemption_specifier: RuntimePreemption,
72}
73
74impl<'ctx> CtxMappable<'ctx, UnrolledRecord> for Alias<'ctx> {
75    type Error = AliasError;
76
77    fn try_map(record: &UnrolledRecord, ctx: &'ctx MapCtx) -> Result<Self, Self::Error> {
78        let fields = record.fields();
79
80        if !ctx.use_strtab() {
81            return Err(AliasError::V1Unsupported);
82        }
83
84        // Every alias record has at least 5 fields, corresponding to
85        // [strtab_offset, strtab_size, *v1], where v1 has 3 mandatory fields:
86        // [alias type, aliasee value#, linkage, ...]
87        if fields.len() < 5 {
88            return Err(AliasError::TooShort(fields.len()));
89        }
90
91        let name = ctx.strtab.read_name(record)?;
92        let ty = ctx
93            .type_table
94            .get(fields[2])
95            .ok_or(AliasError::Type(fields[2]))?;
96        let value_index = fields[3];
97        let linkage = Linkage::from(fields[4]);
98
99        let visibility = fields
100            .get(5)
101            .map_or_else(|| Ok(Visibility::Default), |v| Visibility::try_from(*v))?;
102
103        let storage_class = fields.get(6).map_or_else(
104            || Ok(DllStorageClass::Default),
105            |v| DllStorageClass::try_from(*v),
106        )?;
107
108        let tls_mode = fields
109            .get(7)
110            .copied()
111            .map(ThreadLocalMode::from)
112            .unwrap_or(ThreadLocalMode::NotThreadLocal);
113
114        let unnamed_addr = fields
115            .get(8)
116            .copied()
117            .map(UnnamedAddr::from)
118            .unwrap_or(UnnamedAddr::None);
119
120        let preemption_specifier = fields
121            .get(9)
122            .copied()
123            .map(RuntimePreemption::from)
124            .unwrap_or(RuntimePreemption::DsoPreemptable);
125
126        Ok(Alias {
127            name,
128            ty,
129            value_index,
130            linkage,
131            visibility,
132            storage_class,
133            tls_mode,
134            unnamed_addr,
135            preemption_specifier,
136        })
137    }
138}