llvm_mapper/record/
alias.rs1use 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#[derive(Debug, Error)]
17pub enum AliasError {
18 #[error("alias record too short: {0} < 5 fields")]
20 TooShort(usize),
21
22 #[error("unsupported alias record format (v1)")]
24 V1Unsupported,
25
26 #[error("error while accessing string table")]
28 Strtab(#[from] StrtabError),
29
30 #[error("invalid type table index: {0}")]
32 Type(u64),
33
34 #[error("invalid visibility")]
36 Visibility(#[from] TryFromPrimitiveError<Visibility>),
37
38 #[error("invalid storage class")]
40 DllStorageClass(#[from] TryFromPrimitiveError<DllStorageClass>),
41}
42
43#[derive(Debug)]
45pub struct Alias<'ctx> {
46 pub name: &'ctx str,
48
49 pub ty: &'ctx Type,
51
52 pub value_index: u64,
54
55 pub linkage: Linkage,
57
58 pub visibility: Visibility,
60
61 pub storage_class: DllStorageClass,
63
64 pub tls_mode: ThreadLocalMode,
66
67 pub unnamed_addr: UnnamedAddr,
69
70 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 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}