use super::Relocation;
use super::Symbol;
use crate::coff;
use crate::common::FromFFI;
use crate::common::into_optional;
use crate::declare_iterator;
use crate::generic;
use crate::pe;
use std::marker::PhantomData;
use std::pin::Pin;
use lief_ffi as ffi;
pub struct Section<'a> {
ptr: cxx::UniquePtr<ffi::COFF_Section>,
_owner: PhantomData<&'a ffi::COFF_Binary>,
}
impl FromFFI<ffi::COFF_Section> for Section<'_> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::COFF_Section>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
impl Section<'_> {
pub fn sizeof_raw_data(&self) -> u32 {
self.ptr.sizeof_raw_data()
}
pub fn virtual_size(&self) -> u32 {
self.ptr.virtual_size()
}
pub fn pointerto_raw_data(&self) -> u32 {
self.ptr.pointerto_raw_data()
}
pub fn pointerto_relocation(&self) -> u32 {
self.ptr.pointerto_relocation()
}
pub fn pointerto_line_numbers(&self) -> u32 {
self.ptr.pointerto_line_numbers()
}
pub fn numberof_relocations(&self) -> u16 {
self.ptr.numberof_relocations()
}
pub fn numberof_line_numbers(&self) -> u16 {
self.ptr.numberof_line_numbers()
}
pub fn characteristics(&self) -> pe::section::Characteristics {
pe::section::Characteristics::from(self.ptr.characteristics())
}
pub fn is_discardable(&self) -> bool {
self.ptr.is_discardable()
}
pub fn has_extended_relocations(&self) -> bool {
self.ptr.has_extended_relocations()
}
pub fn relocations(&self) -> Relocations<'_> {
Relocations::new(self.ptr.relocations())
}
pub fn symbols(&self) -> Symbols<'_> {
Symbols::new(self.ptr.symbols())
}
pub fn comdat_info(&self) -> Option<ComdatInfo<'_>> {
into_optional(self.ptr.comdat_info())
}
pub fn coff_string(&self) -> Option<coff::String<'_>> {
into_optional(self.ptr.coff_string())
}
}
impl generic::Section for Section<'_> {
fn as_generic(&self) -> &ffi::AbstractSection {
self.ptr.as_ref().unwrap().as_ref()
}
fn as_generic_mut(&mut self) -> Pin<&mut ffi::AbstractSection> {
unsafe {
Pin::new_unchecked({
(self.ptr.as_ref().unwrap().as_ref() as *const ffi::AbstractSection
as *mut ffi::AbstractSection)
.as_mut()
.unwrap()
})
}
}
}
impl std::fmt::Debug for Section<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn generic::Section;
f.debug_struct("Section")
.field("base", &base)
.field("sizeof_raw_data", &self.sizeof_raw_data())
.field("virtual_size", &self.virtual_size())
.field("pointerto_raw_data", &self.pointerto_raw_data())
.field("pointerto_relocation", &self.pointerto_relocation())
.field("pointerto_line_numbers", &self.pointerto_line_numbers())
.field("numberof_relocations", &self.numberof_relocations())
.field("numberof_line_numbers", &self.numberof_line_numbers())
.field("characteristics", &self.characteristics())
.finish()
}
}
impl std::fmt::Display for Section<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.ptr.to_string())
}
}
pub struct ComdatInfo<'a> {
ptr: cxx::UniquePtr<ffi::COFF_Section_ComdataInfo>,
_owner: PhantomData<&'a ffi::COFF_Binary>,
}
impl ComdatInfo<'_> {
pub fn symbol(&self) -> Option<Symbol<'_>> {
into_optional(self.ptr.symbol())
}
pub fn kind(&self) -> coff::symbol::ComdatSelection {
coff::symbol::ComdatSelection::from(self.ptr.kind())
}
}
impl FromFFI<ffi::COFF_Section_ComdataInfo> for ComdatInfo<'_> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::COFF_Section_ComdataInfo>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
impl std::fmt::Debug for ComdatInfo<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ComdatInfo")
.field("symbol", &self.symbol())
.field("kind", &self.kind())
.finish()
}
}
declare_iterator!(
Relocations,
Relocation<'a>,
ffi::COFF_Relocation,
ffi::COFF_Section,
ffi::COFF_Section_it_relocations
);
declare_iterator!(
Symbols,
Symbol<'a>,
ffi::COFF_Symbol,
ffi::COFF_Section,
ffi::COFF_Section_it_symbols
);