mirror of
https://github.com/lief-project/LIEF.git
synced 2026-10-11 22:09:53 +00:00
Add rust bindings
This commit is contained in:
@@ -3,3 +3,6 @@ build/
|
||||
*.whl
|
||||
lief.egg-info/
|
||||
dist/
|
||||
api/rust/cargo/target/*
|
||||
api/rust/examples/target/*
|
||||
Cargo.lock
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
include:
|
||||
- project: 'LIEF/ci'
|
||||
ref: main
|
||||
file: 'main.yml'
|
||||
+21
-20
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -6,3 +6,7 @@ if(LIEF_C_API)
|
||||
add_subdirectory(c)
|
||||
endif()
|
||||
|
||||
if(LIEF_RUST_API)
|
||||
add_subdirectory(rust)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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"
|
||||
@@ -0,0 +1 @@
|
||||
# LIEF Rust Bindings
|
||||
@@ -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"
|
||||
@@ -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(())
|
||||
}
|
||||
@@ -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" ] }
|
||||
@@ -0,0 +1,3 @@
|
||||
fn main() -> miette::Result<()> {
|
||||
lief_build::build()
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
include!(concat!(env!("AUTOCXX_RS"), "/", "autocxx-autocxx_ffi-gen.rs"));
|
||||
|
||||
pub use autocxx_ffi::*;
|
||||
@@ -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" ] }
|
||||
@@ -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(())
|
||||
}
|
||||
@@ -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" }
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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 &[];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
//! # LIEF
|
||||
//!
|
||||
//! 
|
||||
//!
|
||||
//! 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;
|
||||
@@ -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;
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -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)))
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
);
|
||||
@@ -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
|
||||
);
|
||||
@@ -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
|
||||
);
|
||||
@@ -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,
|
||||
}
|
||||
@@ -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
|
||||
);
|
||||
@@ -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
|
||||
);
|
||||
@@ -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
|
||||
);
|
||||
@@ -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
|
||||
);
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
);
|
||||
@@ -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
|
||||
);
|
||||
@@ -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
|
||||
);
|
||||
@@ -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
|
||||
);
|
||||
@@ -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
|
||||
);
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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())
|
||||
}
|
||||
@@ -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"
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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(); }
|
||||
};
|
||||
@@ -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"
|
||||
@@ -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
Reference in New Issue
Block a user