section parsing
This commit is contained in:
parent
3ede0398eb
commit
489afcc88b
|
@ -1,19 +1,18 @@
|
||||||
use std::{
|
use std::{fs::File, io::Read};
|
||||||
fs::File,
|
|
||||||
io::Read,
|
|
||||||
};
|
|
||||||
|
|
||||||
use goblin::mach::Mach;
|
use goblin::mach::Mach;
|
||||||
use pyo3::{prelude::*, exceptions::PyTypeError};
|
use pyo3::{exceptions::PyTypeError, prelude::*};
|
||||||
|
|
||||||
mod exports;
|
mod exports;
|
||||||
mod header;
|
mod header;
|
||||||
mod imports;
|
mod imports;
|
||||||
|
mod sections;
|
||||||
mod symbols;
|
mod symbols;
|
||||||
|
|
||||||
use exports::Export;
|
use exports::Export;
|
||||||
use header::Header;
|
use header::Header;
|
||||||
use imports::Import;
|
use imports::Import;
|
||||||
|
use sections::{Sections, Section};
|
||||||
use symbols::Symbols;
|
use symbols::Symbols;
|
||||||
|
|
||||||
#[pyclass]
|
#[pyclass]
|
||||||
|
@ -74,6 +73,23 @@ impl Object {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn sections(&self) -> Sections {
|
||||||
|
match self.inner.as_ref().unwrap() {
|
||||||
|
goblin::Object::Mach(Mach::Binary(macho)) => {
|
||||||
|
let mut sections = vec![];
|
||||||
|
for sect_iter in macho.segments.sections() {
|
||||||
|
sections.extend(sect_iter.map(|section| {
|
||||||
|
let (sect, _data) = section.unwrap();
|
||||||
|
Section::from(sect)
|
||||||
|
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
Sections { sections }
|
||||||
|
},
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[getter]
|
#[getter]
|
||||||
fn libs(&self) -> Vec<&str> {
|
fn libs(&self) -> Vec<&str> {
|
||||||
match self.inner.as_ref().unwrap() {
|
match self.inner.as_ref().unwrap() {
|
||||||
|
@ -93,9 +109,11 @@ impl Object {
|
||||||
fn exports(&self) -> Result<Vec<Export>, PyErr> {
|
fn exports(&self) -> Result<Vec<Export>, PyErr> {
|
||||||
match self.inner.as_ref().unwrap() {
|
match self.inner.as_ref().unwrap() {
|
||||||
goblin::Object::Mach(Mach::Binary(macho)) => {
|
goblin::Object::Mach(Mach::Binary(macho)) => {
|
||||||
let exports = macho.exports().map_err(|_| PyErr::new::<PyTypeError, _>("failed"))?;
|
let exports = macho
|
||||||
|
.exports()
|
||||||
|
.map_err(|_| PyErr::new::<PyTypeError, _>("failed"))?;
|
||||||
Ok(exports.into_iter().map(|exp| exp.into()).collect())
|
Ok(exports.into_iter().map(|exp| exp.into()).collect())
|
||||||
},
|
}
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,9 +121,11 @@ impl Object {
|
||||||
fn imports(&self) -> Result<Vec<Import>, PyErr> {
|
fn imports(&self) -> Result<Vec<Import>, PyErr> {
|
||||||
match self.inner.as_ref().unwrap() {
|
match self.inner.as_ref().unwrap() {
|
||||||
goblin::Object::Mach(Mach::Binary(macho)) => {
|
goblin::Object::Mach(Mach::Binary(macho)) => {
|
||||||
let imports = macho.imports().map_err(|_| PyErr::new::<PyTypeError, _>("failed"))?;
|
let imports = macho
|
||||||
|
.imports()
|
||||||
|
.map_err(|_| PyErr::new::<PyTypeError, _>("failed"))?;
|
||||||
Ok(imports.into_iter().map(|exp| exp.into()).collect())
|
Ok(imports.into_iter().map(|exp| exp.into()).collect())
|
||||||
},
|
}
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
79
crates/goblin-pyo3/src/sections.rs
Normal file
79
crates/goblin-pyo3/src/sections.rs
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
#[pyclass]
|
||||||
|
pub struct Section {
|
||||||
|
#[pyo3(get)]
|
||||||
|
name: Option<String>,
|
||||||
|
#[pyo3(get)]
|
||||||
|
segment: Option<String>,
|
||||||
|
#[pyo3(get)]
|
||||||
|
addr: u64,
|
||||||
|
#[pyo3(get)]
|
||||||
|
size: u64,
|
||||||
|
#[pyo3(get)]
|
||||||
|
offset: u32,
|
||||||
|
#[pyo3(get)]
|
||||||
|
align: u32,
|
||||||
|
#[pyo3(get)]
|
||||||
|
reloff: u32,
|
||||||
|
#[pyo3(get)]
|
||||||
|
nreloc: u32,
|
||||||
|
#[pyo3(get)]
|
||||||
|
flags: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pymethods]
|
||||||
|
impl Section {
|
||||||
|
fn __repr__(&self) -> String {
|
||||||
|
format!("{:?}", self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<goblin::mach::segment::Section> for Section {
|
||||||
|
fn from(section: goblin::mach::segment::Section) -> Self {
|
||||||
|
Section {
|
||||||
|
name: section.name().ok().map(|s| s.to_string()),
|
||||||
|
segment: section.segname().ok().map(|s| s.to_string()),
|
||||||
|
addr: section.addr,
|
||||||
|
size: section.size,
|
||||||
|
offset: section.offset,
|
||||||
|
align: section.align,
|
||||||
|
reloff: section.reloff,
|
||||||
|
nreloc: section.nreloc,
|
||||||
|
flags: section.flags,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
#[pyclass]
|
||||||
|
pub struct Sections {
|
||||||
|
pub(crate) sections: Vec<Section>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pymethods]
|
||||||
|
impl Sections {
|
||||||
|
fn __iter__(slf: PyRef<'_, Self>) -> PyResult<Py<SectionIter>> {
|
||||||
|
let iter = SectionIter {
|
||||||
|
inner: slf.sections.clone().into_iter(),
|
||||||
|
};
|
||||||
|
Py::new(slf.py(), iter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pyclass]
|
||||||
|
struct SectionIter {
|
||||||
|
inner: std::vec::IntoIter<Section>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pymethods]
|
||||||
|
impl SectionIter {
|
||||||
|
fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> {
|
||||||
|
slf
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __next__(mut slf: PyRefMut<'_, Self>) -> Option<Section> {
|
||||||
|
slf.inner.next()
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,12 +1,74 @@
|
||||||
use goblin::mach::symbols::Nlist;
|
use goblin::mach::symbols::{N_TYPE, n_type_to_str, N_EXT, N_WEAK_REF, N_WEAK_DEF, N_UNDF, N_STAB};
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
#[pyclass]
|
||||||
|
struct Nlist {
|
||||||
|
#[pyo3(get)]
|
||||||
|
n_strx: usize,
|
||||||
|
#[pyo3(get)]
|
||||||
|
n_type: u8,
|
||||||
|
#[pyo3(get)]
|
||||||
|
n_sect: usize,
|
||||||
|
#[pyo3(get)]
|
||||||
|
n_desc: u16,
|
||||||
|
#[pyo3(get)]
|
||||||
|
n_value: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pymethods]
|
||||||
|
impl Nlist {
|
||||||
|
fn __repr__(&self) -> String {
|
||||||
|
format!("{:?}", self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Nlist {
|
||||||
|
/// Gets this symbol's type in bits 0xe
|
||||||
|
pub fn get_type(&self) -> u8 {
|
||||||
|
self.n_type & N_TYPE
|
||||||
|
}
|
||||||
|
/// Gets the str representation of the type of this symbol
|
||||||
|
pub fn type_str(&self) -> &'static str {
|
||||||
|
n_type_to_str(self.get_type())
|
||||||
|
}
|
||||||
|
/// Whether this symbol is global or not
|
||||||
|
pub fn is_global(&self) -> bool {
|
||||||
|
self.n_type & N_EXT != 0
|
||||||
|
}
|
||||||
|
/// Whether this symbol is weak or not
|
||||||
|
pub fn is_weak(&self) -> bool {
|
||||||
|
self.n_desc & (N_WEAK_REF | N_WEAK_DEF) != 0
|
||||||
|
}
|
||||||
|
/// Whether this symbol is undefined or not
|
||||||
|
pub fn is_undefined(&self) -> bool {
|
||||||
|
self.n_sect == 0 && self.n_type & N_TYPE == N_UNDF
|
||||||
|
}
|
||||||
|
/// Whether this symbol is a symbolic debugging entry
|
||||||
|
pub fn is_stab(&self) -> bool {
|
||||||
|
self.n_type & N_STAB != 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<goblin::mach::symbols::Nlist> for Nlist {
|
||||||
|
fn from(list: goblin::mach::symbols::Nlist) -> Self {
|
||||||
|
Self {
|
||||||
|
n_strx: list.n_strx,
|
||||||
|
n_type: list.n_type,
|
||||||
|
n_sect: list.n_sect,
|
||||||
|
n_desc: list.n_desc,
|
||||||
|
n_value: list.n_value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
#[pyclass]
|
#[pyclass]
|
||||||
struct Symbol {
|
struct Symbol {
|
||||||
#[pyo3(get)]
|
#[pyo3(get)]
|
||||||
name: String,
|
name: String,
|
||||||
|
|
||||||
|
#[pyo3(get)]
|
||||||
meta: Nlist,
|
meta: Nlist,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,14 +99,21 @@ impl Symbol {
|
||||||
self.meta.is_stab()
|
self.meta.is_stab()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[getter]
|
||||||
|
fn section(&self) -> usize {
|
||||||
|
self.meta.n_sect
|
||||||
|
}
|
||||||
|
|
||||||
fn __repr__(&self) -> String {
|
fn __repr__(&self) -> String {
|
||||||
format!(
|
format!(
|
||||||
"Symbol {{ name: {}, global: {}, weak: {}, undefined: {}, stab: {} }}",
|
"Symbol {{ name: {}, type: {}, global: {}, weak: {}, undefined: {}, stab: {}, meta: {:?} }}",
|
||||||
self.name,
|
self.name,
|
||||||
|
self.typ(),
|
||||||
self.global(),
|
self.global(),
|
||||||
self.weak(),
|
self.weak(),
|
||||||
self.undefined(),
|
self.undefined(),
|
||||||
self.stab()
|
self.stab(),
|
||||||
|
self.meta,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,7 +140,7 @@ impl From<goblin::mach::symbols::SymbolIterator<'_>> for Symbols {
|
||||||
let (symname, meta) = sym.unwrap();
|
let (symname, meta) = sym.unwrap();
|
||||||
Symbol {
|
Symbol {
|
||||||
name: symname.to_string(),
|
name: symname.to_string(),
|
||||||
meta,
|
meta: meta.into(),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -95,5 +164,3 @@ impl SymbolIter {
|
||||||
slf.inner.next()
|
slf.inner.next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ print(g.name)
|
||||||
|
|
||||||
print("symbols")
|
print("symbols")
|
||||||
for sym in g.symbols():
|
for sym in g.symbols():
|
||||||
|
if not sym.undefined:
|
||||||
print(sym)
|
print(sym)
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -20,3 +21,8 @@ print(len(g.exports()))
|
||||||
|
|
||||||
print("imports")
|
print("imports")
|
||||||
print(len(g.imports()))
|
print(len(g.imports()))
|
||||||
|
|
||||||
|
print("sections")
|
||||||
|
sections = iter(g.sections())
|
||||||
|
print(next(sections))
|
||||||
|
print(next(sections))
|
||||||
|
|
Loading…
Reference in a new issue