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}