1 /// === Sym bindings ===
3 pub const STB_LOCAL
: u8 = 0;
5 pub const STB_GLOBAL
: u8 = 1;
7 pub const STB_WEAK
: u8 = 2;
8 /// Number of defined types..
9 pub const STB_NUM
: u8 = 3;
10 /// Start of OS-specific.
11 pub const STB_LOOS
: u8 = 10;
13 pub const STB_GNU_UNIQUE
: u8 = 10;
14 /// End of OS-specific.
15 pub const STB_HIOS
: u8 = 12;
16 /// Start of processor-specific.
17 pub const STB_LOPROC
: u8 = 13;
18 /// End of processor-specific.
19 pub const STB_HIPROC
: u8 = 15;
22 /// Symbol type is unspecified.
23 pub const STT_NOTYPE
: u8 = 0;
24 /// Symbol is a data object.
25 pub const STT_OBJECT
: u8 = 1;
26 /// Symbol is a code object.
27 pub const STT_FUNC
: u8 = 2;
28 /// Symbol associated with a section.
29 pub const STT_SECTION
: u8 = 3;
30 /// Symbol's name is file name.
31 pub const STT_FILE
: u8 = 4;
32 /// Symbol is a common data object.
33 pub const STT_COMMON
: u8 = 5;
34 /// Symbol is thread-local data object.
35 pub const STT_TLS
: u8 = 6;
36 /// Number of defined types.
37 pub const STT_NUM
: u8 = 7;
38 /// Start of OS-specific.
39 pub const STT_LOOS
: u8 = 10;
40 /// Symbol is indirect code object.
41 pub const STT_GNU_IFUNC
: u8 = 10;
42 /// End of OS-specific.
43 pub const STT_HIOS
: u8 = 12;
44 /// Start of processor-specific.
45 pub const STT_LOPROC
: u8 = 13;
46 /// End of processor-specific.
47 pub const STT_HIPROC
: u8 = 15;
49 /// === Sym visibility ===
50 /// Default: Visibility is specified by the symbol's binding type
51 pub const STV_DEFAULT
: u8 = 0;
52 /// Internal: use of this attribute is currently reserved.
53 pub const STV_INTERNAL
: u8 = 1;
54 /// Hidden: Not visible to other components, necessarily protected. Binding scope becomes local
55 /// when the object is included in an executable or shared object.
56 pub const STV_HIDDEN
: u8 = 2;
57 /// Protected: Symbol defined in current component is visible in other components, but cannot be preempted.
58 /// Any reference from within the defining component must be resolved to the definition in that
60 pub const STV_PROTECTED
: u8 = 3;
61 /// Exported: ensures a symbol remains global, cannot be demoted or eliminated by any other symbol
62 /// visibility technique.
63 pub const STV_EXPORTED
: u8 = 4;
64 /// Singleton: ensures a symbol remains global, and that a single instance of the definition is
65 /// bound to by all references within a process. Cannot be demoted or eliminated.
66 pub const STV_SINGLETON
: u8 = 5;
67 /// Eliminate: extends the hidden attribute. Not written in any symbol table of a dynamic
68 /// executable or shared object.
69 pub const STV_ELIMINATE
: u8 = 6;
73 /// This is the first four bits of the "info" byte.
75 pub fn st_bind(info
: u8) -> u8 {
81 /// This is the last four bits of the "info" byte.
83 pub fn st_type(info
: u8) -> u8 {
87 /// Get the ST visibility.
89 /// This is the last three bits of the "other" byte.
91 pub fn st_visibility(other
: u8) -> u8 {
95 /// Is this information defining an import?
97 pub fn is_import(info
: u8, value
: u64) -> bool
{
98 let bind
= st_bind(info
);
99 bind
== STB_GLOBAL
&& value
== 0
102 /// Convenience function to get the &'static str type from the symbols `st_info`.
104 pub fn get_type(info
: u8) -> &'
static str {
105 type_to_str(st_type(info
))
108 /// Get the string for some bind.
110 pub fn bind_to_str(typ
: u8) -> &'
static str {
112 STB_LOCAL
=> "LOCAL",
113 STB_GLOBAL
=> "GLOBAL",
116 STB_GNU_UNIQUE
=> "GNU_UNIQUE",
121 /// Get the string for some type.
123 pub fn type_to_str(typ
: u8) -> &'
static str {
125 STT_NOTYPE
=> "NOTYPE",
126 STT_OBJECT
=> "OBJECT",
128 STT_SECTION
=> "SECTION",
130 STT_COMMON
=> "COMMON",
133 STT_GNU_IFUNC
=> "GNU_IFUNC",
138 /// Get the string for some visibility
140 pub fn visibility_to_str(typ
: u8) -> &'
static str {
142 STV_DEFAULT
=> "DEFAULT",
143 STV_INTERNAL
=> "INTERNAL",
144 STV_HIDDEN
=> "HIDDEN",
145 STV_PROTECTED
=> "PROTECTED",
146 STV_EXPORTED
=> "EXPORTED",
147 STV_SINGLETON
=> "SINGLETON",
148 STV_ELIMINATE
=> "ELIMINATE",
153 macro_rules
! elf_sym_std_impl
{
160 assert_eq
!(::std
::mem
::size_of
::<Sym
>(), SIZEOF_SYM
);
164 use crate::elf
::sym
::Sym
as ElfSym
;
170 /// Checks whether this `Sym` has `STB_GLOBAL`/`STB_WEAK` bind and a `st_value` of 0
172 pub fn is_import(&self) -> bool
{
173 let bind
= self.st_info
>> 4;
174 (bind
== STB_GLOBAL
|| bind
== STB_WEAK
) && self.st_value
== 0
176 /// Checks whether this `Sym` has type `STT_FUNC`
178 pub fn is_function(&self) -> bool
{
179 st_type(self.st_info
) == STT_FUNC
183 impl From
<Sym
> for ElfSym
{
185 fn from(sym
: Sym
) -> Self {
187 st_name
: sym
.st_name
as usize,
188 st_info
: sym
.st_info
,
189 st_other
: sym
.st_other
,
190 st_shndx
: sym
.st_shndx
as usize,
191 st_value
: u64::from(sym
.st_value
),
192 st_size
: u64::from(sym
.st_size
),
197 impl From
<ElfSym
> for Sym
{
199 fn from(sym
: ElfSym
) -> Self {
201 st_name
: sym
.st_name
as u32,
202 st_info
: sym
.st_info
,
203 st_other
: sym
.st_other
,
204 st_shndx
: sym
.st_shndx
as u16,
205 st_value
: sym
.st_value
as $size
,
206 st_size
: sym
.st_size
as $size
,
211 impl fmt
::Debug
for Sym
{
212 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
213 let bind
= st_bind(self.st_info
);
214 let typ
= st_type(self.st_info
);
215 let vis
= st_visibility(self.st_other
);
216 f
.debug_struct("Sym")
217 .field("st_name", &self.st_name
)
218 .field("st_value", &format_args
!("{:x}", self.st_value
))
219 .field("st_size", &self.st_size
)
231 &format_args
!("{} {}", self.st_other
, visibility_to_str(vis
)),
233 .field("st_shndx", &self.st_shndx
)
240 /// This function creates a `Sym` slice directly from a raw pointer
242 pub unsafe fn from_raw
<'a
>(symp
: *const Sym
, count
: usize) -> &'a
[Sym
] {
243 slice
::from_raw_parts(symp
, count
)
247 use crate::error
::Result
;
250 use std
::io
::{Read, Seek}
;
251 use std
::io
::SeekFrom
::Start
;
253 pub fn from_fd(fd
: &mut File
, offset
: usize, count
: usize) -> Result
<Vec
<Sym
>> {
254 // TODO: AFAIK this shouldn't work, since i pass in a byte size...
255 let mut syms
= vec
![Sym
::default(); count
];
256 fd
.seek(Start(offset
as u64))?
;
258 fd
.read_exact(plain
::as_mut_bytes(&mut *syms
))?
;
267 #[cfg(feature = "alloc")]
268 use scroll
::{Pread, Pwrite, SizeWith}
;
271 pub use crate::elf
::sym
::*;
274 #[derive(Clone, Copy, PartialEq, Default)]
275 #[cfg_attr(feature = "alloc", derive(Pread, Pwrite, SizeWith))]
276 /// 32-bit Sym - used for both static and dynamic symbol information in a binary
278 /// Symbol name (string tbl index)
284 /// Symbol type and binding
286 /// Symbol visibility
292 // Declare that the type is plain.
293 unsafe impl plain
::Plain
for Sym {}
295 pub const SIZEOF_SYM
: usize = 4 + 1 + 1 + 2 + 4 + 4;
297 elf_sym_std_impl
!(u32);
301 pub use crate::elf
::sym
::*;
304 #[derive(Clone, Copy, PartialEq, Default)]
305 #[cfg_attr(feature = "alloc", derive(Pread, Pwrite, SizeWith))]
306 /// 64-bit Sym - used for both static and dynamic symbol information in a binary
308 /// Symbol name (string tbl index)
310 /// Symbol type and binding
312 /// Symbol visibility
322 // Declare that the type is plain.
323 unsafe impl plain
::Plain
for Sym {}
325 pub const SIZEOF_SYM
: usize = 4 + 1 + 1 + 2 + 8 + 8;
327 elf_sym_std_impl
!(u64);
330 use crate::container
::{Container, Ctx}
;
331 #[cfg(feature = "alloc")]
332 use crate::error
::Result
;
333 #[cfg(feature = "alloc")]
335 use core
::fmt
::{self, Debug}
;
338 use scroll
::ctx
::SizeWith
;
340 #[derive(Clone, Copy, PartialEq, Default)]
341 /// A unified Sym definition - convertible to and from 32-bit and 64-bit variants
353 pub fn size(container
: Container
) -> usize {
354 Self::size_with(&Ctx
::from(container
))
356 /// Checks whether this `Sym` has `STB_GLOBAL`/`STB_WEAK` bind and a `st_value` of 0
358 pub fn is_import(&self) -> bool
{
359 let bind
= self.st_bind();
360 (bind
== STB_GLOBAL
|| bind
== STB_WEAK
) && self.st_value
== 0
362 /// Checks whether this `Sym` has type `STT_FUNC`
364 pub fn is_function(&self) -> bool
{
365 st_type(self.st_info
) == STT_FUNC
369 /// This is the first four bits of the "info" byte.
371 pub fn st_bind(&self) -> u8 {
376 /// This is the last four bits of the "info" byte.
378 pub fn st_type(&self) -> u8 {
379 st_type(self.st_info
)
381 /// Get the ST visibility.
383 /// This is the last three bits of the "other" byte.
385 pub fn st_visibility(&self) -> u8 {
386 st_visibility(self.st_other
)
388 #[cfg(feature = "endian_fd")]
389 /// Parse `count` vector of ELF symbols from `offset`
390 pub fn parse(bytes
: &[u8], mut offset
: usize, count
: usize, ctx
: Ctx
) -> Result
<Vec
<Sym
>> {
391 let mut syms
= Vec
::with_capacity(count
);
393 let sym
= bytes
.gread_with(&mut offset
, ctx
)?
;
400 impl fmt
::Debug
for Sym
{
401 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
402 let bind
= self.st_bind();
403 let typ
= self.st_type();
404 let vis
= self.st_visibility();
405 f
.debug_struct("Sym")
406 .field("st_name", &self.st_name
)
418 &format_args
!("{} {}", self.st_other
, visibility_to_str(vis
)),
420 .field("st_shndx", &self.st_shndx
)
421 .field("st_value", &format_args
!("0x{:x}", self.st_value
))
422 .field("st_size", &self.st_size
)
427 impl ctx
::SizeWith
<Ctx
> for Sym
{
429 fn size_with(&Ctx { container, .. }
: &Ctx
) -> usize {
431 Container
::Little
=> sym32
::SIZEOF_SYM
,
432 Container
::Big
=> sym64
::SIZEOF_SYM
,
438 impl<'a
> ctx
::TryFromCtx
<'a
, Ctx
> for Sym
{
439 type Error
= crate::error
::Error
;
441 fn try_from_ctx(bytes
: &'a
[u8], Ctx { container, le}
: Ctx
) -> result
::Result
<(Self, usize), Self::Error
> {
442 let sym
= match container
{
443 Container
::Little
=> {
444 (bytes
.pread_with
::<sym32
::Sym
>(0, le
)?
.into(), sym32
::SIZEOF_SYM
)
447 (bytes
.pread_with
::<sym64
::Sym
>(0, le
)?
.into(), sym64
::SIZEOF_SYM
)
454 impl ctx
::TryIntoCtx
<Ctx
> for Sym
{
455 type Error
= crate::error
::Error
;
457 fn try_into_ctx(self, bytes
: &mut [u8], Ctx {container, le}
: Ctx
) -> result
::Result
<usize, Self::Error
> {
459 Container
::Little
=> {
460 let sym
: sym32
::Sym
= self.into();
461 Ok(bytes
.pwrite_with(sym
, 0, le
)?
)
464 let sym
: sym64
::Sym
= self.into();
465 Ok(bytes
.pwrite_with(sym
, 0, le
)?
)
471 impl ctx
::IntoCtx
<Ctx
> for Sym
{
473 fn into_ctx(self, bytes
: &mut [u8], Ctx {container, le}
: Ctx
) {
475 Container
::Little
=> {
476 let sym
: sym32
::Sym
= self.into();
477 bytes
.pwrite_with(sym
, 0, le
).unwrap();
480 let sym
: sym64
::Sym
= self.into();
481 bytes
.pwrite_with(sym
, 0, le
).unwrap();
490 /// An ELF symbol table, allowing lazy iteration over symbols
491 pub struct Symtab
<'a
> {
499 impl<'a
> Debug
for Symtab
<'a
> {
500 fn fmt(&self, fmt
: &mut fmt
::Formatter
) -> fmt
::Result
{
501 let len
= self.bytes
.len();
502 fmt
.debug_struct("Symtab")
503 .field("bytes", &len
)
504 .field("range", &format_args
!("{:#x}..{:#x}", self.start
, self.end
))
505 .field("count", &self.count
)
506 .field("Symbols", &self.to_vec())
511 impl<'a
> Symtab
<'a
> {
512 /// Parse a table of `count` ELF symbols from `offset`.
513 pub fn parse(bytes
: &'a
[u8], offset
: usize, count
: usize, ctx
: Ctx
) -> Result
<Symtab
<'a
>> {
515 .checked_mul(Sym
::size_with(&ctx
))
516 .ok_or_else(|| crate::error
::Error
::Malformed(
517 format
!("Too many ELF symbols (offset {:#x}, count {})", offset
, count
)
519 // TODO: make this a better error message when too large
520 let bytes
= bytes
.pread_with(offset
, size
)?
;
521 Ok(Symtab { bytes, count, ctx, start: offset, end: offset+size }
)
524 /// Try to parse a single symbol from the binary, at `index`.
526 pub fn get(&self, index
: usize) -> Option
<Sym
> {
527 if index
>= self.count
{
530 Some(self.bytes
.pread_with(index
* Sym
::size_with(&self.ctx
), self.ctx
).unwrap())
534 /// The number of symbols in the table.
536 pub fn len(&self) -> usize {
540 /// Returns true if table has no symbols.
542 pub fn is_empty(&self) -> bool
{
546 /// Iterate over all symbols.
548 pub fn iter(&self) -> SymIterator
<'a
> {
552 /// Parse all symbols into a vector.
553 pub fn to_vec(&self) -> Vec
<Sym
> {
554 self.iter().collect()
558 impl<'a
, 'b
> IntoIterator
for &'b Symtab
<'a
> {
559 type Item
= <SymIterator
<'a
> as Iterator
>::Item
;
560 type IntoIter
= SymIterator
<'a
>;
563 fn into_iter(self) -> Self::IntoIter
{
574 /// An iterator over symbols in an ELF symbol table
575 pub struct SymIterator
<'a
> {
583 impl<'a
> Iterator
for SymIterator
<'a
> {
587 fn next(&mut self) -> Option
<Self::Item
> {
588 if self.index
>= self.count
{
592 Some(self.bytes
.gread_with(&mut self.offset
, self.ctx
).unwrap())
597 impl<'a
> ExactSizeIterator
for SymIterator
<'a
> {
599 fn len(&self) -> usize {
600 self.count
- self.index