Objective-C¶
API
Introduction¶
LIEF Extended reads Objective-C classes, methods, properties, and protocols from Mach-O metadata. It can also generate header-like declarations.
This information comes from Objective-C runtime metadata in the file, so it can be present even when source-level debug information is unavailable.
Inspect metadata¶
macho: lief.MachO.Binary
metadata = macho.objc_metadata
if metadata is not None:
print("Objective-C metadata found")
std::unique_ptr<LIEF::MachO::Binary> macho;
std::unique_ptr<LIEF::objc::Metadata> metadata = macho->objc_metadata();
if (metadata != nullptr) {
std::cout << "Objective metadata found\n";
}
let macho: &lief::macho::Binary = some_macho;
if let Some(metadata) = macho.objc_metadata() {
println!("Objective-C metadata found");
}
macho: lief.MachO.Binary
metadata = macho.objc_metadata
for clazz in metadata.classes:
print(f"name={clazz.name}")
for meth in clazz.methods:
print(f" method.name={meth.name}")
print(metadata.to_decl())
std::unique_ptr<LIEF::MachO::Binary> bin;
std::unique_ptr<LIEF::objc::Metadata> metadata = bin->objc_metadata();
for (const LIEF::objc::Class& clazz : metadata->classes()) {
std::cout << "name=" << clazz.name() << '\n';
for (const LIEF::objc::Method& meth : clazz.methods()) {
std::cout << " method.name=" << meth.name() << '\n';
}
}
std::cout << metadata->to_decl();
let macho: &lief::macho::Binary = some_macho;
let Some(metadata) = macho.objc_metadata() else {
process::exit(1);
};
for class in metadata.classes() {
println!("name={}", class.name());
for method in class.methods() {
println!(" method.name={}", method.name());
}
}
println!("{}", metadata.to_decl());
Class Dump¶
Generate header-like declarations to review the classes and protocols found in the binary. The output describes the recorded metadata, including method signatures. It does not recover method implementations or the original headers.

LIEF provides a way to generate this header-like information at various levels:
Technically, this output is created by generating a Clang AST and applying the LLVM printer visitor to it.
fn classdump(macho: &lief::macho::Binary) {
let metadata = macho.objc_metadata().expect("Missing Objective-C info");
for class in metadata.classes() {
println!("{}", class.to_decl());
}
}
@interface APMEventFilter<APMAudienceFilter> {
bool _sessionScoped;
bool _dynamic;
bool _sequence;
int _audienceID;
int _filterID;
NSString * _eventName;
NSData * _data;
}
// Address: 0x0101859ee0
- (NSObject *)initWithAudienceID:(APMEventFilter *)self filterID:(SEL)id eventName:(int)arg2 data:(int)arg3 sessionScoped:(NSObject *)arg4 dynamic:(NSObject *)arg5 sequence:(bool)arg6 :(bool)arg7 :(bool)arg8;
// Address: 0x0101682590
- (int)audienceID:(APMEventFilter *)self :(SEL)id;
// Address: 0x01017b6d98
- (int)filterID:(APMEventFilter *)self :(SEL)id;
// Address: 0x01018a4a6c
- (bool)isSessionScoped:(APMEventFilter *)self :(SEL)id;
// Address: 0x01017630d4
- (bool)isDynamic:(APMEventFilter *)self :(SEL)id;
// Address: 0x01016adbb4
- (bool)isSequence:(APMEventFilter *)self :(SEL)id;
// Address: 0x010187a5f8
- (NSObject *)eventName:(APMEventFilter *)self :(SEL)id;
// Address: 0x0101581bfc
- (NSObject *)data:(APMEventFilter *)self :(SEL)id;
// Address: 0x01018e1f3c
- (void).cxx_destruct:(APMEventFilter *)self :(SEL)id;
@property void eventName;
@property void data;
@property void audienceID;
@property void filterID;
@property void sessionScoped;
@property void dynamic;
@property void sequence;
@property void hash;
@property void superclass;
@property void description;
@property void debugDescription;
@end
def print_without_address(macho: lief.MachO.Binary):
metadata = macho.objc_metadata
config = lief.objc.DeclOpt()
config.show_annotations = False
for cls in metadata.classes:
print(cls.to_decl(config))
References¶
API¶
You can find the documentation of the API for the different languages here:
Rust API: lief::objc