elf_utilities/symbol/
elf64.rs

1//! Type definitions for 64-bit ELF binaries.
2
3use crate::*;
4use serde::{Deserialize, Serialize};
5
6/// Symbol64 is a entry of symbol table section.
7///
8/// Symbol64 はシンボルテーブルセクションのエントリである.
9/// ELF64で用いることを想定している.
10///
11/// Defaultトレイトを実装しているので,
12/// `Default::default()` を呼び出すことで簡単にNULLシンボルを作成できる.
13///
14/// # Examples
15///
16/// ```
17/// use elf_utilities::symbol::Symbol64;
18/// let null_sym : Symbol64 = Default::default();
19///
20/// // Symbol64::new_null_symbol() のエイリアスでも作成可能.
21/// let null_sym2 : Symbol64 = Symbol64::new_null_symbol();
22///
23/// assert_eq!(null_sym, null_sym2);
24/// ```
25///
26/// ELFファイルを生成する用途でこのライブラリを使用できるように,
27/// バイト列への変換もサポートしている.
28///
29/// # Examples
30///
31/// ```
32/// use elf_utilities::symbol::Symbol64;
33/// let null_sym : Symbol64 = Default::default();
34///
35/// // to_le_bytes() を利用してバイト列に変換できる.
36/// let sym_bytes = null_sym.to_le_bytes();
37/// assert_eq!(Symbol64::SIZE, sym_bytes.len())
38/// ```
39#[derive(Default, Debug, Clone, Hash, PartialOrd, Ord, PartialEq, Eq, Serialize, Deserialize)]
40#[repr(C)]
41pub struct Symbol64 {
42    /// Symbol name index.
43    pub st_name: Elf64Word,
44
45    /// Information that includes [symbol binds and symbol types](https://docs.rs/elf-utilities/latest/elf_utilities/symbol/elf64/index.html#constants).
46    /// symbol typeやsymbol bindを使用する際は,対応するメソッドを使用することを推奨する.
47    pub st_info: u8,
48
49    /// Symbol's visibility.
50    /// See [Visibility](../symbol_visibility/Visibility).
51    pub st_other: u8,
52
53    /// A section table index that includes the symbol.
54    pub st_shndx: Elf64Section,
55
56    /// Symbol's value.
57    pub st_value: Elf64Addr,
58
59    /// Symbol's size.
60    pub st_size: Elf64Xword,
61
62    /// option member for utilities.
63    #[serde(skip_serializing)]
64    #[serde(skip_deserializing)]
65    pub symbol_name: String,
66}
67
68#[allow(dead_code)]
69impl Symbol64 {
70    pub const SIZE: usize = 24;
71    /// NULLシンボルの作成
72    pub fn new_null_symbol() -> Self {
73        Default::default()
74    }
75
76    /// for utilities
77    pub fn compare_by<P>(&self, predicate: P) -> bool
78    where
79        P: Fn(&Self) -> bool,
80    {
81        predicate(self)
82    }
83
84    pub fn get_type(&self) -> symbol::Type {
85        symbol::Type::from(self.st_info & 0x0f)
86    }
87
88    pub fn get_bind(&self) -> symbol::Bind {
89        symbol::Bind::from(self.st_info >> 4)
90    }
91
92    pub fn get_visibility(&self) -> symbol::Visibility {
93        symbol::Visibility::from(self.st_other & 0x03)
94    }
95
96    /// Set symbol's information to Symbol64
97    /// # Examples
98    ///
99    /// ```
100    /// use elf_utilities::symbol;
101    /// let mut null_sym = symbol::Symbol64::new_null_symbol();
102    ///
103    /// null_sym.set_info(symbol::Type::Func, symbol::Bind::Global);
104    ///
105    /// assert_eq!((1 << 4) | 2, null_sym.st_info);
106    /// ```
107    pub fn set_info(&mut self, sym_type: symbol::Type, bind: symbol::Bind) {
108        self.st_info = bind.to_byte() << 4 | sym_type.to_byte();
109    }
110
111    /// Create Vec<u8> from Symbol64's each fields.
112    ///
113    /// # Examples
114    ///
115    /// ```
116    /// use elf_utilities::symbol::Symbol64;
117    /// let null_sym : Symbol64 = Default::default();
118    ///
119    /// assert_eq!([0].repeat(Symbol64::SIZE), null_sym.to_le_bytes());
120    /// ```
121    pub fn to_le_bytes(&self) -> Vec<u8> {
122        bincode::serialize(self).unwrap()
123    }
124
125    pub fn deserialize(buf: &[u8], start: usize) -> Result<Self, Box<dyn std::error::Error>> {
126        // bincode::ErrorKindをトレイトオブジェクトとするため,この冗長な書き方が必要
127        match bincode::deserialize(&buf[start..]) {
128            Ok(header) => Ok(header),
129            Err(e) => Err(e),
130        }
131    }
132}