Add rust bindings

This commit is contained in:
Romain Thomas
2024-04-27 10:25:58 +02:00
parent 6d1a230da2
commit d447511a64
245 changed files with 19628 additions and 79 deletions
+3
View File
@@ -3,3 +3,6 @@ build/
*.whl
lief.egg-info/
dist/
api/rust/cargo/target/*
api/rust/examples/target/*
Cargo.lock
+4
View File
@@ -0,0 +1,4 @@
include:
- project: 'LIEF/ci'
ref: main
file: 'main.yml'
+21 -20
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.15)
cmake_minimum_required(VERSION 3.24)
enable_language(C)
enable_language(CXX)
@@ -98,6 +98,25 @@ message(STATUS "CMAKE_LINK_LIBRARY_FILE_FLAG: ${CMAKE_LINK_LIBRARY_FILE_FLA
message(STATUS "CMAKE_LINK_INTERFACE_LIBRARIES: ${CMAKE_LINK_INTERFACE_LIBRARIES}")
message(STATUS "CMAKE_CXX_IMPLICIT_LINK_LIBRARIES: ${CMAKE_CXX_IMPLICIT_LINK_LIBRARIES}")
message(STATUS "CMAKE_SYSTEM_PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}")
message(STATUS "CMAKE_MSVC_RUNTIME_LIBRARY: ${CMAKE_MSVC_RUNTIME_LIBRARY}")
if(LIEF_INSTALL)
if(UNIX)
include(GNUInstallDirs)
set(CMAKE_INSTALL_LIBDIR "lib")
else()
if(WIN32)
set(CMAKE_INSTALL_LIBDIR "lib")
set(CMAKE_INSTALL_DATADIR "share")
set(CMAKE_INSTALL_INCLUDEDIR "include")
set(CMAKE_INSTALL_BINDIR "bin")
set(CMAKE_INSTALL_DATAROOTDIR "share")
message(STATUS "Setting installation destination on Windows to: ${CMAKE_INSTALL_PREFIX}")
else()
message(FATAL_ERROR "System not UNIX nor WIN32 - not implemented yet")
endif()
endif()
endif()
# LIEF Source definition
# ======================
@@ -414,6 +433,7 @@ if(LIEF_DOC)
add_subdirectory(doc)
endif()
# Post-build operations
# ======================
if(BUILD_SHARED_LIBS AND CMAKE_BUILD_TYPE MATCHES "Release")
@@ -465,25 +485,6 @@ if(LIEF_INSTALL)
endif()
endif()
# Installation
# ======================
if(UNIX)
include(GNUInstallDirs)
set(CMAKE_INSTALL_LIBDIR "lib")
else()
if(WIN32)
set(CMAKE_INSTALL_LIBDIR "lib")
set(CMAKE_INSTALL_DATADIR "share")
set(CMAKE_INSTALL_INCLUDEDIR "include")
set(CMAKE_INSTALL_BINDIR "bin")
set(CMAKE_INSTALL_DATAROOTDIR "share")
message(STATUS "Setting installation destination on Windows to: ${CMAKE_INSTALL_PREFIX}")
else()
message(FATAL_ERROR "System not UNIX nor WIN32 - not implemented yet")
endif()
endif()
install(
TARGETS LIB_LIEF lief_spdlog
EXPORT LIEFExport
+17 -6
View File
@@ -131,17 +131,22 @@ import lief
# ELF
binary = lief.parse("/usr/bin/ls")
print(binary)
for section in binary.sections:
print(section.name, section.virtual_address)
# PE
binary = lief.parse("C:\\Windows\\explorer.exe")
print(binary)
if rheader := pe.rich_header:
print(rheader.key)
# Mach-O
binary = lief.parse("/usr/bin/ls")
print(binary)
for fixup in binary.dyld_chained_fixups:
print(fixup)
```
### C++
```cpp
@@ -150,17 +155,23 @@ print(binary)
int main(int argc, char** argv) {
// ELF
if (std::unique_ptr<const LIEF::ELF::Binary> elf = LIEF::ELF::Parser::parse("/bin/ls")) {
std::cout << *elf << '\n';
for (const LIEF::ELF::Section& section : elf->sections()) {
std::cout << section->name() << ' ' << section->virtual_address() << '\n';
}
}
// PE
if (std::unique_ptr<const LIEF::PE::Binary> pe = LIEF::PE::Parser::parse("C:\\Windows\\explorer.exe")) {
std::cout << *pe << '\n';
if (const LIEF::PE::RichHeader* rheader : pe->rich_header()) {
std::cout << rheader->key() << '\n';
}
}
// Mach-O
if (std::unique_ptr<LIEF::MachO::FatBinary> macho = LIEF::MachO::Parser::parse("/bin/ls")) {
std::cout << *macho << '\n';
for (const LIEF::MachO::DyldChainedFixups& fixup : macho->dyld_chained_fixups()) {
std::cout << fixup << '\n';
}
}
return 0;
+4
View File
@@ -6,3 +6,7 @@ if(LIEF_C_API)
add_subdirectory(c)
endif()
if(LIEF_RUST_API)
add_subdirectory(rust)
endif()
+18
View File
@@ -0,0 +1,18 @@
target_include_directories(LIB_LIEF PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>")
add_subdirectory(src)
if(LIEF_INSTALL)
install(
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
COMPONENT headers)
install(
FILES ${CMAKE_CURRENT_SOURCE_DIR}/autocxx_ffi.rs
DESTINATION ${CMAKE_INSTALL_LIBDIR}/LIEF/)
endif()
+389
View File
@@ -0,0 +1,389 @@
use autocxx::prelude::*;
include_cpp! {
#include "LIEF/rust/LIEF.hpp"
#include "LIEF/rust/Stream.hpp"
name!(autocxx_ffi)
generate_pod!("Span")
block_constructors!("Span")
generate!("RustStream")
block_constructors!("RustStream")
// -------------------------------------------------------------------------
// Abstract
// -------------------------------------------------------------------------
generate!("AbstractBinary")
block_constructors!("AbstractBinary")
generate!("AbstractSymbol")
block_constructors!("AbstractSymbol")
generate!("AbstractSection")
block_constructors!("AbstractSection")
generate!("AbstractRelocation")
block_constructors!("AbstractRelocation")
// -------------------------------------------------------------------------
// ELF
// -------------------------------------------------------------------------
generate!("ELF_Binary")
block_constructors!("ELF_Binary")
generate!("ELF_Binary_it_segments")
block_constructors!("ELF_Binary_it_segments")
generate!("ELF_Binary_it_sections")
block_constructors!("ELF_Binary_it_sections")
generate!("ELF_Binary_it_dynamic_entries")
block_constructors!("ELF_Binary_it_dynamic_entries")
generate!("ELF_Binary_it_dynamic_symbols")
block_constructors!("ELF_Binary_it_dynamic_symbols")
generate!("ELF_Binary_it_exported_symbols")
block_constructors!("ELF_Binary_it_exported_symbols")
generate!("ELF_Binary_it_imported_symbols")
block_constructors!("ELF_Binary_it_imported_symbols")
generate!("ELF_Binary_it_symtab_symbols")
block_constructors!("ELF_Binary_it_symtab_symbols")
generate!("ELF_Binary_it_notes")
block_constructors!("ELF_Binary_it_notes")
generate!("ELF_Binary_it_pltgot_relocations")
block_constructors!("ELF_Binary_it_pltgot_relocations")
generate!("ELF_Binary_it_dynamic_relocations")
block_constructors!("ELF_Binary_it_dynamic_relocations")
generate!("ELF_Binary_it_object_relocations")
block_constructors!("ELF_Binary_it_object_relocations")
generate!("ELF_Binary_it_symbols_version")
block_constructors!("ELF_Binary_it_symbols_version")
generate!("ELF_Binary_it_symbols_version_requirement")
block_constructors!("ELF_Binary_it_symbols_version_requirement")
generate!("ELF_Binary_it_symbols_version_definition")
block_constructors!("ELF_Binary_it_symbols_version_definition")
generate!("ELF_Binary_it_relocations")
block_constructors!("ELF_Binary_it_relocations")
generate!("ELF_DynamicEntry")
block_constructors!("ELF_DynamicEntry")
generate!("ELF_DynamicEntryArray")
block_constructors!("ELF_DynamicEntryArray")
generate!("ELF_DynamicEntryFlags")
block_constructors!("ELF_DynamicEntryFlags")
generate!("ELF_DynamicEntryLibrary")
block_constructors!("ELF_DynamicEntryLibrary")
generate!("ELF_DynamicEntryRpath")
block_constructors!("ELF_DynamicEntryRpath")
generate!("ELF_DynamicEntryRunPath")
block_constructors!("ELF_DynamicEntryRunPath")
generate!("ELF_DynamicSharedObject")
block_constructors!("ELF_DynamicSharedObject")
generate!("ELF_GnuHash")
block_constructors!("ELF_GnuHash")
generate!("ELF_Header")
block_constructors!("ELF_Header")
generate!("ELF_Relocation")
block_constructors!("ELF_Relocation")
generate!("ELF_Section")
block_constructors!("ELF_Section")
generate!("ELF_Segment")
block_constructors!("ELF_Segment")
generate!("ELF_Symbol")
block_constructors!("ELF_Symbol")
generate!("ELF_SymbolVersion")
block_constructors!("ELF_SymbolVersion")
generate!("ELF_SymbolVersionAux")
block_constructors!("ELF_SymbolVersionAux")
generate!("ELF_SymbolVersionAuxRequirement")
block_constructors!("ELF_SymbolVersionAuxRequirement")
generate!("ELF_SymbolVersionDefinition")
block_constructors!("ELF_SymbolVersionDefinition")
generate!("ELF_SymbolVersionRequirement")
block_constructors!("ELF_SymbolVersionRequirement")
generate!("ELF_SysvHash")
block_constructors!("ELF_SysvHash")
generate!("ELF_Utils")
block_constructors!("ELF_Utils")
generate!("ELF_Note")
block_constructors!("ELF_Note")
// -------------------------------------------------------------------------
// PE
// -------------------------------------------------------------------------
generate!("PE_Binary")
block_constructors!("PE_Binary")
generate!("PE_Binary_it_debug")
block_constructors!("PE_Binary_it_debug")
generate!("PE_Binary_it_sections")
block_constructors!("PE_Binary_it_sections")
generate!("PE_Binary_it_relocations")
block_constructors!("PE_Binary_it_relocations")
generate!("PE_Binary_it_imports")
block_constructors!("PE_Binary_it_imports")
generate!("PE_Binary_it_delay_imports")
block_constructors!("PE_Binary_it_delay_imports")
generate!("PE_Binary_it_data_directories")
block_constructors!("PE_Binary_it_data_directories")
generate!("PE_Binary_it_signatures")
block_constructors!("PE_Binary_it_signatures")
generate!("PE_CodeIntegrity")
block_constructors!("PE_CodeIntegrity")
generate!("PE_ContentInfo")
block_constructors!("PE_ContentInfo")
generate!("PE_ContentInfo_Content")
block_constructors!("PE_ContentInfo_Content")
generate!("PE_DataDirectory")
block_constructors!("PE_DataDirectory")
generate!("PE_DelayImport")
block_constructors!("PE_DelayImport")
generate!("PE_DelayImport_it_entries")
block_constructors!("PE_DelayImport_it_entries")
generate!("PE_DelayImportEntry")
block_constructors!("PE_DelayImportEntry")
generate!("PE_DosHeader")
block_constructors!("PE_DosHeader")
generate!("PE_Export")
block_constructors!("PE_Export")
generate!("PE_Export_it_entries")
block_constructors!("PE_Export_it_entries")
generate!("PE_ExportEntry")
block_constructors!("PE_ExportEntry")
generate!("PE_Header")
block_constructors!("PE_Header")
generate!("PE_Import")
block_constructors!("PE_Import")
generate!("PE_Import_it_entries")
block_constructors!("PE_Import_it_entries")
generate!("PE_ImportEntry")
block_constructors!("PE_ImportEntry")
generate!("PE_OptionalHeader")
block_constructors!("PE_OptionalHeader")
generate!("PE_Relocation")
block_constructors!("PE_Relocation")
generate!("PE_Relocation_it_entries")
block_constructors!("PE_Relocation_it_entries")
generate!("PE_RelocationEntry")
block_constructors!("PE_RelocationEntry")
generate!("PE_ResourceData")
block_constructors!("PE_ResourceData")
generate!("PE_ResourceDirectory")
block_constructors!("PE_ResourceDirectory")
generate!("PE_ResourceNode")
block_constructors!("PE_ResourceNode")
generate!("PE_ResourceNode_it_childs")
block_constructors!("PE_ResourceNode_it_childs")
generate!("PE_ResourcesManager")
block_constructors!("PE_ResourcesManager")
generate!("PE_RichEntry")
block_constructors!("PE_RichEntry")
generate!("PE_RichHeader")
block_constructors!("PE_RichHeader")
generate!("PE_RichHeader_it_entries")
block_constructors!("PE_RichHeader_it_entries")
generate!("PE_Section")
block_constructors!("PE_Section")
generate!("PE_Debug")
block_constructors!("PE_Debug")
generate!("PE_CodeView")
block_constructors!("PE_CodeView")
generate!("PE_CodeViewPDB")
block_constructors!("PE_CodeViewPDB")
generate!("PE_Pogo")
block_constructors!("PE_Pogo")
generate!("PE_Pogo_it_entries")
block_constructors!("PE_Pogo_it_entries")
generate!("PE_PogoEntry")
block_constructors!("PE_PogoEntry")
generate!("PE_Repro")
block_constructors!("PE_Repro")
generate!("PE_Signature")
block_constructors!("PE_Signature")
generate!("PE_Signature_it_signers")
block_constructors!("PE_Signature_it_signers")
generate!("PE_Signature_it_certificates")
block_constructors!("PE_Signature_it_certificates")
generate!("PE_SignerInfo")
block_constructors!("PE_SignerInfo")
generate!("PE_SignerInfo_it_authenticated_attributes")
block_constructors!("PE_SignerInfo_it_authenticated_attributes")
generate!("PE_SignerInfo_it_unauthenticated_attributes")
block_constructors!("PE_SignerInfo_it_unauthenticated_attributes")
generate!("PE_TLS")
block_constructors!("PE_TLS")
generate!("PE_Utils")
block_constructors!("PE_Utils")
generate!("PE_x509")
block_constructors!("PE_x509")
generate!("PE_RsaInfo")
block_constructors!("PE_RsaInfo")
generate!("PE_Attribute")
block_constructors!("PE_Attribute")
generate!("PE_ContentType")
block_constructors!("PE_ContentType")
generate!("PE_GenericType")
block_constructors!("PE_GenericType")
generate!("PE_MsSpcNestedSignature")
block_constructors!("PE_MsSpcNestedSignature")
generate!("PE_MsSpcStatementType")
block_constructors!("PE_MsSpcStatementType")
generate!("PE_PKCS9AtSequenceNumber")
block_constructors!("PE_PKCS9AtSequenceNumber")
generate!("PE_PKCS9CounterSignature")
block_constructors!("PE_PKCS9CounterSignature")
generate!("PE_PKCS9MessageDigest")
block_constructors!("PE_PKCS9MessageDigest")
generate!("PE_PKCS9SigningTime")
block_constructors!("PE_PKCS9SigningTime")
generate!("PE_SpcSpOpusInfo")
block_constructors!("PE_SpcSpOpusInfo")
generate!("PE_LoadConfiguration")
block_constructors!("PE_LoadConfiguration")
generate!("PE_LoadConfigurationV0")
block_constructors!("PE_LoadConfigurationV0")
generate!("PE_LoadConfigurationV1")
block_constructors!("PE_LoadConfigurationV1")
generate!("PE_LoadConfigurationV2")
block_constructors!("PE_LoadConfigurationV2")
generate!("PE_LoadConfigurationV3")
block_constructors!("PE_LoadConfigurationV3")
generate!("PE_LoadConfigurationV4")
block_constructors!("PE_LoadConfigurationV4")
generate!("PE_LoadConfigurationV5")
block_constructors!("PE_LoadConfigurationV5")
generate!("PE_LoadConfigurationV6")
block_constructors!("PE_LoadConfigurationV6")
generate!("PE_LoadConfigurationV7")
block_constructors!("PE_LoadConfigurationV7")
generate!("PE_LoadConfigurationV8")
block_constructors!("PE_LoadConfigurationV8")
generate!("PE_LoadConfigurationV9")
block_constructors!("PE_LoadConfigurationV9")
generate!("PE_LoadConfigurationV10")
block_constructors!("PE_LoadConfigurationV10")
generate!("PE_LoadConfigurationV11")
block_constructors!("PE_LoadConfigurationV11")
// -------------------------------------------------------------------------
// Mach-O
// -------------------------------------------------------------------------
generate!("MachO_Binary")
block_constructors!("MachO_Binary")
generate!("MachO_Binary_it_symbols")
block_constructors!("MachO_Binary_it_symbols")
generate!("MachO_Binary_it_relocations")
block_constructors!("MachO_Binary_it_relocations")
generate!("MachO_Binary_it_commands")
block_constructors!("MachO_Binary_it_commands")
generate!("MachO_Binary_it_symbols")
block_constructors!("MachO_Binary_it_symbols")
generate!("MachO_Binary_it_segments")
block_constructors!("MachO_Binary_it_segments")
generate!("MachO_Binary_it_sections")
block_constructors!("MachO_Binary_it_sections")
generate!("MachO_Binary_it_libraries")
block_constructors!("MachO_Binary_it_libraries")
generate!("MachO_BindingInfo")
block_constructors!("MachO_BindingInfo")
generate!("MachO_BuildVersion")
block_constructors!("MachO_BuildVersion")
generate!("MachO_BuildToolVersion")
block_constructors!("MachO_BuildToolVersion")
generate!("MachO_ChainedBindingInfo")
block_constructors!("MachO_ChainedBindingInfo")
generate!("MachO_CodeSignature")
block_constructors!("MachO_CodeSignature")
generate!("MachO_CodeSignatureDir")
block_constructors!("MachO_CodeSignatureDir")
generate!("MachO_Command")
block_constructors!("MachO_Command")
generate!("MachO_DataCodeEntry")
block_constructors!("MachO_DataCodeEntry")
generate!("MachO_DataInCode")
block_constructors!("MachO_DataInCode")
generate!("MachO_DataInCode_it_entries")
block_constructors!("MachO_DataInCode_it_entries")
generate!("MachO_DyldBindingInfo")
block_constructors!("MachO_DyldBindingInfo")
generate!("MachO_DyldChainedFixups")
block_constructors!("MachO_DyldChainedFixups")
generate!("MachO_DyldChainedFixups_it_bindings")
block_constructors!("MachO_DyldChainedFixups_it_bindings")
generate!("MachO_DyldEnvironment")
block_constructors!("MachO_DyldEnvironment")
generate!("MachO_DyldExportsTrie")
block_constructors!("MachO_DyldExportsTrie")
generate!("MachO_DyldExportsTrie_it_exports")
block_constructors!("MachO_DyldExportsTrie_it_exports")
generate!("MachO_DyldInfo")
block_constructors!("MachO_DyldInfo")
generate!("MachO_DyldInfo_it_bindings")
block_constructors!("MachO_DyldInfo_it_bindings")
generate!("MachO_DyldInfo_it_exports")
block_constructors!("MachO_DyldInfo_it_exports")
generate!("MachO_Dylib")
block_constructors!("MachO_Dylib")
generate!("MachO_Dylinker")
block_constructors!("MachO_Dylinker")
generate!("MachO_DynamicSymbolCommand")
block_constructors!("MachO_DynamicSymbolCommand")
generate!("MachO_EncryptionInfo")
block_constructors!("MachO_EncryptionInfo")
generate!("MachO_ExportInfo")
block_constructors!("MachO_ExportInfo")
generate!("MachO_FatBinary")
block_constructors!("MachO_FatBinary")
generate!("MachO_Fileset")
block_constructors!("MachO_Fileset")
generate!("MachO_FunctionStarts")
block_constructors!("MachO_FunctionStarts")
generate!("MachO_Header")
block_constructors!("MachO_Header")
generate!("MachO_LinkerOptHint")
block_constructors!("MachO_LinkerOptHint")
generate!("MachO_Main")
block_constructors!("MachO_Main")
generate!("MachO_RPathCommand")
block_constructors!("MachO_RPathCommand")
generate!("MachO_Relocation")
block_constructors!("MachO_Relocation")
generate!("MachO_RelocationDyld")
block_constructors!("MachO_RelocationDyld")
generate!("MachO_RelocationFixup")
block_constructors!("MachO_RelocationFixup")
generate!("MachO_RelocationObject")
block_constructors!("MachO_RelocationObject")
generate!("MachO_Section")
block_constructors!("MachO_Section")
generate!("MachO_Section_it_relocations")
block_constructors!("MachO_Section_it_relocations")
generate!("MachO_SegmentCommand")
block_constructors!("MachO_SegmentCommand")
generate!("MachO_SegmentCommand_it_sections")
block_constructors!("MachO_SegmentCommand_it_sections")
generate!("MachO_SegmentCommand_it_relocations")
block_constructors!("MachO_SegmentCommand_it_relocations")
generate!("MachO_SegmentSplitInfo")
block_constructors!("MachO_SegmentSplitInfo")
generate!("MachO_SourceVersion")
block_constructors!("MachO_SourceVersion")
generate!("MachO_SubFramework")
block_constructors!("MachO_SubFramework")
generate!("MachO_Symbol")
block_constructors!("MachO_Symbol")
generate!("MachO_SymbolCommand")
block_constructors!("MachO_SymbolCommand")
generate!("MachO_ThreadCommand")
block_constructors!("MachO_ThreadCommand")
generate!("MachO_TwoLevelHints")
block_constructors!("MachO_TwoLevelHints")
generate!("MachO_UUIDCommand")
block_constructors!("MachO_UUIDCommand")
generate!("MachO_Utils")
block_constructors!("MachO_Utils")
generate!("MachO_VersionMin")
block_constructors!("MachO_VersionMin")
safety!(unsafe)
}
+17
View File
@@ -0,0 +1,17 @@
[workspace.package]
authors = ["Romain Thomas <[email protected]>"]
license = "Apache-2.0"
description = "Official Rust bindings for LIEF."
readme = "README.md"
version = "0.15.0"
[workspace]
members = [
"lief-ffi",
"lief",
"lief-ffigen",
]
default-members = [
"lief",
]
resolver = "2"
+1
View File
@@ -0,0 +1 @@
# LIEF Rust Bindings
+14
View File
@@ -0,0 +1,14 @@
[package]
name = "lief-build"
edition = "2021"
description = "Build helper for the Rust bindings of LIEF"
version.workspace = true
authors.workspace = true
license.workspace = true
[dependencies]
miette = { version="5.10", features = [ "fancy" ] }
reqwest = { version = "0.11.24", features = ["blocking"] }
zip = "0.6.6"
git-version = "0.3.9"
semver = "1.0.22"
+197
View File
@@ -0,0 +1,197 @@
use std::env;
use semver::Version;
use std::path::{PathBuf, Path};
use miette::IntoDiagnostic;
use git_version::git_version;
const GIT_VERSION: &str = git_version!(
args = ["--tags", "--long", "--dirty"],
prefix = "git:",
cargo_prefix = "cargo:",
fallback="latest"
);
const GH_URL: &str = "https://github.com/lief-project/LIEF/releases/download";
const DEFAULT_S3_URL: &str = "https://lief-rs.s3.fr-par.scw.cloud";
const SUPPORTED_TARGETS: &[&str; 4] = &[
"x86_64-unknown-linux-gnu",
"x86_64-apple-darwin",
"x86_64-pc-windows-msvc",
"aarch64-apple-darwin",
];
fn get_s3_url() -> String {
env::var("LIEF_RUST_S3_PREFIX").unwrap_or(DEFAULT_S3_URL.to_string())
}
fn get_target() -> String {
let current_target = env::var("TARGET").unwrap();
let supported = SUPPORTED_TARGETS
.iter()
.find(|&supported| *supported == current_target);
if supported.is_none() {
panic!("Target: {} is not currently supported.", current_target);
}
current_target.to_string()
}
fn get_filename(target: &String) -> String {
if let Some(crt) = get_crt_prefix() {
return format!("LIEF-rs-{}-{}.zip", crt, target);
}
format!("LIEF-rs-{}.zip", target)
}
fn get_urls_from_cargo(target: &String, version: &str) -> Vec<String> {
let mut urls = Vec::new();
let s3_prefix = get_s3_url();
let github_url = format!("{GH_URL}/{version}/{}", get_filename(target));
let s3_url = format!("{s3_prefix}/precompiled/{version}/{}", get_filename(target));
let s3_latest_url = format!("{s3_prefix}/precompiled/latest/{}", get_filename(target));
urls.push(github_url);
urls.push(s3_url);
urls.push(s3_latest_url); // Fallback if it's not yet a release
urls
}
fn get_urls_from_git(target: &String, version: &str) -> Vec<String> {
let mut urls = Vec::new();
let parts: Vec<&str> = version.split('-').collect();
let cargo_version = env::var("CARGO_PKG_VERSION").unwrap();
if parts.is_empty() { // Fallback on cargo version
eprintln!("Invalid Git-based version. Falling back to Cargo-based version");
return get_urls_from_cargo(target, cargo_version.as_str());
}
let git_ver = parts[0];
let sem_version = Version::parse(git_ver);
if sem_version.is_err() {
eprintln!("Invalid Git-based version. Falling back to Cargo-based version");
return get_urls_from_cargo(target, cargo_version.as_str());
}
if parts.len() == 1 { // Tagged version
println!("Using tagged version: {git_ver}");
let s3_prefix = get_s3_url();
let github_url = format!("{GH_URL}/{git_ver}/{}", get_filename(target));
let s3_url = format!("{s3_prefix}/precompiled/{git_ver}/{}", get_filename(target));
urls.push(github_url);
urls.push(s3_url);
return urls;
}
get_nightly_url(target)
}
fn get_nightly_url(target: &String) -> Vec<String> {
println!("Using nightly url");
let mut urls = Vec::new();
let s3_prefix = get_s3_url();
let s3_url = format!("{s3_prefix}/precompiled/latest/{}", get_filename(target));
urls.push(s3_url);
urls
}
fn get_cache_urls() -> Vec<String> {
let version = String::from(GIT_VERSION);
let target = get_target();
if version.starts_with("cargo:") {
let tag = version.strip_prefix("cargo:").expect("Can't strip 'cargo:' prefix");
return get_urls_from_cargo(&target, tag);
}
if version.starts_with("git:") {
let git_ver = version.strip_prefix("git:")
.expect("Can't strip 'git:' prefix")
.to_string();
return get_urls_from_git(&target, &git_ver);
}
get_nightly_url(&target)
}
fn emit_cargo_directives(root: &Path) -> miette::Result<()> {
println!("cargo:rustc-link-search=native={}/lib", root.display());
println!("cargo:rustc-env=AUTOCXX_RS={}/rs", root.display());
println!("cargo:rustc-link-lib=lief-sys");
println!("cargo:rustc-link-lib=LIEF");
Ok(())
}
fn download(dst_archive: &PathBuf) -> bool {
let urls = get_cache_urls();
if urls.is_empty() {
panic!("Can't determine precompiled URL for this build.\n
Please consider opening a GitHub issue.");
}
for url in urls.iter() {
println!("Trying to download from {}", url);
let mut resp =
reqwest::blocking::get(url).expect("failed to download LIEF cache");
if resp.status().is_client_error() || resp.status().is_server_error() {
eprintln!("Can't download precompiled LIEF ffi bindings from: {}", url);
continue;
}
let mut out = std::fs::File::create(dst_archive).expect("failed to create zip cache file");
std::io::copy(&mut resp, &mut out).expect("failed to copy cache content");
return true;
}
false
}
fn get_crt_prefix() -> Option<String> {
let os = env::var("CARGO_CFG_TARGET_OS").expect("Can't access 'CARGO_CFG_TARGET_OS");
if os.to_lowercase() != "windows" {
return None;
}
let use_static_crt = {
let target_features = env::var("CARGO_CFG_TARGET_FEATURE").unwrap_or_default();
target_features.split(',').any(|f| f == "crt-static")
};
if use_static_crt {
return Some("MT".to_string());
}
Some("MD".to_string())
}
fn build_from_precompiled() -> miette::Result<()> {
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
let target = env::var("TARGET").unwrap();
println!("Target: {}", target);
println!("Arch: {}", target_arch);
println!("OS: {}", target_os);
println!("Version: {}", GIT_VERSION);
if let Ok(var) = env::var("LIEF_RUST_PRECOMPILED") {
let root = PathBuf::from(var);
return emit_cargo_directives(&root);
}
let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
let dst_dir = out_dir.join("lief-rs");
let dst_archive = dst_dir.join("cache.zip");
if !dst_dir.exists() {
std::fs::create_dir_all(&dst_dir).into_diagnostic()?;
}
println!("Cache dst: {}", &dst_dir.display().to_string());
if !dst_archive.exists() && !download(&dst_archive) {
panic!("Can't download precompiled ffi package");
}
let cache_file = std::fs::File::open(dst_archive).into_diagnostic()?;
let mut zip = zip::ZipArchive::new(&cache_file).into_diagnostic()?;
zip.extract(&dst_dir).into_diagnostic()?;
emit_cargo_directives(&dst_dir)
}
pub fn build() -> miette::Result<()> {
build_from_precompiled()?;
Ok(())
}
+15
View File
@@ -0,0 +1,15 @@
[package]
name = "lief-ffi"
description = "LIEF ffi"
edition = "2021"
version.workspace = true
authors.workspace = true
license.workspace = true
[dependencies]
cxx = { version = "1.0.117", features = [ "c++20" ] }
autocxx = "0.26"
[build-dependencies]
lief-build = { path = "../lief-build" }
miette = { version="5.10", features = [ "fancy" ] }
+3
View File
@@ -0,0 +1,3 @@
fn main() -> miette::Result<()> {
lief_build::build()
}
+3
View File
@@ -0,0 +1,3 @@
include!(concat!(env!("AUTOCXX_RS"), "/", "autocxx-autocxx_ffi-gen.rs"));
pub use autocxx_ffi::*;
+18
View File
@@ -0,0 +1,18 @@
[package]
name = "lief-ffigen"
edition = "2021"
description = "Generate FFI bindings for LIEF"
version.workspace = true
authors.workspace = true
license.workspace = true
[dependencies]
cc = "1.0"
autocxx-build = "0.26.0"
cmake = "0.1.50"
toml = "0.8.6"
serde = "1.0"
thiserror = "1.0"
zip = "0.6.6"
miette = { version="5.10", features = [ "fancy" ] }
clap = { version="4.5.1", features = [ "derive" ] }
+57
View File
@@ -0,0 +1,57 @@
use clap::Parser;
use std::path::PathBuf;
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
struct Args {
#[arg(short, long)]
output_dir: String,
#[arg(long)]
lief_dir: String,
#[arg(long)]
host: String,
#[arg(short, long)]
target: String,
}
fn main() -> miette::Result<()> {
let args = Args::parse();
std::env::set_var("PROFILE", "release");
std::env::set_var("OPT_LEVEL", "3");
std::env::set_var("DEBUG", "0");
let host = args.host;
let target = args.target;
let precompiled_dir = PathBuf::from(args.output_dir);
let lief_dir = PathBuf::from(args.lief_dir);
let lief_lib_dir = lief_dir.join("lib");
let lief_ffi_file = lief_lib_dir.join("LIEF").join("autocxx_ffi.rs");
let lief_inc_dir = lief_dir.join("include");
let autocxx_gen_dir = precompiled_dir.join("autocxx_builder");
let autocxx_builder = autocxx_build::Builder::new(
&lief_ffi_file, [&lief_inc_dir]
);
let mut cxx_builder = autocxx_builder
.custom_gendir(autocxx_gen_dir)
.extra_clang_args(&["-std=c++17"])
.build()?;
cxx_builder
.out_dir(precompiled_dir.join("cxx_builder"))
.host(&host)
.target(&target)
.std("c++17")
.flag("-O3")
.compile("lief-sys");
Ok(())
}
+18
View File
@@ -0,0 +1,18 @@
[package]
name = "lief"
description = "Official Rust bindings for LIEF"
edition = "2021"
version.workspace = true
authors.workspace = true
license.workspace = true
[lib]
doctest = false
[dependencies]
cxx = "1.0.109"
bitflags = "2.4"
num-traits = "0.2"
num-derive = "0.4"
num-bigint = "0.4"
lief-ffi = { path = "../lief-ffi" }
+57
View File
@@ -0,0 +1,57 @@
use lief_ffi as ffi;
use super::elf;
use super::macho;
use super::pe;
use crate::common::FromFFI;
use std::io::{Read, Seek};
#[derive(Debug)]
pub enum Binary {
ELF(elf::Binary),
PE(pe::Binary),
MachO(macho::FatBinary),
}
impl Binary {
pub fn parse(path: &str) -> Option<Binary> {
if ffi::ELF_Utils::is_elf(path) {
return Some(Binary::ELF(elf::Binary::parse(path)));
}
if ffi::PE_Utils::is_pe(path) {
return Some(Binary::PE(pe::Binary::parse(path)));
}
if ffi::MachO_Utils::is_macho(path) {
return Some(Binary::MachO(macho::FatBinary::parse(path)));
}
None
}
pub fn from<R: Read + Seek>(reader: &mut R) -> Option<Binary> {
let mut buffer = std::vec::Vec::new();
if reader.read_to_end(&mut buffer).is_err() {
return None;
}
let mut ffi_stream =
unsafe { ffi::RustStream::from_rust(buffer.as_mut_ptr(), buffer.len()) };
buffer.clear();
if ffi_stream.is_elf() {
return Some(Binary::ELF(elf::Binary::from_ffi(
ffi_stream.pin_mut().as_elf(),
)));
}
if ffi_stream.is_macho() {
return Some(Binary::MachO(macho::FatBinary::from_ffi(
ffi_stream.pin_mut().as_macho(),
)));
}
if ffi_stream.is_pe() {
return Some(Binary::PE(pe::Binary::from_ffi(
ffi_stream.pin_mut().as_pe(),
)));
}
None
}
}
+75
View File
@@ -0,0 +1,75 @@
use cxx::memory::UniquePtrTarget;
use std::marker::PhantomData;
#[doc(hidden)]
pub trait FromFFI<T: UniquePtrTarget> {
fn from_ffi(ptr: cxx::UniquePtr<T>) -> Self;
}
#[doc(hidden)]
pub fn into_optional<T: FromFFI<U>, U: UniquePtrTarget>(raw_ffi: cxx::UniquePtr<U>) -> Option<T> {
if raw_ffi.is_null() {
None
} else {
Some(T::from_ffi(raw_ffi))
}
}
pub struct Iterator<'a, Parent: UniquePtrTarget, It: UniquePtrTarget> {
#[doc(hidden)]
pub it: cxx::UniquePtr<It>,
_owner: PhantomData<&'a Parent>,
}
impl<'a, Parent: UniquePtrTarget, It: UniquePtrTarget> Iterator<'a, Parent, It> {
#[doc(hidden)]
pub fn new(it: cxx::UniquePtr<It>) -> Self {
Self {
it,
_owner: PhantomData,
}
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! declare_iterator_conv {
($name:ident, $from:ty, $ffi:ty, $parent:ty, $ffi_iterator:ty, $conv: expr) => {
pub type $name<'a> = $crate::common::Iterator<'a, $parent, $ffi_iterator>;
impl<'a> Iterator for $name<'a> {
type Item = $from;
fn next(&mut self) -> Option<Self::Item> {
let next = self.it.as_mut().unwrap().next();
if next.is_null() {
None
} else {
Some($conv(next))
}
}
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! declare_iterator {
($name:ident, $from:ty, $ffi:ty, $parent:ty, $ffi_iterator:ty) => {
crate::declare_iterator_conv!($name, $from, $ffi, $parent, $ffi_iterator, |n| {
Self::Item::from_ffi(n)
});
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! to_slice {
($e:expr) => {
let content_ptr = $e;
unsafe {
if content_ptr.size > 0 {
return std::slice::from_raw_parts_mut(content_ptr.ptr, content_ptr.size as usize);
}
return &[];
}
};
}
+40
View File
@@ -0,0 +1,40 @@
pub mod binary;
pub mod dynamic;
pub mod hash;
pub mod header;
pub mod note;
pub mod relocation;
pub mod section;
pub mod segment;
pub mod symbol;
pub mod symbol_versioning;
#[doc(inline)]
pub use binary::Binary;
#[doc(inline)]
pub use header::Header;
#[doc(inline)]
pub use section::Section;
#[doc(inline)]
pub use segment::Segment;
#[doc(inline)]
pub use symbol::Symbol;
#[doc(inline)]
pub use hash::Sysv as SysvHash;
#[doc(inline)]
pub use hash::Gnu as GnuHash;
#[doc(inline)]
pub use note::Notes;
#[doc(inline)]
pub use symbol_versioning::{
SymbolVersion, SymbolVersionAux, SymbolVersionAuxRequirement, SymbolVersionDefinition,
SymbolVersionRequirement,
};
+145
View File
@@ -0,0 +1,145 @@
use lief_ffi as ffi;
use super::hash::{Sysv, Gnu};
use super::dynamic::DynamicEntries;
use super::header::Header;
use super::section::Sections;
use super::segment::Segments;
use super::symbol::{DynamicSymbols, ExportedSymbols, ImportedSymbols, SymtabSymbols};
use super::note::ItNotes;
use super::relocation::{PltGotRelocations, DynamicRelocations, ObjectRelocations, Relocations};
use super::symbol_versioning::{SymbolVersion, SymbolVersionDefinition, SymbolVersionRequirement};
use crate::generic;
use crate::declare_iterator;
use crate::common::{into_optional, FromFFI};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ElfClass {
Elf32,
Elf64,
Unknown,
}
impl ElfClass {
const ELF_CLASS32: u32 = 1;
const ELF_CLASS64: u32 = 2;
pub fn from_value(value: u32) -> Self {
match value {
Self::ELF_CLASS32 => ElfClass::Elf32,
Self::ELF_CLASS64 => ElfClass::Elf64,
_ => ElfClass::Unknown,
}
}
}
pub struct Binary {
ptr: cxx::UniquePtr<ffi::ELF_Binary>,
}
impl std::fmt::Debug for Binary {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Binary")
.field("header", &self.header())
.finish()
}
}
impl FromFFI<ffi::ELF_Binary> for Binary {
fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_Binary>) -> Self {
Self {
ptr,
}
}
}
impl Binary {
pub fn parse(path: &str) -> Self {
let bin = ffi::ELF_Binary::parse(path);
Binary::from_ffi(bin)
}
pub fn header(&self) -> Header {
Header::from_ffi(self.ptr.header())
}
pub fn sysv_hash(&self) -> Option<Sysv> {
into_optional(self.ptr.sysv_hash())
}
pub fn gnu_hash(&self) -> Option<Gnu> {
into_optional(self.ptr.gnu_hash())
}
pub fn sections(&self) -> Sections {
Sections::new(self.ptr.sections())
}
pub fn segments(&self) -> Segments {
Segments::new(self.ptr.segments())
}
pub fn dynamic_entries(&self) -> DynamicEntries {
DynamicEntries::new(self.ptr.dynamic_entries())
}
pub fn dynamic_symbols(&self) -> DynamicSymbols {
DynamicSymbols::new(self.ptr.dynamic_symbols())
}
pub fn exported_symbols(&self) -> ExportedSymbols {
ExportedSymbols::new(self.ptr.exported_symbols())
}
pub fn imported_symbols(&self) -> ImportedSymbols {
ImportedSymbols::new(self.ptr.imported_symbols())
}
pub fn symtab_symbols(&self) -> SymtabSymbols {
SymtabSymbols::new(self.ptr.symtab_symbols())
}
pub fn symbols_version(&self) -> SymbolsVersion {
SymbolsVersion::new(self.ptr.symbols_version())
}
pub fn symbols_version_requirement(&self) -> SymbolsVersionRequirement {
SymbolsVersionRequirement::new(self.ptr.symbols_version_requirement())
}
pub fn symbols_version_definition(&self) -> SymbolsVersionDefinition {
SymbolsVersionDefinition::new(self.ptr.symbols_version_definition())
}
pub fn notes(&self) -> ItNotes {
ItNotes::new(self.ptr.notes())
}
pub fn pltgot_relocations(&self) -> PltGotRelocations {
PltGotRelocations::new(self.ptr.pltgot_relocations())
}
pub fn dynamic_relocations(&self) -> DynamicRelocations {
DynamicRelocations::new(self.ptr.dynamic_relocations())
}
pub fn object_relocations(&self) -> ObjectRelocations {
ObjectRelocations::new(self.ptr.object_relocations())
}
pub fn relocations(&self) -> Relocations {
Relocations::new(self.ptr.relocations())
}
}
impl generic::Binary for Binary {
fn as_generic(&self) -> &ffi::AbstractBinary {
self.ptr.as_ref().unwrap().as_ref()
}
}
declare_iterator!(SymbolsVersion, SymbolVersion<'a>, ffi::ELF_SymbolVersion, ffi::ELF_Binary, ffi::ELF_Binary_it_symbols_version);
declare_iterator!(SymbolsVersionRequirement, SymbolVersionRequirement<'a>, ffi::ELF_SymbolVersionRequirement, ffi::ELF_Binary, ffi::ELF_Binary_it_symbols_version_requirement);
declare_iterator!(SymbolsVersionDefinition, SymbolVersionDefinition<'a>, ffi::ELF_SymbolVersionDefinition, ffi::ELF_Binary, ffi::ELF_Binary_it_symbols_version_definition);
+527
View File
@@ -0,0 +1,527 @@
use std::marker::PhantomData;
use lief_ffi as ffi;
use crate::common::FromFFI;
use crate::declare_iterator;
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Tag {
DT_NULL,
NEEDED,
PLTRELSZ,
PLTGOT,
HASH,
STRTAB,
SYMTAB,
RELA,
RELASZ,
RELAENT,
STRSZ,
SYMENT,
INIT,
FINI,
SONAME,
RPATH,
SYMBOLIC,
REL,
RELSZ,
RELENT,
PLTREL,
DEBUG,
TEXTREL,
JMPREL,
BIND_NOW,
INIT_ARRAY,
FINI_ARRAY,
INIT_ARRAYSZ,
FINI_ARRAYSZ,
RUNPATH,
FLAGS,
PREINIT_ARRAY,
PREINIT_ARRAYSZ,
SYMTAB_SHNDX,
RELRSZ,
RELR,
RELRENT,
GNU_HASH,
RELACOUNT,
RELCOUNT,
FLAGS_1,
VERSYM,
VERDEF,
VERDEFNUM,
VERNEED,
VERNEEDNUM,
ANDROID_REL_OFFSET,
ANDROID_REL_SIZE,
ANDROID_REL,
ANDROID_RELSZ,
ANDROID_RELA,
ANDROID_RELASZ,
ANDROID_RELR,
ANDROID_RELRSZ,
ANDROID_RELRENT,
ANDROID_RELRCOUNT,
MIPS_RLD_VERSION,
MIPS_TIME_STAMP,
MIPS_ICHECKSUM,
MIPS_IVERSION,
MIPS_FLAGS,
MIPS_BASE_ADDRESS,
MIPS_MSYM,
MIPS_CONFLICT,
MIPS_LIBLIST,
MIPS_LOCAL_GOTNO,
MIPS_CONFLICTNO,
MIPS_LIBLISTNO,
MIPS_SYMTABNO,
MIPS_UNREFEXTNO,
MIPS_GOTSYM,
MIPS_HIPAGENO,
MIPS_RLD_MAP,
MIPS_DELTA_CLASS,
MIPS_DELTA_CLASS_NO,
MIPS_DELTA_INSTANCE,
MIPS_DELTA_INSTANCE_NO,
MIPS_DELTA_RELOC,
MIPS_DELTA_RELOC_NO,
MIPS_DELTA_SYM,
MIPS_DELTA_SYM_NO,
MIPS_DELTA_CLASSSYM,
MIPS_DELTA_CLASSSYM_NO,
MIPS_CXX_FLAGS,
MIPS_PIXIE_INIT,
MIPS_SYMBOL_LIB,
MIPS_LOCALPAGE_GOTIDX,
MIPS_LOCAL_GOTIDX,
MIPS_HIDDEN_GOTIDX,
MIPS_PROTECTED_GOTIDX,
MIPS_OPTIONS,
MIPS_INTERFACE,
MIPS_DYNSTR_ALIGN,
MIPS_INTERFACE_SIZE,
MIPS_RLD_TEXT_RESOLVE_ADDR,
MIPS_PERF_SUFFIX,
MIPS_COMPACT_SIZE,
MIPS_GP_VALUE,
MIPS_AUX_DYNAMIC,
MIPS_PLTGOT,
MIPS_RWPLT,
MIPS_RLD_MAP_REL,
MIPS_XHASH,
AARCH64_BTI_PLT,
AARCH64_PAC_PLT,
AARCH64_VARIANT_PCS,
AARCH64_MEMTAG_MODE,
AARCH64_MEMTAG_HEAP,
AARCH64_MEMTAG_STACK,
AARCH64_MEMTAG_GLOBALS,
AARCH64_MEMTAG_GLOBALSSZ,
HEXAGON_SYMSZ,
HEXAGON_VER,
HEXAGON_PLT,
PPC_GOT,
PPC_OPT,
PPC64_GLINK,
PPC64_OPT,
RISCV_VARIANT_CC,
UNKNOWN(u64),
}
impl Tag {
pub fn from_value(value: u64) -> Self {
match value {
0x00000000 => Tag::DT_NULL,
0x00000001 => Tag::NEEDED,
0x00000002 => Tag::PLTRELSZ,
0x00000003 => Tag::PLTGOT,
0x00000004 => Tag::HASH,
0x00000005 => Tag::STRTAB,
0x00000006 => Tag::SYMTAB,
0x00000007 => Tag::RELA,
0x00000008 => Tag::RELASZ,
0x00000009 => Tag::RELAENT,
0x0000000a => Tag::STRSZ,
0x0000000b => Tag::SYMENT,
0x0000000c => Tag::INIT,
0x0000000d => Tag::FINI,
0x0000000e => Tag::SONAME,
0x0000000f => Tag::RPATH,
0x00000010 => Tag::SYMBOLIC,
0x00000011 => Tag::REL,
0x00000012 => Tag::RELSZ,
0x00000013 => Tag::RELENT,
0x00000014 => Tag::PLTREL,
0x00000015 => Tag::DEBUG,
0x00000016 => Tag::TEXTREL,
0x00000017 => Tag::JMPREL,
0x00000018 => Tag::BIND_NOW,
0x00000019 => Tag::INIT_ARRAY,
0x0000001a => Tag::FINI_ARRAY,
0x0000001b => Tag::INIT_ARRAYSZ,
0x0000001c => Tag::FINI_ARRAYSZ,
0x0000001d => Tag::RUNPATH,
0x0000001e => Tag::FLAGS,
0x00000020 => Tag::PREINIT_ARRAY,
0x00000021 => Tag::PREINIT_ARRAYSZ,
0x00000022 => Tag::SYMTAB_SHNDX,
0x00000023 => Tag::RELRSZ,
0x00000024 => Tag::RELR,
0x00000025 => Tag::RELRENT,
0x6ffffef5 => Tag::GNU_HASH,
0x6ffffff9 => Tag::RELACOUNT,
0x6ffffffa => Tag::RELCOUNT,
0x6ffffffb => Tag::FLAGS_1,
0x6ffffff0 => Tag::VERSYM,
0x6ffffffc => Tag::VERDEF,
0x6ffffffd => Tag::VERDEFNUM,
0x6ffffffe => Tag::VERNEED,
0x6fffffff => Tag::VERNEEDNUM,
0x6000000d => Tag::ANDROID_REL_OFFSET,
0x6000000e => Tag::ANDROID_REL_SIZE,
0x6000000f => Tag::ANDROID_REL,
0x60000010 => Tag::ANDROID_RELSZ,
0x60000011 => Tag::ANDROID_RELA,
0x60000012 => Tag::ANDROID_RELASZ,
0x6fffe000 => Tag::ANDROID_RELR,
0x6fffe001 => Tag::ANDROID_RELRSZ,
0x6fffe003 => Tag::ANDROID_RELRENT,
0x6fffe005 => Tag::ANDROID_RELRCOUNT,
0x170000001 => Tag::MIPS_RLD_VERSION,
0x170000002 => Tag::MIPS_TIME_STAMP,
0x170000003 => Tag::MIPS_ICHECKSUM,
0x170000004 => Tag::MIPS_IVERSION,
0x170000005 => Tag::MIPS_FLAGS,
0x170000006 => Tag::MIPS_BASE_ADDRESS,
0x170000007 => Tag::MIPS_MSYM,
0x170000008 => Tag::MIPS_CONFLICT,
0x170000009 => Tag::MIPS_LIBLIST,
0x17000000a => Tag::MIPS_LOCAL_GOTNO,
0x17000000b => Tag::MIPS_CONFLICTNO,
0x170000010 => Tag::MIPS_LIBLISTNO,
0x170000011 => Tag::MIPS_SYMTABNO,
0x170000012 => Tag::MIPS_UNREFEXTNO,
0x170000013 => Tag::MIPS_GOTSYM,
0x170000014 => Tag::MIPS_HIPAGENO,
0x170000016 => Tag::MIPS_RLD_MAP,
0x170000017 => Tag::MIPS_DELTA_CLASS,
0x170000018 => Tag::MIPS_DELTA_CLASS_NO,
0x170000019 => Tag::MIPS_DELTA_INSTANCE,
0x17000001a => Tag::MIPS_DELTA_INSTANCE_NO,
0x17000001b => Tag::MIPS_DELTA_RELOC,
0x17000001c => Tag::MIPS_DELTA_RELOC_NO,
0x17000001d => Tag::MIPS_DELTA_SYM,
0x17000001e => Tag::MIPS_DELTA_SYM_NO,
0x170000020 => Tag::MIPS_DELTA_CLASSSYM,
0x170000021 => Tag::MIPS_DELTA_CLASSSYM_NO,
0x170000022 => Tag::MIPS_CXX_FLAGS,
0x170000023 => Tag::MIPS_PIXIE_INIT,
0x170000024 => Tag::MIPS_SYMBOL_LIB,
0x170000025 => Tag::MIPS_LOCALPAGE_GOTIDX,
0x170000026 => Tag::MIPS_LOCAL_GOTIDX,
0x170000027 => Tag::MIPS_HIDDEN_GOTIDX,
0x170000028 => Tag::MIPS_PROTECTED_GOTIDX,
0x170000029 => Tag::MIPS_OPTIONS,
0x17000002a => Tag::MIPS_INTERFACE,
0x17000002b => Tag::MIPS_DYNSTR_ALIGN,
0x17000002c => Tag::MIPS_INTERFACE_SIZE,
0x17000002d => Tag::MIPS_RLD_TEXT_RESOLVE_ADDR,
0x17000002e => Tag::MIPS_PERF_SUFFIX,
0x17000002f => Tag::MIPS_COMPACT_SIZE,
0x170000030 => Tag::MIPS_GP_VALUE,
0x170000031 => Tag::MIPS_AUX_DYNAMIC,
0x170000032 => Tag::MIPS_PLTGOT,
0x170000034 => Tag::MIPS_RWPLT,
0x170000035 => Tag::MIPS_RLD_MAP_REL,
0x170000036 => Tag::MIPS_XHASH,
0x270000001 => Tag::AARCH64_BTI_PLT,
0x270000003 => Tag::AARCH64_PAC_PLT,
0x270000005 => Tag::AARCH64_VARIANT_PCS,
0x270000009 => Tag::AARCH64_MEMTAG_MODE,
0x27000000b => Tag::AARCH64_MEMTAG_HEAP,
0x27000000c => Tag::AARCH64_MEMTAG_STACK,
0x27000000d => Tag::AARCH64_MEMTAG_GLOBALS,
0x27000000f => Tag::AARCH64_MEMTAG_GLOBALSSZ,
0x370000000 => Tag::HEXAGON_SYMSZ,
0x370000001 => Tag::HEXAGON_VER,
0x370000002 => Tag::HEXAGON_PLT,
0x470000000 => Tag::PPC_GOT,
0x470000001 => Tag::PPC_OPT,
0x570000000 => Tag::PPC64_GLINK,
0x570000003 => Tag::PPC64_OPT,
0x670000003 => Tag::RISCV_VARIANT_CC,
_ => Tag::UNKNOWN(value),
}
}
}
#[derive(Debug)]
pub enum Entries<'a> {
Generic(Generic<'a>),
Library(Library<'a>),
Array(Array<'a>),
Rpath(Rpath<'a>),
RunPath(RunPath<'a>),
SharedObject(SharedObject<'a>),
}
pub trait DynamicEntry {
#[doc(hidden)]
fn as_base(&self) -> &ffi::ELF_DynamicEntry;
fn tag(&self) -> Tag {
Tag::from_value(self.as_base().tag())
}
fn value(&self) -> u64 {
self.as_base().value()
}
}
impl FromFFI<ffi::ELF_DynamicEntry> for Entries<'_> {
fn from_ffi(ffi_entry: cxx::UniquePtr<ffi::ELF_DynamicEntry>) -> Self {
unsafe {
let cmd_ref = ffi_entry.as_ref().unwrap();
if ffi::ELF_DynamicEntryLibrary::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::ELF_DynamicEntry>;
type To = cxx::UniquePtr<ffi::ELF_DynamicEntryLibrary>;
std::mem::transmute::<From, To>(ffi_entry)
};
Entries::Library(Library::from_ffi(raw))
}
else if ffi::ELF_DynamicEntryArray::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::ELF_DynamicEntry>;
type To = cxx::UniquePtr<ffi::ELF_DynamicEntryArray>;
std::mem::transmute::<From, To>(ffi_entry)
};
Entries::Array(Array::from_ffi(raw))
}
else if ffi::ELF_DynamicEntryRpath::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::ELF_DynamicEntry>;
type To = cxx::UniquePtr<ffi::ELF_DynamicEntryRpath>;
std::mem::transmute::<From, To>(ffi_entry)
};
Entries::Rpath(Rpath::from_ffi(raw))
}
else if ffi::ELF_DynamicEntryRunPath::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::ELF_DynamicEntry>;
type To = cxx::UniquePtr<ffi::ELF_DynamicEntryRunPath>;
std::mem::transmute::<From, To>(ffi_entry)
};
Entries::RunPath(RunPath::from_ffi(raw))
}
else if ffi::ELF_DynamicSharedObject::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::ELF_DynamicEntry>;
type To = cxx::UniquePtr<ffi::ELF_DynamicSharedObject>;
std::mem::transmute::<From, To>(ffi_entry)
};
Entries::SharedObject(SharedObject::from_ffi(raw))
}
else {
Entries::Generic(Generic::from_ffi(ffi_entry))
}
}
}
}
pub struct Generic<'a> {
ptr: cxx::UniquePtr<ffi::ELF_DynamicEntry>,
_owner: PhantomData<&'a ffi::ELF_Binary>
}
impl FromFFI<ffi::ELF_DynamicEntry> for Generic<'_> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_DynamicEntry>) -> Self {
Self {
ptr,
_owner: PhantomData
}
}
}
impl DynamicEntry for Generic<'_> {
fn as_base(&self) -> &ffi::ELF_DynamicEntry {
self.ptr.as_ref().unwrap()
}
}
impl std::fmt::Debug for Generic<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Generic").finish()
}
}
pub struct Library<'a> {
ptr: cxx::UniquePtr<ffi::ELF_DynamicEntryLibrary>,
_owner: PhantomData<&'a ffi::ELF_Binary>
}
impl Library<'_> {
pub fn name(&self) -> String {
self.ptr.name().to_string()
}
}
impl FromFFI<ffi::ELF_DynamicEntryLibrary> for Library<'_> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_DynamicEntryLibrary>) -> Self {
Self {
ptr,
_owner: PhantomData
}
}
}
impl DynamicEntry for Library<'_> {
fn as_base(&self) -> &ffi::ELF_DynamicEntry {
self.ptr.as_ref().unwrap().as_ref()
}
}
impl std::fmt::Debug for Library<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Library").finish()
}
}
pub struct Array<'a> {
ptr: cxx::UniquePtr<ffi::ELF_DynamicEntryArray>,
_owner: PhantomData<&'a ffi::ELF_Binary>
}
impl Array<'_> {
pub fn array(&self) -> Vec<u64> {
Vec::from(self.ptr.array().as_slice())
}
}
impl FromFFI<ffi::ELF_DynamicEntryArray> for Array<'_> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_DynamicEntryArray>) -> Self {
Self {
ptr,
_owner: PhantomData
}
}
}
impl DynamicEntry for Array<'_> {
fn as_base(&self) -> &ffi::ELF_DynamicEntry {
self.ptr.as_ref().unwrap().as_ref()
}
}
impl std::fmt::Debug for Array<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Array").finish()
}
}
pub struct Rpath<'a> {
ptr: cxx::UniquePtr<ffi::ELF_DynamicEntryRpath>,
_owner: PhantomData<&'a ffi::ELF_Binary>
}
impl Rpath<'_> {
pub fn rpath(&self) -> String {
self.ptr.rpath().to_string()
}
}
impl FromFFI<ffi::ELF_DynamicEntryRpath> for Rpath<'_> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_DynamicEntryRpath>) -> Self {
Self {
ptr,
_owner: PhantomData
}
}
}
impl DynamicEntry for Rpath<'_> {
fn as_base(&self) -> &ffi::ELF_DynamicEntry {
self.ptr.as_ref().unwrap().as_ref()
}
}
impl std::fmt::Debug for Rpath<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Rpath").finish()
}
}
pub struct RunPath<'a> {
ptr: cxx::UniquePtr<ffi::ELF_DynamicEntryRunPath>,
_owner: PhantomData<&'a ffi::ELF_Binary>
}
impl RunPath<'_> {
pub fn runpath(&self) -> String {
self.ptr.runpath().to_string()
}
}
impl FromFFI<ffi::ELF_DynamicEntryRunPath> for RunPath<'_> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_DynamicEntryRunPath>) -> Self {
Self {
ptr,
_owner: PhantomData
}
}
}
impl DynamicEntry for RunPath<'_> {
fn as_base(&self) -> &ffi::ELF_DynamicEntry {
self.ptr.as_ref().unwrap().as_ref()
}
}
impl std::fmt::Debug for RunPath<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("RunPath").finish()
}
}
pub struct SharedObject<'a> {
ptr: cxx::UniquePtr<ffi::ELF_DynamicSharedObject>,
_owner: PhantomData<&'a ffi::ELF_Binary>
}
impl SharedObject<'_> {
pub fn name(&self) -> String {
self.ptr.name().to_string()
}
}
impl FromFFI<ffi::ELF_DynamicSharedObject> for SharedObject<'_> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_DynamicSharedObject>) -> Self {
Self {
ptr,
_owner: PhantomData
}
}
}
impl DynamicEntry for SharedObject<'_> {
fn as_base(&self) -> &ffi::ELF_DynamicEntry {
self.ptr.as_ref().unwrap().as_ref()
}
}
impl std::fmt::Debug for SharedObject<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SharedObject").finish()
}
}
declare_iterator!(DynamicEntries, Entries<'a>, ffi::ELF_DynamicEntry, ffi::ELF_Binary, ffi::ELF_Binary_it_dynamic_entries);
+100
View File
@@ -0,0 +1,100 @@
use lief_ffi as ffi;
use std::fmt;
use crate::common::FromFFI;
use std::marker::PhantomData;
pub struct Sysv<'a> {
ptr: cxx::UniquePtr<ffi::ELF_SysvHash>,
_owner: PhantomData<&'a ffi::ELF_Binary>
}
impl Sysv<'_> {
pub fn nbucket(&self) -> u32 {
self.ptr.nbucket()
}
pub fn nchain(&self) -> u32 {
self.ptr.nchain()
}
pub fn buckets(&self) -> Vec<u32> {
Vec::from(self.ptr.buckets().as_slice())
}
pub fn chains(&self) -> Vec<u32> {
Vec::from(self.ptr.chains().as_slice())
}
}
impl fmt::Debug for Sysv<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Sysv")
.field("nbucket", &self.nbucket())
.field("nchain", &self.nchain())
.field("buckets", &self.buckets())
.field("chains", &self.chains())
.finish()
}
}
impl FromFFI<ffi::ELF_SysvHash> for Sysv<'_> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_SysvHash>) -> Self {
Self {
ptr,
_owner: PhantomData
}
}
}
pub struct Gnu<'a> {
ptr: cxx::UniquePtr<ffi::ELF_GnuHash>,
_owner: PhantomData<&'a ffi::ELF_Binary>
}
impl Gnu<'_> {
pub fn nb_buckets(&self) -> u32 {
self.ptr.nb_buckets()
}
pub fn symbol_index(&self) -> u32 {
self.ptr.symbol_index()
}
pub fn shift2(&self) -> u32 {
self.ptr.shift2()
}
pub fn maskwords(&self) -> u32 {
self.ptr.maskwords()
}
pub fn bloom_filters(&self) -> Vec<u64> {
Vec::from(self.ptr.bloom_filters().as_slice())
}
pub fn buckets(&self) -> Vec<u32> {
Vec::from(self.ptr.buckets().as_slice())
}
pub fn hash_values(&self) -> Vec<u32> {
Vec::from(self.ptr.hash_values().as_slice())
}
}
impl fmt::Debug for Gnu<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("GnuHash")
.field("nb_buckets", &self.nb_buckets())
.field("symbol_index", &self.symbol_index())
.field("shift2", &self.shift2())
.field("maskwords", &self.maskwords())
.field("bloom_filters", &self.bloom_filters())
.field("buckets", &self.buckets())
.field("hash_values", &self.hash_values())
.finish()
}
}
impl FromFFI<ffi::ELF_GnuHash> for Gnu<'_> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_GnuHash>) -> Self {
Self {
ptr,
_owner: PhantomData
}
}
}
+252
View File
@@ -0,0 +1,252 @@
use lief_ffi as ffi;
use std::{fmt, marker::PhantomData};
use crate::common::FromFFI;
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum FileType {
NONE,
REL,
EXEC,
DYN,
CORE,
UNKNOWN(u32),
}
impl FileType {
pub fn from_value(value: u32) -> Self {
match value {
0x00000000 => FileType::NONE,
0x00000001 => FileType::REL,
0x00000002 => FileType::EXEC,
0x00000003 => FileType::DYN,
0x00000004 => FileType::CORE,
_ => FileType::UNKNOWN(value),
}
}
}
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Version {
NONE,
CURRENT,
UNKNOWN(u32),
}
impl Version {
pub fn from_value(value: u32) -> Self {
match value {
0x00000000 => Version::NONE,
0x00000001 => Version::CURRENT,
_ => Version::UNKNOWN(value),
}
}
}
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Class {
NONE,
ELF32,
ELF64,
UNKNOWN(u32),
}
impl Class {
pub fn from_value(value: u32) -> Self {
match value {
0x00000000 => Class::NONE,
0x00000001 => Class::ELF32,
0x00000002 => Class::ELF64,
_ => Class::UNKNOWN(value),
}
}
}
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum OsAbi {
SYSTEMV,
HPUX,
NETBSD,
GNU,
LINUX,
HURD,
SOLARIS,
AIX,
IRIX,
FREEBSD,
TRU64,
MODESTO,
OPENBSD,
OPENVMS,
NSK,
AROS,
FENIXOS,
CLOUDABI,
C6000_ELFABI,
AMDGPU_HSA,
C6000_LINUX,
ARM,
STANDALONE,
UNKNOWN(u32),
}
impl OsAbi {
pub fn from_value(value: u32) -> Self {
match value {
0x00000000 => OsAbi::SYSTEMV,
0x00000001 => OsAbi::HPUX,
0x00000002 => OsAbi::NETBSD,
0x00000003 => OsAbi::LINUX,
0x00000004 => OsAbi::HURD,
0x00000006 => OsAbi::SOLARIS,
0x00000007 => OsAbi::AIX,
0x00000008 => OsAbi::IRIX,
0x00000009 => OsAbi::FREEBSD,
0x0000000a => OsAbi::TRU64,
0x0000000b => OsAbi::MODESTO,
0x0000000c => OsAbi::OPENBSD,
0x0000000d => OsAbi::OPENVMS,
0x0000000e => OsAbi::NSK,
0x0000000f => OsAbi::AROS,
0x00000010 => OsAbi::FENIXOS,
0x00000011 => OsAbi::CLOUDABI,
/* 0x00000040 => OsAbi::C6000_ELFABI, */
0x00000040 => OsAbi::AMDGPU_HSA,
0x00000041 => OsAbi::C6000_LINUX,
0x00000061 => OsAbi::ARM,
0x000000ff => OsAbi::STANDALONE,
_ => OsAbi::UNKNOWN(value),
}
}
}
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum ElfData {
NONE,
LSB,
MSB,
UNKNOWN(u32),
}
impl ElfData {
pub fn from_value(value: u32) -> Self {
match value {
0x00000000 => ElfData::NONE,
0x00000001 => ElfData::LSB,
0x00000002 => ElfData::MSB,
_ => ElfData::UNKNOWN(value),
}
}
}
pub struct Header<'a> {
ptr: cxx::UniquePtr<ffi::ELF_Header>,
_owner: PhantomData<&'a ffi::ELF_Binary>
}
impl FromFFI<ffi::ELF_Header> for Header<'_> {
fn from_ffi(hdr: cxx::UniquePtr<ffi::ELF_Header>) -> Self {
Self {
ptr: hdr,
_owner: PhantomData
}
}
}
impl Header<'_> {
pub fn entrypoint(&self) -> u64 {
self.ptr.entrypoint()
}
pub fn file_type(&self) -> FileType {
FileType::from_value(self.ptr.file_type())
}
pub fn object_file_version(&self) -> Version {
Version::from_value(self.ptr.object_file_version())
}
pub fn identity_class(&self) -> Class {
Class::from_value(self.ptr.identity_class())
}
pub fn identity_data(&self) -> ElfData {
ElfData::from_value(self.ptr.identity_data())
}
pub fn identity_version(&self) -> Version {
Version::from_value(self.ptr.identity_version())
}
pub fn identity_os_abi(&self) -> OsAbi {
OsAbi::from_value(self.ptr.identity_os_abi())
}
pub fn machine_type(&self) -> u32 {
self.ptr.machine_type()
}
pub fn program_headers_offset(&self) -> u64 {
self.ptr.program_headers_offset()
}
pub fn section_headers_offset(&self) -> u64 {
self.ptr.section_headers_offset()
}
pub fn processor_flag(&self) -> u32 {
self.ptr.processor_flag()
}
pub fn header_size(&self) -> u32 {
self.ptr.header_size()
}
pub fn program_header_size(&self) -> u32 {
self.ptr.program_header_size()
}
pub fn numberof_segments(&self) -> u32 {
self.ptr.numberof_segments()
}
pub fn section_header_size(&self) -> u32 {
self.ptr.section_header_size()
}
pub fn numberof_sections(&self) -> u32 {
self.ptr.numberof_sections()
}
pub fn section_name_table_idx(&self) -> u32 {
self.ptr.section_name_table_idx()
}
}
impl fmt::Debug for Header<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Header")
.field("entrypoint", &self.entrypoint())
.field("object_file_version", &self.object_file_version())
.field("identity_class", &self.identity_class())
.field("identity_os_abi", &self.identity_os_abi())
.field("identity_data", &self.identity_data())
.field("identity_version", &self.identity_version())
.field("file_type", &self.file_type())
.field("machine_type", &self.machine_type())
.field("program_headers_offset", &self.program_headers_offset())
.field("section_headers_offset", &self.section_headers_offset())
.field("processor_flag", &self.processor_flag())
.field("header_size", &self.header_size())
.field("program_header_size", &self.program_header_size())
.field("numberof_segments", &self.numberof_segments())
.field("section_header_size", &self.section_header_size())
.field("numberof_sections", &self.numberof_sections())
.field("section_name_table_idx", &self.section_name_table_idx())
.finish()
}
}
+180
View File
@@ -0,0 +1,180 @@
use lief_ffi as ffi;
use std::marker::PhantomData;
use crate::common::FromFFI;
use crate::declare_iterator;
use crate::to_slice;
#[derive(Debug)]
pub enum Notes<'a> {
Generic(Generic<'a>)
}
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Type {
GNU_ABI_TAG,
GNU_HWCAP,
GNU_BUILD_ID,
GNU_GOLD_VERSION,
GNU_PROPERTY_TYPE_0,
GNU_BUILD_ATTRIBUTE_OPEN,
GNU_BUILD_ATTRIBUTE_FUNC,
CRASHPAD,
CORE_PRSTATUS,
CORE_FPREGSET,
CORE_PRPSINFO,
CORE_TASKSTRUCT,
CORE_AUXV,
CORE_PSTATUS,
CORE_FPREGS,
CORE_PSINFO,
CORE_LWPSTATUS,
CORE_LWPSINFO,
CORE_WIN32PSTATUS,
CORE_FILE,
CORE_PRXFPREG,
CORE_SIGINFO,
CORE_ARM_VFP,
CORE_ARM_TLS,
CORE_ARM_HW_BREAK,
CORE_ARM_HW_WATCH,
CORE_ARM_SYSTEM_CALL,
CORE_ARM_SVE,
CORE_ARM_PAC_MASK,
CORE_ARM_PACA_KEYS,
CORE_ARM_PACG_KEYS,
CORE_TAGGED_ADDR_CTRL,
CORE_PAC_ENABLED_KEYS,
CORE_X86_TLS,
CORE_X86_IOPERM,
CORE_X86_XSTATE,
CORE_X86_CET,
ANDROID_IDENT,
ANDROID_MEMTAG,
ANDROID_KUSER,
GO_BUILDID,
STAPSDT,
UNKNOWN(u32),
}
impl Type {
pub fn from_value(value: u32) -> Self {
match value {
0x00000001 => Type::GNU_ABI_TAG,
0x00000002 => Type::GNU_HWCAP,
0x00000003 => Type::GNU_BUILD_ID,
0x00000004 => Type::GNU_GOLD_VERSION,
0x00000005 => Type::GNU_PROPERTY_TYPE_0,
0x00000006 => Type::GNU_BUILD_ATTRIBUTE_OPEN,
0x00000007 => Type::GNU_BUILD_ATTRIBUTE_FUNC,
0x00000008 => Type::CRASHPAD,
0x00000009 => Type::CORE_PRSTATUS,
0x0000000a => Type::CORE_FPREGSET,
0x0000000b => Type::CORE_PRPSINFO,
0x0000000c => Type::CORE_TASKSTRUCT,
0x0000000d => Type::CORE_AUXV,
0x0000000e => Type::CORE_PSTATUS,
0x0000000f => Type::CORE_FPREGS,
0x00000010 => Type::CORE_PSINFO,
0x00000011 => Type::CORE_LWPSTATUS,
0x00000012 => Type::CORE_LWPSINFO,
0x00000013 => Type::CORE_WIN32PSTATUS,
0x00000014 => Type::CORE_FILE,
0x00000015 => Type::CORE_PRXFPREG,
0x00000016 => Type::CORE_SIGINFO,
0x00000017 => Type::CORE_ARM_VFP,
0x00000018 => Type::CORE_ARM_TLS,
0x00000019 => Type::CORE_ARM_HW_BREAK,
0x0000001a => Type::CORE_ARM_HW_WATCH,
0x0000001b => Type::CORE_ARM_SYSTEM_CALL,
0x0000001c => Type::CORE_ARM_SVE,
0x0000001d => Type::CORE_ARM_PAC_MASK,
0x0000001e => Type::CORE_ARM_PACA_KEYS,
0x0000001f => Type::CORE_ARM_PACG_KEYS,
0x00000020 => Type::CORE_TAGGED_ADDR_CTRL,
0x00000021 => Type::CORE_PAC_ENABLED_KEYS,
0x00000022 => Type::CORE_X86_TLS,
0x00000023 => Type::CORE_X86_IOPERM,
0x00000024 => Type::CORE_X86_XSTATE,
0x00000025 => Type::CORE_X86_CET,
0x00000026 => Type::ANDROID_IDENT,
0x00000027 => Type::ANDROID_MEMTAG,
0x00000028 => Type::ANDROID_KUSER,
0x00000029 => Type::GO_BUILDID,
0x0000002a => Type::STAPSDT,
_ => Type::UNKNOWN(value),
}
}
}
pub trait NoteBase {
#[doc(hidden)]
fn get_base(&self) -> &ffi::ELF_Note;
fn name(&self) -> String {
self.get_base().name().to_string()
}
fn get_type(&self) -> Type {
Type::from_value(self.get_base().get_type())
}
fn original_type(&self) -> u32 {
self.get_base().original_type()
}
fn size(&self) -> u64 {
self.get_base().size()
}
fn description(&self) -> &[u8] {
to_slice!(self.get_base().description());
}
}
impl NoteBase for Generic<'_> {
fn get_base(&self) -> &ffi::ELF_Note {
self.ptr.as_ref().unwrap()
}
}
impl FromFFI<ffi::ELF_Note> for Notes<'_> {
fn from_ffi(entry: cxx::UniquePtr<ffi::ELF_Note>) -> Self {
Notes::Generic(Generic::from_ffi(entry))
}
}
pub struct Generic<'a> {
ptr: cxx::UniquePtr<ffi::ELF_Note>,
_owner: PhantomData<&'a ffi::ELF_Binary>
}
impl std::fmt::Debug for &dyn NoteBase {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("NoteBase")
.field("name", &self.name())
.field("type", &self.get_type())
.field("size", &self.size())
.finish()
}
}
impl std::fmt::Debug for Generic<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn NoteBase;
f.debug_struct("GenericNote")
.field("base", &base)
.finish()
}
}
impl FromFFI<ffi::ELF_Note> for Generic<'_> {
fn from_ffi(cmd: cxx::UniquePtr<ffi::ELF_Note>) -> Self {
Self {
ptr: cmd,
_owner: PhantomData
}
}
}
declare_iterator!(ItNotes, Notes<'a>, ffi::ELF_Note, ffi::ELF_Binary, ffi::ELF_Binary_it_notes);
File diff suppressed because it is too large Load Diff
+214
View File
@@ -0,0 +1,214 @@
use lief_ffi as ffi;
use std::fmt;
use std::marker::PhantomData;
use bitflags::bitflags;
use crate::to_slice;
use crate::generic;
use crate::common::FromFFI;
use crate::declare_iterator;
pub struct Section<'a> {
ptr: cxx::UniquePtr<ffi::ELF_Section>,
_owner: PhantomData<&'a ()>
}
impl Section<'_> {
pub fn get_type(&self) -> Type {
Type::from_value(self.ptr.get_type())
}
pub fn flags(&self) -> Flags {
Flags::from_value(self.ptr.flags())
}
pub fn alignment(&self) -> u64 {
self.ptr.alignment()
}
pub fn information(&self) -> u64 {
self.ptr.information()
}
pub fn entry_size(&self) -> u64 {
self.ptr.entry_size()
}
pub fn link(&self) -> u64 {
self.ptr.link()
}
pub fn file_offset(&self) -> u64 {
self.ptr.file_offset()
}
pub fn original_size(&self) -> u64 {
self.ptr.original_size()
}
pub fn content(&self) -> &[u8] {
to_slice!(self.ptr.content());
}
}
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Type {
SHT_NULL,
PROGBITS,
SYMTAB,
STRTAB,
RELA,
HASH,
DYNAMIC,
NOTE,
NOBITS,
REL,
SHLIB,
DYNSYM,
INIT_ARRAY,
FINI_ARRAY,
PREINIT_ARRAY,
GROUP,
SYMTAB_SHNDX,
RELR,
ANDROID_REL,
ANDROID_RELA,
LLVM_ADDRSIG,
ANDROID_RELR,
GNU_ATTRIBUTES,
GNU_HASH,
GNU_VERDEF,
GNU_VERNEED,
GNU_VERSYM,
ARM_EXIDX,
ARM_PREEMPTMAP,
ARM_ATTRIBUTES,
ARM_DEBUGOVERLAY,
ARM_OVERLAYSECTION,
HEX_ORDERED,
X86_64_UNWIND,
MIPS_REGINFO,
MIPS_OPTIONS,
MIPS_ABIFLAGS,
UNKNOWN(u64),
}
impl Type {
pub fn from_value(value: u64) -> Self {
match value {
0x00000000 => Type::SHT_NULL,
0x00000001 => Type::PROGBITS,
0x00000002 => Type::SYMTAB,
0x00000003 => Type::STRTAB,
0x00000004 => Type::RELA,
0x00000005 => Type::HASH,
0x00000006 => Type::DYNAMIC,
0x00000007 => Type::NOTE,
0x00000008 => Type::NOBITS,
0x00000009 => Type::REL,
0x0000000a => Type::SHLIB,
0x0000000b => Type::DYNSYM,
0x0000000e => Type::INIT_ARRAY,
0x0000000f => Type::FINI_ARRAY,
0x00000010 => Type::PREINIT_ARRAY,
0x00000011 => Type::GROUP,
0x00000012 => Type::SYMTAB_SHNDX,
0x00000013 => Type::RELR,
0x60000001 => Type::ANDROID_REL,
0x60000002 => Type::ANDROID_RELA,
0x6fff4c03 => Type::LLVM_ADDRSIG,
0x6fffff00 => Type::ANDROID_RELR,
0x6ffffff5 => Type::GNU_ATTRIBUTES,
0x6ffffff6 => Type::GNU_HASH,
0x6ffffffd => Type::GNU_VERDEF,
0x6ffffffe => Type::GNU_VERNEED,
0x6fffffff => Type::GNU_VERSYM,
0x170000001 => Type::ARM_EXIDX,
0x170000002 => Type::ARM_PREEMPTMAP,
0x170000003 => Type::ARM_ATTRIBUTES,
0x170000004 => Type::ARM_DEBUGOVERLAY,
0x170000005 => Type::ARM_OVERLAYSECTION,
0x270000000 => Type::HEX_ORDERED,
0x270000001 => Type::X86_64_UNWIND,
0x370000006 => Type::MIPS_REGINFO,
0x37000000d => Type::MIPS_OPTIONS,
0x37000002a => Type::MIPS_ABIFLAGS,
_ => Type::UNKNOWN(value),
}
}
}
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Flags: u64 {
const NONE = 0x0;
const WRITE = 0x1;
const ALLOC = 0x2;
const EXECINSTR = 0x4;
const MERGE = 0x10;
const STRINGS = 0x20;
const INFO_LINK = 0x40;
const LINK_ORDER = 0x80;
const OS_NONCONFORMING = 0x100;
const GROUP = 0x200;
const TLS = 0x400;
const COMPRESSED = 0x800;
const GNU_RETAIN = 0x200000;
const EXCLUDE = 0x80000000;
const XCORE_SHF_DP_SECTION = 0x110000000;
const XCORE_SHF_CP_SECTION = 0x120000000;
const X86_64_LARGE = 0x210000000;
const HEX_GPREL = 0x310000000;
const MIPS_NODUPES = 0x410000000;
const MIPS_NAMES = 0x420000000;
const MIPS_LOCAL = 0x440000000;
const MIPS_NOSTRIP = 0x480000000;
const MIPS_GPREL = 0x410000000;
const MIPS_MERGE = 0x420000000;
const MIPS_ADDR = 0x440000000;
const MIPS_STRING = 0x480000000;
const ARM_PURECODE = 0x520000000;
}
}
impl Flags {
pub fn from_value(value: u64) -> Self {
Flags::from_bits_truncate(value)
}
}
impl fmt::Debug for Section<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let base = self as &dyn generic::Section;
f.debug_struct("Section")
.field("base", &base)
.field("type", &self.get_type())
.field("flags", &self.flags())
.field("alignment", &self.alignment())
.field("information", &self.information())
.field("entry_size", &self.entry_size())
.field("link", &self.link())
.field("file_offset", &self.file_offset())
.field("original_size", &self.original_size())
.finish()
}
}
impl fmt::Display for Section<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.ptr.to_string())
}
}
impl FromFFI<ffi::ELF_Section> for Section<'_> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_Section>) -> Self {
Self {
ptr,
_owner: PhantomData
}
}
}
impl generic::Section for Section<'_> {
fn as_generic(&self) -> &ffi::AbstractSection {
self.ptr.as_ref().unwrap().as_ref()
}
}
declare_iterator!(Sections, Section<'a>, ffi::ELF_Section, ffi::ELF_Binary, ffi::ELF_Binary_it_sections);
+157
View File
@@ -0,0 +1,157 @@
use lief_ffi as ffi;
use bitflags::bitflags;
use std::fmt;
use std::marker::PhantomData;
use crate::common::FromFFI;
use crate::{declare_iterator, to_slice};
#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Type {
PT_NULL,
LOAD,
DYNAMIC,
INTERP,
NOTE,
SHLIB,
PHDR,
TLS,
GNU_EH_FRAME,
GNU_STACK,
GNU_PROPERTY,
GNU_RELRO,
ARM_ARCHEXT,
ARM_EXIDX,
ARM_UNWIND,
AARCH64_MEMTAG_MTE,
MIPS_REGINFO,
MIPS_RTPROC,
MIPS_OPTIONS,
MIPS_ABIFLAGS,
RISCV_ATTRIBUTES,
UNKNOWN(u64),
}
impl Type {
pub fn from_value(value: u64) -> Self {
match value {
0x00000000 => Type::PT_NULL,
0x00000001 => Type::LOAD,
0x00000002 => Type::DYNAMIC,
0x00000003 => Type::INTERP,
0x00000004 => Type::NOTE,
0x00000005 => Type::SHLIB,
0x00000006 => Type::PHDR,
0x00000007 => Type::TLS,
0x6474e550 => Type::GNU_EH_FRAME,
0x6474e551 => Type::GNU_STACK,
0x6474e553 => Type::GNU_PROPERTY,
0x6474e552 => Type::GNU_RELRO,
0x270000000 => Type::ARM_ARCHEXT,
0x270000001 => Type::ARM_EXIDX,
0x470000002 => Type::AARCH64_MEMTAG_MTE,
0x670000000 => Type::MIPS_REGINFO,
0x670000001 => Type::MIPS_RTPROC,
0x670000002 => Type::MIPS_OPTIONS,
0x670000003 => Type::MIPS_ABIFLAGS,
0x870000003 => Type::RISCV_ATTRIBUTES,
_ => Type::UNKNOWN(value),
}
}
}
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Flags: u32 {
const NONE = 0x0;
const X = 0x1;
const W = 0x2;
const R = 0x4;
}
}
impl Flags {
pub fn from_value(value: u32) -> Self {
Flags::from_bits_truncate(value)
}
}
pub struct Segment<'a> {
ptr: cxx::UniquePtr<ffi::ELF_Segment>,
_owner: PhantomData<&'a ffi::ELF_Binary>
}
impl fmt::Debug for Segment<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Segment")
.field("p_type", &self.p_type())
.field("flags", &self.flags())
.field("file_offset", &self.file_offset())
.field("virtual_address", &self.virtual_address())
.field("physical_address", &self.physical_address())
.field("physical_size", &self.physical_size())
.field("virtual_size", &self.virtual_size())
.field("alignment", &self.alignment())
.finish()
}
}
impl FromFFI<ffi::ELF_Segment> for Segment<'_> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_Segment>) -> Self {
Segment {
ptr,
_owner: PhantomData
}
}
}
impl<'a> Segment<'a> {
pub fn content(&self) -> &[u8] {
to_slice!(self.ptr.content());
}
pub fn p_type(&self) -> Type {
Type::from_value(self.ptr.stype())
}
pub fn flags(&self) -> u32 {
self.ptr.flags()
}
pub fn file_offset(&self) -> u64 {
self.ptr.file_offset()
}
pub fn virtual_address(&self) -> u64 {
self.ptr.virtual_address()
}
pub fn physical_address(&self) -> u64 {
self.ptr.physical_address()
}
pub fn physical_size(&self) -> u64 {
self.ptr.physical_size()
}
pub fn virtual_size(&self) -> u64 {
self.ptr.virtual_size()
}
pub fn alignment(&self) -> u64 {
self.ptr.alignment()
}
}
impl fmt::Display for Segment<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.ptr.to_string())
}
}
declare_iterator!(Segments, Segment<'a>, ffi::ELF_Segment, ffi::ELF_Binary, ffi::ELF_Binary_it_segments);
+163
View File
@@ -0,0 +1,163 @@
use lief_ffi as ffi;
use std::fmt;
use std::marker::PhantomData;
use crate::common::{FromFFI, into_optional};
use crate::declare_iterator;
use crate::generic;
use crate::elf::Section;
use super::SymbolVersion;
pub struct Symbol<'a> {
ptr: cxx::UniquePtr<ffi::ELF_Symbol>,
_owner: PhantomData<&'a ffi::ELF_Binary>
}
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Binding {
LOCAL,
GLOBAL,
WEAK,
GNU_UNIQUE,
UNKNOWN(u32),
}
impl Binding {
pub fn from_value(value: u32) -> Self {
match value {
0x00000000 => Binding::LOCAL,
0x00000001 => Binding::GLOBAL,
0x00000002 => Binding::WEAK,
0x0000000a => Binding::GNU_UNIQUE,
_ => Binding::UNKNOWN(value),
}
}
}
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Type {
NOTYPE,
OBJECT,
FUNC,
SECTION,
FILE,
COMMON,
TLS,
GNU_IFUNC,
UNKNOWN(u32),
}
impl Type {
pub fn from_value(value: u32) -> Self {
match value {
0x00000000 => Type::NOTYPE,
0x00000001 => Type::OBJECT,
0x00000002 => Type::FUNC,
0x00000003 => Type::SECTION,
0x00000004 => Type::FILE,
0x00000005 => Type::COMMON,
0x00000006 => Type::TLS,
0x0000000a => Type::GNU_IFUNC,
_ => Type::UNKNOWN(value),
}
}
}
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Visibility {
DEFAULT,
INTERNAL,
HIDDEN,
PROTECTED,
UNKNOWN(u32),
}
impl Visibility {
pub fn from_value(value: u32) -> Self {
match value {
0x00000000 => Visibility::DEFAULT,
0x00000001 => Visibility::INTERNAL,
0x00000002 => Visibility::HIDDEN,
0x00000003 => Visibility::PROTECTED,
_ => Visibility::UNKNOWN(value),
}
}
}
impl Symbol<'_> {
pub fn get_type(&self) -> Type {
Type::from_value(self.ptr.get_type())
}
pub fn binding(&self) -> Binding {
Binding::from_value(self.ptr.binding())
}
pub fn information(&self) -> u8 {
self.ptr.information()
}
pub fn other(&self) -> u8 {
self.ptr.other()
}
pub fn section_idx(&self) -> u16 {
self.ptr.section_idx()
}
pub fn visibility(&self) -> Visibility {
Visibility::from_value(self.ptr.visibility())
}
pub fn section(&self) -> Option<Section> {
into_optional(self.ptr.section())
}
pub fn symbol_version(&self) -> Option<SymbolVersion> {
into_optional(self.ptr.symbol_version())
}
}
impl fmt::Debug for Symbol<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let base = self as &dyn generic::Symbol;
f.debug_struct("Symbol")
.field("base", &base)
.field("type", &self.get_type())
.field("binding", &self.binding())
.field("information", &self.information())
.field("other", &self.other())
.field("section_idx", &self.section_idx())
.field("visibility", &self.visibility())
.field("section", &self.section())
.field("symbol_version", &self.symbol_version())
.finish()
}
}
impl FromFFI<ffi::ELF_Symbol> for Symbol<'_> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_Symbol>) -> Self {
Self {
ptr,
_owner: PhantomData
}
}
}
impl generic::Symbol for Symbol<'_> {
fn as_generic(&self) -> &ffi::AbstractSymbol {
self.ptr.as_ref().unwrap().as_ref()
}
}
impl fmt::Display for Symbol<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.ptr.to_string())
}
}
declare_iterator!(DynamicSymbols, Symbol<'a>, ffi::ELF_Symbol, ffi::ELF_Binary, ffi::ELF_Binary_it_dynamic_symbols);
declare_iterator!(ExportedSymbols, Symbol<'a>, ffi::ELF_Symbol, ffi::ELF_Binary, ffi::ELF_Binary_it_exported_symbols);
declare_iterator!(ImportedSymbols, Symbol<'a>, ffi::ELF_Symbol, ffi::ELF_Binary, ffi::ELF_Binary_it_imported_symbols);
declare_iterator!(SymtabSymbols, Symbol<'a>, ffi::ELF_Symbol, ffi::ELF_Binary, ffi::ELF_Binary_it_symtab_symbols);
@@ -0,0 +1,182 @@
use lief_ffi as ffi;
use std::fmt;
use std::marker::PhantomData;
use crate::common::{FromFFI, into_optional};
pub struct SymbolVersion<'a> {
ptr: cxx::UniquePtr<ffi::ELF_SymbolVersion>,
_owner: PhantomData<&'a ffi::ELF_Binary>
}
impl SymbolVersion<'_> {
pub fn value(&self) -> u16 {
self.ptr.value()
}
pub fn symbol_version_auxiliary(&self) -> Option<SymbolVersionAux> {
into_optional(self.ptr.symbol_version_auxiliary())
}
}
impl fmt::Debug for SymbolVersion<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SymbolVersion")
.field("value", &self.value())
.field("symbol_version_auxiliary", &self.symbol_version_auxiliary())
.finish()
}
}
impl FromFFI<ffi::ELF_SymbolVersion> for SymbolVersion<'_> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_SymbolVersion>) -> Self {
Self {
ptr,
_owner: PhantomData
}
}
}
pub struct SymbolVersionAux<'a> {
ptr: cxx::UniquePtr<ffi::ELF_SymbolVersionAux>,
_owner: PhantomData<&'a ()>
}
impl SymbolVersionAux<'_> {
pub fn name(&self) -> String {
self.ptr.name().to_string()
}
}
impl fmt::Debug for SymbolVersionAux<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SymbolVersionAux")
.field("name", &self.name())
.finish()
}
}
impl FromFFI<ffi::ELF_SymbolVersionAux> for SymbolVersionAux<'_> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_SymbolVersionAux>) -> Self {
Self {
ptr,
_owner: PhantomData
}
}
}
pub struct SymbolVersionAuxRequirement<'a> {
ptr: cxx::UniquePtr<ffi::ELF_SymbolVersionAuxRequirement>,
_owner: PhantomData<&'a ()>
}
impl SymbolVersionAuxRequirement<'_> {
pub fn hash(&self) -> u32 {
self.ptr.hash()
}
pub fn flags(&self) -> u16 {
self.ptr.flags()
}
pub fn other(&self) -> u16 {
self.ptr.other()
}
}
impl fmt::Debug for SymbolVersionAuxRequirement<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SymbolVersionAuxRequirement")
.field("hash", &self.hash())
.field("flags", &self.flags())
.field("other", &self.other())
.finish()
}
}
impl FromFFI<ffi::ELF_SymbolVersionAuxRequirement> for SymbolVersionAuxRequirement<'_> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_SymbolVersionAuxRequirement>) -> Self {
Self {
ptr,
_owner: PhantomData
}
}
}
pub struct SymbolVersionDefinition<'a> {
ptr: cxx::UniquePtr<ffi::ELF_SymbolVersionDefinition>,
_owner: PhantomData<&'a ()>
}
impl SymbolVersionDefinition<'_> {
pub fn version(&self) -> u16 {
self.ptr.version()
}
pub fn flags(&self) -> u16 {
self.ptr.flags()
}
pub fn ndx(&self) -> u16 {
self.ptr.ndx()
}
pub fn hash(&self) -> u32 {
self.ptr.hash()
}
}
impl fmt::Debug for SymbolVersionDefinition<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SymbolVersionDefinition")
.field("version", &self.version())
.field("flags", &self.flags())
.field("ndx", &self.ndx())
.field("hash", &self.hash())
.finish()
}
}
impl FromFFI<ffi::ELF_SymbolVersionDefinition> for SymbolVersionDefinition<'_> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_SymbolVersionDefinition>) -> Self {
Self {
ptr,
_owner: PhantomData
}
}
}
pub struct SymbolVersionRequirement<'a> {
ptr: cxx::UniquePtr<ffi::ELF_SymbolVersionRequirement>,
_owner: PhantomData<&'a ()>
}
impl SymbolVersionRequirement<'_> {
pub fn version(&self) -> u16 {
self.ptr.version()
}
pub fn cnt(&self) -> u32 {
self.ptr.cnt()
}
pub fn name(&self) -> String {
self.ptr.name().to_string()
}
}
impl fmt::Debug for SymbolVersionRequirement<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SymbolVersionRequirement")
.field("verison", &self.version())
.field("cnt", &self.cnt())
.field("name", &self.name())
.finish()
}
}
impl FromFFI<ffi::ELF_SymbolVersionRequirement> for SymbolVersionRequirement<'_> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_SymbolVersionRequirement>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
+95
View File
@@ -0,0 +1,95 @@
use crate::to_slice;
use lief_ffi as ffi;
pub trait Symbol {
#[doc(hidden)]
fn as_generic(&self) -> &ffi::AbstractSymbol;
fn name(&self) -> String {
self.as_generic().name().to_string()
}
fn value(&self) -> u64 {
self.as_generic().value()
}
fn size(&self) -> u64 {
self.as_generic().size()
}
}
impl std::fmt::Debug for &dyn Symbol {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Symbol")
.field("name", &self.name())
.field("value", &self.value())
.field("size", &self.size())
.finish()
}
}
pub trait Section {
#[doc(hidden)]
fn as_generic(&self) -> &ffi::AbstractSection;
fn name(&self) -> String {
self.as_generic().name().to_string()
}
fn size(&self) -> u64 {
self.as_generic().size()
}
fn offset(&self) -> u64 {
self.as_generic().offset()
}
fn virtual_address(&self) -> u64 {
self.as_generic().virtual_address()
}
fn content(&self) -> &[u8] {
to_slice!(self.as_generic().content());
}
}
impl std::fmt::Debug for &dyn Section {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Section")
.field("name", &self.name())
.field("size", &self.size())
.field("offset", &self.offset())
.field("virtual_address", &self.virtual_address())
.finish()
}
}
pub trait Relocation {
#[doc(hidden)]
fn as_generic(&self) -> &ffi::AbstractRelocation;
fn address(&self) -> u64 {
self.as_generic().address()
}
fn size(&self) -> u64 {
self.as_generic().size()
}
}
impl std::fmt::Debug for &dyn Relocation {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Relocation")
.field("address", &self.address())
.field("size", &self.size())
.finish()
}
}
pub trait Binary {
#[doc(hidden)]
fn as_generic(&self) -> &ffi::AbstractBinary;
fn entrypoint(&self) -> u64 {
self.as_generic().entrypoint()
}
fn imagebase(&self) -> u64 {
self.as_generic().imagebase()
}
fn is_pie(&self) -> bool {
self.as_generic().is_pie()
}
}
+63
View File
@@ -0,0 +1,63 @@
//! # LIEF
//!
//! ![LIEF Design](https://raw.githubusercontent.com/lief-project/LIEF/main/.github/images/architecture.png)
//!
//! This package provides Rust bindings for [LIEF](https://lief.re). It exposes most of the
//! LIEF API to **read** these formats:
//! - ELF
//! - PE
//! - Mach-O
//!
//! The bindings require at least Rust version **1.74.0** with the 2021 edition and support:
//! - Windows x86-64 (support `/MT` and `/MD` linking)
//! - Linux x86-64 (Ubuntu 20.04, Almalinux 9, Debian 11.5, Fedora 29)
//! - macOS (`x86-64` and `aarch64` with at least OSX Big Sur: 11.0)
//!
//! ## Getting Started
//!
//! ```toml
//! [package]
//! name = "my-awesome-project"
//! version = "0.0.1"
//! edition = "2021"
//!
//! [dependencies]
//! # For nightly
//! lief = { git = "https://github.com/lief-project/LIEF", branch = "main" }
//! # For releases
//! lief = 0.15.0
//! ```
//!
//! ```rust
//! fn main() {
//! let path = std::env::args().last().unwrap();
//! let mut file = std::fs::File::open(path).expect("Can't open the file");
//! match lief::Binary::from(&mut file) {
//! Some(lief::Binary::ELF(elf)) => {
//! // Process ELF file
//! },
//! Some(lief::Binary::PE(pe)) => {
//! // Process PE file
//! },
//! Some(lief::Binary::MachO(macho)) => {
//! // Process Mach-O file (including FatMachO)
//! },
//! None => {
//! // Parsing error
//! }
//! }
//! return;
//! }
//! ```
#![doc(html_no_source)]
pub mod elf;
pub mod generic;
pub mod macho;
pub mod pe;
mod binary;
mod common;
#[doc(inline)]
pub use binary::Binary;
+23
View File
@@ -0,0 +1,23 @@
pub mod binary;
pub mod binding_info;
pub mod commands;
pub mod export_info;
pub mod fat_binary;
pub mod relocation;
pub mod section;
pub mod symbol;
#[doc(inline)]
pub use binary::Binary;
#[doc(inline)]
pub use binding_info::BindingInfo;
#[doc(inline)]
pub use export_info::ExportInfo;
#[doc(inline)]
pub use fat_binary::FatBinary;
#[doc(inline)]
pub use relocation::Relocation;
#[doc(inline)]
pub use section::Section;
#[doc(inline)]
pub use symbol::Symbol;
+173
View File
@@ -0,0 +1,173 @@
use super::commands::build_version::BuildVersion;
use super::commands::code_signature::CodeSignature;
use super::commands::code_signature_dir::CodeSignatureDir;
use super::commands::data_in_code::DataInCode;
use super::commands::dyld_chained_fixups::DyldChainedFixups;
use super::commands::dyld_environment::DyldEnvironment;
use super::commands::dyld_export_trie::DyldExportsTrie;
use super::commands::dyldinfo::DyldInfo;
use super::commands::dylib::Libraries;
use super::commands::dylinker::Dylinker;
use super::commands::dynamic_symbol_command::DynamicSymbolCommand;
use super::commands::encryption_info::EncryptionInfo;
use super::commands::functionstarts::FunctionStarts;
use super::commands::linker_opt_hint::LinkerOptHint;
use super::commands::main_cmd::Main;
use super::commands::rpath::RPath;
use super::commands::segment::Segments;
use super::commands::segment_split_info::SegmentSplitInfo;
use super::commands::source_version::SourceVersion;
use super::commands::sub_framework::SubFramework;
use super::commands::symbol_command::SymbolCommand;
use super::commands::thread_command::ThreadCommand;
use super::commands::two_level_hints::TwoLevelHints;
use super::commands::uuid::UUID;
use super::commands::version_min::VersionMin;
use super::commands::CommandsIter;
use super::relocation::Relocations;
use super::section::Sections;
use super::symbol::Symbols;
use lief_ffi as ffi;
use crate::common::{into_optional, FromFFI};
use crate::generic;
pub struct Binary {
ptr: cxx::UniquePtr<ffi::MachO_Binary>,
}
impl std::fmt::Debug for Binary {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Binary").finish()
}
}
impl FromFFI<ffi::MachO_Binary> for Binary {
fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_Binary>) -> Self {
Binary { ptr }
}
}
impl Binary {
pub fn commands(&self) -> CommandsIter {
CommandsIter::new(self.ptr.commands())
}
pub fn sections(&self) -> Sections {
Sections::new(self.ptr.sections())
}
pub fn segments(&self) -> Segments {
Segments::new(self.ptr.segments())
}
pub fn libraries(&self) -> Libraries {
Libraries::new(self.ptr.libraries())
}
pub fn relocations(&self) -> Relocations {
Relocations::new(self.ptr.relocations())
}
pub fn symbols(&self) -> Symbols {
Symbols::new(self.ptr.symbols())
}
pub fn dyld_info(&self) -> Option<DyldInfo> {
into_optional(self.ptr.dyld_info())
}
pub fn uuid(&self) -> Option<UUID> {
into_optional(self.ptr.uuid())
}
pub fn main_command(&self) -> Option<Main> {
into_optional(self.ptr.main_command())
}
pub fn dylinker(&self) -> Option<Dylinker> {
into_optional(self.ptr.dylinker())
}
pub fn function_starts(&self) -> Option<FunctionStarts> {
into_optional(self.ptr.function_starts())
}
pub fn source_version(&self) -> Option<SourceVersion> {
into_optional(self.ptr.source_version())
}
pub fn thread_command(&self) -> Option<ThreadCommand> {
into_optional(self.ptr.thread_command())
}
pub fn rpath(&self) -> Option<RPath> {
into_optional(self.ptr.rpath())
}
pub fn symbol_command(&self) -> Option<SymbolCommand> {
into_optional(self.ptr.symbol_command())
}
pub fn dynamic_symbol(&self) -> Option<DynamicSymbolCommand> {
into_optional(self.ptr.dynamic_symbol_command())
}
pub fn code_signature(&self) -> Option<CodeSignature> {
into_optional(self.ptr.code_signature())
}
pub fn code_signature_dir(&self) -> Option<CodeSignatureDir> {
into_optional(self.ptr.code_signature_dir())
}
pub fn data_in_code(&self) -> Option<DataInCode> {
into_optional(self.ptr.data_in_code())
}
pub fn segment_split_info(&self) -> Option<SegmentSplitInfo> {
into_optional(self.ptr.segment_split_info())
}
pub fn encryption_info(&self) -> Option<EncryptionInfo> {
into_optional(self.ptr.encryption_info())
}
pub fn sub_framework(&self) -> Option<SubFramework> {
into_optional(self.ptr.sub_framework())
}
pub fn dyld_environment(&self) -> Option<DyldEnvironment> {
into_optional(self.ptr.dyld_environment())
}
pub fn build_version(&self) -> Option<BuildVersion> {
into_optional(self.ptr.build_version())
}
pub fn dyld_chained_fixups(&self) -> Option<DyldChainedFixups> {
into_optional(self.ptr.dyld_chained_fixups())
}
pub fn dyld_exports_trie(&self) -> Option<DyldExportsTrie> {
into_optional(self.ptr.dyld_exports_trie())
}
pub fn two_level_hints(&self) -> Option<TwoLevelHints> {
into_optional(self.ptr.two_level_hints())
}
pub fn linker_opt_hint(&self) -> Option<LinkerOptHint> {
into_optional(self.ptr.linker_opt_hint())
}
pub fn version_min(&self) -> Option<VersionMin> {
into_optional(self.ptr.version_min())
}
}
impl generic::Binary for Binary {
fn as_generic(&self) -> &ffi::AbstractBinary {
self.ptr.as_ref().unwrap().as_ref()
}
}
@@ -0,0 +1,266 @@
use lief_ffi as ffi;
use super::commands::dylib::Dylib;
use super::commands::Segment;
use super::symbol::Symbol;
use std::{fmt, marker::PhantomData};
use crate::common::{into_optional, FromFFI};
#[derive(Debug)]
pub enum BindingInfo<'a> {
Generic(Generic<'a>),
Dyld(Dyld<'a>),
Chained(Chained<'a>),
}
pub trait AsGeneric {
#[doc(hidden)]
fn as_generic(&self) -> &ffi::MachO_BindingInfo;
fn library(&self) -> Option<Dylib> {
into_optional(self.as_generic().library())
}
fn symbol(&self) -> Option<Symbol> {
into_optional(self.as_generic().symbol())
}
fn segment(&self) -> Option<Segment> {
into_optional(self.as_generic().segment())
}
fn address(&self) -> u64 {
self.as_generic().address()
}
fn addend(&self) -> i64 {
self.as_generic().addend()
}
fn library_ordinal(&self) -> i32 {
self.as_generic().library_ordinal()
}
}
impl std::fmt::Debug for &dyn AsGeneric {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("AsGeneric")
.field("address", &self.address())
.field("addend", &self.addend())
.field("library_ordinal", &self.library_ordinal())
.finish()
}
}
impl<'a> FromFFI<ffi::MachO_BindingInfo> for BindingInfo<'a> {
fn from_ffi(ffi_entry: cxx::UniquePtr<ffi::MachO_BindingInfo>) -> Self {
unsafe {
let cmd_ref = ffi_entry.as_ref().unwrap();
if ffi::MachO_ChainedBindingInfo::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::MachO_BindingInfo>;
type To = cxx::UniquePtr<ffi::MachO_ChainedBindingInfo>;
std::mem::transmute::<From, To>(ffi_entry)
};
BindingInfo::Chained(Chained::from_ffi(raw))
} else if ffi::MachO_DyldBindingInfo::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::MachO_BindingInfo>;
type To = cxx::UniquePtr<ffi::MachO_DyldBindingInfo>;
std::mem::transmute::<From, To>(ffi_entry)
};
BindingInfo::Dyld(Dyld::from_ffi(raw))
} else {
BindingInfo::Generic(Generic::from_ffi(ffi_entry))
}
}
}
}
pub struct Generic<'a> {
ptr: cxx::UniquePtr<ffi::MachO_BindingInfo>,
_owner: PhantomData<&'a ()>,
}
impl fmt::Debug for Generic<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let base = self as &dyn AsGeneric;
f.debug_struct("Generic").field("base", &base).finish()
}
}
impl<'a> FromFFI<ffi::MachO_BindingInfo> for Generic<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_BindingInfo>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
impl AsGeneric for Generic<'_> {
fn as_generic(&self) -> &ffi::MachO_BindingInfo {
self.ptr.as_ref().unwrap()
}
}
pub struct Dyld<'a> {
ptr: cxx::UniquePtr<ffi::MachO_DyldBindingInfo>,
_owner: PhantomData<&'a ()>,
}
#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum BINDING_CLASS {
WEAK,
LAZY,
STANDARD,
THREADED,
UNKNOWN(u64),
}
impl BINDING_CLASS {
pub fn from_value(value: u64) -> Self {
match value {
0x00000001 => BINDING_CLASS::WEAK,
0x00000002 => BINDING_CLASS::LAZY,
0x00000003 => BINDING_CLASS::STANDARD,
0x00000064 => BINDING_CLASS::THREADED,
_ => BINDING_CLASS::UNKNOWN(value),
}
}
}
#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum BIND_TYPES {
POINTER,
TEXT_ABSOLUTE32,
TEXT_PCREL32,
UNKNOWN(u64),
}
impl BIND_TYPES {
pub fn from_value(value: u64) -> Self {
match value {
0x00000001 => BIND_TYPES::POINTER,
0x00000002 => BIND_TYPES::TEXT_ABSOLUTE32,
0x00000003 => BIND_TYPES::TEXT_PCREL32,
_ => BIND_TYPES::UNKNOWN(value),
}
}
}
impl Dyld<'_> {
pub fn binding_class(&self) -> BINDING_CLASS {
BINDING_CLASS::from_value(self.ptr.binding_class())
}
pub fn binding_type(&self) -> BIND_TYPES {
BIND_TYPES::from_value(self.ptr.binding_type())
}
pub fn is_non_weak_definition(&self) -> bool {
self.ptr.is_non_weak_definition()
}
pub fn original_offset(&self) -> u64 {
self.ptr.original_offset()
}
}
impl fmt::Debug for Dyld<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let base = self as &dyn AsGeneric;
f.debug_struct("Dyld")
.field("base", &base)
.field("binding_class", &self.binding_class())
.field("binding_type", &self.binding_type())
.field("is_non_weak_definition", &self.is_non_weak_definition())
.field("original_offset", &self.original_offset())
.finish()
}
}
impl FromFFI<ffi::MachO_DyldBindingInfo> for Dyld<'_> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_DyldBindingInfo>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
impl AsGeneric for Dyld<'_> {
fn as_generic(&self) -> &ffi::MachO_BindingInfo {
self.ptr.as_ref().unwrap().as_ref()
}
}
pub struct Chained<'a> {
ptr: cxx::UniquePtr<ffi::MachO_ChainedBindingInfo>,
_owner: PhantomData<&'a ()>,
}
#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum CHAINED_FORMAT {
IMPORT,
IMPORT_ADDEND,
IMPORT_ADDEND64,
UNKNOWN(u32),
}
impl CHAINED_FORMAT {
pub fn from_value(value: u32) -> Self {
match value {
0x00000001 => CHAINED_FORMAT::IMPORT,
0x00000002 => CHAINED_FORMAT::IMPORT_ADDEND,
0x00000003 => CHAINED_FORMAT::IMPORT_ADDEND64,
_ => CHAINED_FORMAT::UNKNOWN(value),
}
}
}
impl Chained<'_> {
pub fn format(&self) -> CHAINED_FORMAT {
CHAINED_FORMAT::from_value(self.ptr.format())
}
pub fn ptr_format(&self) -> u32 {
self.ptr.ptr_format()
}
pub fn offset(&self) -> u32 {
self.ptr.offset()
}
}
impl fmt::Debug for Chained<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let base = self as &dyn AsGeneric;
f.debug_struct("Chained")
.field("base", &base)
.field("format", &self.format())
.field("ptr_format", &self.ptr_format())
.field("offset", &self.offset())
.finish()
}
}
impl FromFFI<ffi::MachO_ChainedBindingInfo> for Chained<'_> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_ChainedBindingInfo>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
impl AsGeneric for Chained<'_> {
fn as_generic(&self) -> &ffi::MachO_BindingInfo {
self.ptr.as_ref().unwrap().as_ref()
}
}
+517
View File
@@ -0,0 +1,517 @@
use std::marker::PhantomData;
use lief_ffi as ffi;
pub mod build_version;
pub mod code_signature;
pub mod code_signature_dir;
pub mod data_in_code;
pub mod dyld_chained_fixups;
pub mod dyld_environment;
pub mod dyld_export_trie;
pub mod dyldinfo;
pub mod dylib;
pub mod dylinker;
pub mod dynamic_symbol_command;
pub mod encryption_info;
pub mod functionstarts;
pub mod linker_opt_hint;
pub mod main_cmd;
pub mod rpath;
pub mod segment;
pub mod segment_split_info;
pub mod source_version;
pub mod sub_framework;
pub mod symbol_command;
pub mod thread_command;
pub mod two_level_hints;
pub mod uuid;
pub mod version_min;
pub use build_version::BuildVersion;
pub use code_signature::CodeSignature;
pub use code_signature_dir::CodeSignatureDir;
pub use data_in_code::DataInCode;
pub use dyld_chained_fixups::DyldChainedFixups;
pub use dyld_environment::DyldEnvironment;
pub use dyld_export_trie::DyldExportsTrie;
pub use dyldinfo::DyldInfo;
pub use dylib::{Dylib, Libraries};
pub use dylinker::Dylinker;
pub use dynamic_symbol_command::DynamicSymbolCommand;
pub use encryption_info::EncryptionInfo;
pub use functionstarts::FunctionStarts;
pub use linker_opt_hint::LinkerOptHint;
pub use main_cmd::Main;
pub use rpath::RPath;
pub use segment::Segment;
pub use segment_split_info::SegmentSplitInfo;
pub use source_version::SourceVersion;
pub use sub_framework::SubFramework;
pub use symbol_command::SymbolCommand;
pub use thread_command::ThreadCommand;
pub use two_level_hints::TwoLevelHints;
pub use uuid::UUID;
pub use version_min::VersionMin;
use crate::common::FromFFI;
use crate::{declare_iterator, to_slice};
#[derive(Debug, Copy, Clone)]
pub enum LoadCommandTypes {
BuildVersion,
CodeSignature,
DataInCode,
DyldChainedFixups,
DyldEnvironment,
DyldExportsTrie,
DyldInfo,
DyldInfoOnly,
DylibCodeSignDrs,
Dysymtab,
EncryptionInfo,
EncryptionInfo64,
FilesetEntry,
FunctionStarts,
Fvmfile,
Ident,
Idfvmlib,
IdDylib,
IdDylinker,
LazyLoadDylib,
LinkerOptimizationHint,
LinkerOption,
LoadFvmLib,
LoadDylib,
LoadDylinker,
LoadUpwardDylib,
LoadWeakDylib,
Main,
Note,
PrebindCksum,
PreboundDylib,
Prepage,
ReExportDylib,
Routines,
Routines64,
Rpath,
Segment,
Segment64,
SegmentSplitInfo,
SourceVersion,
SubClient,
SubFramework,
SubLibrary,
SubUmbrella,
Symseg,
Symtab,
Thread,
TwoLevelHints,
Unixthread,
Uuid,
VersionMinIphoneOS,
VersionMinMacOSX,
VersionMinTvOS,
VersionMinWatchOS,
Unknown(u64),
}
impl LoadCommandTypes {
const LC_BUILD_VERSION: u64 = 0x00000032;
const LC_CODE_SIGNATURE: u64 = 0x0000001D;
const LC_DATA_IN_CODE: u64 = 0x00000029;
const LC_DYLD_CHAINED_FIXUPS: u64 = 0x80000034;
const LC_DYLD_ENVIRONMENT: u64 = 0x00000027;
const LC_DYLD_EXPORTS_TRIE: u64 = 0x80000033;
const LC_DYLD_INFO: u64 = 0x00000022;
const LC_DYLD_INFO_ONLY: u64 = 0x80000022;
const LC_DYLIB_CODE_SIGN_DRS: u64 = 0x0000002B;
const LC_DYSYMTAB: u64 = 0x0000000B;
const LC_ENCRYPTION_INFO: u64 = 0x00000021;
const LC_ENCRYPTION_INFO_64: u64 = 0x0000002C;
const LC_FILESET_ENTRY: u64 = 0x80000035;
const LC_FUNCTION_STARTS: u64 = 0x00000026;
const LC_FVMFILE: u64 = 0x00000009;
const LC_IDENT: u64 = 0x00000008;
const LC_IDFVMLIB: u64 = 0x00000007;
const LC_ID_DYLIB: u64 = 0x0000000D;
const LC_ID_DYLINKER: u64 = 0x0000000F;
const LC_LAZY_LOAD_DYLIB: u64 = 0x00000020;
const LC_LINKER_OPTIMIZATION_HINT: u64 = 0x0000002E;
const LC_LINKER_OPTION: u64 = 0x0000002D;
const LC_LOADFVMLIB: u64 = 0x00000006;
const LC_LOAD_DYLIB: u64 = 0x0000000C;
const LC_LOAD_DYLINKER: u64 = 0x0000000E;
const LC_LOAD_UPWARD_DYLIB: u64 = 0x80000023;
const LC_LOAD_WEAK_DYLIB: u64 = 0x80000018;
const LC_MAIN: u64 = 0x80000028;
const LC_NOTE: u64 = 0x00000031;
const LC_PREBIND_CKSUM: u64 = 0x00000017;
const LC_PREBOUND_DYLIB: u64 = 0x00000010;
const LC_PREPAGE: u64 = 0x0000000A;
const LC_REEXPORT_DYLIB: u64 = 0x8000001F;
const LC_ROUTINES: u64 = 0x00000011;
const LC_ROUTINES_64: u64 = 0x0000001A;
const LC_RPATH: u64 = 0x8000001C;
const LC_SEGMENT: u64 = 0x00000001;
const LC_SEGMENT_64: u64 = 0x00000019;
const LC_SEGMENT_SPLIT_INFO: u64 = 0x0000001E;
const LC_SOURCE_VERSION: u64 = 0x0000002A;
const LC_SUB_CLIENT: u64 = 0x00000014;
const LC_SUB_FRAMEWORK: u64 = 0x00000012;
const LC_SUB_LIBRARY: u64 = 0x00000015;
const LC_SUB_UMBRELLA: u64 = 0x00000013;
const LC_SYMSEG: u64 = 0x00000003;
const LC_SYMTAB: u64 = 0x00000002;
const LC_THREAD: u64 = 0x00000004;
const LC_TWOLEVEL_HINTS: u64 = 0x00000016;
const LC_UNIXTHREAD: u64 = 0x00000005;
const LC_UUID: u64 = 0x0000001B;
const LC_VERSION_MIN_IPHONEOS: u64 = 0x00000025;
const LC_VERSION_MIN_MACOSX: u64 = 0x00000024;
const LC_VERSION_MIN_TVOS: u64 = 0x0000002F;
const LC_VERSION_MIN_WATCHOS: u64 = 0x00000030;
pub fn from_value(value: u64) -> Self {
match value {
LoadCommandTypes::LC_BUILD_VERSION => LoadCommandTypes::BuildVersion,
LoadCommandTypes::LC_CODE_SIGNATURE => LoadCommandTypes::CodeSignature,
LoadCommandTypes::LC_DATA_IN_CODE => LoadCommandTypes::DataInCode,
LoadCommandTypes::LC_DYLD_CHAINED_FIXUPS => LoadCommandTypes::DyldChainedFixups,
LoadCommandTypes::LC_DYLD_ENVIRONMENT => LoadCommandTypes::DyldEnvironment,
LoadCommandTypes::LC_DYLD_EXPORTS_TRIE => LoadCommandTypes::DyldExportsTrie,
LoadCommandTypes::LC_DYLD_INFO => LoadCommandTypes::DyldInfo,
LoadCommandTypes::LC_DYLD_INFO_ONLY => LoadCommandTypes::DyldInfoOnly,
LoadCommandTypes::LC_DYLIB_CODE_SIGN_DRS => LoadCommandTypes::DylibCodeSignDrs,
LoadCommandTypes::LC_DYSYMTAB => LoadCommandTypes::Dysymtab,
LoadCommandTypes::LC_ENCRYPTION_INFO => LoadCommandTypes::EncryptionInfo,
LoadCommandTypes::LC_ENCRYPTION_INFO_64 => LoadCommandTypes::EncryptionInfo64,
LoadCommandTypes::LC_FILESET_ENTRY => LoadCommandTypes::FilesetEntry,
LoadCommandTypes::LC_FUNCTION_STARTS => LoadCommandTypes::FunctionStarts,
LoadCommandTypes::LC_FVMFILE => LoadCommandTypes::Fvmfile,
LoadCommandTypes::LC_IDENT => LoadCommandTypes::Ident,
LoadCommandTypes::LC_IDFVMLIB => LoadCommandTypes::Idfvmlib,
LoadCommandTypes::LC_ID_DYLIB => LoadCommandTypes::IdDylib,
LoadCommandTypes::LC_ID_DYLINKER => LoadCommandTypes::IdDylinker,
LoadCommandTypes::LC_LAZY_LOAD_DYLIB => LoadCommandTypes::LazyLoadDylib,
LoadCommandTypes::LC_LINKER_OPTIMIZATION_HINT => {
LoadCommandTypes::LinkerOptimizationHint
}
LoadCommandTypes::LC_LINKER_OPTION => LoadCommandTypes::LinkerOption,
LoadCommandTypes::LC_LOADFVMLIB => LoadCommandTypes::LoadFvmLib,
LoadCommandTypes::LC_LOAD_DYLIB => LoadCommandTypes::LoadDylib,
LoadCommandTypes::LC_LOAD_DYLINKER => LoadCommandTypes::LoadDylinker,
LoadCommandTypes::LC_LOAD_UPWARD_DYLIB => LoadCommandTypes::LoadUpwardDylib,
LoadCommandTypes::LC_LOAD_WEAK_DYLIB => LoadCommandTypes::LoadWeakDylib,
LoadCommandTypes::LC_MAIN => LoadCommandTypes::Main,
LoadCommandTypes::LC_NOTE => LoadCommandTypes::Note,
LoadCommandTypes::LC_PREBIND_CKSUM => LoadCommandTypes::PrebindCksum,
LoadCommandTypes::LC_PREBOUND_DYLIB => LoadCommandTypes::PreboundDylib,
LoadCommandTypes::LC_PREPAGE => LoadCommandTypes::Prepage,
LoadCommandTypes::LC_REEXPORT_DYLIB => LoadCommandTypes::ReExportDylib,
LoadCommandTypes::LC_ROUTINES => LoadCommandTypes::Routines,
LoadCommandTypes::LC_ROUTINES_64 => LoadCommandTypes::Routines64,
LoadCommandTypes::LC_RPATH => LoadCommandTypes::Rpath,
LoadCommandTypes::LC_SEGMENT => LoadCommandTypes::Segment,
LoadCommandTypes::LC_SEGMENT_64 => LoadCommandTypes::Segment64,
LoadCommandTypes::LC_SEGMENT_SPLIT_INFO => LoadCommandTypes::SegmentSplitInfo,
LoadCommandTypes::LC_SOURCE_VERSION => LoadCommandTypes::SourceVersion,
LoadCommandTypes::LC_SUB_CLIENT => LoadCommandTypes::SubClient,
LoadCommandTypes::LC_SUB_FRAMEWORK => LoadCommandTypes::SubFramework,
LoadCommandTypes::LC_SUB_LIBRARY => LoadCommandTypes::SubLibrary,
LoadCommandTypes::LC_SUB_UMBRELLA => LoadCommandTypes::SubUmbrella,
LoadCommandTypes::LC_SYMSEG => LoadCommandTypes::Symseg,
LoadCommandTypes::LC_SYMTAB => LoadCommandTypes::Symtab,
LoadCommandTypes::LC_THREAD => LoadCommandTypes::Thread,
LoadCommandTypes::LC_TWOLEVEL_HINTS => LoadCommandTypes::TwoLevelHints,
LoadCommandTypes::LC_UNIXTHREAD => LoadCommandTypes::Unixthread,
LoadCommandTypes::LC_UUID => LoadCommandTypes::Uuid,
LoadCommandTypes::LC_VERSION_MIN_IPHONEOS => LoadCommandTypes::VersionMinIphoneOS,
LoadCommandTypes::LC_VERSION_MIN_MACOSX => LoadCommandTypes::VersionMinMacOSX,
LoadCommandTypes::LC_VERSION_MIN_TVOS => LoadCommandTypes::VersionMinTvOS,
LoadCommandTypes::LC_VERSION_MIN_WATCHOS => LoadCommandTypes::VersionMinWatchOS,
_ => LoadCommandTypes::Unknown(value),
}
}
}
#[derive(Debug)]
pub enum Commands<'a> {
Generic(Generic<'a>),
BuildVersion(BuildVersion<'a>),
CodeSignature(CodeSignature<'a>),
CodeSignatureDir(CodeSignatureDir<'a>),
DataInCode(DataInCode<'a>),
DyldChainedFixups(DyldChainedFixups<'a>),
DyldEnvironment(DyldEnvironment<'a>),
DyldExportsTrie(DyldExportsTrie<'a>),
DyldInfo(DyldInfo<'a>),
Dylib(Dylib<'a>),
Dylinker(Dylinker<'a>),
DynamicSymbolCommand(DynamicSymbolCommand<'a>),
EncryptionInfo(EncryptionInfo<'a>),
FunctionStarts(FunctionStarts<'a>),
LinkerOptHint(LinkerOptHint<'a>),
Main(Main<'a>),
RPath(RPath<'a>),
Segment(Segment<'a>),
SegmentSplitInfo(SegmentSplitInfo<'a>),
SourceVersion(SourceVersion<'a>),
SubFramework(SubFramework<'a>),
SymbolCommand(SymbolCommand<'a>),
ThreadCommand(ThreadCommand<'a>),
TwoLevelHints(TwoLevelHints<'a>),
UUID(UUID<'a>),
VersionMin(VersionMin<'a>),
}
impl<'a> Commands<'a> {
fn from_ffi(ffi_entry: cxx::UniquePtr<ffi::MachO_Command>) -> Self {
unsafe {
let cmd_ref = ffi_entry.as_ref().unwrap();
if ffi::MachO_Dylib::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::MachO_Command>;
type To = cxx::UniquePtr<ffi::MachO_Dylib>;
std::mem::transmute::<From, To>(ffi_entry)
};
Commands::Dylib(Dylib::from_ffi(raw))
} else if ffi::MachO_Main::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::MachO_Command>;
type To = cxx::UniquePtr<ffi::MachO_Main>;
std::mem::transmute::<From, To>(ffi_entry)
};
Commands::Main(Main::from_ffi(raw))
} else if ffi::MachO_SegmentCommand::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::MachO_Command>;
type To = cxx::UniquePtr<ffi::MachO_SegmentCommand>;
std::mem::transmute::<From, To>(ffi_entry)
};
Commands::Segment(Segment::from_ffi(raw))
} else if ffi::MachO_DyldInfo::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::MachO_Command>;
type To = cxx::UniquePtr<ffi::MachO_DyldInfo>;
std::mem::transmute::<From, To>(ffi_entry)
};
Commands::DyldInfo(DyldInfo::from_ffi(raw))
} else if ffi::MachO_UUIDCommand::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::MachO_Command>;
type To = cxx::UniquePtr<ffi::MachO_UUIDCommand>;
std::mem::transmute::<From, To>(ffi_entry)
};
Commands::UUID(UUID::from_ffi(raw))
} else if ffi::MachO_Dylinker::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::MachO_Command>;
type To = cxx::UniquePtr<ffi::MachO_Dylinker>;
std::mem::transmute::<From, To>(ffi_entry)
};
Commands::Dylinker(Dylinker::from_ffi(raw))
} else if ffi::MachO_FunctionStarts::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::MachO_Command>;
type To = cxx::UniquePtr<ffi::MachO_FunctionStarts>;
std::mem::transmute::<From, To>(ffi_entry)
};
Commands::FunctionStarts(FunctionStarts::from_ffi(raw))
} else if ffi::MachO_SourceVersion::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::MachO_Command>;
type To = cxx::UniquePtr<ffi::MachO_SourceVersion>;
std::mem::transmute::<From, To>(ffi_entry)
};
Commands::SourceVersion(SourceVersion::from_ffi(raw))
} else if ffi::MachO_ThreadCommand::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::MachO_Command>;
type To = cxx::UniquePtr<ffi::MachO_ThreadCommand>;
std::mem::transmute::<From, To>(ffi_entry)
};
Commands::ThreadCommand(ThreadCommand::from_ffi(raw))
} else if ffi::MachO_RPathCommand::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::MachO_Command>;
type To = cxx::UniquePtr<ffi::MachO_RPathCommand>;
std::mem::transmute::<From, To>(ffi_entry)
};
Commands::RPath(RPath::from_ffi(raw))
} else if ffi::MachO_SymbolCommand::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::MachO_Command>;
type To = cxx::UniquePtr<ffi::MachO_SymbolCommand>;
std::mem::transmute::<From, To>(ffi_entry)
};
Commands::SymbolCommand(SymbolCommand::from_ffi(raw))
} else if ffi::MachO_DynamicSymbolCommand::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::MachO_Command>;
type To = cxx::UniquePtr<ffi::MachO_DynamicSymbolCommand>;
std::mem::transmute::<From, To>(ffi_entry)
};
Commands::DynamicSymbolCommand(DynamicSymbolCommand::from_ffi(raw))
} else if ffi::MachO_CodeSignature::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::MachO_Command>;
type To = cxx::UniquePtr<ffi::MachO_CodeSignature>;
std::mem::transmute::<From, To>(ffi_entry)
};
Commands::CodeSignature(CodeSignature::from_ffi(raw))
} else if ffi::MachO_CodeSignatureDir::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::MachO_Command>;
type To = cxx::UniquePtr<ffi::MachO_CodeSignatureDir>;
std::mem::transmute::<From, To>(ffi_entry)
};
Commands::CodeSignatureDir(CodeSignatureDir::from_ffi(raw))
} else if ffi::MachO_DataInCode::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::MachO_Command>;
type To = cxx::UniquePtr<ffi::MachO_DataInCode>;
std::mem::transmute::<From, To>(ffi_entry)
};
Commands::DataInCode(DataInCode::from_ffi(raw))
} else if ffi::MachO_SegmentSplitInfo::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::MachO_Command>;
type To = cxx::UniquePtr<ffi::MachO_SegmentSplitInfo>;
std::mem::transmute::<From, To>(ffi_entry)
};
Commands::SegmentSplitInfo(SegmentSplitInfo::from_ffi(raw))
} else if ffi::MachO_EncryptionInfo::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::MachO_Command>;
type To = cxx::UniquePtr<ffi::MachO_EncryptionInfo>;
std::mem::transmute::<From, To>(ffi_entry)
};
Commands::EncryptionInfo(EncryptionInfo::from_ffi(raw))
} else if ffi::MachO_SubFramework::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::MachO_Command>;
type To = cxx::UniquePtr<ffi::MachO_SubFramework>;
std::mem::transmute::<From, To>(ffi_entry)
};
Commands::SubFramework(SubFramework::from_ffi(raw))
} else if ffi::MachO_DyldEnvironment::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::MachO_Command>;
type To = cxx::UniquePtr<ffi::MachO_DyldEnvironment>;
std::mem::transmute::<From, To>(ffi_entry)
};
Commands::DyldEnvironment(DyldEnvironment::from_ffi(raw))
} else if ffi::MachO_BuildVersion::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::MachO_Command>;
type To = cxx::UniquePtr<ffi::MachO_BuildVersion>;
std::mem::transmute::<From, To>(ffi_entry)
};
Commands::BuildVersion(BuildVersion::from_ffi(raw))
} else if ffi::MachO_DyldChainedFixups::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::MachO_Command>;
type To = cxx::UniquePtr<ffi::MachO_DyldChainedFixups>;
std::mem::transmute::<From, To>(ffi_entry)
};
Commands::DyldChainedFixups(DyldChainedFixups::from_ffi(raw))
} else if ffi::MachO_DyldExportsTrie::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::MachO_Command>;
type To = cxx::UniquePtr<ffi::MachO_DyldExportsTrie>;
std::mem::transmute::<From, To>(ffi_entry)
};
Commands::DyldExportsTrie(DyldExportsTrie::from_ffi(raw))
} else if ffi::MachO_TwoLevelHints::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::MachO_Command>;
type To = cxx::UniquePtr<ffi::MachO_TwoLevelHints>;
std::mem::transmute::<From, To>(ffi_entry)
};
Commands::TwoLevelHints(TwoLevelHints::from_ffi(raw))
} else if ffi::MachO_LinkerOptHint::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::MachO_Command>;
type To = cxx::UniquePtr<ffi::MachO_LinkerOptHint>;
std::mem::transmute::<From, To>(ffi_entry)
};
Commands::LinkerOptHint(LinkerOptHint::from_ffi(raw))
} else if ffi::MachO_VersionMin::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::MachO_Command>;
type To = cxx::UniquePtr<ffi::MachO_VersionMin>;
std::mem::transmute::<From, To>(ffi_entry)
};
Commands::VersionMin(VersionMin::from_ffi(raw))
} else {
Commands::Generic(Generic::from_ffi(ffi_entry))
}
}
}
}
pub struct Generic<'a> {
ptr: cxx::UniquePtr<ffi::MachO_Command>,
_owner: PhantomData<&'a ffi::MachO_Binary>,
}
impl std::fmt::Debug for Generic<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Generic").finish()
}
}
impl FromFFI<ffi::MachO_Command> for Generic<'_> {
fn from_ffi(cmd: cxx::UniquePtr<ffi::MachO_Command>) -> Self {
Self {
ptr: cmd,
_owner: PhantomData,
}
}
}
pub trait Command {
#[doc(hidden)]
fn get_base(&self) -> &ffi::MachO_Command;
fn size(&self) -> u32 {
self.get_base().size()
}
fn offset(&self) -> u64 {
self.get_base().command_offset()
}
fn command_type(&self) -> LoadCommandTypes {
LoadCommandTypes::from_value(self.get_base().cmd_type())
}
fn data(&self) -> &[u8] {
to_slice!(self.get_base().data());
}
}
impl Command for Generic<'_> {
fn get_base(&self) -> &ffi::MachO_Command {
self.ptr.as_ref().unwrap()
}
}
impl std::fmt::Debug for &dyn Command {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Command")
.field("offset", &self.offset())
.field("size", &self.size())
.field("type", &self.command_type())
.field("data_len", &self.data().len())
.finish()
}
}
declare_iterator!(
CommandsIter,
Commands<'a>,
ffi::MachO_Command,
ffi::MachO_Binary,
ffi::MachO_Binary_it_commands
);
@@ -0,0 +1,74 @@
use std::marker::PhantomData;
use lief_ffi as ffi;
use super::Command;
use crate::common::FromFFI;
pub struct BuildVersion<'a> {
ptr: cxx::UniquePtr<ffi::MachO_BuildVersion>,
_owner: PhantomData<&'a ffi::MachO_Binary>,
}
#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum PLATFORM {
MACOS,
IOS,
TVOS,
WATCHOS,
UNKNOWN(u32),
}
impl PLATFORM {
pub fn from_value(value: u32) -> Self {
match value {
0x00000001 => PLATFORM::MACOS,
0x00000002 => PLATFORM::IOS,
0x00000003 => PLATFORM::TVOS,
0x00000004 => PLATFORM::WATCHOS,
_ => PLATFORM::UNKNOWN(value),
}
}
}
impl BuildVersion<'_> {
pub fn sdk(&self) -> Vec<u64> {
Vec::from(self.ptr.sdk().as_slice())
}
pub fn minos(&self) -> Vec<u64> {
Vec::from(self.ptr.minos().as_slice())
}
pub fn platform(&self) -> PLATFORM {
PLATFORM::from_value(self.ptr.platform())
}
}
impl std::fmt::Debug for BuildVersion<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn Command;
f.debug_struct("BuildVersion")
.field("base", &base)
.field("sdk", &self.sdk())
.field("minos", &self.minos())
.field("platform", &self.platform())
.finish()
}
}
impl FromFFI<ffi::MachO_BuildVersion> for BuildVersion<'_> {
fn from_ffi(cmd: cxx::UniquePtr<ffi::MachO_BuildVersion>) -> Self {
Self {
ptr: cmd,
_owner: PhantomData,
}
}
}
impl Command for BuildVersion<'_> {
fn get_base(&self) -> &ffi::MachO_Command {
self.ptr.as_ref().unwrap().as_ref()
}
}
@@ -0,0 +1,49 @@
use super::Command;
use lief_ffi as ffi;
use crate::common::FromFFI;
use crate::to_slice;
use std::marker::PhantomData;
pub struct CodeSignature<'a> {
ptr: cxx::UniquePtr<ffi::MachO_CodeSignature>,
_owner: PhantomData<&'a ffi::MachO_Binary>,
}
impl CodeSignature<'_> {
pub fn data_offset(&self) -> u32 {
self.ptr.data_offset()
}
pub fn data_size(&self) -> u32 {
self.ptr.data_size()
}
pub fn content(&self) -> &[u8] {
to_slice!(self.ptr.content());
}
}
impl std::fmt::Debug for CodeSignature<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn Command;
f.debug_struct("CodeSignature")
.field("base", &base)
.field("data_offset", &self.data_offset())
.field("data_size", &self.data_size())
.finish()
}
}
impl FromFFI<ffi::MachO_CodeSignature> for CodeSignature<'_> {
fn from_ffi(cmd: cxx::UniquePtr<ffi::MachO_CodeSignature>) -> Self {
Self {
ptr: cmd,
_owner: PhantomData,
}
}
}
impl Command for CodeSignature<'_> {
fn get_base(&self) -> &ffi::MachO_Command {
self.ptr.as_ref().unwrap().as_ref()
}
}
@@ -0,0 +1,49 @@
use super::Command;
use lief_ffi as ffi;
use crate::common::FromFFI;
use crate::to_slice;
use std::marker::PhantomData;
pub struct CodeSignatureDir<'a> {
ptr: cxx::UniquePtr<ffi::MachO_CodeSignatureDir>,
_owner: PhantomData<&'a ffi::MachO_Binary>,
}
impl CodeSignatureDir<'_> {
pub fn data_offset(&self) -> u32 {
self.ptr.data_offset()
}
pub fn data_size(&self) -> u32 {
self.ptr.data_size()
}
pub fn content(&self) -> &[u8] {
to_slice!(self.ptr.content());
}
}
impl std::fmt::Debug for CodeSignatureDir<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn Command;
f.debug_struct("CodeSignatureDir")
.field("base", &base)
.field("data_offset", &self.data_offset())
.field("data_size", &self.data_size())
.finish()
}
}
impl FromFFI<ffi::MachO_CodeSignatureDir> for CodeSignatureDir<'_> {
fn from_ffi(cmd: cxx::UniquePtr<ffi::MachO_CodeSignatureDir>) -> Self {
Self {
ptr: cmd,
_owner: PhantomData,
}
}
}
impl Command for CodeSignatureDir<'_> {
fn get_base(&self) -> &ffi::MachO_Command {
self.ptr.as_ref().unwrap().as_ref()
}
}
@@ -0,0 +1,120 @@
use super::Command;
use lief_ffi as ffi;
use crate::to_slice;
use crate::{common::FromFFI, declare_iterator};
use std::marker::PhantomData;
pub struct DataInCode<'a> {
ptr: cxx::UniquePtr<ffi::MachO_DataInCode>,
_owner: PhantomData<&'a ffi::MachO_Binary>,
}
impl DataInCode<'_> {
pub fn data_offset(&self) -> u32 {
self.ptr.data_offset()
}
pub fn data_size(&self) -> u32 {
self.ptr.data_size()
}
pub fn content(&self) -> &[u8] {
to_slice!(self.ptr.content());
}
pub fn entries(&self) -> Entries {
Entries::new(self.ptr.entries())
}
}
impl std::fmt::Debug for DataInCode<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn Command;
f.debug_struct("DataInCode")
.field("base", &base)
.field("data_offset", &self.data_offset())
.field("data_size", &self.data_size())
.finish()
}
}
impl FromFFI<ffi::MachO_DataInCode> for DataInCode<'_> {
fn from_ffi(cmd: cxx::UniquePtr<ffi::MachO_DataInCode>) -> Self {
Self {
ptr: cmd,
_owner: PhantomData,
}
}
}
impl Command for DataInCode<'_> {
fn get_base(&self) -> &ffi::MachO_Command {
self.ptr.as_ref().unwrap().as_ref()
}
}
pub struct DataCodeEntry<'a> {
ptr: cxx::UniquePtr<ffi::MachO_DataCodeEntry>,
_owner: PhantomData<&'a ffi::MachO_DataInCode>,
}
#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum ENTRY_TYPE {
DATA,
JUMP_TABLE_8,
JUMP_TABLE_16,
JUMP_TABLE_32,
ABS_JUMP_TABLE_32,
UNKNOWN(u32),
}
impl ENTRY_TYPE {
pub fn from_value(value: u32) -> Self {
match value {
0x00000001 => ENTRY_TYPE::DATA,
0x00000002 => ENTRY_TYPE::JUMP_TABLE_8,
0x00000003 => ENTRY_TYPE::JUMP_TABLE_16,
0x00000004 => ENTRY_TYPE::JUMP_TABLE_32,
0x00000005 => ENTRY_TYPE::ABS_JUMP_TABLE_32,
_ => ENTRY_TYPE::UNKNOWN(value),
}
}
}
impl DataCodeEntry<'_> {
pub fn offset(&self) -> u32 {
self.ptr.offset()
}
pub fn length(&self) -> u32 {
self.ptr.length()
}
pub fn get_type(&self) -> ENTRY_TYPE {
ENTRY_TYPE::from_value(self.ptr.get_type())
}
}
impl std::fmt::Debug for DataCodeEntry<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("DataCodeEntry")
.field("offset", &self.offset())
.field("length", &self.length())
.field("type", &self.get_type())
.finish()
}
}
impl FromFFI<ffi::MachO_DataCodeEntry> for DataCodeEntry<'_> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_DataCodeEntry>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
declare_iterator!(
Entries,
DataCodeEntry<'a>,
ffi::MachO_DataCodeEntry,
ffi::MachO_DataInCode,
ffi::MachO_DataInCode_it_entries
);
@@ -0,0 +1,86 @@
use super::Command;
use lief_ffi as ffi;
use crate::macho::binding_info::{Chained, CHAINED_FORMAT};
use crate::{common::FromFFI, declare_iterator};
use std::marker::PhantomData;
pub struct DyldChainedFixups<'a> {
ptr: cxx::UniquePtr<ffi::MachO_DyldChainedFixups>,
_owner: PhantomData<&'a ffi::MachO_Binary>,
}
impl std::fmt::Debug for DyldChainedFixups<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn Command;
f.debug_struct("DyldChainedFixups")
.field("base", &base)
.field("data_offset", &self.data_offset())
.field("data_size", &self.data_size())
.field("fixups_version", &self.fixups_version())
.field("starts_offset", &self.starts_offset())
.field("imports_offset", &self.imports_offset())
.field("symbols_offset", &self.symbols_offset())
.field("imports_count", &self.imports_count())
.field("symbols_format", &self.symbols_format())
.field("imports_format", &self.imports_format())
.finish()
}
}
impl DyldChainedFixups<'_> {
pub fn data_offset(&self) -> u32 {
self.ptr.data_offset()
}
pub fn data_size(&self) -> u32 {
self.ptr.data_size()
}
pub fn fixups_version(&self) -> u32 {
self.ptr.fixups_version()
}
pub fn starts_offset(&self) -> u32 {
self.ptr.starts_offset()
}
pub fn imports_offset(&self) -> u32 {
self.ptr.imports_offset()
}
pub fn symbols_offset(&self) -> u32 {
self.ptr.symbols_offset()
}
pub fn imports_count(&self) -> u32 {
self.ptr.imports_count()
}
pub fn symbols_format(&self) -> u32 {
self.ptr.symbols_format()
}
pub fn imports_format(&self) -> CHAINED_FORMAT {
CHAINED_FORMAT::from_value(self.ptr.imports_format())
}
pub fn bindings(&self) -> Bindings {
Bindings::new(self.ptr.bindings())
}
}
impl FromFFI<ffi::MachO_DyldChainedFixups> for DyldChainedFixups<'_> {
fn from_ffi(cmd: cxx::UniquePtr<ffi::MachO_DyldChainedFixups>) -> Self {
Self {
ptr: cmd,
_owner: PhantomData,
}
}
}
impl Command for DyldChainedFixups<'_> {
fn get_base(&self) -> &ffi::MachO_Command {
self.ptr.as_ref().unwrap().as_ref()
}
}
declare_iterator!(
Bindings,
Chained<'a>,
ffi::MachO_ChainedBindingInfo,
ffi::MachO_DyldChainedFixups,
ffi::MachO_DyldChainedFixups_it_bindings
);
@@ -0,0 +1,41 @@
use super::Command;
use lief_ffi as ffi;
use crate::common::FromFFI;
use std::marker::PhantomData;
pub struct DyldEnvironment<'a> {
ptr: cxx::UniquePtr<ffi::MachO_DyldEnvironment>,
_owner: PhantomData<&'a ffi::MachO_Binary>,
}
impl DyldEnvironment<'_> {
pub fn value(&self) -> String {
self.ptr.value().to_string()
}
}
impl std::fmt::Debug for DyldEnvironment<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn Command;
f.debug_struct("DyldEnvironment")
.field("base", &base)
.field("value", &self.value())
.finish()
}
}
impl FromFFI<ffi::MachO_DyldEnvironment> for DyldEnvironment<'_> {
fn from_ffi(cmd: cxx::UniquePtr<ffi::MachO_DyldEnvironment>) -> Self {
Self {
ptr: cmd,
_owner: PhantomData,
}
}
}
impl Command for DyldEnvironment<'_> {
fn get_base(&self) -> &ffi::MachO_Command {
self.ptr.as_ref().unwrap().as_ref()
}
}
@@ -0,0 +1,62 @@
use super::Command;
use crate::common::FromFFI;
use crate::macho::export_info::ExportInfo;
use crate::to_slice;
use lief_ffi as ffi;
use std::marker::PhantomData;
use crate::declare_iterator;
pub struct DyldExportsTrie<'a> {
ptr: cxx::UniquePtr<ffi::MachO_DyldExportsTrie>,
_owner: PhantomData<&'a ffi::MachO_Binary>,
}
impl DyldExportsTrie<'_> {
pub fn data_offset(&self) -> u32 {
self.ptr.data_offset()
}
pub fn data_size(&self) -> u32 {
self.ptr.data_size()
}
pub fn content(&self) -> &[u8] {
to_slice!(self.ptr.content());
}
pub fn exports(&self) -> ExportInfos {
ExportInfos::new(self.ptr.exports())
}
}
impl std::fmt::Debug for DyldExportsTrie<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn Command;
f.debug_struct("DyldExportsTrie")
.field("base", &base)
.field("data_offset", &self.data_offset())
.field("data_size", &self.data_size())
.finish()
}
}
impl FromFFI<ffi::MachO_DyldExportsTrie> for DyldExportsTrie<'_> {
fn from_ffi(cmd: cxx::UniquePtr<ffi::MachO_DyldExportsTrie>) -> Self {
Self {
ptr: cmd,
_owner: PhantomData,
}
}
}
impl Command for DyldExportsTrie<'_> {
fn get_base(&self) -> &ffi::MachO_Command {
self.ptr.as_ref().unwrap().as_ref()
}
}
declare_iterator!(
ExportInfos,
ExportInfo<'a>,
ffi::MachO_ExportInfo,
ffi::MachO_DyldExportsTrie,
ffi::MachO_DyldExportsTrie_it_exports
);
@@ -0,0 +1,83 @@
use super::Command;
use crate::common::FromFFI;
use crate::macho::binding_info::Dyld;
use crate::macho::{BindingInfo, ExportInfo};
use std::marker::PhantomData;
use crate::{declare_iterator, declare_iterator_conv, to_slice};
use lief_ffi as ffi;
pub struct DyldInfo<'a> {
ptr: cxx::UniquePtr<ffi::MachO_DyldInfo>,
_owner: PhantomData<&'a ffi::MachO_Binary>,
}
impl std::fmt::Debug for DyldInfo<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn Command;
f.debug_struct("DyldInfo")
.field("base", &base)
.field("rebase_opcodes", &self.rebase_opcodes().is_empty())
.field("bind_opcodes", &self.bind_opcodes().is_empty())
.field("weak_bind_opcodes", &self.weak_bind_opcodes().is_empty())
.field("lazy_bind_opcodes", &self.lazy_bind_opcodes().is_empty())
.field("export_trie", &self.export_trie().is_empty())
.finish()
}
}
impl FromFFI<ffi::MachO_DyldInfo> for DyldInfo<'_> {
fn from_ffi(cmd: cxx::UniquePtr<ffi::MachO_DyldInfo>) -> Self {
Self {
ptr: cmd,
_owner: PhantomData,
}
}
}
impl<'a> DyldInfo<'a> {
pub fn rebase_opcodes(&self) -> &[u8] {
to_slice!(self.ptr.rebase_opcodes());
}
pub fn bind_opcodes(&self) -> &[u8] {
to_slice!(self.ptr.bind_opcodes());
}
pub fn weak_bind_opcodes(&self) -> &[u8] {
to_slice!(self.ptr.weak_bind_opcodes());
}
pub fn lazy_bind_opcodes(&self) -> &[u8] {
to_slice!(self.ptr.lazy_bind_opcodes());
}
pub fn export_trie(&self) -> &[u8] {
to_slice!(self.ptr.export_trie());
}
pub fn bindings(&self) -> BindingInfos {
BindingInfos::new(self.ptr.bindings())
}
pub fn exports(&self) -> ExportInfos {
ExportInfos::new(self.ptr.exports())
}
}
impl Command for DyldInfo<'_> {
fn get_base(&self) -> &ffi::MachO_Command {
self.ptr.as_ref().unwrap().as_ref()
}
}
declare_iterator_conv!(
BindingInfos,
BindingInfo<'a>,
ffi::MachO_BindingInfo,
ffi::MachO_DyldInfo,
ffi::MachO_DyldInfo_it_bindings,
|n| BindingInfo::Dyld(Dyld::from_ffi(n))
);
declare_iterator!(
ExportInfos,
ExportInfo<'a>,
ffi::MachO_ExportInfo,
ffi::MachO_DyldInfo,
ffi::MachO_DyldInfo_it_exports
);
@@ -0,0 +1,62 @@
use super::Command;
use lief_ffi as ffi;
use crate::common::FromFFI;
use crate::declare_iterator;
use std::marker::PhantomData;
pub struct Dylib<'a> {
ptr: cxx::UniquePtr<ffi::MachO_Dylib>,
_owner: PhantomData<&'a ffi::MachO_Binary>,
}
impl Dylib<'_> {
pub fn name(&self) -> String {
self.ptr.name().to_string()
}
pub fn timestamp(&self) -> u32 {
self.ptr.timestamp()
}
pub fn current_version(&self) -> Vec<u64> {
Vec::from(self.ptr.current_version().as_slice())
}
pub fn compatibility_version(&self) -> Vec<u64> {
Vec::from(self.ptr.compatibility_version().as_slice())
}
}
impl std::fmt::Debug for Dylib<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn Command;
f.debug_struct("Dylib")
.field("base", &base)
.field("name", &self.name())
.field("timestamp", &self.timestamp())
.field("current_version", &self.current_version())
.field("compatibility_version", &self.compatibility_version())
.finish()
}
}
impl FromFFI<ffi::MachO_Dylib> for Dylib<'_> {
fn from_ffi(cmd: cxx::UniquePtr<ffi::MachO_Dylib>) -> Self {
Self {
ptr: cmd,
_owner: PhantomData,
}
}
}
impl Command for Dylib<'_> {
fn get_base(&self) -> &ffi::MachO_Command {
self.ptr.as_ref().unwrap().as_ref()
}
}
declare_iterator!(
Libraries,
Dylib<'a>,
ffi::MachO_Dylib,
ffi::MachO_Binary,
ffi::MachO_Binary_it_libraries
);
@@ -0,0 +1,40 @@
use super::Command;
use crate::common::FromFFI;
use lief_ffi as ffi;
use std::marker::PhantomData;
pub struct Dylinker<'a> {
ptr: cxx::UniquePtr<ffi::MachO_Dylinker>,
_owner: PhantomData<&'a ffi::MachO_Binary>,
}
impl std::fmt::Debug for Dylinker<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn Command;
f.debug_struct("Dylinker")
.field("base", &base)
.field("name", &self.name())
.finish()
}
}
impl Dylinker<'_> {
pub fn name(&self) -> String {
self.ptr.name().to_string()
}
}
impl FromFFI<ffi::MachO_Dylinker> for Dylinker<'_> {
fn from_ffi(cmd: cxx::UniquePtr<ffi::MachO_Dylinker>) -> Self {
Self {
ptr: cmd,
_owner: PhantomData,
}
}
}
impl Command for Dylinker<'_> {
fn get_base(&self) -> &ffi::MachO_Command {
self.ptr.as_ref().unwrap().as_ref()
}
}
@@ -0,0 +1,123 @@
use super::Command;
use crate::common::FromFFI;
use lief_ffi as ffi;
use std::marker::PhantomData;
pub struct DynamicSymbolCommand<'a> {
ptr: cxx::UniquePtr<ffi::MachO_DynamicSymbolCommand>,
_owner: PhantomData<&'a ffi::MachO_Binary>,
}
impl DynamicSymbolCommand<'_> {
pub fn idx_local_symbol(&self) -> u32 {
self.ptr.idx_local_symbol()
}
pub fn nb_local_symbols(&self) -> u32 {
self.ptr.nb_local_symbols()
}
pub fn idx_external_define_symbol(&self) -> u32 {
self.ptr.idx_external_define_symbol()
}
pub fn nb_external_define_symbols(&self) -> u32 {
self.ptr.nb_external_define_symbols()
}
pub fn idx_undefined_symbol(&self) -> u32 {
self.ptr.idx_undefined_symbol()
}
pub fn nb_undefined_symbols(&self) -> u32 {
self.ptr.nb_undefined_symbols()
}
pub fn toc_offset(&self) -> u32 {
self.ptr.toc_offset()
}
pub fn nb_toc(&self) -> u32 {
self.ptr.nb_toc()
}
pub fn module_table_offset(&self) -> u32 {
self.ptr.module_table_offset()
}
pub fn nb_module_table(&self) -> u32 {
self.ptr.nb_module_table()
}
pub fn external_reference_symbol_offset(&self) -> u32 {
self.ptr.external_reference_symbol_offset()
}
pub fn nb_external_reference_symbols(&self) -> u32 {
self.ptr.nb_external_reference_symbols()
}
pub fn indirect_symbol_offset(&self) -> u32 {
self.ptr.indirect_symbol_offset()
}
pub fn nb_indirect_symbols(&self) -> u32 {
self.ptr.nb_indirect_symbols()
}
pub fn external_relocation_offset(&self) -> u32 {
self.ptr.external_relocation_offset()
}
pub fn nb_external_relocations(&self) -> u32 {
self.ptr.nb_external_relocations()
}
pub fn local_relocation_offset(&self) -> u32 {
self.ptr.local_relocation_offset()
}
pub fn nb_local_relocations(&self) -> u32 {
self.ptr.nb_local_relocations()
}
}
impl std::fmt::Debug for DynamicSymbolCommand<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn Command;
f.debug_struct("DynamicSymbolCommand")
.field("base", &base)
.field("idx_local_symbol", &self.idx_local_symbol())
.field("nb_local_symbols", &self.nb_local_symbols())
.field(
"idx_external_define_symbol",
&self.idx_external_define_symbol(),
)
.field(
"nb_external_define_symbols",
&self.nb_external_define_symbols(),
)
.field("idx_undefined_symbol", &self.idx_undefined_symbol())
.field("nb_undefined_symbols", &self.nb_undefined_symbols())
.field("toc_offset", &self.toc_offset())
.field("nb_toc", &self.nb_toc())
.field("module_table_offset", &self.module_table_offset())
.field("nb_module_table", &self.nb_module_table())
.field(
"external_reference_symbol_offset",
&self.external_reference_symbol_offset(),
)
.field(
"nb_external_reference_symbols",
&self.nb_external_reference_symbols(),
)
.field("indirect_symbol_offset", &self.indirect_symbol_offset())
.field("nb_indirect_symbols", &self.nb_indirect_symbols())
.field(
"external_relocation_offset",
&self.external_relocation_offset(),
)
.field("nb_external_relocations", &self.nb_external_relocations())
.field("local_relocation_offset", &self.local_relocation_offset())
.field("nb_local_relocations", &self.nb_local_relocations())
.finish()
}
}
impl FromFFI<ffi::MachO_DynamicSymbolCommand> for DynamicSymbolCommand<'_> {
fn from_ffi(cmd: cxx::UniquePtr<ffi::MachO_DynamicSymbolCommand>) -> Self {
Self {
ptr: cmd,
_owner: PhantomData,
}
}
}
impl Command for DynamicSymbolCommand<'_> {
fn get_base(&self) -> &ffi::MachO_Command {
self.ptr.as_ref().unwrap().as_ref()
}
}
@@ -0,0 +1,48 @@
use super::Command;
use crate::common::FromFFI;
use lief_ffi as ffi;
use std::marker::PhantomData;
pub struct EncryptionInfo<'a> {
ptr: cxx::UniquePtr<ffi::MachO_EncryptionInfo>,
_owner: PhantomData<&'a ffi::MachO_Binary>,
}
impl EncryptionInfo<'_> {
pub fn crypt_offset(&self) -> u32 {
self.ptr.crypt_offset()
}
pub fn crypt_size(&self) -> u32 {
self.ptr.crypt_size()
}
pub fn crypt_id(&self) -> u32 {
self.ptr.crypt_id()
}
}
impl std::fmt::Debug for EncryptionInfo<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn Command;
f.debug_struct("EncryptionInfo")
.field("base", &base)
.field("crypt_id", &self.crypt_id())
.field("crypt_offset", &self.crypt_offset())
.field("crypt_size", &self.crypt_size())
.finish()
}
}
impl FromFFI<ffi::MachO_EncryptionInfo> for EncryptionInfo<'_> {
fn from_ffi(cmd: cxx::UniquePtr<ffi::MachO_EncryptionInfo>) -> Self {
Self {
ptr: cmd,
_owner: PhantomData,
}
}
}
impl Command for EncryptionInfo<'_> {
fn get_base(&self) -> &ffi::MachO_Command {
self.ptr.as_ref().unwrap().as_ref()
}
}
@@ -0,0 +1,51 @@
use super::Command;
use crate::common::FromFFI;
use crate::to_slice;
use lief_ffi as ffi;
use std::marker::PhantomData;
pub struct FunctionStarts<'a> {
ptr: cxx::UniquePtr<ffi::MachO_FunctionStarts>,
_owner: PhantomData<&'a ffi::MachO_Binary>,
}
impl FunctionStarts<'_> {
pub fn data_offset(&self) -> u32 {
self.ptr.data_offset()
}
pub fn data_size(&self) -> u32 {
self.ptr.data_size()
}
pub fn functions(&self) -> Vec<u64> {
Vec::from(self.ptr.functions().as_slice())
}
pub fn content(&self) -> &[u8] {
to_slice!(self.ptr.content());
}
}
impl std::fmt::Debug for FunctionStarts<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn Command;
f.debug_struct("FunctionStarts")
.field("base", &base)
.field("data_offset", &self.data_offset())
.field("data_size", &self.data_size())
.finish()
}
}
impl FromFFI<ffi::MachO_FunctionStarts> for FunctionStarts<'_> {
fn from_ffi(cmd: cxx::UniquePtr<ffi::MachO_FunctionStarts>) -> Self {
Self {
ptr: cmd,
_owner: PhantomData,
}
}
}
impl Command for FunctionStarts<'_> {
fn get_base(&self) -> &ffi::MachO_Command {
self.ptr.as_ref().unwrap().as_ref()
}
}
@@ -0,0 +1,49 @@
use super::Command;
use crate::common::FromFFI;
use crate::to_slice;
use lief_ffi as ffi;
use std::marker::PhantomData;
pub struct LinkerOptHint<'a> {
ptr: cxx::UniquePtr<ffi::MachO_LinkerOptHint>,
_owner: PhantomData<&'a ffi::MachO_Binary>,
}
impl LinkerOptHint<'_> {
pub fn data_offset(&self) -> u32 {
self.ptr.data_offset()
}
pub fn data_size(&self) -> u32 {
self.ptr.data_size()
}
pub fn content(&self) -> &[u8] {
to_slice!(self.ptr.content());
}
}
impl std::fmt::Debug for LinkerOptHint<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn Command;
f.debug_struct("LinkerOptHint")
.field("base", &base)
.field("data_offset", &self.data_offset())
.field("data_size", &self.data_size())
.finish()
}
}
impl FromFFI<ffi::MachO_LinkerOptHint> for LinkerOptHint<'_> {
fn from_ffi(cmd: cxx::UniquePtr<ffi::MachO_LinkerOptHint>) -> Self {
Self {
ptr: cmd,
_owner: PhantomData,
}
}
}
impl Command for LinkerOptHint<'_> {
fn get_base(&self) -> &ffi::MachO_Command {
self.ptr.as_ref().unwrap().as_ref()
}
}
@@ -0,0 +1,44 @@
use super::Command;
use crate::common::FromFFI;
use lief_ffi as ffi;
use std::marker::PhantomData;
pub struct Main<'a> {
ptr: cxx::UniquePtr<ffi::MachO_Main>,
_owner: PhantomData<&'a ffi::MachO_Binary>,
}
impl Main<'_> {
pub fn entrypoint(&self) -> u64 {
self.ptr.entrypoint()
}
pub fn stack_size(&self) -> u64 {
self.ptr.stack_size()
}
}
impl std::fmt::Debug for Main<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn Command;
f.debug_struct("Main")
.field("base", &base)
.field("entrypoint", &self.entrypoint())
.field("stack_size", &self.stack_size())
.finish()
}
}
impl<'a> FromFFI<ffi::MachO_Main> for Main<'a> {
fn from_ffi(cmd: cxx::UniquePtr<ffi::MachO_Main>) -> Self {
Self {
ptr: cmd,
_owner: PhantomData,
}
}
}
impl Command for Main<'_> {
fn get_base(&self) -> &ffi::MachO_Command {
self.ptr.as_ref().unwrap().as_ref()
}
}
@@ -0,0 +1,42 @@
use super::Command;
use lief_ffi as ffi;
use crate::common::FromFFI;
use std::marker::PhantomData;
pub struct RPath<'a> {
ptr: cxx::UniquePtr<ffi::MachO_RPathCommand>,
_owner: PhantomData<&'a ffi::MachO_Binary>
}
impl RPath<'_> {
pub fn path(&self) -> String {
self.ptr.path().to_string()
}
}
impl std::fmt::Debug for RPath<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn Command;
f.debug_struct("RPath")
.field("base", &base)
.field("path", &self.path())
.finish()
}
}
impl FromFFI<ffi::MachO_RPathCommand> for RPath<'_> {
fn from_ffi(cmd: cxx::UniquePtr<ffi::MachO_RPathCommand>) -> Self {
Self {
ptr: cmd,
_owner: PhantomData
}
}
}
impl Command for RPath<'_> {
fn get_base(&self) -> &ffi::MachO_Command {
self.ptr.as_ref().unwrap().as_ref()
}
}
@@ -0,0 +1,91 @@
use super::Command;
use lief_ffi as ffi;
use crate::common::FromFFI;
use crate::declare_iterator;
use std::marker::PhantomData;
use crate::to_slice;
use crate::macho::section::Section;
use crate::macho::relocation::Relocation;
pub struct Segment<'a> {
ptr: cxx::UniquePtr<ffi::MachO_SegmentCommand>,
_owner: PhantomData<&'a ffi::MachO_Binary>
}
impl Segment<'_> {
pub fn name(&self) -> String {
self.ptr.name().to_string()
}
pub fn virtual_address(&self) -> u64 {
self.ptr.virtual_address()
}
pub fn virtual_size(&self) -> u64 {
self.ptr.virtual_size()
}
pub fn file_size(&self) -> u64 {
self.ptr.file_size()
}
pub fn file_offset(&self) -> u64 {
self.ptr.file_offset()
}
pub fn max_protection(&self) -> u32 {
self.ptr.max_protection()
}
pub fn init_protection(&self) -> u32 {
self.ptr.init_protection()
}
pub fn numberof_sections(&self) -> u32 {
self.ptr.numberof_sections()
}
pub fn flags(&self) -> u32 {
self.ptr.flags()
}
pub fn content(&self) -> &[u8] {
to_slice!(self.ptr.content());
}
pub fn sections(&self) -> Sections {
Sections::new(self.ptr.sections())
}
pub fn relocations(&self) -> Relocations {
Relocations::new(self.ptr.relocations())
}
}
impl std::fmt::Debug for Segment<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn Command;
f.debug_struct("Segment")
.field("base", &base)
.field("name", &self.name())
.field("virtual_address", &self.virtual_address())
.field("virtual_size", &self.virtual_size())
.field("file_size", &self.file_size())
.field("file_offset", &self.file_offset())
.field("max_protection", &self.max_protection())
.field("init_protection", &self.init_protection())
.field("numberof_sections", &self.numberof_sections())
.field("flags", &self.flags())
.finish()
}
}
impl FromFFI<ffi::MachO_SegmentCommand> for Segment<'_> {
fn from_ffi(cmd: cxx::UniquePtr<ffi::MachO_SegmentCommand>) -> Self {
Self {
ptr: cmd,
_owner: PhantomData
}
}
}
impl Command for Segment<'_> {
fn get_base(&self) -> &ffi::MachO_Command {
self.ptr.as_ref().unwrap().as_ref()
}
}
declare_iterator!(Segments, Segment<'a>, ffi::MachO_SegmentCommand, ffi::MachO_Binary, ffi::MachO_Binary_it_segments);
declare_iterator!(Sections, Section<'a>, ffi::MachO_Section, ffi::MachO_SegmentCommand, ffi::MachO_SegmentCommand_it_sections);
declare_iterator!(Relocations, Relocation<'a>, ffi::MachO_Relocation, ffi::MachO_SegmentCommand, ffi::MachO_SegmentCommand_it_relocations);
@@ -0,0 +1,51 @@
use super::Command;
use lief_ffi as ffi;
use crate::common::FromFFI;
use crate::to_slice;
use std::marker::PhantomData;
pub struct SegmentSplitInfo<'a> {
ptr: cxx::UniquePtr<ffi::MachO_SegmentSplitInfo>,
_owner: PhantomData<&'a ffi::MachO_Binary>
}
impl SegmentSplitInfo<'_> {
pub fn data_offset(&self) -> u32 {
self.ptr.data_offset()
}
pub fn data_size(&self) -> u32 {
self.ptr.data_size()
}
pub fn content(&self) -> &[u8] {
to_slice!(self.ptr.content());
}
}
impl std::fmt::Debug for SegmentSplitInfo<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn Command;
f.debug_struct("SegmentSplitInfo")
.field("base", &base)
.field("data_offset", &self.data_offset())
.field("data_size", &self.data_size())
.finish()
}
}
impl<'a> FromFFI<ffi::MachO_SegmentSplitInfo> for SegmentSplitInfo<'a> {
fn from_ffi(cmd: cxx::UniquePtr<ffi::MachO_SegmentSplitInfo>) -> Self {
Self {
ptr: cmd,
_owner: PhantomData
}
}
}
impl Command for SegmentSplitInfo<'_> {
fn get_base(&self) -> &ffi::MachO_Command {
self.ptr.as_ref().unwrap().as_ref()
}
}
@@ -0,0 +1,41 @@
use super::Command;
use lief_ffi as ffi;
use crate::common::FromFFI;
use std::marker::PhantomData;
pub struct SourceVersion<'a> {
ptr: cxx::UniquePtr<ffi::MachO_SourceVersion>,
_owner: PhantomData<&'a ffi::MachO_Binary>
}
impl SourceVersion<'_> {
pub fn version(&self) -> Vec<u64> {
Vec::from(self.ptr.version().as_slice())
}
}
impl std::fmt::Debug for SourceVersion<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn Command;
f.debug_struct("SourceVersion")
.field("base", &base)
.field("version", &self.version())
.finish()
}
}
impl<'a> FromFFI<ffi::MachO_SourceVersion> for SourceVersion<'a> {
fn from_ffi(cmd: cxx::UniquePtr<ffi::MachO_SourceVersion>) -> Self {
Self {
ptr: cmd,
_owner: PhantomData
}
}
}
impl Command for SourceVersion<'_> {
fn get_base(&self) -> &ffi::MachO_Command {
self.ptr.as_ref().unwrap().as_ref()
}
}
@@ -0,0 +1,43 @@
use super::Command;
use lief_ffi as ffi;
use crate::common::FromFFI;
use std::marker::PhantomData;
pub struct SubFramework<'a> {
ptr: cxx::UniquePtr<ffi::MachO_SubFramework>,
_owner: PhantomData<&'a ffi::MachO_Binary>
}
impl SubFramework<'_> {
pub fn umbrella(&self) -> String {
self.ptr.umbrella().to_string()
}
}
impl std::fmt::Debug for SubFramework<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn Command;
f.debug_struct("SubFramework")
.field("base", &base)
.field("umbrella", &self.umbrella())
.finish()
}
}
impl FromFFI<ffi::MachO_SubFramework> for SubFramework<'_> {
fn from_ffi(cmd: cxx::UniquePtr<ffi::MachO_SubFramework>) -> Self {
Self {
ptr: cmd,
_owner: PhantomData
}
}
}
impl Command for SubFramework<'_> {
fn get_base(&self) -> &ffi::MachO_Command {
self.ptr.as_ref().unwrap().as_ref()
}
}
@@ -0,0 +1,68 @@
use super::Command;
use lief_ffi as ffi;
use crate::common::FromFFI;
use crate::to_slice;
use std::marker::PhantomData;
pub struct SymbolCommand<'a> {
ptr: cxx::UniquePtr<ffi::MachO_SymbolCommand>,
_owner: PhantomData<&'a ffi::MachO_Binary>
}
impl SymbolCommand<'_> {
pub fn symbol_offset(&self) -> u32 {
self.ptr.symbol_offset()
}
pub fn numberof_symbols(&self) -> u32 {
self.ptr.numberof_symbols()
}
pub fn strings_offset(&self) -> u32 {
self.ptr.strings_offset()
}
pub fn strings_size(&self) -> u32 {
self.ptr.strings_size()
}
pub fn original_str_size(&self) -> u32 {
self.ptr.original_str_size()
}
pub fn original_nb_symbols(&self) -> u32 {
self.ptr.original_nb_symbols()
}
pub fn symbol_table(&self) -> &[u8] {
to_slice!(self.ptr.symbol_table());
}
pub fn string_table(&self) -> &[u8] {
to_slice!(self.ptr.string_table());
}
}
impl std::fmt::Debug for SymbolCommand<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn Command;
f.debug_struct("SymbolCommand")
.field("base", &base)
.field("symbol_offset", &self.symbol_offset())
.field("numberof_symbols", &self.numberof_symbols())
.field("strings_offset", &self.strings_offset())
.field("strings_size", &self.strings_size())
.finish()
}
}
impl FromFFI<ffi::MachO_SymbolCommand> for SymbolCommand<'_> {
fn from_ffi(cmd: cxx::UniquePtr<ffi::MachO_SymbolCommand>) -> Self {
Self {
ptr: cmd,
_owner: PhantomData
}
}
}
impl Command for SymbolCommand<'_> {
fn get_base(&self) -> &ffi::MachO_Command {
self.ptr.as_ref().unwrap().as_ref()
}
}
@@ -0,0 +1,54 @@
use lief_ffi as ffi;
use super::Command;
use crate::common::FromFFI;
use crate::to_slice;
use std::marker::PhantomData;
pub struct ThreadCommand<'a> {
ptr: cxx::UniquePtr<ffi::MachO_ThreadCommand>,
_owner: PhantomData<&'a ffi::MachO_Binary>
}
impl ThreadCommand<'_> {
pub fn flavor(&self) -> u32 {
self.ptr.flavor()
}
pub fn count(&self) -> u32 {
self.ptr.count()
}
pub fn pc(&self) -> u64 {
self.ptr.pc()
}
pub fn state(&self) -> &[u8] {
to_slice!(self.ptr.state());
}
}
impl std::fmt::Debug for ThreadCommand<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn Command;
f.debug_struct("ThreadCommand")
.field("base", &base)
.field("flavor", &self.flavor())
.field("count", &self.count())
.field("pc", &self.pc())
.finish()
}
}
impl FromFFI<ffi::MachO_ThreadCommand> for ThreadCommand<'_> {
fn from_ffi(cmd: cxx::UniquePtr<ffi::MachO_ThreadCommand>) -> Self {
Self {
ptr: cmd,
_owner: PhantomData
}
}
}
impl Command for ThreadCommand<'_> {
fn get_base(&self) -> &ffi::MachO_Command {
self.ptr.as_ref().unwrap().as_ref()
}
}
@@ -0,0 +1,50 @@
use super::Command;
use lief_ffi as ffi;
use crate::common::FromFFI;
use crate::to_slice;
use std::marker::PhantomData;
pub struct TwoLevelHints<'a> {
ptr: cxx::UniquePtr<ffi::MachO_TwoLevelHints>,
_owner: PhantomData<&'a ffi::MachO_Binary>
}
impl TwoLevelHints<'_> {
pub fn offset(&self) -> u32 {
self.ptr.offset()
}
pub fn original_nb_hints(&self) -> u32 {
self.ptr.original_nb_hints()
}
pub fn content(&self) -> &[u8] {
to_slice!(self.ptr.content());
}
}
impl std::fmt::Debug for TwoLevelHints<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn Command;
f.debug_struct("TwoLevelHints")
.field("base", &base)
.field("offset", &self.offset())
.finish()
}
}
impl FromFFI<ffi::MachO_TwoLevelHints> for TwoLevelHints<'_> {
fn from_ffi(cmd: cxx::UniquePtr<ffi::MachO_TwoLevelHints>) -> Self {
Self {
ptr: cmd,
_owner: PhantomData
}
}
}
impl Command for TwoLevelHints<'_> {
fn get_base(&self) -> &ffi::MachO_Command {
self.ptr.as_ref().unwrap().as_ref()
}
}
@@ -0,0 +1,42 @@
use super::Command;
use lief_ffi as ffi;
use crate::common::FromFFI;
use std::marker::PhantomData;
pub struct UUID<'a> {
ptr: cxx::UniquePtr<ffi::MachO_UUIDCommand>,
_owner: PhantomData<&'a ffi::MachO_Binary>
}
impl UUID<'_> {
pub fn uuid(&self) -> Vec<u64> {
Vec::from(self.ptr.uuid().as_slice())
}
}
impl std::fmt::Debug for UUID<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn Command;
f.debug_struct("UUID")
.field("base", &base)
.field("uuid", &self.uuid())
.finish()
}
}
impl FromFFI<ffi::MachO_UUIDCommand> for UUID<'_> {
fn from_ffi(cmd: cxx::UniquePtr<ffi::MachO_UUIDCommand>) -> Self {
Self {
ptr: cmd,
_owner: PhantomData
}
}
}
impl Command for UUID<'_> {
fn get_base(&self) -> &ffi::MachO_Command {
self.ptr.as_ref().unwrap().as_ref()
}
}
@@ -0,0 +1,46 @@
use super::Command;
use lief_ffi as ffi;
use crate::common::FromFFI;
use std::marker::PhantomData;
pub struct VersionMin<'a> {
ptr: cxx::UniquePtr<ffi::MachO_VersionMin>,
_owner: PhantomData<&'a ffi::MachO_Binary>
}
impl VersionMin<'_> {
pub fn version(&self) -> Vec<u64> {
Vec::from(self.ptr.version().as_slice())
}
pub fn sdk(&self) -> Vec<u64> {
Vec::from(self.ptr.sdk().as_slice())
}
}
impl std::fmt::Debug for VersionMin<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn Command;
f.debug_struct("VersionMin")
.field("base", &base)
.field("version", &self.version())
.field("sdk", &self.sdk())
.finish()
}
}
impl FromFFI<ffi::MachO_VersionMin> for VersionMin<'_> {
fn from_ffi(cmd: cxx::UniquePtr<ffi::MachO_VersionMin>) -> Self {
Self {
ptr: cmd,
_owner: PhantomData
}
}
}
impl Command for VersionMin<'_> {
fn get_base(&self) -> &ffi::MachO_Command {
self.ptr.as_ref().unwrap().as_ref()
}
}
@@ -0,0 +1,86 @@
use lief_ffi as ffi;
use std::{fmt, marker::PhantomData};
use crate::common::{into_optional, FromFFI};
use super::{commands::Dylib, Symbol};
pub struct ExportInfo<'a> {
ptr: cxx::UniquePtr<ffi::MachO_ExportInfo>,
_owner: PhantomData<&'a ()>,
}
#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum KIND {
REGULAR,
THREAD_LOCAL,
ABSOLUTE,
UNKNOWN(u64),
}
impl KIND {
pub fn from_value(value: u64) -> Self {
match value {
0x00000000 => KIND::REGULAR,
0x00000001 => KIND::THREAD_LOCAL,
0x00000002 => KIND::ABSOLUTE,
_ => KIND::UNKNOWN(value),
}
}
}
impl fmt::Debug for ExportInfo<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ExportInfo")
.field("node_offset", &self.node_offset())
.field("flags", &self.flags())
.field("address", &self.address())
.field("other", &self.other())
.field("kind", &self.kind())
.finish()
}
}
impl ExportInfo<'_> {
pub fn node_offset(&self) -> u64 {
self.ptr.node_offset()
}
pub fn flags(&self) -> u64 {
self.ptr.flags()
}
pub fn address(&self) -> u64 {
self.ptr.address()
}
pub fn other(&self) -> u64 {
self.ptr.other()
}
pub fn kind(&self) -> KIND {
KIND::from_value(self.ptr.other())
}
pub fn symbol(&self) -> Option<Symbol> {
into_optional(self.ptr.symbol())
}
pub fn alias(&self) -> Option<Symbol> {
into_optional(self.ptr.alias())
}
pub fn alias_library(&self) -> Option<Dylib> {
into_optional(self.ptr.alias_library())
}
}
impl<'a> FromFFI<ffi::MachO_ExportInfo> for ExportInfo<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_ExportInfo>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
@@ -0,0 +1,59 @@
use super::binary::Binary;
use lief_ffi as ffi;
use crate::common::FromFFI;
pub struct FatBinary {
pub nb_macho: u32,
ptr: cxx::UniquePtr<ffi::MachO_FatBinary>,
}
impl FromFFI<ffi::MachO_FatBinary> for FatBinary {
fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_FatBinary>) -> Self {
Self {
nb_macho: ptr.size(),
ptr,
}
}
}
impl std::fmt::Debug for FatBinary {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("FatBinary")
.field("nb_macho", &self.nb_macho)
.finish()
}
}
pub struct FatBinaryIterator<'a> {
index: u32,
fat: &'a FatBinary,
}
impl FatBinary {
pub fn parse(path: &str) -> FatBinary {
let bin = ffi::MachO_FatBinary::parse(path);
FatBinary {
nb_macho: bin.size(),
ptr: bin,
}
}
pub fn iter(&self) -> FatBinaryIterator {
FatBinaryIterator {
index: 0,
fat: self,
}
}
}
impl<'a> Iterator for FatBinaryIterator<'a> {
type Item = Binary;
fn next(&mut self) -> Option<Self::Item> {
if self.index >= self.fat.nb_macho {
return None;
}
self.index += 1;
Some(Binary::from_ffi(self.fat.ptr.binary_at(self.index - 1)))
}
}
+221
View File
@@ -0,0 +1,221 @@
use std::marker::PhantomData;
use super::commands::segment::Segment;
use super::section::Section;
use super::symbol::Symbol;
use crate::common::{into_optional, FromFFI};
use crate::declare_iterator;
use crate::generic;
use lief_ffi as ffi;
#[derive(Debug)]
pub enum Relocation<'a> {
Generic(Generic<'a>),
Dyld(Dyld<'a>),
Fixup(Fixup<'a>),
Object(Object<'a>),
}
impl<'a> FromFFI<ffi::MachO_Relocation> for Relocation<'a> {
fn from_ffi(ffi_entry: cxx::UniquePtr<ffi::MachO_Relocation>) -> Self {
unsafe {
let cmd_ref = ffi_entry.as_ref().unwrap();
if ffi::MachO_RelocationDyld::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::MachO_Relocation>;
type To = cxx::UniquePtr<ffi::MachO_RelocationDyld>;
std::mem::transmute::<From, To>(ffi_entry)
};
Relocation::Dyld(Dyld::from_ffi(raw))
} else if ffi::MachO_RelocationFixup::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::MachO_Relocation>;
type To = cxx::UniquePtr<ffi::MachO_RelocationFixup>;
std::mem::transmute::<From, To>(ffi_entry)
};
Relocation::Fixup(Fixup::from_ffi(raw))
} else if ffi::MachO_RelocationObject::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::MachO_Relocation>;
type To = cxx::UniquePtr<ffi::MachO_RelocationObject>;
std::mem::transmute::<From, To>(ffi_entry)
};
Relocation::Object(Object::from_ffi(raw))
} else {
Relocation::Generic(Generic::from_ffi(ffi_entry))
}
}
}
}
pub trait RelocationBase {
#[doc(hidden)]
fn get_base(&self) -> &ffi::MachO_Relocation;
fn is_pc_relative(&self) -> bool {
self.get_base().is_pc_relative()
}
fn symbol(&self) -> Option<Symbol> {
into_optional(self.get_base().symbol())
}
fn section(&self) -> Option<Section> {
into_optional(self.get_base().section())
}
fn segment(&self) -> Option<Segment> {
into_optional(self.get_base().segment())
}
}
impl std::fmt::Debug for &dyn RelocationBase {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Section")
.field("is_pc_relative", &self.is_pc_relative())
.field("symbol", &self.symbol())
.field("section", &self.section())
.field("segment", &self.segment())
.finish()
}
}
pub struct Generic<'a> {
ptr: cxx::UniquePtr<ffi::MachO_Relocation>,
_owner: PhantomData<&'a ()>,
}
impl RelocationBase for Generic<'_> {
fn get_base(&self) -> &ffi::MachO_Relocation {
self.ptr.as_ref().unwrap()
}
}
impl generic::Relocation for Generic<'_> {
fn as_generic(&self) -> &ffi::AbstractRelocation {
self.ptr.as_ref().unwrap().as_ref()
}
}
impl std::fmt::Debug for Generic<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn RelocationBase;
f.debug_struct("Generic").field("base", &base).finish()
}
}
impl FromFFI<ffi::MachO_Relocation> for Generic<'_> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_Relocation>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
pub struct Dyld<'a> {
ptr: cxx::UniquePtr<ffi::MachO_RelocationDyld>,
_owner: PhantomData<&'a ()>,
}
impl FromFFI<ffi::MachO_RelocationDyld> for Dyld<'_> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_RelocationDyld>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
impl RelocationBase for Dyld<'_> {
fn get_base(&self) -> &ffi::MachO_Relocation {
self.ptr.as_ref().unwrap().as_ref()
}
}
impl std::fmt::Debug for Dyld<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn RelocationBase;
f.debug_struct("Dyld").field("base", &base).finish()
}
}
pub struct Fixup<'a> {
ptr: cxx::UniquePtr<ffi::MachO_RelocationFixup>,
_owner: PhantomData<&'a ()>,
}
impl Fixup<'_> {
pub fn target(&self) -> u64 {
self.ptr.target()
}
pub fn ptr_format(&self) -> u32 {
self.ptr.ptr_format()
}
pub fn offset(&self) -> u32 {
self.ptr.offset()
}
}
impl FromFFI<ffi::MachO_RelocationFixup> for Fixup<'_> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_RelocationFixup>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
impl RelocationBase for Fixup<'_> {
fn get_base(&self) -> &ffi::MachO_Relocation {
self.ptr.as_ref().unwrap().as_ref()
}
}
impl std::fmt::Debug for Fixup<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn RelocationBase;
f.debug_struct("Fixup")
.field("base", &base)
.field("target", &self.target())
.field("ptr_format", &self.ptr_format())
.field("offset", &self.offset())
.finish()
}
}
pub struct Object<'a> {
ptr: cxx::UniquePtr<ffi::MachO_RelocationObject>,
_owner: PhantomData<&'a ()>,
}
impl FromFFI<ffi::MachO_RelocationObject> for Object<'_> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_RelocationObject>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
impl RelocationBase for Object<'_> {
fn get_base(&self) -> &ffi::MachO_Relocation {
self.ptr.as_ref().unwrap().as_ref()
}
}
impl std::fmt::Debug for Object<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn RelocationBase;
f.debug_struct("Object").field("base", &base).finish()
}
}
declare_iterator!(
Relocations,
Relocation<'a>,
ffi::MachO_Relocation,
ffi::MachO_Binary,
ffi::MachO_Binary_it_relocations
);
+175
View File
@@ -0,0 +1,175 @@
use super::commands::segment::Segment;
use super::Relocation;
use lief_ffi as ffi;
use std::fmt;
use std::marker::PhantomData;
use crate::common::{into_optional, FromFFI};
use crate::declare_iterator;
use crate::generic;
pub struct Section<'a> {
ptr: cxx::UniquePtr<ffi::MachO_Section>,
_owner: PhantomData<&'a ()>,
}
#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum TYPE {
REGULAR,
ZEROFILL,
CSTRING_LITERALS,
S_4BYTE_LITERALS,
S_8BYTE_LITERALS,
LITERAL_POINTERS,
NON_LAZY_SYMBOL_POINTERS,
LAZY_SYMBOL_POINTERS,
SYMBOL_STUBS,
MOD_INIT_FUNC_POINTERS,
MOD_TERM_FUNC_POINTERS,
COALESCED,
GB_ZEROFILL,
INTERPOSING,
S_16BYTE_LITERALS,
DTRACE_DOF,
LAZY_DYLIB_SYMBOL_POINTERS,
THREAD_LOCAL_REGULAR,
THREAD_LOCAL_ZEROFILL,
THREAD_LOCAL_VARIABLES,
THREAD_LOCAL_VARIABLE_POINTERS,
THREAD_LOCAL_INIT_FUNCTION_POINTERS,
UNKNOWN(u64),
}
impl TYPE {
pub fn from_value(value: u64) -> Self {
match value {
0x00000000 => TYPE::REGULAR,
0x00000001 => TYPE::ZEROFILL,
0x00000002 => TYPE::CSTRING_LITERALS,
0x00000003 => TYPE::S_4BYTE_LITERALS,
0x00000004 => TYPE::S_8BYTE_LITERALS,
0x00000005 => TYPE::LITERAL_POINTERS,
0x00000006 => TYPE::NON_LAZY_SYMBOL_POINTERS,
0x00000007 => TYPE::LAZY_SYMBOL_POINTERS,
0x00000008 => TYPE::SYMBOL_STUBS,
0x00000009 => TYPE::MOD_INIT_FUNC_POINTERS,
0x0000000a => TYPE::MOD_TERM_FUNC_POINTERS,
0x0000000b => TYPE::COALESCED,
0x0000000c => TYPE::GB_ZEROFILL,
0x0000000d => TYPE::INTERPOSING,
0x0000000e => TYPE::S_16BYTE_LITERALS,
0x0000000f => TYPE::DTRACE_DOF,
0x00000010 => TYPE::LAZY_DYLIB_SYMBOL_POINTERS,
0x00000011 => TYPE::THREAD_LOCAL_REGULAR,
0x00000012 => TYPE::THREAD_LOCAL_ZEROFILL,
0x00000013 => TYPE::THREAD_LOCAL_VARIABLES,
0x00000014 => TYPE::THREAD_LOCAL_VARIABLE_POINTERS,
0x00000015 => TYPE::THREAD_LOCAL_INIT_FUNCTION_POINTERS,
_ => TYPE::UNKNOWN(value),
}
}
}
impl Section<'_> {
pub fn segment_name(&self) -> String {
self.ptr.segment_name().to_string()
}
pub fn address(&self) -> u64 {
self.ptr.address()
}
pub fn alignment(&self) -> u32 {
self.ptr.alignment()
}
pub fn relocation_offset(&self) -> u32 {
self.ptr.relocation_offset()
}
pub fn numberof_relocations(&self) -> u32 {
self.ptr.numberof_relocations()
}
pub fn raw_flags(&self) -> u32 {
self.ptr.raw_flags()
}
pub fn flags(&self) -> u32 {
self.ptr.flags()
}
pub fn section_type(&self) -> TYPE {
TYPE::from_value(self.ptr.section_type())
}
pub fn reserved1(&self) -> u32 {
self.ptr.reserved1()
}
pub fn reserved2(&self) -> u32 {
self.ptr.reserved2()
}
pub fn reserved3(&self) -> u32 {
self.ptr.reserved3()
}
pub fn segment(&self) -> Option<Segment> {
into_optional(self.ptr.segment())
}
pub fn relocations(&self) -> Relocations {
Relocations::new(self.ptr.relocations())
}
}
impl fmt::Debug for Section<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let base = self as &dyn generic::Section;
f.debug_struct("Section")
.field("base", &base)
.field("segment_name", &self.segment_name())
.field("address", &self.address())
.field("alignment", &self.alignment())
.field("relocation_offset", &self.relocation_offset())
.field("numberof_relocations", &self.numberof_relocations())
.field("raw_flags", &self.raw_flags())
.field("flags", &self.flags())
.field("type", &self.section_type())
.field("reserved1", &self.reserved1())
.field("reserved2", &self.reserved2())
.field("reserved3", &self.reserved3())
.finish()
}
}
impl<'a> FromFFI<ffi::MachO_Section> for Section<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_Section>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
impl generic::Section for Section<'_> {
fn as_generic(&self) -> &ffi::AbstractSection {
self.ptr.as_ref().unwrap().as_ref()
}
}
declare_iterator!(
Sections,
Section<'a>,
ffi::MachO_Section,
ffi::MachO_Binary,
ffi::MachO_Binary_it_sections
);
declare_iterator!(
Relocations,
Relocation<'a>,
ffi::MachO_Relocation,
ffi::MachO_Section,
ffi::MachO_Section_it_relocations
);
+134
View File
@@ -0,0 +1,134 @@
use std::marker::PhantomData;
use crate::common::{into_optional, FromFFI};
use crate::declare_iterator;
use crate::generic;
use lief_ffi as ffi;
use super::commands::Dylib;
use super::{BindingInfo, ExportInfo};
pub struct Symbol<'a> {
ptr: cxx::UniquePtr<ffi::MachO_Symbol>,
_owner: PhantomData<&'a ()>,
}
#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum CATEGORY {
NONE,
LOCAL,
EXTERNAL,
UNDEFINED,
INDIRECT_ABS,
INDIRECT_LOCAL,
UNKNOWN(u32),
}
impl CATEGORY {
pub fn from_value(value: u32) -> Self {
match value {
0x00000000 => CATEGORY::NONE,
0x00000001 => CATEGORY::LOCAL,
0x00000002 => CATEGORY::EXTERNAL,
0x00000003 => CATEGORY::UNDEFINED,
0x00000004 => CATEGORY::INDIRECT_ABS,
0x00000005 => CATEGORY::INDIRECT_LOCAL,
_ => CATEGORY::UNKNOWN(value),
}
}
}
#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum ORIGIN {
DYLD_EXPORT,
DYLD_BIND,
LC_SYMTAB,
UNKNOWN(u32),
}
impl ORIGIN {
pub fn from_value(value: u32) -> Self {
match value {
0x00000001 => ORIGIN::DYLD_EXPORT,
0x00000002 => ORIGIN::DYLD_BIND,
0x00000003 => ORIGIN::LC_SYMTAB,
_ => ORIGIN::UNKNOWN(value),
}
}
}
impl Symbol<'_> {
pub fn get_type(&self) -> u8 {
self.ptr.get_type()
}
pub fn numberof_sections(&self) -> u8 {
self.ptr.numberof_sections()
}
pub fn description(&self) -> u16 {
self.ptr.description()
}
pub fn origin(&self) -> ORIGIN {
ORIGIN::from_value(self.ptr.origin())
}
pub fn category(&self) -> CATEGORY {
CATEGORY::from_value(self.ptr.category())
}
pub fn export_info(&self) -> Option<ExportInfo> {
into_optional(self.ptr.export_info())
}
pub fn binding_info(&self) -> Option<BindingInfo> {
into_optional(self.ptr.binding_info())
}
pub fn library(&self) -> Option<Dylib> {
into_optional(self.ptr.library())
}
}
impl std::fmt::Debug for Symbol<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn generic::Symbol;
f.debug_struct("Symbol")
.field("base", &base)
.field("type", &self.get_type())
.field("numberof_sections", &self.numberof_sections())
.field("description", &self.description())
.field("origin", &self.origin())
.field("category", &self.category())
.field("export_info", &self.export_info())
.field("binding_info", &self.binding_info())
.field("library", &self.library())
.finish()
}
}
impl<'a> FromFFI<ffi::MachO_Symbol> for Symbol<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_Symbol>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
impl generic::Symbol for Symbol<'_> {
fn as_generic(&self) -> &ffi::AbstractSymbol {
self.ptr.as_ref().unwrap().as_ref()
}
}
declare_iterator!(
Symbols,
Symbol<'a>,
ffi::MachO_Symbol,
ffi::MachO_Binary,
ffi::MachO_Binary_it_symbols
);
+69
View File
@@ -0,0 +1,69 @@
pub mod binary;
pub mod data_directory;
pub mod debug;
pub mod delay_import;
pub mod export;
pub mod headers;
pub mod import;
pub mod load_configuration;
pub mod relocation;
pub mod resources;
pub mod rich_header;
pub mod section;
pub mod signature;
pub mod tls;
pub mod code_integrity;
#[doc(inline)]
pub use binary::Binary;
#[doc(inline)]
pub use data_directory::DataDirectory;
#[doc(inline)]
pub use delay_import::DelayImport;
#[doc(inline)]
pub use export::Export;
#[doc(inline)]
pub use headers::{DosHeader, Header, OptionalHeader};
#[doc(inline)]
pub use relocation::Relocation;
#[doc(inline)]
pub use resources::Manager as ResourcesManager;
#[doc(inline)]
pub use resources::Node as ResourceNode;
#[doc(inline)]
pub use rich_header::{RichEntry, RichHeader};
#[doc(inline)]
pub use section::Section;
#[doc(inline)]
pub use tls::TLS;
use num_derive::{FromPrimitive, ToPrimitive};
#[allow(non_camel_case_types)]
#[derive(FromPrimitive, ToPrimitive)]
#[repr(u32)]
pub enum Algorithms {
UNKNOWN = 0,
SHA_512,
SHA_384,
SHA_256,
SHA_1,
MD5,
MD4,
MD2,
RSA,
EC,
MD5_RSA,
SHA1_DSA,
SHA1_RSA,
SHA_256_RSA,
SHA_384_RSA,
SHA_512_RSA,
SHA1_ECDSA,
SHA_256_ECDSA,
SHA_384_ECDSA,
SHA_512_ECDSA,
}
+136
View File
@@ -0,0 +1,136 @@
use lief_ffi as ffi;
use super::data_directory::DataDirectories;
use super::debug;
use super::delay_import::DelayImports;
use super::export::Export;
use super::import::Imports;
use super::load_configuration::LoadConfiguration;
use super::relocation::Relocations;
use super::resources::Manager as ResourcesManager;
use super::resources::Node as ResourceNode;
use super::rich_header::RichHeader;
use super::section::Sections;
use super::signature::Signatures;
use super::tls::TLS;
use crate::common::{into_optional, FromFFI};
use crate::declare_iterator;
use crate::generic;
use crate::to_slice;
use super::Algorithms;
use super::{DosHeader, Header, OptionalHeader};
pub struct Binary {
ptr: cxx::UniquePtr<ffi::PE_Binary>,
}
impl FromFFI<ffi::PE_Binary> for Binary {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_Binary>) -> Self {
Self { ptr }
}
}
impl Binary {
pub fn parse(path: &str) -> Self {
let bin = ffi::PE_Binary::parse(path);
Self { ptr: bin }
}
pub fn dos_header(&self) -> DosHeader {
DosHeader::from_ffi(self.ptr.dos_header())
}
pub fn optional_header(&self) -> OptionalHeader {
OptionalHeader::from_ffi(self.ptr.optional_header())
}
pub fn header(&self) -> Header {
Header::from_ffi(self.ptr.header())
}
pub fn tls(&self) -> Option<TLS> {
into_optional(self.ptr.tls())
}
pub fn rich_header(&self) -> Option<RichHeader> {
into_optional(self.ptr.rich_header())
}
pub fn export(&self) -> Option<Export> {
into_optional(self.ptr.get_export())
}
pub fn resources(&self) -> Option<ResourceNode> {
into_optional(self.ptr.resources())
}
pub fn resources_manager(&self) -> Option<ResourcesManager> {
into_optional(self.ptr.resources_manager())
}
pub fn imports(&self) -> Imports {
Imports::new(self.ptr.imports())
}
pub fn data_directories(&self) -> DataDirectories {
DataDirectories::new(self.ptr.data_directories())
}
pub fn sections(&self) -> Sections {
Sections::new(self.ptr.sections())
}
pub fn relocations(&self) -> Relocations {
Relocations::new(self.ptr.relocations())
}
pub fn delay_imports(&self) -> DelayImports {
DelayImports::new(self.ptr.delay_imports())
}
pub fn signatures(&self) -> Signatures {
Signatures::new(self.ptr.signatures())
}
pub fn debug(&self) -> DebugEntries {
DebugEntries::new(self.ptr.debug())
}
pub fn authentihash(&self, algo: Algorithms) -> Vec<u8> {
Vec::from(self.ptr.authentihash(algo as u32).as_slice())
}
pub fn load_configuration(&self) -> Option<LoadConfiguration> {
into_optional(self.ptr.load_configuration())
}
pub fn dos_stub(&self) -> &[u8] {
to_slice!(self.ptr.dos_stub());
}
pub fn overlay(&self) -> &[u8] {
to_slice!(self.ptr.overlay());
}
}
impl std::fmt::Debug for Binary {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Binary").finish()
}
}
impl generic::Binary for Binary {
fn as_generic(&self) -> &ffi::AbstractBinary {
self.ptr.as_ref().unwrap().as_ref()
}
}
declare_iterator!(
DebugEntries,
debug::Entries<'a>,
ffi::PE_Debug,
ffi::PE_Binary,
ffi::PE_Binary_it_debug
);
@@ -0,0 +1,44 @@
use lief_ffi as ffi;
use crate::common::FromFFI;
use std::marker::PhantomData;
pub struct CodeIntegrity<'a> {
ptr: cxx::UniquePtr<ffi::PE_CodeIntegrity>,
_owner: PhantomData<&'a ffi::PE_LoadConfigurationV2>,
}
impl std::fmt::Debug for CodeIntegrity<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("CodeIntegrity")
.field("flags", &self.flags())
.field("catalog", &self.catalog())
.field("catalog_offset", &self.catalog_offset())
.field("reserved", &self.reserved())
.finish()
}
}
impl CodeIntegrity<'_> {
pub fn flags(&self) -> u16 {
self.ptr.flags()
}
pub fn catalog(&self) -> u16 {
self.ptr.catalog()
}
pub fn catalog_offset(&self) -> u32 {
self.ptr.catalog_offset()
}
pub fn reserved(&self) -> u32 {
self.ptr.reserved()
}
}
impl<'a> FromFFI<ffi::PE_CodeIntegrity> for CodeIntegrity<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_CodeIntegrity>) -> Self {
CodeIntegrity {
ptr,
_owner: PhantomData,
}
}
}
@@ -0,0 +1,101 @@
use std::marker::PhantomData;
use crate::common::into_optional;
use crate::common::FromFFI;
use crate::declare_iterator;
use crate::pe::Section;
use lief_ffi as ffi;
pub struct DataDirectory<'a> {
ptr: cxx::UniquePtr<ffi::PE_DataDirectory>,
_owner: PhantomData<&'a ffi::PE_Binary>,
}
#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone)]
pub enum Type {
EXPORT_TABLE,
IMPORT_TABLE,
RESOURCE_TABLE,
EXCEPTION_TABLE,
CERTIFICATE_TABLE,
BASE_RELOCATION_TABLE,
DEBUG,
ARCHITECTURE,
GLOBAL_PTR,
TLS_TABLE,
LOAD_CONFIG_TABLE,
BOUND_IMPORT,
IAT,
DELAY_IMPORT_DESCRIPTOR,
CLR_RUNTIME_HEADER,
RESERVED,
UNKNOWN(u64),
}
impl Type {
pub fn from_value(value: u64) -> Self {
match value {
0x00000000 => Type::EXPORT_TABLE,
0x00000001 => Type::IMPORT_TABLE,
0x00000002 => Type::RESOURCE_TABLE,
0x00000003 => Type::EXCEPTION_TABLE,
0x00000004 => Type::CERTIFICATE_TABLE,
0x00000005 => Type::BASE_RELOCATION_TABLE,
0x00000006 => Type::DEBUG,
0x00000007 => Type::ARCHITECTURE,
0x00000008 => Type::GLOBAL_PTR,
0x00000009 => Type::TLS_TABLE,
0x0000000a => Type::LOAD_CONFIG_TABLE,
0x0000000b => Type::BOUND_IMPORT,
0x0000000c => Type::IAT,
0x0000000d => Type::DELAY_IMPORT_DESCRIPTOR,
0x0000000e => Type::CLR_RUNTIME_HEADER,
0x0000000f => Type::RESERVED,
_ => Type::UNKNOWN(value),
}
}
}
impl std::fmt::Debug for DataDirectory<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("DataDirectory")
.field("type", &self.get_type())
.field("rva", &self.rva())
.field("size", &self.size())
.field("section", &self.section())
.finish()
}
}
impl<'a> FromFFI<ffi::PE_DataDirectory> for DataDirectory<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_DataDirectory>) -> Self {
DataDirectory {
ptr,
_owner: PhantomData,
}
}
}
impl DataDirectory<'_> {
pub fn rva(&self) -> u32 {
self.ptr.RVA()
}
pub fn size(&self) -> u32 {
self.ptr.size()
}
pub fn get_type(&self) -> Type {
Type::from_value(self.ptr.get_type().into())
}
pub fn section(&self) -> Option<Section> {
into_optional(self.ptr.section())
}
}
declare_iterator!(
DataDirectories,
DataDirectory<'a>,
ffi::PE_DataDirectory,
ffi::PE_Binary,
ffi::PE_Binary_it_data_directories
);
+349
View File
@@ -0,0 +1,349 @@
use std::marker::PhantomData;
use crate::declare_iterator;
use crate::{common::FromFFI, to_slice};
use lief_ffi as ffi;
#[derive(Debug)]
pub enum Entries<'a> {
Generic(Generic<'a>),
CodeView(CodeView<'a>),
CodeViewPDB(CodeViewPDB<'a>),
Repro(Repro<'a>),
Pogo(Pogo<'a>),
}
#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone)]
pub enum Type {
COFF,
CODEVIEW,
FPO,
MISC,
EXCEPTION,
FIXUP,
OMAP_TO_SRC,
OMAP_FROM_SRC,
BORLAND,
RESERVED10,
CLSID,
VC_FEATURE,
POGO,
ILTCG,
MPX,
REPRO,
EX_DLLCHARACTERISTICS,
UNKNOWN(u32),
}
impl Type {
pub fn from_value(value: u32) -> Self {
match value {
0x00000001 => Type::COFF,
0x00000002 => Type::CODEVIEW,
0x00000003 => Type::FPO,
0x00000004 => Type::MISC,
0x00000005 => Type::EXCEPTION,
0x00000006 => Type::FIXUP,
0x00000007 => Type::OMAP_TO_SRC,
0x00000008 => Type::OMAP_FROM_SRC,
0x00000009 => Type::BORLAND,
0x0000000a => Type::RESERVED10,
0x0000000b => Type::CLSID,
0x0000000c => Type::VC_FEATURE,
0x0000000d => Type::POGO,
0x0000000e => Type::ILTCG,
0x0000000f => Type::MPX,
0x00000010 => Type::REPRO,
0x00000014 => Type::EX_DLLCHARACTERISTICS,
_ => Type::UNKNOWN(value),
}
}
}
pub trait DebugEntry {
#[doc(hidden)]
fn get_base(&self) -> &ffi::PE_Debug;
fn characteristics(&self) -> u32 {
self.get_base().characteristics()
}
fn timestamp(&self) -> u32 {
self.get_base().timestamp()
}
fn major_version(&self) -> u16 {
self.get_base().major_version()
}
fn minor_version(&self) -> u16 {
self.get_base().minor_version()
}
fn get_type(&self) -> Type {
Type::from_value(self.get_base().get_type())
}
fn sizeof_data(&self) -> u32 {
self.get_base().sizeof_data()
}
fn addressof_rawdata(&self) -> u32 {
self.get_base().addressof_rawdata()
}
fn pointerto_rawdata(&self) -> u32 {
self.get_base().pointerto_rawdata()
}
}
impl std::fmt::Debug for &dyn DebugEntry {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("DebugEntry")
.field("characteristics", &self.characteristics())
.field("timestamp", &self.timestamp())
.field("major_version", &self.major_version())
.field("minor_version", &self.minor_version())
.field("type", &self.get_type())
.field("sizeof_data", &self.sizeof_data())
.field("addressof_rawdata", &self.addressof_rawdata())
.field("pointerto_rawdata", &self.pointerto_rawdata())
.finish()
}
}
impl<'a> FromFFI<ffi::PE_Debug> for Entries<'a> {
fn from_ffi(ffi_entry: cxx::UniquePtr<ffi::PE_Debug>) -> Self {
unsafe {
let debug_ref = ffi_entry.as_ref().unwrap();
if ffi::PE_Pogo::classof(debug_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::PE_Debug>;
type To = cxx::UniquePtr<ffi::PE_Pogo>;
std::mem::transmute::<From, To>(ffi_entry)
};
Entries::Pogo(Pogo::from_ffi(raw))
} else if ffi::PE_CodeViewPDB::classof(debug_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::PE_Debug>;
type To = cxx::UniquePtr<ffi::PE_CodeViewPDB>;
std::mem::transmute::<From, To>(ffi_entry)
};
Entries::CodeViewPDB(CodeViewPDB::from_ffi(raw))
} else if ffi::PE_Repro::classof(debug_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::PE_Debug>;
type To = cxx::UniquePtr<ffi::PE_Repro>;
std::mem::transmute::<From, To>(ffi_entry)
};
Entries::Repro(Repro::from_ffi(raw))
} else if ffi::PE_CodeView::classof(debug_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::PE_Debug>;
type To = cxx::UniquePtr<ffi::PE_CodeView>;
std::mem::transmute::<From, To>(ffi_entry)
};
Entries::CodeView(CodeView::from_ffi(raw))
} else {
Entries::Generic(Generic::from_ffi(ffi_entry))
}
}
}
}
pub struct Generic<'a> {
ptr: cxx::UniquePtr<ffi::PE_Debug>,
_owner: PhantomData<&'a ffi::PE_Binary>,
}
impl<'a> FromFFI<ffi::PE_Debug> for Generic<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_Debug>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
impl DebugEntry for Generic<'_> {
fn get_base(&self) -> &ffi::PE_Debug {
self.ptr.as_ref().unwrap()
}
}
impl std::fmt::Debug for Generic<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn DebugEntry;
f.debug_struct("Generic").field("base", &base).finish()
}
}
pub struct Pogo<'a> {
ptr: cxx::UniquePtr<ffi::PE_Pogo>,
_owner: PhantomData<&'a ffi::PE_Binary>,
}
impl Pogo<'_> {
pub fn entries(&self) -> PogoEntries {
PogoEntries::new(self.ptr.entries())
}
}
impl<'a> FromFFI<ffi::PE_Pogo> for Pogo<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_Pogo>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
impl DebugEntry for Pogo<'_> {
fn get_base(&self) -> &ffi::PE_Debug {
self.ptr.as_ref().unwrap().as_ref()
}
}
impl std::fmt::Debug for Pogo<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn DebugEntry;
f.debug_struct("Pogo").field("base", &base).finish()
}
}
pub struct PogoEntry<'a> {
ptr: cxx::UniquePtr<ffi::PE_PogoEntry>,
_owner: PhantomData<&'a ffi::PE_Pogo>,
}
impl<'a> FromFFI<ffi::PE_PogoEntry> for PogoEntry<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_PogoEntry>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
impl PogoEntry<'_> {
pub fn start_rva(&self) -> u32 {
self.ptr.start_rva()
}
pub fn size(&self) -> u32 {
self.ptr.size()
}
pub fn name(&self) -> String {
self.ptr.name().to_string()
}
}
impl std::fmt::Debug for PogoEntry<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("PogoEntry")
.field("name", &self.name())
.field("size", &self.size())
.field("start_rva", &self.start_rva())
.finish()
}
}
pub struct CodeView<'a> {
ptr: cxx::UniquePtr<ffi::PE_CodeView>,
_owner: PhantomData<&'a ffi::PE_Binary>,
}
impl<'a> FromFFI<ffi::PE_CodeView> for CodeView<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_CodeView>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
impl DebugEntry for CodeView<'_> {
fn get_base(&self) -> &ffi::PE_Debug {
self.ptr.as_ref().unwrap().as_ref()
}
}
impl std::fmt::Debug for CodeView<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("CodeView").finish()
}
}
pub struct CodeViewPDB<'a> {
ptr: cxx::UniquePtr<ffi::PE_CodeViewPDB>,
_owner: PhantomData<&'a ffi::PE_Binary>,
}
impl<'a> FromFFI<ffi::PE_CodeViewPDB> for CodeViewPDB<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_CodeViewPDB>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
impl CodeViewPDB<'_> {
pub fn age(&self) -> u32 {
self.ptr.age()
}
pub fn filename(&self) -> String {
self.ptr.filename().to_string()
}
}
impl DebugEntry for CodeViewPDB<'_> {
fn get_base(&self) -> &ffi::PE_Debug {
self.ptr.as_ref().unwrap().as_ref().as_ref()
}
}
impl std::fmt::Debug for CodeViewPDB<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn DebugEntry;
f.debug_struct("CodeViewPDB")
.field("base", &base)
.field("age", &self.age())
.field("filename", &self.filename())
.finish()
}
}
pub struct Repro<'a> {
ptr: cxx::UniquePtr<ffi::PE_Repro>,
_owner: PhantomData<&'a ffi::PE_Binary>,
}
impl<'a> FromFFI<ffi::PE_Repro> for Repro<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_Repro>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
impl Repro<'_> {
pub fn hash(&self) -> &[u8] {
to_slice!(self.ptr.hash());
}
}
impl DebugEntry for Repro<'_> {
fn get_base(&self) -> &ffi::PE_Debug {
self.ptr.as_ref().unwrap().as_ref()
}
}
impl std::fmt::Debug for Repro<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn DebugEntry;
f.debug_struct("Repro").field("base", &base).finish()
}
}
declare_iterator!(
PogoEntries,
PogoEntry<'a>,
ffi::PE_PogoEntry,
ffi::PE_Pogo,
ffi::PE_Pogo_it_entries
);
+134
View File
@@ -0,0 +1,134 @@
use std::marker::PhantomData;
use crate::{common::FromFFI, declare_iterator, generic};
use lief_ffi as ffi;
pub struct DelayImport<'a> {
ptr: cxx::UniquePtr<ffi::PE_DelayImport>,
_owner: PhantomData<&'a ffi::PE_Binary>,
}
impl DelayImport<'_> {
pub fn attribute(&self) -> u32 {
self.ptr.attribute()
}
pub fn name(&self) -> String {
self.ptr.name().to_string()
}
pub fn handle(&self) -> u32 {
self.ptr.handle()
}
pub fn iat(&self) -> u32 {
self.ptr.iat()
}
pub fn names_table(&self) -> u32 {
self.ptr.names_table()
}
pub fn biat(&self) -> u32 {
self.ptr.biat()
}
pub fn uiat(&self) -> u32 {
self.ptr.uiat()
}
pub fn timestamp(&self) -> u32 {
self.ptr.timestamp()
}
pub fn entries(&self) -> Entries {
Entries::new(self.ptr.entries())
}
}
impl std::fmt::Debug for DelayImport<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("DelayImport")
.field("attribute", &self.attribute())
.field("name", &self.name())
.field("handle", &self.handle())
.field("iat", &self.iat())
.field("names_table", &self.names_table())
.field("biat", &self.biat())
.field("uiat", &self.uiat())
.field("timestamp", &self.timestamp())
.finish()
}
}
impl<'a> FromFFI<ffi::PE_DelayImport> for DelayImport<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_DelayImport>) -> Self {
DelayImport {
ptr,
_owner: PhantomData,
}
}
}
pub struct DelayImportEntry<'a> {
ptr: cxx::UniquePtr<ffi::PE_DelayImportEntry>,
_owner: PhantomData<&'a ffi::PE_DelayImport>,
}
impl DelayImportEntry<'_> {
pub fn is_ordinal(&self) -> bool {
self.ptr.is_ordinal()
}
pub fn ordinal(&self) -> u16 {
self.ptr.ordinal()
}
pub fn hint_name_rva(&self) -> u64 {
self.ptr.hint_name_rva()
}
pub fn hint(&self) -> u16 {
self.ptr.hint()
}
pub fn iat_value(&self) -> u64 {
self.ptr.iat_value()
}
pub fn data(&self) -> u64 {
self.ptr.data()
}
}
impl generic::Symbol for DelayImportEntry<'_> {
fn as_generic(&self) -> &ffi::AbstractSymbol {
self.ptr.as_ref().unwrap().as_ref()
}
}
impl std::fmt::Debug for DelayImportEntry<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn generic::Symbol;
f.debug_struct("DelayImportEntry")
.field("base", &base)
.field("ordinal", &self.ordinal())
.field("hint_name_rva", &self.hint_name_rva())
.field("hint", &self.hint())
.field("iat_value", &self.iat_value())
.field("data", &self.data())
.finish()
}
}
impl<'a> FromFFI<ffi::PE_DelayImportEntry> for DelayImportEntry<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_DelayImportEntry>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
declare_iterator!(
DelayImports,
DelayImport<'a>,
ffi::PE_DelayImport,
ffi::PE_Binary,
ffi::PE_Binary_it_delay_imports
);
declare_iterator!(
Entries,
DelayImportEntry<'a>,
ffi::PE_DelayImportEntry,
ffi::PE_DelayImport,
ffi::PE_DelayImport_it_entries
);
+113
View File
@@ -0,0 +1,113 @@
use lief_ffi as ffi;
use crate::common::FromFFI;
use crate::declare_iterator;
use crate::generic;
use std::marker::PhantomData;
pub struct Export<'a> {
ptr: cxx::UniquePtr<ffi::PE_Export>,
_owner: PhantomData<&'a ffi::PE_Binary>,
}
impl Export<'_> {
pub fn export_flags(&self) -> u32 {
self.ptr.export_flags()
}
pub fn timestamp(&self) -> u32 {
self.ptr.timestamp()
}
pub fn major_version(&self) -> u32 {
self.ptr.major_version()
}
pub fn minor_version(&self) -> u32 {
self.ptr.minor_version()
}
pub fn ordinal_base(&self) -> u32 {
self.ptr.ordinal_base()
}
pub fn name(&self) -> String {
self.ptr.name().to_string()
}
pub fn entries(&self) -> ExportEntries {
ExportEntries::new(self.ptr.entries())
}
}
impl std::fmt::Debug for Export<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Export")
.field("export_flags", &self.export_flags())
.field("timestamp", &self.timestamp())
.field("major_version", &self.major_version())
.field("minor_version", &self.minor_version())
.field("ordinal_base", &self.ordinal_base())
.field("name", &self.name())
.finish()
}
}
impl<'a> FromFFI<ffi::PE_Export> for Export<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_Export>) -> Self {
Export {
ptr,
_owner: PhantomData,
}
}
}
pub struct Entry<'a> {
ptr: cxx::UniquePtr<ffi::PE_ExportEntry>,
_owner: PhantomData<&'a ffi::PE_Export>,
}
impl Entry<'_> {
pub fn ordinal(&self) -> u16 {
self.ptr.ordinal()
}
pub fn address(&self) -> u32 {
self.ptr.address()
}
pub fn is_extern(&self) -> bool {
self.ptr.is_extern()
}
pub fn is_forwarded(&self) -> bool {
self.ptr.is_forwarded()
}
}
impl generic::Symbol for Entry<'_> {
fn as_generic(&self) -> &ffi::AbstractSymbol {
self.ptr.as_ref().unwrap().as_ref()
}
}
impl std::fmt::Debug for Entry<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn generic::Symbol;
f.debug_struct("ExportEntry")
.field("base", &base)
.field("ordinal", &self.ordinal())
.field("address", &self.address())
.finish()
}
}
impl<'a> FromFFI<ffi::PE_ExportEntry> for Entry<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ExportEntry>) -> Self {
Entry {
ptr,
_owner: PhantomData,
}
}
}
declare_iterator!(
ExportEntries,
Entry<'a>,
ffi::PE_ExportEntry,
ffi::PE_Export,
ffi::PE_Export_it_entries
);
+367
View File
@@ -0,0 +1,367 @@
use std::marker::PhantomData;
use crate::common::FromFFI;
use lief_ffi as ffi;
pub struct DosHeader<'a> {
ptr: cxx::UniquePtr<ffi::PE_DosHeader>,
_owner: PhantomData<&'a ffi::PE_Binary>,
}
impl FromFFI<ffi::PE_DosHeader> for DosHeader<'_> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_DosHeader>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
impl<'a> DosHeader<'a> {
pub fn magic(&self) -> u16 {
self.ptr.magic()
}
pub fn used_bytes_in_last_page(&self) -> u16 {
self.ptr.used_bytes_in_last_page()
}
pub fn file_size_in_pages(&self) -> u16 {
self.ptr.file_size_in_pages()
}
pub fn numberof_relocation(&self) -> u16 {
self.ptr.numberof_relocation()
}
pub fn header_size_in_paragraphs(&self) -> u16 {
self.ptr.header_size_in_paragraphs()
}
pub fn minimum_extra_paragraphs(&self) -> u16 {
self.ptr.minimum_extra_paragraphs()
}
pub fn maximum_extra_paragraphs(&self) -> u16 {
self.ptr.maximum_extra_paragraphs()
}
pub fn initial_relative_ss(&self) -> u16 {
self.ptr.initial_relative_ss()
}
pub fn initial_sp(&self) -> u16 {
self.ptr.initial_sp()
}
pub fn checksum(&self) -> u16 {
self.ptr.checksum()
}
pub fn initial_ip(&self) -> u16 {
self.ptr.initial_ip()
}
pub fn initial_relative_cs(&self) -> u16 {
self.ptr.initial_relative_cs()
}
pub fn addressof_relocation_table(&self) -> u16 {
self.ptr.addressof_relocation_table()
}
pub fn overlay_number(&self) -> u16 {
self.ptr.overlay_number()
}
pub fn reserved(&self) -> Vec<u16> {
Vec::from_iter(self.ptr.reserved().iter().map(|x| *x as u16))
}
pub fn oem_id(&self) -> u16 {
self.ptr.oem_id()
}
pub fn oem_info(&self) -> u16 {
self.ptr.oem_info()
}
pub fn reserved2(&self) -> Vec<u16> {
Vec::from_iter(self.ptr.reserved().iter().map(|x| *x as u16))
}
pub fn addressof_new_exeheader(&self) -> u32 {
self.ptr.addressof_new_exeheader()
}
}
impl std::fmt::Debug for DosHeader<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("DosHeader")
.field("magic", &self.magic())
.field("used_bytes_in_last_page", &self.used_bytes_in_last_page())
.field("file_size_in_pages", &self.file_size_in_pages())
.field("numberof_relocation", &self.numberof_relocation())
.field(
"header_size_in_paragraphs",
&self.header_size_in_paragraphs(),
)
.field("minimum_extra_paragraphs", &self.minimum_extra_paragraphs())
.field("maximum_extra_paragraphs", &self.maximum_extra_paragraphs())
.field("initial_relative_ss", &self.initial_relative_ss())
.field("initial_sp", &self.initial_sp())
.field("checksum", &self.checksum())
.field("initial_ip", &self.initial_ip())
.field("initial_relative_cs", &self.initial_relative_cs())
.field(
"addressof_relocation_table",
&self.addressof_relocation_table(),
)
.field("overlay_number", &self.overlay_number())
.field("reserved", &self.reserved())
.field("oem_info", &self.oem_info())
.field("oem_id", &self.oem_id())
.field("reserved2", &self.reserved2())
.field("addressof_new_exeheader", &self.addressof_new_exeheader())
.finish()
}
}
pub struct Header<'a> {
ptr: cxx::UniquePtr<ffi::PE_Header>,
_owner: PhantomData<&'a ffi::PE_Binary>,
}
impl FromFFI<ffi::PE_Header> for Header<'_> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_Header>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
impl Header<'_> {
pub fn machine(&self) -> u32 {
self.ptr.machine()
}
pub fn nb_sections(&self) -> u16 {
self.ptr.numberof_sections()
}
pub fn time_date_stamp(&self) -> u32 {
self.ptr.time_date_stamp()
}
pub fn pointerto_symbol_table(&self) -> u32 {
self.ptr.pointerto_symbol_table()
}
pub fn numberof_symbols(&self) -> u32 {
self.ptr.numberof_symbols()
}
pub fn sizeof_optional_header(&self) -> u16 {
self.ptr.sizeof_optional_header()
}
pub fn characteristics(&self) -> u32 {
self.ptr.characteristics()
}
}
impl std::fmt::Debug for Header<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Header")
.field("machine", &self.machine())
.field("nb_sections", &self.nb_sections())
.field("time_date_stamp", &self.time_date_stamp())
.field("pointerto_symbol_table", &self.pointerto_symbol_table())
.field("numberof_symbols", &self.numberof_symbols())
.field("sizeof_optional_header", &self.sizeof_optional_header())
.field("characteristics", &self.characteristics())
.finish()
}
}
pub struct OptionalHeader<'a> {
ptr: cxx::UniquePtr<ffi::PE_OptionalHeader>,
_owner: PhantomData<&'a ffi::PE_Binary>,
}
impl FromFFI<ffi::PE_OptionalHeader> for OptionalHeader<'_> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_OptionalHeader>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
impl OptionalHeader<'_> {
pub fn major_linker_version(&self) -> u8 {
self.ptr.major_linker_version()
}
pub fn minor_linker_version(&self) -> u8 {
self.ptr.minor_linker_version()
}
pub fn sizeof_code(&self) -> u32 {
self.ptr.sizeof_code()
}
pub fn sizeof_initialized_data(&self) -> u32 {
self.ptr.sizeof_initialized_data()
}
pub fn sizeof_uninitialized_data(&self) -> u32 {
self.ptr.sizeof_uninitialized_data()
}
pub fn addressof_entrypoint(&self) -> u32 {
self.ptr.addressof_entrypoint()
}
pub fn baseof_code(&self) -> u32 {
self.ptr.baseof_code()
}
pub fn baseof_data(&self) -> u32 {
self.ptr.baseof_data()
}
pub fn imagebase(&self) -> u64 {
self.ptr.imagebase()
}
pub fn section_alignment(&self) -> u32 {
self.ptr.section_alignment()
}
pub fn file_alignment(&self) -> u32 {
self.ptr.file_alignment()
}
pub fn major_operating_system_version(&self) -> u32 {
self.ptr.major_operating_system_version()
}
pub fn minor_operating_system_version(&self) -> u32 {
self.ptr.minor_operating_system_version()
}
pub fn major_image_version(&self) -> u32 {
self.ptr.major_image_version()
}
pub fn minor_image_version(&self) -> u32 {
self.ptr.minor_image_version()
}
pub fn major_subsystem_version(&self) -> u32 {
self.ptr.major_subsystem_version()
}
pub fn minor_subsystem_version(&self) -> u32 {
self.ptr.minor_subsystem_version()
}
pub fn win32_version_value(&self) -> u32 {
self.ptr.win32_version_value()
}
pub fn sizeof_image(&self) -> u32 {
self.ptr.sizeof_image()
}
pub fn sizeof_headers(&self) -> u32 {
self.ptr.sizeof_headers()
}
pub fn checksum(&self) -> u32 {
self.ptr.checksum()
}
pub fn computed_checksum(&self) -> u32 {
self.ptr.computed_checksum()
}
pub fn subsystem(&self) -> u32 {
self.ptr.subsystem()
}
pub fn dll_characteristics(&self) -> u32 {
self.ptr.dll_characteristics()
}
pub fn sizeof_stack_reserve(&self) -> u64 {
self.ptr.sizeof_stack_reserve()
}
pub fn sizeof_stack_commit(&self) -> u64 {
self.ptr.sizeof_stack_commit()
}
pub fn sizeof_heap_reserve(&self) -> u64 {
self.ptr.sizeof_heap_reserve()
}
pub fn sizeof_heap_commit(&self) -> u64 {
self.ptr.sizeof_heap_commit()
}
pub fn loader_flags(&self) -> u32 {
self.ptr.loader_flags()
}
pub fn numberof_rva_and_size(&self) -> u32 {
self.ptr.numberof_rva_and_size()
}
}
impl std::fmt::Debug for OptionalHeader<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("OptionalHeader")
.field("major_linker_version", &self.major_linker_version())
.field("minor_linker_version", &self.minor_linker_version())
.field("sizeof_code", &self.sizeof_code())
.field("sizeof_initialized_data", &self.sizeof_initialized_data())
.field(
"sizeof_uninitialized_data",
&self.sizeof_uninitialized_data(),
)
.field("addressof_entrypoint", &self.addressof_entrypoint())
.field("baseof_code", &self.baseof_code())
.field("baseof_data", &self.baseof_data())
.field("imagebase", &self.imagebase())
.field("section_alignment", &self.section_alignment())
.field("file_alignment", &self.file_alignment())
.field(
"major_operating_system_version",
&self.major_operating_system_version(),
)
.field(
"minor_operating_system_version",
&self.minor_operating_system_version(),
)
.field("major_image_version", &self.major_image_version())
.field("minor_image_version", &self.minor_image_version())
.field("major_subsystem_version", &self.major_subsystem_version())
.field("minor_subsystem_version", &self.minor_subsystem_version())
.field("win32_version_value", &self.win32_version_value())
.field("sizeof_image", &self.sizeof_image())
.field("sizeof_headers", &self.sizeof_headers())
.field("checksum", &self.checksum())
.field("subsystem", &self.subsystem())
.field("dll_characteristics", &self.dll_characteristics())
.field("sizeof_stack_reserve", &self.sizeof_stack_reserve())
.field("sizeof_stack_commit", &self.sizeof_stack_commit())
.field("sizeof_heap_reserve", &self.sizeof_heap_reserve())
.field("sizeof_heap_commit", &self.sizeof_heap_commit())
.field("loader_flags", &self.loader_flags())
.field("numberof_rva_and_size", &self.numberof_rva_and_size())
.finish()
}
}
+136
View File
@@ -0,0 +1,136 @@
use std::marker::PhantomData;
use crate::common::into_optional;
use crate::declare_iterator;
use crate::pe::DataDirectory;
use crate::{common::FromFFI, generic};
use lief_ffi as ffi;
pub struct Import<'a> {
ptr: cxx::UniquePtr<ffi::PE_Import>,
_owner: PhantomData<&'a ffi::PE_Binary>,
}
impl std::fmt::Debug for Import<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Import")
.field("name", &self.name())
.field("forwarder_chain", &self.forwarder_chain())
.field("timedatestamp", &self.timedatestamp())
.field("import_address_table_rva", &self.import_address_table_rva())
.field("import_lookup_table_rva", &self.import_lookup_table_rva())
.field("directory", &self.directory())
.field("iat_directory", &self.iat_directory())
.finish()
}
}
impl<'a> FromFFI<ffi::PE_Import> for Import<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_Import>) -> Self {
Import {
ptr,
_owner: PhantomData,
}
}
}
impl Import<'_> {
pub fn entries(&self) -> ImportEntries {
ImportEntries::new(self.ptr.entries())
}
pub fn forwarder_chain(&self) -> u32 {
self.ptr.forwarder_chain()
}
pub fn timedatestamp(&self) -> u32 {
self.ptr.timedatestamp()
}
pub fn import_address_table_rva(&self) -> u32 {
self.ptr.import_address_table_rva()
}
pub fn import_lookup_table_rva(&self) -> u32 {
self.ptr.import_lookup_table_rva()
}
pub fn name(&self) -> String {
self.ptr.name().to_string()
}
pub fn directory(&self) -> Option<DataDirectory> {
into_optional(self.ptr.directory())
}
pub fn iat_directory(&self) -> Option<DataDirectory> {
into_optional(self.ptr.iat_directory())
}
}
pub struct ImportEntry<'a> {
ptr: cxx::UniquePtr<ffi::PE_ImportEntry>,
_owner: PhantomData<&'a ffi::PE_Import>,
}
impl ImportEntry<'_> {
pub fn is_ordinal(&self) -> bool {
self.ptr.is_ordinal()
}
pub fn ordinal(&self) -> u16 {
self.ptr.ordinal()
}
pub fn hint_name_rva(&self) -> u64 {
self.ptr.hint_name_rva()
}
pub fn hint(&self) -> u16 {
self.ptr.hint()
}
pub fn iat_value(&self) -> u64 {
self.ptr.iat_value()
}
pub fn data(&self) -> u64 {
self.ptr.data()
}
pub fn iat_address(&self) -> u64 {
self.ptr.iat_address()
}
}
impl<'a> FromFFI<ffi::PE_ImportEntry> for ImportEntry<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ImportEntry>) -> Self {
ImportEntry {
ptr,
_owner: PhantomData,
}
}
}
impl generic::Symbol for ImportEntry<'_> {
fn as_generic(&self) -> &ffi::AbstractSymbol {
self.ptr.as_ref().unwrap().as_ref()
}
}
impl std::fmt::Debug for ImportEntry<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn generic::Symbol;
f.debug_struct("ImportEntry")
.field("base", &base)
.field("ordinal", &self.ordinal())
.field("hint_name_rva", &self.hint_name_rva())
.field("hint", &self.hint())
.field("iat_value", &self.iat_value())
.field("data", &self.data())
.field("iat_address", &self.iat_address())
.finish()
}
}
declare_iterator!(
ImportEntries,
ImportEntry<'a>,
ffi::PE_ImportEntry,
ffi::PE_Import,
ffi::PE_Import_it_entries
);
declare_iterator!(
Imports,
Import<'a>,
ffi::PE_Import,
ffi::PE_Binary,
ffi::PE_Binary_it_imports
);
File diff suppressed because it is too large Load Diff
+153
View File
@@ -0,0 +1,153 @@
use std::marker::PhantomData;
use lief_ffi as ffi;
use crate::common::FromFFI;
use crate::{declare_iterator, generic};
pub struct Relocation<'a> {
ptr: cxx::UniquePtr<ffi::PE_Relocation>,
_owner: PhantomData<&'a ffi::PE_Binary>,
}
impl Relocation<'_> {
pub fn virtual_address(&self) -> u32 {
self.ptr.virtual_address()
}
pub fn block_size(&self) -> u32 {
self.ptr.block_size()
}
pub fn entries(&self) -> RelocationEntries {
RelocationEntries::new(self.ptr.entries())
}
}
impl std::fmt::Debug for Relocation<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Relocation")
.field("virtual_address", &self.virtual_address())
.field("block_size", &self.block_size())
.finish()
}
}
impl<'a> FromFFI<ffi::PE_Relocation> for Relocation<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_Relocation>) -> Self {
Relocation {
ptr,
_owner: PhantomData,
}
}
}
#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone)]
pub enum BaseType {
ABS,
HIGH,
LOW,
HIGHLOW,
HIGHADJ,
MIPS_JMPADDR,
ARM_MOV32A,
ARM_MOV32,
RISCV_HI20,
SECTION,
REL,
ARM_MOV32T,
THUMB_MOV32,
RISCV_LOW12I,
RISCV_LOW12S,
IA64_IMM64,
MIPS_JMPADDR16,
DIR64,
HIGH3ADJ,
UNKNOWN(u32),
}
impl BaseType {
pub fn from_value(value: u32) -> Self {
match value {
0x00000000 => BaseType::ABS,
0x00000001 => BaseType::HIGH,
0x00000002 => BaseType::LOW,
0x00000003 => BaseType::HIGHLOW,
0x00000004 => BaseType::HIGHADJ,
0x00000005 => BaseType::MIPS_JMPADDR,
0x00000106 => BaseType::ARM_MOV32A,
0x00000107 => BaseType::ARM_MOV32,
0x00000108 => BaseType::RISCV_HI20,
0x00000006 => BaseType::SECTION,
0x00000007 => BaseType::REL,
0x00000208 => BaseType::ARM_MOV32T,
0x00000209 => BaseType::THUMB_MOV32,
0x0000020a => BaseType::RISCV_LOW12I,
0x00000008 => BaseType::RISCV_LOW12S,
0x00000009 => BaseType::IA64_IMM64,
0x00000309 => BaseType::MIPS_JMPADDR16,
0x0000000a => BaseType::DIR64,
0x0000000b => BaseType::HIGH3ADJ,
_ => BaseType::UNKNOWN(value),
}
}
}
pub struct Entry<'a> {
ptr: cxx::UniquePtr<ffi::PE_RelocationEntry>,
_owner: PhantomData<&'a ffi::PE_Relocation>,
}
impl generic::Relocation for Entry<'_> {
fn as_generic(&self) -> &ffi::AbstractRelocation {
self.ptr.as_ref().unwrap().as_ref()
}
}
impl Entry<'_> {
pub fn position(&self) -> u64 {
self.ptr.position()
}
pub fn get_type(&self) -> BaseType {
BaseType::from_value(self.ptr.get_type())
}
pub fn data(&self) -> u16 {
self.ptr.data()
}
}
impl std::fmt::Debug for Entry<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn generic::Relocation;
f.debug_struct("RelocationEntry")
.field("base", &base)
.field("type", &self.get_type())
.field("data", &self.data())
.field("position", &self.position())
.finish()
}
}
impl<'a> FromFFI<ffi::PE_RelocationEntry> for Entry<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_RelocationEntry>) -> Self {
Entry {
ptr,
_owner: PhantomData,
}
}
}
declare_iterator!(
RelocationEntries,
Entry<'a>,
ffi::PE_RelocationEntry,
ffi::PE_Relocation,
ffi::PE_Relocation_it_entries
);
declare_iterator!(
Relocations,
Relocation<'a>,
ffi::PE_Relocation,
ffi::PE_Binary,
ffi::PE_Binary_it_relocations
);
+189
View File
@@ -0,0 +1,189 @@
use lief_ffi as ffi;
use std::{fmt, marker::PhantomData};
use crate::to_slice;
use crate::{common::FromFFI, declare_iterator};
#[derive(Debug)]
pub enum Node<'a> {
Data(Data<'a>),
Directory(Directory<'a>),
}
pub trait NodeBase {
#[doc(hidden)]
fn get_base(&self) -> &ffi::PE_ResourceNode;
fn id(&self) -> u32 {
self.get_base().id()
}
fn depth(&self) -> u32 {
self.get_base().depth()
}
fn children(&self) -> Children {
Children::new(self.get_base().childs())
}
}
impl std::fmt::Debug for &dyn NodeBase {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("NodeBase").field("id", &self.id()).finish()
}
}
impl<'a> FromFFI<ffi::PE_ResourceNode> for Node<'a> {
fn from_ffi(ffi_entry: cxx::UniquePtr<ffi::PE_ResourceNode>) -> Self {
unsafe {
let cmd_ref = ffi_entry.as_ref().unwrap();
if ffi::PE_ResourceDirectory::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::PE_ResourceNode>;
type To = cxx::UniquePtr<ffi::PE_ResourceDirectory>;
std::mem::transmute::<From, To>(ffi_entry)
};
Node::Directory(Directory::from_ffi(raw))
} else {
assert!(
ffi::PE_ResourceData::classof(cmd_ref),
"Must be a ResourceData node"
);
let raw = {
type From = cxx::UniquePtr<ffi::PE_ResourceNode>;
type To = cxx::UniquePtr<ffi::PE_ResourceData>;
std::mem::transmute::<From, To>(ffi_entry)
};
Node::Data(Data::from_ffi(raw))
}
}
}
}
pub struct Data<'a> {
ptr: cxx::UniquePtr<ffi::PE_ResourceData>,
_owner: PhantomData<&'a Node<'a>>,
}
impl Data<'_> {
pub fn code_page(&self) -> u32 {
self.ptr.code_page()
}
pub fn reserved(&self) -> u32 {
self.ptr.reserved()
}
pub fn offset(&self) -> u32 {
self.ptr.offset()
}
pub fn content(&self) -> &[u8] {
to_slice!(self.ptr.content());
}
}
impl NodeBase for Data<'_> {
fn get_base(&self) -> &ffi::PE_ResourceNode {
self.ptr.as_ref().unwrap().as_ref()
}
}
impl fmt::Debug for Data<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let base = self as &dyn NodeBase;
f.debug_struct("Data")
.field("base", &base)
.field("code_page", &self.code_page())
.field("reserved", &self.reserved())
.field("offset", &self.offset())
.finish()
}
}
impl<'a> FromFFI<ffi::PE_ResourceData> for Data<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ResourceData>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
pub struct Directory<'a> {
ptr: cxx::UniquePtr<ffi::PE_ResourceDirectory>,
_owner: PhantomData<&'a Node<'a>>,
}
impl Directory<'_> {
pub fn characteristics(&self) -> u32 {
self.ptr.characteristics()
}
pub fn time_date_stamp(&self) -> u32 {
self.ptr.time_date_stamp()
}
pub fn major_version(&self) -> u32 {
self.ptr.major_version()
}
pub fn minor_version(&self) -> u32 {
self.ptr.minor_version()
}
pub fn numberof_name_entries(&self) -> u32 {
self.ptr.numberof_name_entries()
}
pub fn numberof_id_entries(&self) -> u32 {
self.ptr.numberof_id_entries()
}
}
impl NodeBase for Directory<'_> {
fn get_base(&self) -> &ffi::PE_ResourceNode {
self.ptr.as_ref().unwrap().as_ref()
}
}
impl fmt::Debug for Directory<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let base = self as &dyn NodeBase;
f.debug_struct("Directory")
.field("base", &base)
.field("characteristics", &self.characteristics())
.field("time_date_stamp", &self.time_date_stamp())
.field("major_version", &self.major_version())
.field("minor_version", &self.minor_version())
.field("numberof_name_entries", &self.numberof_name_entries())
.field("numberof_id_entries", &self.numberof_id_entries())
.finish()
}
}
impl<'a> FromFFI<ffi::PE_ResourceDirectory> for Directory<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ResourceDirectory>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
pub struct Manager<'a> {
ptr: cxx::UniquePtr<ffi::PE_ResourcesManager>,
_owner: PhantomData<&'a Node<'a>>,
}
impl<'a> FromFFI<ffi::PE_ResourcesManager> for Manager<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ResourcesManager>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
declare_iterator!(
Children,
Node<'a>,
ffi::PE_ResourceNode,
ffi::PE_Binary,
ffi::PE_ResourceNode_it_childs
);
+81
View File
@@ -0,0 +1,81 @@
use std::marker::PhantomData;
use lief_ffi as ffi;
use crate::{common::FromFFI, declare_iterator};
pub struct RichHeader<'a> {
ptr: cxx::UniquePtr<ffi::PE_RichHeader>,
_owner: PhantomData<&'a ffi::PE_Binary>,
}
impl std::fmt::Debug for RichHeader<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("RichHeader")
.field("key", &self.key())
.finish()
}
}
impl<'a> FromFFI<ffi::PE_RichHeader> for RichHeader<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_RichHeader>) -> Self {
RichHeader {
ptr,
_owner: PhantomData,
}
}
}
impl<'a> RichHeader<'a> {
pub fn key(&self) -> u32 {
self.ptr.key()
}
pub fn entries(&self) -> Entries {
Entries::new(self.ptr.entries())
}
}
pub struct RichEntry<'a> {
ptr: cxx::UniquePtr<ffi::PE_RichEntry>,
_owner: PhantomData<&'a ffi::PE_RichHeader>,
}
impl RichEntry<'_> {
pub fn id(&self) -> u16 {
self.ptr.id()
}
pub fn build_id(&self) -> u16 {
self.ptr.build_id()
}
pub fn count(&self) -> u32 {
self.ptr.count()
}
}
impl std::fmt::Debug for RichEntry<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("RichEntry")
.field("id", &self.id())
.field("build_id", &self.build_id())
.field("count", &self.count())
.finish()
}
}
impl<'a> FromFFI<ffi::PE_RichEntry> for RichEntry<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_RichEntry>) -> Self {
RichEntry {
ptr,
_owner: PhantomData,
}
}
}
declare_iterator!(
Entries,
RichEntry<'a>,
ffi::PE_RichEntry,
ffi::PE_RichHeader,
ffi::PE_RichHeader_it_entries
);
+130
View File
@@ -0,0 +1,130 @@
use std::marker::PhantomData;
use lief_ffi as ffi;
use crate::declare_iterator;
use crate::to_slice;
use crate::{common::FromFFI, generic};
use bitflags::bitflags;
pub struct Section<'a> {
ptr: cxx::UniquePtr<ffi::PE_Section>,
_owner: PhantomData<&'a ffi::PE_Binary>,
}
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Characteristics: u64 {
const TYPE_NO_PAD = 0x8;
const CNT_CODE = 0x20;
const CNT_INITIALIZED_DATA = 0x40;
const CNT_UNINITIALIZED_DATA = 0x80;
const LNK_OTHER = 0x100;
const LNK_INFO = 0x200;
const LNK_REMOVE = 0x800;
const LNK_COMDAT = 0x1000;
const GPREL = 0x8000;
const MEM_PURGEABLE = 0x10000;
const MEM_16BIT = 0x20000;
const MEM_LOCKED = 0x40000;
const MEM_PRELOAD = 0x80000;
const ALIGN_1BYTES = 0x100000;
const ALIGN_2BYTES = 0x200000;
const ALIGN_4BYTES = 0x300000;
const ALIGN_8BYTES = 0x400000;
const ALIGN_16BYTES = 0x500000;
const ALIGN_32BYTES = 0x600000;
const ALIGN_64BYTES = 0x700000;
const ALIGN_128BYTES = 0x800000;
const ALIGN_256BYTES = 0x900000;
const ALIGN_512BYTES = 0xa00000;
const ALIGN_1024BYTES = 0xb00000;
const ALIGN_2048BYTES = 0xc00000;
const ALIGN_4096BYTES = 0xd00000;
const ALIGN_8192BYTES = 0xe00000;
const LNK_NRELOC_OVFL = 0x1000000;
const MEM_DISCARDABLE = 0x2000000;
const MEM_NOT_CACHED = 0x4000000;
const MEM_NOT_PAGED = 0x8000000;
const MEM_SHARED = 0x10000000;
const MEM_EXECUTE = 0x20000000;
const MEM_READ = 0x40000000;
const MEM_WRITE = 0x80000000;
}
}
impl Characteristics {
pub fn from_value(value: u64) -> Self {
Characteristics::from_bits_truncate(value)
}
}
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) -> u32 {
self.ptr.numberof_relocations()
}
pub fn numberof_line_numbers(&self) -> u32 {
self.ptr.numberof_line_numbers()
}
pub fn characteristics(&self) -> Characteristics {
Characteristics::from_value(self.ptr.characteristics())
}
pub fn padding(&self) -> &[u8] {
to_slice!(self.ptr.padding());
}
}
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<'a> FromFFI<ffi::PE_Section> for Section<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_Section>) -> Self {
Section {
ptr,
_owner: PhantomData,
}
}
}
impl generic::Section for Section<'_> {
fn as_generic(&self) -> &ffi::AbstractSection {
self.ptr.as_ref().unwrap().as_ref()
}
}
declare_iterator!(
Sections,
Section<'a>,
ffi::PE_Section,
ffi::PE_Binary,
ffi::PE_Binary_it_sections
);
+102
View File
@@ -0,0 +1,102 @@
use bitflags::bitflags;
use lief_ffi as ffi;
pub mod attributes;
pub mod content_info;
pub mod rsa_info;
pub mod signer_info;
pub mod x509;
pub use content_info::ContentInfo;
pub use rsa_info::RsaInfo;
pub use signer_info::{SignerInfo, Signers};
pub use x509::{Certificates, X509};
use crate::common::FromFFI;
use crate::declare_iterator;
use std::marker::PhantomData;
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct VerificationFlags: u32 {
const OK = 0;
const INVALID_SIGNER = 1 << 0;
const UNSUPPORTED_ALGORITHM = 1 << 1;
const INCONSISTENT_DIGEST_ALGORITHM = 1 << 2;
const CERT_NOT_FOUND = 1 << 3;
const CORRUPTED_CONTENT_INFO = 1 << 4;
const CORRUPTED_AUTH_DATA = 1 << 5;
const MISSING_PKCS9_MESSAGE_DIGEST = 1 << 6;
const BAD_DIGEST = 1 << 7;
const BAD_SIGNATURE = 1 << 8;
const NO_SIGNATURE = 1 << 9;
const CERT_EXPIRED = 1 << 10;
const CERT_FUTURE = 1 << 11;
}
}
impl VerificationFlags {
pub fn from_value(value: u32) -> Self {
VerificationFlags::from_bits_truncate(value)
}
}
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct VerificationChecks: u32 {
const DEFAULT = 1 << 0;
const HASH_ONLY = 1 << 1;
const LIFETIME_SIGNING = 1 << 2;
const SKIP_CERT_TIME = 1 << 3;
}
}
pub struct Signature<'a> {
ptr: cxx::UniquePtr<ffi::PE_Signature>,
_owner: PhantomData<&'a ()>,
}
impl std::fmt::Debug for Signature<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Signature").finish()
}
}
impl FromFFI<ffi::PE_Signature> for Signature<'_> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_Signature>) -> Self {
Signature {
ptr,
_owner: PhantomData,
}
}
}
impl<'a> Signature<'a> {
pub fn from_file(path: &str) -> Option<Self> {
let ffi = ffi::PE_Signature::parse(path);
if ffi.is_null() {
return None;
}
Some(Signature::from_ffi(ffi))
}
pub fn content_info(&'a self) -> ContentInfo<'a> {
ContentInfo::from_ffi(self.ptr.content_info())
}
pub fn certificates(&'a self) -> Certificates<'a> {
Certificates::new(self.ptr.certificates())
}
pub fn signers(&'a self) -> Signers<'a> {
Signers::new(self.ptr.signers())
}
}
declare_iterator!(
Signatures,
Signature<'a>,
ffi::PE_Signature,
ffi::PE_Binary,
ffi::PE_Binary_it_signatures
);
@@ -0,0 +1,357 @@
use std::marker::PhantomData;
use lief_ffi as ffi;
use crate::to_slice;
use crate::common::FromFFI;
use super::{Signature, SignerInfo};
#[derive(Debug)]
pub enum Attribute<'a> {
ContentType(ContentType<'a>),
GenericType(GenericType<'a>),
MsSpcNestedSignature(MsSpcNestedSignature<'a>),
MsSpcStatementType(MsSpcStatementType<'a>),
PKCS9AtSequenceNumber(PKCS9AtSequenceNumber<'a>),
PKCS9CounterSignature(PKCS9CounterSignature<'a>),
PKCS9MessageDigest(PKCS9MessageDigest<'a>),
PKCS9SigningTime(PKCS9SigningTime<'a>),
SpcSpOpusInfo(SpcSpOpusInfo<'a>),
}
impl<'a> FromFFI<ffi::PE_Attribute> for Attribute<'a> {
fn from_ffi(ffi_entry: cxx::UniquePtr<ffi::PE_Attribute>) -> Self {
unsafe {
let cmd_ref = ffi_entry.as_ref().unwrap();
if ffi::PE_ContentType::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::PE_Attribute>;
type To = cxx::UniquePtr<ffi::PE_ContentType>;
std::mem::transmute::<From, To>(ffi_entry)
};
Attribute::ContentType(ContentType::from_ffi(raw))
} else if ffi::PE_MsSpcNestedSignature::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::PE_Attribute>;
type To = cxx::UniquePtr<ffi::PE_MsSpcNestedSignature>;
std::mem::transmute::<From, To>(ffi_entry)
};
Attribute::MsSpcNestedSignature(MsSpcNestedSignature::from_ffi(raw))
} else if ffi::PE_MsSpcStatementType::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::PE_Attribute>;
type To = cxx::UniquePtr<ffi::PE_MsSpcStatementType>;
std::mem::transmute::<From, To>(ffi_entry)
};
Attribute::MsSpcStatementType(MsSpcStatementType::from_ffi(raw))
} else if ffi::PE_PKCS9AtSequenceNumber::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::PE_Attribute>;
type To = cxx::UniquePtr<ffi::PE_PKCS9AtSequenceNumber>;
std::mem::transmute::<From, To>(ffi_entry)
};
Attribute::PKCS9AtSequenceNumber(PKCS9AtSequenceNumber::from_ffi(raw))
} else if ffi::PE_PKCS9CounterSignature::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::PE_Attribute>;
type To = cxx::UniquePtr<ffi::PE_PKCS9CounterSignature>;
std::mem::transmute::<From, To>(ffi_entry)
};
Attribute::PKCS9CounterSignature(PKCS9CounterSignature::from_ffi(raw))
} else if ffi::PE_PKCS9MessageDigest::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::PE_Attribute>;
type To = cxx::UniquePtr<ffi::PE_PKCS9MessageDigest>;
std::mem::transmute::<From, To>(ffi_entry)
};
Attribute::PKCS9MessageDigest(PKCS9MessageDigest::from_ffi(raw))
} else if ffi::PE_PKCS9SigningTime::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::PE_Attribute>;
type To = cxx::UniquePtr<ffi::PE_PKCS9SigningTime>;
std::mem::transmute::<From, To>(ffi_entry)
};
Attribute::PKCS9SigningTime(PKCS9SigningTime::from_ffi(raw))
} else if ffi::PE_SpcSpOpusInfo::classof(cmd_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::PE_Attribute>;
type To = cxx::UniquePtr<ffi::PE_SpcSpOpusInfo>;
std::mem::transmute::<From, To>(ffi_entry)
};
Attribute::SpcSpOpusInfo(SpcSpOpusInfo::from_ffi(raw))
} else {
assert!(
ffi::PE_GenericType::classof(cmd_ref),
"Must be a GenericType node"
);
let raw = {
type From = cxx::UniquePtr<ffi::PE_Attribute>;
type To = cxx::UniquePtr<ffi::PE_GenericType>;
std::mem::transmute::<From, To>(ffi_entry)
};
Attribute::GenericType(GenericType::from_ffi(raw))
}
}
}
}
pub struct ContentType<'a> {
ptr: cxx::UniquePtr<ffi::PE_ContentType>,
_owner: PhantomData<&'a ffi::PE_SignerInfo>,
}
impl std::fmt::Debug for ContentType<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ContentType")
.field("oid", &self.oid())
.finish()
}
}
impl<'a> FromFFI<ffi::PE_ContentType> for ContentType<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ContentType>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
impl ContentType<'_> {
pub fn oid(&self) -> String {
self.ptr.oid().to_string()
}
}
pub struct GenericType<'a> {
ptr: cxx::UniquePtr<ffi::PE_GenericType>,
_owner: PhantomData<&'a ffi::PE_SignerInfo>,
}
impl std::fmt::Debug for GenericType<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("GenericType")
.field("oid", &self.oid())
.finish()
}
}
impl<'a> FromFFI<ffi::PE_GenericType> for GenericType<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_GenericType>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
impl GenericType<'_> {
pub fn oid(&self) -> String {
self.ptr.oid().to_string()
}
}
pub struct MsSpcNestedSignature<'a> {
ptr: cxx::UniquePtr<ffi::PE_MsSpcNestedSignature>,
_owner: PhantomData<&'a ffi::PE_SignerInfo>,
}
impl std::fmt::Debug for MsSpcNestedSignature<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("MsSpcNestedSignature").finish()
}
}
impl<'a> FromFFI<ffi::PE_MsSpcNestedSignature> for MsSpcNestedSignature<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_MsSpcNestedSignature>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
impl MsSpcNestedSignature<'_> {
pub fn signature(&self) -> Signature {
Signature::from_ffi(self.ptr.sig())
}
}
pub struct MsSpcStatementType<'a> {
ptr: cxx::UniquePtr<ffi::PE_MsSpcStatementType>,
_owner: PhantomData<&'a ffi::PE_SignerInfo>,
}
impl std::fmt::Debug for MsSpcStatementType<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("MsSpcStatementType")
.field("oid", &self.oid())
.finish()
}
}
impl<'a> FromFFI<ffi::PE_MsSpcStatementType> for MsSpcStatementType<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_MsSpcStatementType>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
impl MsSpcStatementType<'_> {
pub fn oid(&self) -> String {
self.ptr.oid().to_string()
}
}
pub struct PKCS9AtSequenceNumber<'a> {
ptr: cxx::UniquePtr<ffi::PE_PKCS9AtSequenceNumber>,
_owner: PhantomData<&'a ffi::PE_SignerInfo>,
}
impl std::fmt::Debug for PKCS9AtSequenceNumber<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("PKCS9AtSequenceNumber")
.field("number", &self.number())
.finish()
}
}
impl PKCS9AtSequenceNumber<'_> {
pub fn number(&self) -> u32 {
self.ptr.number()
}
}
impl<'a> FromFFI<ffi::PE_PKCS9AtSequenceNumber> for PKCS9AtSequenceNumber<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_PKCS9AtSequenceNumber>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
pub struct PKCS9CounterSignature<'a> {
ptr: cxx::UniquePtr<ffi::PE_PKCS9CounterSignature>,
_owner: PhantomData<&'a ffi::PE_SignerInfo>,
}
impl std::fmt::Debug for PKCS9CounterSignature<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("PKCS9CounterSignature").finish()
}
}
impl<'a> FromFFI<ffi::PE_PKCS9CounterSignature> for PKCS9CounterSignature<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_PKCS9CounterSignature>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
impl PKCS9CounterSignature<'_> {
pub fn signer(&self) -> SignerInfo {
SignerInfo::from_ffi(self.ptr.signer())
}
}
pub struct PKCS9MessageDigest<'a> {
ptr: cxx::UniquePtr<ffi::PE_PKCS9MessageDigest>,
_owner: PhantomData<&'a ffi::PE_SignerInfo>,
}
impl std::fmt::Debug for PKCS9MessageDigest<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("PKCS9MessageDigest").finish()
}
}
impl PKCS9MessageDigest<'_> {
pub fn digest(&self) -> &[u8] {
to_slice!(self.ptr.digest());
}
}
impl<'a> FromFFI<ffi::PE_PKCS9MessageDigest> for PKCS9MessageDigest<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_PKCS9MessageDigest>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
pub struct PKCS9SigningTime<'a> {
ptr: cxx::UniquePtr<ffi::PE_PKCS9SigningTime>,
_owner: PhantomData<&'a ffi::PE_SignerInfo>,
}
impl std::fmt::Debug for PKCS9SigningTime<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("PKCS9SigningTime")
.field("time", &self.time())
.finish()
}
}
impl<'a> FromFFI<ffi::PE_PKCS9SigningTime> for PKCS9SigningTime<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_PKCS9SigningTime>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
impl PKCS9SigningTime<'_> {
pub fn time(&self) -> Vec<u64> {
Vec::from(self.ptr.time().as_slice())
}
}
pub struct SpcSpOpusInfo<'a> {
ptr: cxx::UniquePtr<ffi::PE_SpcSpOpusInfo>,
_owner: PhantomData<&'a ffi::PE_SignerInfo>,
}
impl std::fmt::Debug for SpcSpOpusInfo<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SpcSpOpusInfo")
.field("program_name", &self.program_name())
.field("more_info", &self.more_info())
.finish()
}
}
impl<'a> FromFFI<ffi::PE_SpcSpOpusInfo> for SpcSpOpusInfo<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_SpcSpOpusInfo>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
impl SpcSpOpusInfo<'_> {
pub fn program_name(&self) -> String {
self.ptr.program_name().to_string()
}
pub fn more_info(&self) -> String {
self.ptr.more_info().to_string()
}
}
@@ -0,0 +1,33 @@
use std::marker::PhantomData;
use lief_ffi as ffi;
use crate::common::FromFFI;
pub struct ContentInfo<'a> {
ptr: cxx::UniquePtr<ffi::PE_ContentInfo>,
_owner: PhantomData<&'a ffi::PE_Signature>,
}
impl ContentInfo<'_> {
pub fn content_type(&self) -> String {
self.ptr.content_type().to_string()
}
}
impl std::fmt::Debug for ContentInfo<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ContentInfo")
.field("content_type", &self.content_type())
.finish()
}
}
impl<'a> FromFFI<ffi::PE_ContentInfo> for ContentInfo<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ContentInfo>) -> Self {
ContentInfo {
ptr,
_owner: PhantomData,
}
}
}
@@ -0,0 +1,61 @@
use lief_ffi as ffi;
use num_bigint::BigUint;
use crate::common::FromFFI;
use std::marker::PhantomData;
pub struct RsaInfo<'a> {
ptr: cxx::UniquePtr<ffi::PE_RsaInfo>,
_owner: PhantomData<&'a ()>,
}
impl std::fmt::Debug for RsaInfo<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("RsaInfo")
.field("key_size", &self.key_size())
.field("has_public_key", &self.has_public_key())
.field("has_private_key", &self.has_private_key())
.finish()
}
}
impl<'a> FromFFI<ffi::PE_RsaInfo> for RsaInfo<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_RsaInfo>) -> Self {
RsaInfo {
ptr,
_owner: PhantomData,
}
}
}
impl<'a> RsaInfo<'a> {
#[allow(non_snake_case)]
pub fn N(&self) -> BigUint {
BigUint::from_bytes_le(self.ptr.N().as_slice())
}
#[allow(non_snake_case)]
pub fn E(&self) -> BigUint {
BigUint::from_bytes_le(self.ptr.E().as_slice())
}
#[allow(non_snake_case)]
pub fn D(&self) -> BigUint {
BigUint::from_bytes_le(self.ptr.D().as_slice())
}
#[allow(non_snake_case)]
pub fn P(&self) -> BigUint {
BigUint::from_bytes_le(self.ptr.P().as_slice())
}
#[allow(non_snake_case)]
pub fn Q(&self) -> BigUint {
BigUint::from_bytes_le(self.ptr.Q().as_slice())
}
pub fn key_size(&self) -> u32 {
self.ptr.key_size()
}
pub fn has_public_key(&self) -> bool {
self.ptr.has_public_key()
}
pub fn has_private_key(&self) -> bool {
self.ptr.has_private_key()
}
}
@@ -0,0 +1,86 @@
use std::marker::PhantomData;
use super::attributes::Attribute;
use super::X509;
use crate::to_slice;
use crate::common::{FromFFI, into_optional};
use crate::declare_iterator;
use lief_ffi as ffi;
pub struct SignerInfo<'a> {
ptr: cxx::UniquePtr<ffi::PE_SignerInfo>,
_owner: PhantomData<&'a ()>, // Can be own by Signature or PKCS9CounterSignature
}
impl std::fmt::Debug for SignerInfo<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SignerInfo")
.field("version", &self.version())
.field("issuer", &self.issuer())
.field("digest_algorithm", &self.digest_algorithm())
.field("encryption_algorithm", &self.encryption_algorithm())
.finish()
}
}
impl<'a> FromFFI<ffi::PE_SignerInfo> for SignerInfo<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_SignerInfo>) -> Self {
SignerInfo {
ptr,
_owner: PhantomData,
}
}
}
impl<'a> SignerInfo<'a> {
pub fn version(&self) -> u32 {
self.ptr.version()
}
pub fn issuer(&self) -> String {
self.ptr.issuer().to_string()
}
pub fn digest_algorithm(&self) -> u32 {
self.ptr.digest_algorithm()
}
pub fn encryption_algorithm(&self) -> u32 {
self.ptr.encryption_algorithm()
}
pub fn serial_number(&self) -> &[u8] {
to_slice!(self.ptr.serial_number());
}
pub fn encrypted_digest(&self) -> Vec<u8> {
Vec::from(self.ptr.encrypted_digest().as_slice())
}
pub fn cert(&self) -> Option<X509> {
into_optional(self.ptr.cert())
}
pub fn authenticated_attributes(&self) -> AuthenticatedAttributes {
AuthenticatedAttributes::new(self.ptr.authenticated_attributes())
}
pub fn unauthenticated_attributes(&self) -> UnAuthenticatedAttributes {
UnAuthenticatedAttributes::new(self.ptr.unauthenticated_attributes())
}
}
declare_iterator!(
Signers,
SignerInfo<'a>,
ffi::PE_SignerInfo,
ffi::PE_Signature,
ffi::PE_Signature_it_signers
);
declare_iterator!(
AuthenticatedAttributes,
Attribute<'a>,
ffi::PE_Attribute,
ffi::PE_SignerInfo,
ffi::PE_SignerInfo_it_authenticated_attributes
);
declare_iterator!(
UnAuthenticatedAttributes,
Attribute<'a>,
ffi::PE_Attribute,
ffi::PE_SignerInfo,
ffi::PE_SignerInfo_it_unauthenticated_attributes
);
@@ -0,0 +1,115 @@
use std::marker::PhantomData;
use lief_ffi as ffi;
use crate::common::{into_optional, FromFFI};
use crate::declare_iterator;
use super::RsaInfo;
pub struct X509<'a> {
ptr: cxx::UniquePtr<ffi::PE_x509>,
_owner: PhantomData<&'a ffi::PE_SignerInfo>,
}
impl std::fmt::Debug for X509<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("x509")
.field("version", &self.version())
.field("signature_algorithm", &self.signature_algorithm())
.field("valid_from", &self.valid_from())
.field("valid_to", &self.valid_to())
.field("issuer", &self.issuer())
.field("key_type", &self.key_type())
.field("subject", &self.subject())
.field("is_ca", &self.is_ca())
.finish()
}
}
impl<'a> FromFFI<ffi::PE_x509> for X509<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_x509>) -> Self {
X509 {
ptr,
_owner: PhantomData,
}
}
}
#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum KeyType {
NONE,
RSA,
ECKEY,
ECKEY_DH,
ECDSA,
RSA_ALT,
RSASSA_PSS,
UNKNOWN(u32),
}
impl KeyType {
pub fn from_value(value: u32) -> Self {
match value {
0x00000000 => KeyType::NONE,
0x00000001 => KeyType::RSA,
0x00000002 => KeyType::ECKEY,
0x00000003 => KeyType::ECKEY_DH,
0x00000004 => KeyType::ECDSA,
0x00000005 => KeyType::RSA_ALT,
0x00000006 => KeyType::RSASSA_PSS,
_ => KeyType::UNKNOWN(value),
}
}
}
impl X509<'_> {
pub fn version(&self) -> u32 {
self.ptr.version()
}
pub fn serial_number(&self) -> Vec<u8> {
Vec::from(self.ptr.serial_number().as_slice())
}
pub fn signature_algorithm(&self) -> String {
self.ptr.signature_algorithm().to_string()
}
pub fn valid_from(&self) -> Vec<u64> {
Vec::from(self.ptr.valid_from().as_slice())
}
pub fn valid_to(&self) -> Vec<u64> {
Vec::from(self.ptr.valid_to().as_slice())
}
pub fn issuer(&self) -> String {
self.ptr.issuer().to_string()
}
pub fn subject(&self) -> String {
self.ptr.subject().to_string()
}
pub fn raw(&self) -> Vec<u8> {
Vec::from(self.ptr.raw().as_slice())
}
pub fn key_type(&self) -> KeyType {
KeyType::from_value(self.ptr.key_type())
}
pub fn is_ca(&self) -> bool {
self.ptr.is_ca()
}
pub fn signature(&self) -> Vec<u8> {
Vec::from(self.ptr.signature().as_slice())
}
pub fn rsa_info(&self) -> Option<RsaInfo> {
into_optional(self.ptr.rsa_info())
}
}
declare_iterator!(
Certificates,
X509<'a>,
ffi::PE_x509,
ffi::PE_Signature,
ffi::PE_Signature_it_certificates
);
+55
View File
@@ -0,0 +1,55 @@
use lief_ffi as ffi;
use crate::common::FromFFI;
use crate::to_slice;
use std::marker::PhantomData;
pub struct TLS<'a> {
ptr: cxx::UniquePtr<ffi::PE_TLS>,
_owner: PhantomData<&'a ffi::PE_Binary>,
}
impl std::fmt::Debug for TLS<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("TLS")
.field("callbacks", &self.callbacks())
.field("addressof_index", &self.addressof_index())
.field("addressof_callbacks", &self.addressof_callbacks())
.field("sizeof_zero_fill", &self.sizeof_zero_fill())
.field("characteristics", &self.characteristics())
.finish()
}
}
impl TLS<'_> {
pub fn callbacks(&self) -> Vec<u64> {
Vec::from(self.ptr.callbacks().as_slice())
}
pub fn addressof_index(&self) -> u64 {
self.ptr.addressof_index()
}
pub fn addressof_callbacks(&self) -> u64 {
self.ptr.addressof_callbacks()
}
pub fn sizeof_zero_fill(&self) -> u64 {
self.ptr.sizeof_zero_fill()
}
pub fn characteristics(&self) -> u64 {
self.ptr.characteristics()
}
pub fn data_template(&self) -> &[u8] {
to_slice!(self.ptr.data_template());
}
pub fn addressof_raw_data(&self) -> Vec<u64> {
Vec::from(self.ptr.addressof_raw_data().as_slice())
}
}
impl<'a> FromFFI<ffi::PE_TLS> for TLS<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_TLS>) -> Self {
TLS {
ptr,
_owner: PhantomData,
}
}
}
+160
View File
@@ -0,0 +1,160 @@
mod utils;
use lief::elf::dynamic;
use lief::elf::dynamic::DynamicEntry;
use lief::elf::note::NoteBase;
use lief::elf::relocation;
use lief::elf::segment;
use lief::elf::Notes;
use lief::generic::Binary as GenericBinary;
use lief::generic::Section;
use lief::generic::Symbol;
use lief::Binary;
fn explore_elf(elf: &lief::elf::Binary) {
format!("{elf:?}");
format!("{} {} {}", elf.entrypoint(), elf.imagebase(), elf.is_pie());
if let Some(sysv) = elf.sysv_hash() {
format!("{sysv:?}");
}
if let Some(gnu) = elf.gnu_hash() {
format!("{gnu:?}");
}
for section in elf.sections() {
format!("Section: {section:?}: {section}");
format!("Name: {}", section.name());
format!("{}", section.content().len());
format!("{size}", size = section.size());
format!(
"{virtual_address}",
virtual_address = section.virtual_address()
);
format!("{offset}", offset = section.offset());
if section.name() == ".text" && section.size() > 0 {
assert!(!section.content().is_empty())
}
}
for segment in elf.segments() {
format!("{segment:?}: {segment}");
if segment.p_type() == segment::Type::PHDR {
assert!(!segment.content().is_empty())
}
}
for sym in elf.exported_symbols() {
format!("{sym:?}");
}
for sym in elf.imported_symbols() {
format!("{sym:?}");
}
for sym in elf.symtab_symbols() {
format!("{sym:?}");
}
for version in elf.symbols_version() {
format!("{version:?}");
}
for note in elf.notes() {
format!("{note:?}");
#[allow(irrefutable_let_patterns)]
if let Notes::Generic(generic) = note {
assert!(!generic.description().is_empty());
assert!(!generic.original_type() != 0);
}
}
for reloc in elf.pltgot_relocations() {
format!("{reloc:?}");
}
for reloc in elf.dynamic_relocations() {
if reloc.encoding() == relocation::Encoding::REL {
assert!(reloc.is_rel());
}
if reloc.encoding() == relocation::Encoding::RELA {
assert!(reloc.is_rela());
}
format!("{reloc:?}");
}
for reloc in elf.object_relocations() {
format!("{reloc:?}");
}
for reloc in elf.relocations() {
format!("{reloc:?}");
}
for sym in elf.dynamic_symbols() {
format!("{sym:?}: {sym}");
format!("{}: {} ({})", sym.name(), sym.value(), sym.size());
}
for sym_ver in elf.symbols_version() {
format!("{sym_ver:?}");
}
for sym_def in elf.symbols_version_definition() {
format!("{sym_def:?}");
}
for sym_req in elf.symbols_version_requirement() {
format!("{sym_req:?}");
}
for entry in elf.dynamic_entries() {
format!("{entry:?}");
match entry {
dynamic::Entries::Generic(gen) => {
format!("{:?}: {}", gen.tag(), gen.value());
}
dynamic::Entries::Library(lib) => {
format!("{:?}: {} {}", lib.tag(), lib.value(), lib.name());
}
dynamic::Entries::Array(array) => {
format!("{:?}: {} {:?}", array.tag(), array.value(), array.array());
}
dynamic::Entries::Rpath(rpath) => {
format!("{:?}: {}", rpath.tag(), rpath.rpath());
}
dynamic::Entries::RunPath(runpath) => {
format!("{:?}: {}", runpath.tag(), runpath.runpath());
}
dynamic::Entries::SharedObject(shared) => {
format!("{:?}: {}", shared.tag(), shared.name());
}
}
}
}
fn test_with(bin_name: &str) {
let path = utils::get_elf_sample(bin_name).unwrap();
let path_str = path.to_str();
if let Some(Binary::ELF(bin)) = Binary::parse(path_str.unwrap()) {
explore_elf(&bin);
}
// Test Read + Seek interface
let mut file = std::fs::File::open(path).expect("Can't open the file");
let binary = Binary::from(&mut file);
assert!(matches!(binary, Some(Binary::ELF(_))));
}
#[test]
fn test_api() {
test_with("elf_reader.mips.elf");
test_with("issue_975_aarch64.o");
test_with("ELF_Core_issue_808.core");
test_with("ELF64_x86-64_library_libfreebl3.so");
test_with("ELF64_x86-64_binary_etterlog.bin");
test_with("ELF64_x86-64_binary_systemd-resolve.bin");
test_with("art_reader.loongarch");
}
+261
View File
@@ -0,0 +1,261 @@
mod utils;
use lief::generic::Binary as GenericBinary;
use lief::macho::binding_info::{self, AsGeneric};
use lief::macho::commands::{Command, Commands};
use lief::Binary;
fn print_binding(binding: &binding_info::BindingInfo) {
format!("{:?}", binding);
match binding {
binding_info::BindingInfo::Generic(generic) => {
format!("{:?}", generic.symbol());
format!("{:?}", generic.library());
format!("{:?}", generic.segment());
}
binding_info::BindingInfo::Dyld(dyld) => {
format!("{:?}", dyld.symbol());
format!("{:?}", dyld.library());
format!("{:?}", dyld.segment());
}
binding_info::BindingInfo::Chained(chained) => {
format!("{:?}", chained.symbol());
format!("{:?}", chained.library());
format!("{:?}", chained.segment());
}
}
}
fn explore_macho(_: &str, macho: &lief::macho::Binary) {
format!("{macho:?}");
format!("{}", macho.entrypoint());
for section in macho.sections() {
format!("{section:?}");
format!("{:?}", section.segment());
for relocation in section.relocations() {
format!("{relocation:?}");
}
}
for command in macho.commands() {
format!("{command:?}");
match command {
Commands::Generic(gen) => {
println!("TYPE: {:?}", gen.command_type());
}
Commands::DyldChainedFixups(cmd) => {
for binding in cmd.bindings() {
format!("{:?}", binding);
}
}
Commands::DataInCode(cmd) => {
format!("{}", cmd.content().len());
for entry in cmd.entries() {
format!("{:?}", entry);
}
}
Commands::SymbolCommand(cmd) => {
format!("{}", cmd.symbol_table().len());
format!("{}", cmd.string_table().len());
format!("{}", cmd.original_str_size());
format!("{}", cmd.original_nb_symbols());
}
Commands::FunctionStarts(cmd) => {
format!("{}", cmd.content().len());
for entry in cmd.functions() {
format!("{:?}", entry);
}
}
Commands::DyldExportsTrie(cmd) => {
format!("{}", cmd.content().len());
for export in cmd.exports() {
format!("{:?}", export);
format!("{:?}", export.symbol());
format!("{:?}", export.alias());
format!("{:?}", export.alias_library());
}
}
Commands::ThreadCommand(cmd) => {
format!("{}", cmd.state().len());
}
Commands::CodeSignature(cmd) => {
format!("{}", cmd.content().len());
}
Commands::CodeSignatureDir(cmd) => {
format!("{}", cmd.content().len());
}
Commands::LinkerOptHint(cmd) => {
format!("{}", cmd.content().len());
}
Commands::TwoLevelHints(cmd) => {
format!("{}", cmd.original_nb_hints());
format!("{}", cmd.content().len());
}
Commands::SegmentSplitInfo(cmd) => {
format!("{}", cmd.content().len());
}
Commands::DyldInfo(cmd) => {
format!("{}", cmd.rebase_opcodes().len());
format!("{}", cmd.bind_opcodes().len());
format!("{}", cmd.weak_bind_opcodes().len());
format!("{}", cmd.lazy_bind_opcodes().len());
format!("{}", cmd.export_trie().len());
for binding in cmd.bindings() {
format!("{:?}", binding);
print_binding(&binding);
}
for export in cmd.exports() {
format!("{:?}", export);
}
}
_ => {}
}
}
for segment in macho.segments() {
format!("{segment:?}");
for section in segment.sections() {
format!("{section:?}");
}
for relocation in segment.relocations() {
format!("{relocation:?}");
}
format!("len: {}", segment.content().len());
}
for lib in macho.libraries() {
format!("{lib:?}");
}
for reloc in macho.relocations() {
format!("{reloc:?}");
}
for sym in macho.symbols() {
format!("{sym:?}");
}
if let Some(info) = macho.dyld_info() {
format!("{info:?}");
}
if let Some(uuid) = macho.uuid() {
format!("{uuid:?}");
}
if let Some(main) = macho.main_command() {
format!("{main:?}");
}
if let Some(linker) = macho.dylinker() {
format!("{linker:?}");
}
if let Some(starts) = macho.function_starts() {
format!("{starts:?}");
}
if let Some(version) = macho.source_version() {
format!("{version:?}");
}
if let Some(cmd) = macho.thread_command() {
format!("{cmd:?}");
}
if let Some(rpath) = macho.rpath() {
format!("{rpath:?}");
}
if let Some(symbol_command) = macho.symbol_command() {
format!("{symbol_command:?}");
}
if let Some(dynamic_symbol) = macho.dynamic_symbol() {
format!("{dynamic_symbol:?}");
}
if let Some(code_signature) = macho.code_signature() {
format!("{code_signature:?}");
}
if let Some(code_signature_dir) = macho.code_signature_dir() {
format!("{code_signature_dir:?}");
}
if let Some(data_in_code) = macho.data_in_code() {
format!("{data_in_code:?}");
}
if let Some(segment_split_info) = macho.segment_split_info() {
format!("{segment_split_info:?}");
}
if let Some(encryption_info) = macho.encryption_info() {
format!("{encryption_info:?}");
}
if let Some(sub_framework) = macho.sub_framework() {
format!("{sub_framework:?}");
}
if let Some(dyld_environment) = macho.dyld_environment() {
format!("{dyld_environment:?}");
}
if let Some(build_version) = macho.build_version() {
format!("{build_version:?}");
}
if let Some(dyld_chained_fixups) = macho.dyld_chained_fixups() {
format!("{dyld_chained_fixups:?}");
}
if let Some(dyld_exports_trie) = macho.dyld_exports_trie() {
format!("{dyld_exports_trie:?}");
}
if let Some(two_level_hints) = macho.two_level_hints() {
format!("{two_level_hints:?}");
}
if let Some(linker_opt_hint) = macho.linker_opt_hint() {
format!("{linker_opt_hint:?}");
}
if let Some(version_min) = macho.version_min() {
format!("{version_min:?}");
}
}
fn test_with(bin_name: &str) {
let path = utils::get_macho_sample(bin_name).unwrap();
let path_str = path.to_str();
if let Some(Binary::MachO(fat)) = Binary::parse(path_str.unwrap()) {
for bin in fat.iter() {
explore_macho(bin_name, &bin);
}
}
// Test Read + Seek interface
let mut file = std::fs::File::open(path).expect("Can't open the file");
let binary = Binary::from(&mut file);
assert!(matches!(binary, Some(Binary::MachO(_))));
}
#[test]
fn test_api() {
test_with("alivcffmpeg_armv7.dylib");
test_with(
"9edfb04c55289c6c682a25211a4b30b927a86fe50b014610d04d6055bd4ac23d_crypt_and_hash.macho",
);
test_with("MachO64_x86-64_binary_safaridriver.bin");
test_with("FAT_MachO_x86_x86-64_library_libdyld.dylib");
test_with("ios1-expr.bin");
test_with("json_api.cpp_1.o");
test_with("python3_issue_476.bin");
test_with("FAT_MachO_x86_x86-64_library_libc++abi.dylib");
}
+462
View File
@@ -0,0 +1,462 @@
mod utils;
use lief::pe::debug::Entries as DebugEntries;
use lief::pe::load_configuration::{
AsBase,
AsLoadConfigV0, AsLoadConfigV1, AsLoadConfigV2,
AsLoadConfigV3, AsLoadConfigV4, AsLoadConfigV5,
AsLoadConfigV6, AsLoadConfigV7, AsLoadConfigV8,
AsLoadConfigV9, AsLoadConfigV10,
LoadConfiguration
};
use lief::pe::resources::{Node, NodeBase};
use lief::pe::Algorithms;
use lief::pe::signature::attributes::Attribute;
use lief::pe::signature::Signature;
use lief::generic::Binary as GenericBinary;
use lief::Binary;
fn get_leaf<'a>(node: &'a Node) -> Option<&'a Node<'a>> {
match node {
Node::Data(_) => {
return Some(node);
}
Node::Directory(dir) => {
for child in dir.children() {
if let Some(Node::Data(data)) = get_leaf(&child) {
format!("{}", data.content().len());
format!("{data:?}");
}
}
}
}
None
}
fn explore_sig_attribute(attr: &Attribute) {
match attr {
Attribute::ContentType(item) => {
format!("{item:?}");
}
Attribute::GenericType(item) => {
format!("{item:?}");
}
Attribute::MsSpcNestedSignature(item) => {
format!("{item:?}");
explore_signature(&item.signature());
}
Attribute::MsSpcStatementType(item) => {
format!("{item:?}");
}
Attribute::PKCS9AtSequenceNumber(item) => {
format!("{item:?}");
}
Attribute::PKCS9CounterSignature(item) => {
format!("{item:?}");
let signer = item.signer();
for attr in signer.authenticated_attributes() {
explore_sig_attribute(&attr);
}
for attr in signer.unauthenticated_attributes() {
explore_sig_attribute(&attr);
}
}
Attribute::PKCS9MessageDigest(item) => {
format!("{item:?}");
format!("{}", item.digest().len());
}
Attribute::PKCS9SigningTime(item) => {
format!("{item:?}");
}
Attribute::SpcSpOpusInfo(item) => {
format!("{item:?}");
}
}
}
fn explore_signature(signature: &Signature) {
format!("{signature:?}");
let content_info = signature.content_info();
format!("{content_info:?}");
for crt in signature.certificates() {
format!("{crt:?}");
format!("{}", crt.serial_number().len());
format!("{}", crt.raw().len());
format!("{}", crt.signature().len());
if let Some(rsa_info) = crt.rsa_info() {
format!("{rsa_info:?}");
format!("{}", rsa_info.N().bits());
format!("{}", rsa_info.E().bits());
format!("{}", rsa_info.D().bits());
format!("{}", rsa_info.P().bits());
format!("{}", rsa_info.Q().bits());
}
}
for signer in signature.signers() {
format!("{signer:?}");
if let Some(crt) = signer.cert() {
format!("{crt:?}");
}
format!("{}", signer.encrypted_digest().len());
format!("{}", signer.serial_number().len());
for attr in signer.authenticated_attributes() {
explore_sig_attribute(&attr);
}
for attr in signer.unauthenticated_attributes() {
explore_sig_attribute(&attr);
}
}
}
fn explore_pe(_: &str, pe: &lief::pe::Binary) {
format!("{pe:?}");
let dos_header = pe.dos_header();
format!("{dos_header:?}");
let optional_header = pe.optional_header();
format!("{optional_header:?}");
let header = pe.header();
format!("{header:?}");
if let Some(tls) = pe.tls() {
format!("{tls:?}");
format!("{}", tls.data_template().len());
format!("{}", tls.addressof_raw_data().len());
}
if let Some(export) = pe.export() {
format!("{export:?}");
for entry in export.entries() {
format!("{entry:?}");
}
}
if let Some(resources) = pe.resources() {
format!("{resources:?}");
match resources {
Node::Data(_) => {}
Node::Directory(dir) => {
for child in dir.children() {
format!("{}", dir.depth());
format!("{child:?}");
}
}
}
}
if let Some(resources) = pe.resources() {
if let Some(leaf) = get_leaf(&resources) {
format!("{leaf:?}");
}
}
if let Some(config) = pe.load_configuration() {
format!("{config:?}");
match config {
LoadConfiguration::Base(item) => {
format!("{:?}", item);
}
LoadConfiguration::V0(item) => {
let base = &item as &dyn AsBase;
format!("{:?}", item);
format!("{:?}", base);
}
LoadConfiguration::V1(item) => {
let base = &item as &dyn AsBase;
let v0 = &item as &dyn AsLoadConfigV0;
format!("{:?}", item);
format!("{:?}", v0);
format!("{:?}", base);
}
LoadConfiguration::V2(item) => {
let base = &item as &dyn AsBase;
let v0 = &item as &dyn AsLoadConfigV0;
let v1 = &item as &dyn AsLoadConfigV1;
format!("{:?}", item);
format!("{:?}", v1);
format!("{:?}", v0);
format!("{:?}", base);
}
LoadConfiguration::V3(item) => {
let base = &item as &dyn AsBase;
let v0 = &item as &dyn AsLoadConfigV0;
let v1 = &item as &dyn AsLoadConfigV1;
let v2 = &item as &dyn AsLoadConfigV2;
format!("{:?}", item);
format!("{:?}", v2);
format!("{:?}", v1);
format!("{:?}", v0);
format!("{:?}", base);
}
LoadConfiguration::V4(item) => {
let base = &item as &dyn AsBase;
let v0 = &item as &dyn AsLoadConfigV0;
let v1 = &item as &dyn AsLoadConfigV1;
let v2 = &item as &dyn AsLoadConfigV2;
let v3 = &item as &dyn AsLoadConfigV3;
format!("{:?}", item);
format!("{:?}", v3);
format!("{:?}", v2);
format!("{:?}", v1);
format!("{:?}", v0);
format!("{:?}", base);
}
LoadConfiguration::V5(item) => {
let base = &item as &dyn AsBase;
let v0 = &item as &dyn AsLoadConfigV0;
let v1 = &item as &dyn AsLoadConfigV1;
let v2 = &item as &dyn AsLoadConfigV2;
let v3 = &item as &dyn AsLoadConfigV3;
let v4 = &item as &dyn AsLoadConfigV4;
format!("{:?}", item);
format!("{:?}", v4);
format!("{:?}", v3);
format!("{:?}", v2);
format!("{:?}", v1);
format!("{:?}", v0);
format!("{:?}", base);
}
LoadConfiguration::V6(item) => {
let base = &item as &dyn AsBase;
let v0 = &item as &dyn AsLoadConfigV0;
let v1 = &item as &dyn AsLoadConfigV1;
let v2 = &item as &dyn AsLoadConfigV2;
let v3 = &item as &dyn AsLoadConfigV3;
let v4 = &item as &dyn AsLoadConfigV4;
let v5 = &item as &dyn AsLoadConfigV5;
format!("{:?}", item);
format!("{:?}", v5);
format!("{:?}", v4);
format!("{:?}", v3);
format!("{:?}", v2);
format!("{:?}", v1);
format!("{:?}", v0);
format!("{:?}", base);
}
LoadConfiguration::V7(item) => {
let base = &item as &dyn AsBase;
let v0 = &item as &dyn AsLoadConfigV0;
let v1 = &item as &dyn AsLoadConfigV1;
let v2 = &item as &dyn AsLoadConfigV2;
let v3 = &item as &dyn AsLoadConfigV3;
let v4 = &item as &dyn AsLoadConfigV4;
let v5 = &item as &dyn AsLoadConfigV5;
let v6 = &item as &dyn AsLoadConfigV6;
format!("{:?}", item);
format!("{:?}", v6);
format!("{:?}", v5);
format!("{:?}", v4);
format!("{:?}", v3);
format!("{:?}", v2);
format!("{:?}", v1);
format!("{:?}", v0);
format!("{:?}", base);
}
LoadConfiguration::V8(item) => {
let base = &item as &dyn AsBase;
let v0 = &item as &dyn AsLoadConfigV0;
let v1 = &item as &dyn AsLoadConfigV1;
let v2 = &item as &dyn AsLoadConfigV2;
let v3 = &item as &dyn AsLoadConfigV3;
let v4 = &item as &dyn AsLoadConfigV4;
let v5 = &item as &dyn AsLoadConfigV5;
let v6 = &item as &dyn AsLoadConfigV6;
let v7 = &item as &dyn AsLoadConfigV7;
format!("{:?}", item);
format!("{:?}", v7);
format!("{:?}", v6);
format!("{:?}", v5);
format!("{:?}", v4);
format!("{:?}", v3);
format!("{:?}", v2);
format!("{:?}", v1);
format!("{:?}", v0);
format!("{:?}", base);
}
LoadConfiguration::V9(item) => {
let base = &item as &dyn AsBase;
let v0 = &item as &dyn AsLoadConfigV0;
let v1 = &item as &dyn AsLoadConfigV1;
let v2 = &item as &dyn AsLoadConfigV2;
let v3 = &item as &dyn AsLoadConfigV3;
let v4 = &item as &dyn AsLoadConfigV4;
let v5 = &item as &dyn AsLoadConfigV5;
let v6 = &item as &dyn AsLoadConfigV6;
let v7 = &item as &dyn AsLoadConfigV7;
let v8 = &item as &dyn AsLoadConfigV8;
format!("{:?}", item);
format!("{:?}", v8);
format!("{:?}", v7);
format!("{:?}", v6);
format!("{:?}", v5);
format!("{:?}", v4);
format!("{:?}", v3);
format!("{:?}", v2);
format!("{:?}", v1);
format!("{:?}", v0);
format!("{:?}", base);
}
LoadConfiguration::V10(item) => {
let base = &item as &dyn AsBase;
let v0 = &item as &dyn AsLoadConfigV0;
let v1 = &item as &dyn AsLoadConfigV1;
let v2 = &item as &dyn AsLoadConfigV2;
let v3 = &item as &dyn AsLoadConfigV3;
let v4 = &item as &dyn AsLoadConfigV4;
let v5 = &item as &dyn AsLoadConfigV5;
let v6 = &item as &dyn AsLoadConfigV6;
let v7 = &item as &dyn AsLoadConfigV7;
let v8 = &item as &dyn AsLoadConfigV8;
let v9 = &item as &dyn AsLoadConfigV9;
format!("{:?}", item);
format!("{:?}", v9);
format!("{:?}", v8);
format!("{:?}", v7);
format!("{:?}", v6);
format!("{:?}", v5);
format!("{:?}", v4);
format!("{:?}", v3);
format!("{:?}", v2);
format!("{:?}", v1);
format!("{:?}", v0);
format!("{:?}", base);
}
LoadConfiguration::V11(item) => {
let base = &item as &dyn AsBase;
let v0 = &item as &dyn AsLoadConfigV0;
let v1 = &item as &dyn AsLoadConfigV1;
let v2 = &item as &dyn AsLoadConfigV2;
let v3 = &item as &dyn AsLoadConfigV3;
let v4 = &item as &dyn AsLoadConfigV4;
let v5 = &item as &dyn AsLoadConfigV5;
let v6 = &item as &dyn AsLoadConfigV6;
let v7 = &item as &dyn AsLoadConfigV7;
let v8 = &item as &dyn AsLoadConfigV8;
let v9 = &item as &dyn AsLoadConfigV9;
let v10 = &item as &dyn AsLoadConfigV10;
format!("{:?}", item);
format!("{:?}", v10);
format!("{:?}", v9);
format!("{:?}", v8);
format!("{:?}", v7);
format!("{:?}", v6);
format!("{:?}", v5);
format!("{:?}", v4);
format!("{:?}", v3);
format!("{:?}", v2);
format!("{:?}", v1);
format!("{:?}", v0);
format!("{:?}", base);
}
}
}
if let Some(header) = pe.rich_header() {
format!("{header:?}");
for entry in header.entries() {
format!("{entry:?}");
}
}
let _ = pe.resources_manager();
for imp in pe.imports() {
format!("{imp:?}");
for entry in imp.entries() {
format!("{entry:?}");
}
}
for dir in pe.data_directories() {
format!("{dir:?}");
}
for section in pe.sections() {
format!("{section:?}");
format!("{}", section.padding().len());
}
for relocation in pe.relocations() {
format!("{relocation:?}");
for entry in relocation.entries() {
format!("{entry:?}");
}
}
for delay_import in pe.delay_imports() {
format!("{delay_import:?}");
for entry in delay_import.entries() {
format!("{entry:?}");
}
}
for signature in pe.signatures() {
explore_signature(&signature);
}
for debug in pe.debug() {
format!("{debug:?}");
match debug {
DebugEntries::Pogo(pogo) => {
for entry in pogo.entries() {
format!("{entry:?}");
}
}
DebugEntries::Repro(repro) => {
assert!(!repro.hash().is_empty());
}
_ => {}
}
}
assert!(pe.entrypoint() > 0);
assert!(!pe.dos_stub().is_empty());
assert!(!pe.authentihash(Algorithms::SHA_256).is_empty());
}
fn test_with(bin_name: &str) {
let path = utils::get_pe_sample(bin_name).unwrap();
let path_str = path.to_str();
if let Some(Binary::PE(bin)) = Binary::parse(path_str.unwrap()) {
explore_pe(bin_name, &bin);
}
// Test Read + Seek interface
let mut file = std::fs::File::open(path).expect("Can't open the file");
let binary = Binary::from(&mut file);
assert!(matches!(binary, Some(Binary::PE(_))));
}
fn test_signature(name: &str) {
let path = utils::get_pkcs7_sample(name).unwrap();
let path_str = path.to_str();
if let Some(sig) = Signature::from_file(path_str.unwrap()) {
explore_signature(&sig);
}
}
#[test]
fn test_api() {
test_with("ntoskrnl.exe");
test_with("steam.exe");
test_with("test.debug.repro.exe");
test_with("PE64_x86-64_library_libLIEF.dll");
test_with("PE32_x86-64_binary_avast-free-antivirus-setup-online.exe");
test_with("PE32_x86-64_binary_self-signed.exe");
test_with("steam.exe");
test_signature("cert0.p7b");
test_signature("cert3.p7b");
test_signature("cert11.p7b");
test_signature("cert9.p7b");
test_signature("cert10.p7b");
}
+42
View File
@@ -0,0 +1,42 @@
use std::env;
use std::path::{Path, PathBuf};
use std::str::FromStr;
pub fn get_sample_dir() -> Option<String> {
match env::var_os("LIEF_SAMPLES_DIR") {
Some(val) => Some(val.into_string().unwrap_or("".to_string())),
None => {
panic!("Can't find 'LIEF_SAMPLES_DIR'");
}
}
}
pub fn get_sample(path: &Path) -> Option<PathBuf> {
let sample_dir = get_sample_dir()?;
let sample_dir_path = PathBuf::from_str(sample_dir.as_str()).ok()?;
Some(sample_dir_path.join(path))
}
#[allow(dead_code)]
pub fn get_elf_sample(name: &str) -> Option<PathBuf> {
let suffix = Path::new("ELF").join(name);
get_sample(suffix.as_path())
}
#[allow(dead_code)]
pub fn get_pe_sample(name: &str) -> Option<PathBuf> {
let suffix = Path::new("PE").join(name);
get_sample(suffix.as_path())
}
#[allow(dead_code)]
pub fn get_macho_sample(name: &str) -> Option<PathBuf> {
let suffix = Path::new("MachO").join(name);
get_sample(suffix.as_path())
}
#[allow(dead_code)]
pub fn get_pkcs7_sample(name: &str) -> Option<PathBuf> {
let suffix = Path::new("pkcs7").join(name);
get_sample(suffix.as_path())
}
+11
View File
@@ -0,0 +1,11 @@
[package]
name = "lief-examples"
version = "0.0.0"
edition = "2021"
[dependencies]
lief = { path = "../cargo/lief" }
[[bin]]
name = "reader"
path = "reader.rs"
+39
View File
@@ -0,0 +1,39 @@
use lief::Binary;
use lief::elf;
use lief::pe;
//use lief::macho::FatBinary;
//use lief::macho::commands::Commands;
use lief::generic::Relocation;
use lief::pe::DosHeader;
// use lief::elf::dynamic::DynamicEntry;
fn explore_elf(elf: &elf::Binary) {
for section in elf.sections() {
println!("{:?}", section);
}
for segment in elf.segments() {
println!("{:?}", segment);
}
for note in elf.notes() {
println!("{:?}", note);
}
for symbol in elf.dynamic_symbols() {
println!("{:?}", symbol);
}
}
fn main() {
let path = std::env::args().last().unwrap();
let mut file = std::fs::File::open(path).expect("Can't open the file");
match Binary::from(&mut file) {
Some(Binary::ELF(elf)) => {
explore_elf(&elf);
},
Some(Binary::PE(pe)) => {
},
_ => {}
}
return;
}
+19
View File
@@ -0,0 +1,19 @@
/* Copyright 2024 R. Thomas
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "LIEF/rust/Abstract/Binary.hpp"
#include "LIEF/rust/Abstract/Relocation.hpp"
#include "LIEF/rust/Abstract/Symbol.hpp"
#include "LIEF/rust/Abstract/Section.hpp"
@@ -0,0 +1,28 @@
/* Copyright 2024 R. Thomas
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <LIEF/Abstract/Binary.hpp>
#include <LIEF/rust/Mirror.hpp>
class AbstractBinary : public Mirror<LIEF::Binary> {
public:
using Mirror::Mirror;
uint64_t entrypoint() const { return get().entrypoint(); }
uint64_t imagebase() const { return get().imagebase(); }
uint64_t original_size() const { return get().original_size(); }
bool is_pie() const { return get().is_pie(); }
bool has_nx() const { return get().has_nx(); }
};
@@ -0,0 +1,25 @@
/* Copyright 2024 R. Thomas
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <LIEF/Abstract/Relocation.hpp>
#include <LIEF/rust/Mirror.hpp>
class AbstractRelocation : public Mirror<LIEF::Relocation> {
public:
using Mirror::Mirror;
uint64_t size() const { return get().size(); }
uint64_t address() const { return get().address(); }
};
@@ -0,0 +1,32 @@
/* Copyright 2024 R. Thomas
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <LIEF/Abstract/Section.hpp>
#include <LIEF/rust/helpers.hpp>
#include <LIEF/rust/Span.hpp>
#include <LIEF/rust/Mirror.hpp>
#include <string>
class AbstractSection : public Mirror<LIEF::Section> {
public:
using Mirror::Mirror;
std::string name() const { return get().name(); }
uint64_t size() const { return get().size(); }
uint64_t offset() const { return get().offset(); }
uint64_t virtual_address() const { return get().virtual_address(); }
Span content() const { return make_span(get().content()); }
};
@@ -0,0 +1,28 @@
/* Copyright 2024 R. Thomas
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <LIEF/Abstract/Symbol.hpp>
#include <LIEF/rust/Mirror.hpp>
#include <string>
class AbstractSymbol : public Mirror<LIEF::Symbol> {
public:
using Mirror::Mirror;
std::string name() const { return get().name(); }
uint64_t size() const { return get().size(); }
uint64_t value() const { return get().value(); }
};
+25
View File
@@ -0,0 +1,25 @@
/* Copyright 2024 R. Thomas
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "LIEF/rust/ELF/Section.hpp"
#include "LIEF/rust/ELF/Binary.hpp"
#include "LIEF/rust/ELF/utils.hpp"
#include "LIEF/rust/ELF/DynamicEntry.hpp"
#include "LIEF/rust/ELF/DynamicEntryArray.hpp"
#include "LIEF/rust/ELF/DynamicEntryFlags.hpp"
#include "LIEF/rust/ELF/DynamicEntryLibrary.hpp"
#include "LIEF/rust/ELF/DynamicEntryRpath.hpp"
#include "LIEF/rust/ELF/DynamicEntryRunPath.hpp"
#include "LIEF/rust/ELF/DynamicSharedObject.hpp"
+253
View File
@@ -0,0 +1,253 @@
/* Copyright 2024 R. Thomas
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <string>
#include <LIEF/ELF/Binary.hpp>
#include <LIEF/ELF/Parser.hpp>
#include "LIEF/rust/Iterator.hpp"
#include "LIEF/rust/Abstract/Binary.hpp"
#include "LIEF/rust/ELF/GnuHash.hpp"
#include "LIEF/rust/ELF/Sysvhash.hpp"
#include "LIEF/rust/ELF/SymbolVersion.hpp"
#include "LIEF/rust/ELF/SymbolVersionDefinition.hpp"
#include "LIEF/rust/ELF/SymbolVersionRequirement.hpp"
#include "LIEF/rust/ELF/Segment.hpp"
#include "LIEF/rust/ELF/Section.hpp"
#include "LIEF/rust/ELF/Symbol.hpp"
#include "LIEF/rust/ELF/Relocation.hpp"
#include "LIEF/rust/ELF/Header.hpp"
#include "LIEF/rust/ELF/Note.hpp"
#include "LIEF/rust/ELF/DynamicEntry.hpp"
class ELF_Binary : public AbstractBinary {
public:
using lief_t = LIEF::ELF::Binary;
ELF_Binary(std::unique_ptr<lief_t> bin) : AbstractBinary(std::move(bin)) {}
static auto parse(std::string path) {
return std::make_unique<ELF_Binary>(LIEF::ELF::Parser::parse(path));
}
class it_sections :
public Iterator<ELF_Section, LIEF::ELF::Binary::it_const_sections>
{
public:
it_sections(const ELF_Binary::lief_t& src)
: Iterator(std::move(src.sections())) { }
auto next() { return Iterator::next(); }
};
class it_segments :
public Iterator<ELF_Segment, LIEF::ELF::Binary::it_const_segments>
{
public:
it_segments(const ELF_Binary::lief_t& src)
: Iterator(std::move(src.segments())) { }
auto next() { return Iterator::next(); }
};
class it_dynamic_entries :
public Iterator<ELF_DynamicEntry, LIEF::ELF::Binary::it_const_dynamic_entries>
{
public:
it_dynamic_entries(const ELF_Binary::lief_t& src)
: Iterator(std::move(src.dynamic_entries())) { }
auto next() { return Iterator::next(); }
};
class it_dynamic_symbols :
public Iterator<ELF_Symbol, LIEF::ELF::Binary::it_const_dynamic_symbols>
{
public:
it_dynamic_symbols(const ELF_Binary::lief_t& src)
: Iterator(std::move(src.dynamic_symbols())) { }
auto next() { return Iterator::next(); }
};
class it_exported_symbols :
public Iterator<ELF_Symbol, LIEF::ELF::Binary::it_const_exported_symbols>
{
public:
it_exported_symbols(const ELF_Binary::lief_t& src)
: Iterator(std::move(src.exported_symbols())) { }
auto next() { return Iterator::next(); }
};
class it_imported_symbols :
public Iterator<ELF_Symbol, LIEF::ELF::Binary::it_const_imported_symbols>
{
public:
it_imported_symbols(const ELF_Binary::lief_t& src)
: Iterator(std::move(src.imported_symbols())) { }
auto next() { return Iterator::next(); }
};
class it_notes :
public Iterator<ELF_Note, LIEF::ELF::Binary::it_const_notes>
{
public:
it_notes(const ELF_Binary::lief_t& src)
: Iterator(std::move(src.notes())) { }
auto next() { return Iterator::next(); }
};
class it_symtab_symbols :
public Iterator<ELF_Symbol, LIEF::ELF::Binary::it_const_symtab_symbols>
{
public:
it_symtab_symbols(const ELF_Binary::lief_t& src)
: Iterator(std::move(src.symtab_symbols())) { }
auto next() { return Iterator::next(); }
};
class it_relocations :
public Iterator<ELF_Relocation, LIEF::ELF::Binary::it_const_relocations>
{
public:
it_relocations(const ELF_Binary::lief_t& src)
: Iterator(std::move(src.relocations())) { }
auto next() { return Iterator::next(); }
};
class it_pltgot_relocations :
public Iterator<ELF_Relocation, LIEF::ELF::Binary::it_const_pltgot_relocations>
{
public:
it_pltgot_relocations(const ELF_Binary::lief_t& src)
: Iterator(std::move(src.pltgot_relocations())) { }
auto next() { return Iterator::next(); }
};
class it_dynamic_relocations :
public Iterator<ELF_Relocation, LIEF::ELF::Binary::it_const_dynamic_relocations>
{
public:
it_dynamic_relocations(const ELF_Binary::lief_t& src)
: Iterator(std::move(src.dynamic_relocations())) { }
auto next() { return Iterator::next(); }
};
class it_object_relocations :
public Iterator<ELF_Relocation, LIEF::ELF::Binary::it_const_object_relocations>
{
public:
it_object_relocations(const ELF_Binary::lief_t& src)
: Iterator(std::move(src.object_relocations())) { }
auto next() { return Iterator::next(); }
};
class it_symbols_version :
public Iterator<ELF_SymbolVersion, LIEF::ELF::Binary::it_const_symbols_version>
{
public:
it_symbols_version(const ELF_Binary::lief_t& src)
: Iterator(std::move(src.symbols_version())) { }
auto next() { return Iterator::next(); }
};
class it_symbols_version_requirement :
public Iterator<ELF_SymbolVersionRequirement, LIEF::ELF::Binary::it_const_symbols_version_requirement>
{
public:
it_symbols_version_requirement(const ELF_Binary::lief_t& src)
: Iterator(std::move(src.symbols_version_requirement())) { }
auto next() { return Iterator::next(); }
};
class it_symbols_version_definition :
public Iterator<ELF_SymbolVersionDefinition, LIEF::ELF::Binary::it_const_symbols_version_definition>
{
public:
it_symbols_version_definition(const ELF_Binary::lief_t& src)
: Iterator(std::move(src.symbols_version_definition())) { }
auto next() { return Iterator::next(); }
};
auto header() const {
return std::make_unique<ELF_Header>(impl().header());
}
auto gnu_hash() const {
return details::try_unique<ELF_GnuHash>(impl().gnu_hash());
}
auto sysv_hash() const {
return details::try_unique<ELF_SysvHash>(impl().sysv_hash());
}
auto sections() const {
return std::make_unique<it_sections>(impl());
}
auto segments() const {
return std::make_unique<it_segments>(impl());
}
auto dynamic_entries() const {
return std::make_unique<it_dynamic_entries>(impl());
}
auto dynamic_symbols() const {
return std::make_unique<it_dynamic_symbols>(impl());
}
auto exported_symbols() const {
return std::make_unique<it_exported_symbols>(impl());
}
auto imported_symbols() const {
return std::make_unique<it_imported_symbols>(impl());
}
auto symtab_symbols() const {
return std::make_unique<it_symtab_symbols>(impl());
}
auto notes() const {
return std::make_unique<it_notes>(impl());
}
auto relocations() const {
return std::make_unique<it_relocations>(impl());
}
auto pltgot_relocations() const {
return std::make_unique<it_pltgot_relocations>(impl());
}
auto dynamic_relocations() const {
return std::make_unique<it_dynamic_relocations>(impl());
}
auto object_relocations() const {
return std::make_unique<it_object_relocations>(impl());
}
auto symbols_version() const {
return std::make_unique<it_symbols_version>(impl());
}
auto symbols_version_requirement() const {
return std::make_unique<it_symbols_version_requirement>(impl());
}
auto symbols_version_definition() const {
return std::make_unique<it_symbols_version_definition>(impl());
}
private:
const lief_t& impl() const { return as<lief_t>(this); }
};

Some files were not shown because too many files have changed in this diff Show More