Difference between revisions of "Logos"

From iPhone Development Wiki
Jump to: navigation, search
m (Block-level: Moved %new before %subclass)
m (It’s confusing to keep this around, so replacing with a link to the current documentation)
(Tag: Replaced)
 
(24 intermediate revisions by 8 users not shown)
Line 1: Line 1:
Logos is a component of the [[Theos]] development suite that allows method hooking code to be written easily and clearly, using a set of special preprocessor directives.
+
{{soft redirect|https://theos.dev/docs/logos}}
  
== Overview ==
+
This article is obsolete, and has been replaced by the [https://theos.dev/docs/logos theos.dev website].
  
The syntax provided by Logos greatly simplifies the development of MobileSubstrate extensions ("tweaks") which can hook other methods throughout the OS.
+
If you need historical installation instructions, you can find the last version of this article [https://iphonedev.wiki/index.php?title=Logos&oldid=5734 here].
In this context, "method hooking" refers to a technique used to replace or modify methods of classes found in other applications on the phone.
 
 
 
== Getting Logos ==
 
 
 
Logos is distributed with [[Theos]], and you can use Logos' syntax in any Theos-built project without any extra setup.  For more information about Theos, visit [[Theos|its page]].
 
 
 
== List of Logos Directives ==
 
 
 
=== Block-level ===
 
 
 
The directives in this category open a block of code which must be closed by an %end directive (shown below). These should not exist within functions or methods.
 
 
 
==== %group ====
 
 
 
<source lang="logos">
 
%group Groupname
 
</source>
 
 
 
Begin a hook group (for conditional initialization or code organization) with the name ''Groupname''. All ungrouped hooks are in the implicit "_ungrouped" group.
 
 
 
==== %hook ====
 
 
 
<source lang="logos">
 
%hook Classname
 
</source>
 
 
 
Open a hook block for the class named ''Classname''.
 
 
 
Can be inside a <tt>%group</tt> block.
 
 
 
Here's a trivial example:
 
 
 
<source lang="logos">
 
%hook SBApplicationController
 
-(void)uninstallApplication:(SBApplication *)application {
 
    NSLog(@"Hey, we're hooking uninstallApplication:!");
 
    %orig; // Call the original implementation of this method
 
    return;
 
}
 
%end
 
</source>
 
 
 
==== %new ====
 
 
 
<source lang="logos">
 
%new
 
%new(signature)
 
</source>
 
 
 
Add a new method to a hooked class or subclass. ''signature'' is the Objective-C type encoding for the new method; if it is omitted, one will be generated.
 
 
 
Can be inside a <tt>%group</tt> block.
 
 
 
==== %subclass ====
 
 
 
<source lang="logos">
 
%subclass Classname: Superclass <Protocol list>
 
</source>
 
 
 
Subclass block - the class is created at runtime and populated with methods. ivars are not yet supported (use associated objects).
 
The %new specifier is needed for a method that doesn't exist in the superclass.
 
To instantiate an object of the new class, you can use the %c operator.
 
 
 
Can be inside a <tt>%group</tt> block.
 
 
 
Here's an example:
 
 
 
<source lang="logos">
 
%subclass MyObject : NSObject
 
 
 
- (id)init {
 
self = %orig;
 
[self setSomeValue:@"value"];
 
return self;
 
}
 
 
 
//the following two new methods act as `@property (nonatomic, retain) id someValue;`
 
%new
 
- (id)someValue {
 
return objc_getAssociatedObject(self, @selector(someValue));
 
}
 
 
 
%new
 
- (void)setSomeValue:(id)value {
 
objc_setAssociatedObject(self, @selector(someValue), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
 
}
 
 
 
%end
 
 
 
%ctor {
 
MyObject *myObject = [[%c(MyObject) alloc] init];
 
NSLog(@"myObject: %@", [myObject someValue]);
 
}
 
</source>
 
 
 
==== %end ====
 
 
 
<source lang="logos">
 
%end
 
</source>
 
 
 
Close a group/hook/subclass block.
 
 
 
=== Top level ===
 
 
 
The directives in this category should not exist within a group/hook/subclass block.
 
 
 
==== %config ====
 
 
 
<source lang="logos">
 
%config(X=Y);
 
</source>
 
 
 
Set a logos configuration flag.
 
 
 
===== Configuration Flags =====
 
 
 
* generator
 
**; MobileSubstrate
 
**: generate code that uses [[MobileSubstrate]] for hooking.
 
**; internal
 
**: generate code that uses only internal Objective-C runtime methods for hooking.
 
* warnings
 
**; none
 
**: suppress all warnings
 
**; default
 
**: non-fatal warnings
 
**; error
 
**: make all warnings fatal
 
* dump
 
**; yaml
 
**: dump the internal parse tree in YAML format
 
**; <strike>perl</strike>
 
**: <strike>dump the internal parse tree in a format suitable for evaluation as perl source.</strike><br /> dump to the perl source feature is removed since [https://github.com/DHowett/theos/commit/a05354a7b9839a5dce48f7c07114f30dd195b537 this commit].
 
 
 
==== %ctor ====
 
 
 
<source lang="logos">
 
%ctor { … }
 
</source>
 
 
 
Generate an anonymous constructor (of default priority).
 
 
 
=== Function level ===
 
 
 
The directives in this category should only exist within a function block.
 
 
 
==== %init ====
 
 
 
<source lang="logos">
 
%init;
 
%init([<class>=<expr>, …]);
 
%init(Group[, [+|-]<class>=<expr>, …]);
 
</source>
 
 
 
Initialize a group (or the default group). Passing no group name will initialize "_ungrouped", and passing class=expr arguments will substitute the given expressions for those classes at initialization time. The + sigil (as in class methods in Objective-C) can be prepended to the classname to substitute an expression for the metaclass. If not specified, the sigil defaults to -, to substitute the class itself. If not specified, the metaclass is derived from the class.
 
 
 
==== %class ====
 
 
 
<source lang="logos">
 
%class Class;
 
</source>
 
 
 
{{warning|<tt>%class</tt> is deprecated. Do not use it in new code.}}
 
 
 
Forward-declare a class. Outmoded by %c, but still exists. Creates a $Class variable, and initializes it with the "_ungrouped" group.
 
 
 
==== %c ====
 
 
 
<source lang="logos">
 
%c([+|-]Class)
 
</source>
 
 
 
Evaluates to <tt>Class</tt> at runtime. If the + sigil is specified, it evaluates to MetaClass instead of Class. If not specified, the sigil defaults to -, evaluating to Class.
 
 
 
==== %orig ====
 
 
 
<source lang="logos">
 
%orig
 
%orig(arg1, …)
 
</source>
 
 
 
Call the original hooked method. Doesn't function in a <tt>%new</tt>'d method. Works in subclasses, strangely enough, because MobileSubstrate will generate a supercall closure at hook time. (If the hooked method doesn't exist in the class we're hooking, it creates a stub that just calls the superclass implementation.) args is passed to the original function - don't include <tt>self</tt> and <tt>_cmd</tt>, Logos does this for you.
 
 
 
==== %log ====
 
 
 
<source lang="logos">
 
%log;
 
%log([(<type>)<expr>, …]);
 
</source>
 
 
 
Dump the method arguments to syslog. Typed arguments included in <tt>%log</tt> will be logged as well.
 
 
 
== File Extensions for Logos ==
 
 
 
{| class="wikitable"
 
|-
 
! Extension
 
! Process order
 
|-
 
| .x
 
| will be processed by Logos, then preprocessed and compiled as objective-c.
 
|-
 
| .xm
 
| will be processed by Logos, then preprocessed and compiled as objective-c++.
 
|-
 
| .xi
 
| will be preprocessed as objective-c first, then Logos will process the result, and then it will be compiled.
 
|-
 
| .xmi
 
| will be preprocessed as objective-c++ first, then Logos will process the result, and then it will be compiled.
 
|}
 
 
 
xi or xmi files can use Logos directives in #define macros.
 
 
 
== Splitting Logos Hooking Code Across Multiple Files ==
 
 
 
By default, the Logos pre-processor will only process one .xm file at build time. However, it is possible to split the Logos hooking code into multiple files.<br>
 
First, the main file has to be renamed to an .xmi file. Then, other .xm files can be included in it using the #include directive. The Logos pre-processor will add those files to the main file before processing it.
 
 
 
== Examples ==
 
 
 
Here is an example of a very simple Logos tweak generated by logify.pl
 
<source lang="logos">
 
%hook SSDownloadAsset
 
- (NSString *)finalizedPath { %log; NSString * r = %orig; NSLog(@" = %@", r); return r; }
 
- (NSString *)downloadPath { %log; NSString * r = %orig; NSLog(@" = %@", r); return r; }
 
- (NSString *)downloadFileName { %log; NSString * r = %orig; NSLog(@" = %@", r); return r; }
 
+ (id)assetWithURL:(id)url type:(int)type { %log; id r = %orig; NSLog(@" = %@", r); return r; }
 
- (id)initWithURLRequest:(id)urlrequest type:(int)type { %log; id r = %orig; NSLog(@" = %@", r); return r; }
 
- (id)initWithURLRequest:(id)urlrequest { %log; id r = %orig; NSLog(@" = %@", r); return r; }
 
- (id)_initWithDownloadMetadata:(id)downloadMetadata type:(id)type { %log; id r = %orig; NSLog(@" = %@", r); return r; }
 
%end
 
</source>
 
 
 
You can use logify.pl to create a Logos source file from a header file that will log all of the functions of that header file. You can find logify.pl at $THEOS/bin/logify.pl and you would use it as so:
 
 
 
<source lang="bash">
 
$THEOS/bin/logify.pl ./SSDownloadAsset.h
 
</source>
 
 
 
[[Category:Development Tools]]
 

Latest revision as of 18:12, 19 February 2022

Soft redirect to:https://theos.dev/docs/logos

This article is obsolete, and has been replaced by the theos.dev website.

If you need historical installation instructions, you can find the last version of this article here.