GithubHelp home page GithubHelp logo

theos / logos Goto Github PK

View Code? Open in Web Editor NEW
194.0 9.0 32.0 524 KB

Preprocessor that simplifies Objective-C hooking.

Home Page: https://github.com/theos/logos/wiki

License: Other

Perl 96.97% Vim Script 3.03%
theos logos

logos's Introduction

Logos

Logos is a Perl regex-based preprocessor that simplifies the boilerplate code needed to create hooks for Objective-C methods and C functions with an elegant Objective-C-like syntax. It’s most commonly used along with the Theos build system, which was originally developed to create jailbreak tweaks. Logos was once integrated in the same Git repo as Theos, but now has been decoupled from Theos to its own repo.

Logos aims to provide an interface for Cydia Substrate by default, but can be configured to directly use the Objective-C runtime.

Documentation is available on the Logos Syntax, Logify, and File Extensions pages of theos.dev.

Example

Source file: Tweak.x

%hook NSObject

- (NSString *)description {
	return [%orig stringByAppendingString:@" (of doom)"];
}

%new
- (void)helloWorld {
	NSLog(@"Awesome!");
}

%end

Logos-processed output: Tweak.x.m

(Modified for brevity)

#include <substrate.h>

static NSString *_logos_method$_ungrouped$NSObject$description(NSObject *self, SEL _cmd) {
	return [_logos_orig$_ungrouped$NSObject$description(self, _cmd) stringByAppendingString:@" (of doom)"];
}

static void _logos_method$_ungrouped$NSObject$helloWorld(NSObject * self, SEL _cmd) {
	NSLog(@"Awesome!");
}

static __attribute__((constructor)) void _logosLocalInit() {
	Class _logos_class$_ungrouped$NSObject = objc_getClass("NSObject");

	MSHookMessageEx(_logos_class$_ungrouped$NSObject, @selector(description), (IMP)&_logos_method$_ungrouped$NSObject$description, (IMP*)&_logos_orig$_ungrouped$NSObject$description);

	class_addMethod(_logos_class$_ungrouped$NSObject, @selector(helloWorld), (IMP)&_logos_method$_ungrouped$NSObject$helloWorld, "v@:");
}

License

Licensed under the GNU General Public License, version 3.0, with an exception that projects created using Logos are not required to use the same license. Refer to LICENSE.md.

logos's People

Contributors

akemin-dayo avatar brendonjkding avatar ccworld1000 avatar coolstar avatar crkatri avatar dhowett avatar eswick avatar hearsedev avatar holyswordman avatar kabiroberai avatar kirb avatar l1ghtmann avatar leptos-null avatar luki120 avatar mstg avatar nin9tyfour avatar nsexceptional avatar rpetrich avatar ryannair05 avatar sbingner avatar theiostream avatar uroboro avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

logos's Issues

%property with custom setter results in compiler error

Problem: When specifying a custom setter for a %property, Logos puts the : in the generated method name (when it shouldn't).

Code:

%group Foo
%hook NSObject

%property(nonatomic, retain, setter=my_Setter:) id obj;

%end
%end

Error:

file.xm:71:231: error: variable has incomplete type 'void'
  ...{ return (id)objc_getAssociatedObject(self, (void *)_logos_method$Foo$NSObject$obj); }; __attribute__((used)) static void _logos_method...
                                                                                                                               ^
file.xm:71:267: error: expected ';' after top level declarator
  ...(void *)_logos_method$Foo$NSObject$obj); }; __attribute__((used)) static void _logos_method$Foo$NSObject$my_Setter:(NSObject * __unuse...
                                                                                                                       ^
                                                                                                                       ;
file.xm:71:278: error: expected ')'
  ...(void *)_logos_method$Foo$NSObject$obj); }; __attribute__((used)) static void _logos_method$Foo$NSObject$my_Setter:(NSObject * __unuse...
                                                                                                                                  ^
file.xm:71:268: note: to match this '('
  ...(void *)_logos_method$Foo$NSObject$obj); }; __attribute__((used)) static void _logos_method$Foo$NSObject$my_Setter:(NSObject * __unuse...
                                                                                                                        ^
file.xm:71:269: error: C++ requires a type specifier for all declarations
  ...(void *)_logos_method$Foo$NSObject$obj); }; __attribute__((used)) static void _logos_method$Foo$NSObject$my_Setter:(NSObject * __unuse...
                                                                                                                         ^
file.xm:71:326: error: expected ';' after top level declarator
  ...static void _logos_method$Foo$NSObject$my_Setter:(NSObject * __unused self, SEL __unused _cmd, id rawValue) { objc_setAssociatedObject(...
                                                                                                                ^
                                                                                                                ;

%property (strong)

I'm trying to make a new property for an ARC project using %property (strong) and I get a compile error of "unrecognized type". It seems like only non-arc types work,

No dependency ordering in Logos

Code such as

%subclass FAFloatyFolderView : FACommonFolderView
%end

%subclass FACommonFolderView : SBFolderView
%end

will generate output:

Class _logos_class$_ungrouped$FACommonFolderView = objc_getClass("FACommonFolderView");
Class _logos_class$_ungrouped$FAFloatyFolderView = objc_allocateClassPair(_logos_class$_ungrouped$FACommonFolderView, "FAFloatyFolderView", 0);
Class _logos_class$_ungrouped$FACommonFolderView = objc_allocateClassPair(_logos_class$_ungrouped$SBFolderView, "FACommonFolderView", 0);

Therefore causing FAFloatyFolderView to be initialized without a superclass, and generating a redundant call to objc_getClass().

Nullability specifiers not supported in %property

What are the steps to reproduce this issue?

%property (nonatomic, retain) UITextField * _Nonnull textField;

What happens?

iDUTagCreationAlertCollectionViewController.x:19:1: error: expected identifier or '('
%property (nonatomic, retain) UITextField * _Nonnull textField;
^

What were you expecting to happen?

Successful compilation.

Any logs, error output, etc?

iDUTagCreationAlertCollectionViewController.x:19:1: error: expected identifier or '('
%property (nonatomic, retain) UITextField * _Nonnull textField;
^

Any other comments?

Nope.

What versions of software are you using?

Operating System: macOS 10.15.4

Toolchain Version:

SDK Version: 13.4

%config(logs=...)

The logs config param for logos should exist, and support full, off, and on (defaulting to on). full will automatically %log all hooked methods. off will disable (consume) %log directives.

Take advantage of weak linking

%c() has shortcomings — for instance the compiler has no idea what type it actually is and can’t do type checking on instancetype methods, forcing use of casts like this:

[(SpringBoard *)[%c(SpringBoard) sharedApplication] doThing];
((SpringBoard *)[%c(SpringBoard) sharedApplication]).isThingDone; // even worse!

Clang supports a weak_import attribute on classes that allows us to skip the linker trying to find the symbol to link, and allows the symbol to be optional just as %c() is.

Which would allow much more elegant code, like maybe:

%weakclass SpringBoard;

//

[[SpringBoard sharedApplication] doThing];
[SpringBoard sharedApplication].isThingDone;

%weakclass X would expand to:

__attribute__((weak_import))
@interface SpringBoard ()
@end

Of course these weak symbols will be resolved at process launch time/library load time just like every other symbol dyld needs to resolve, so %c() is still necessary for late-loaded symbols.

To discuss:

Does this work on a category interface? Worst case scenario, we generate a separate file containing flags to pass the linker for weak import, or use this:

asm(".weak_reference _OBJC_CLASS_$_SpringBoard");

According to this thread the attribute method may require a linker flag anyway due to a limitation of the implementation. I’m really hoping this is a bug and that it’s fixed now, so we can use an #if directive to check the clang version and #error out if it’s a known broken version.

Unnecessary warning for %property on non-object types

The code:

%property (nonatomic) BOOL newProperty;

will throw the warning:

warning: no 'assign', 'retain', or 'copy' attribute is specified - 'assign' is assumed

This warning is unnecessary. The normal objective-c compiler will not throw any warning for:

@property (nonatomic) BOOL newProperty;

Logos errors out on calling %orig with an inline block with multiple lines.

When hooking a method which accepts a block as a paramter, Logos dislikes this form of calling the original implementation:

%hook AwesomeClass

- (void)AwesomeMethod:(void (^)(void))awesomeBlock
{
    %orig(^{
        NSLog(@"Hello");
    }); 
}

%end

However, this works:

%hook AwesomeClass

- (void)AwesomeMethod:(void (^)(void))awesomeBlock
{
    %orig(^{ NSLog(@"Hello"); }); 
}

%end

and putting the block in a variable, works too, obviously.

Logos errors out with this error: "error: missing closing parenthesis"

%init should just call a static function generated at the end

17:22 <@DHowett> that should be being done anyway, come to think of 
             it. however, it complicates custom class expressions
17:22 <@DHowett> as init can wrap scope
17:22 <@DHowett> (the function cannot be variadic, and i do not know 
             what classes the user will want to change
17:22 <@DHowett> actually, that's tractable. i think it can be done)
17:23 <@DHowett> (the static function gets generated at the end, after 
             all. the call can contain all overridden classes)
17:23 <@DHowett> and the prototype and final function as well

Does/will Logos Preprocessor support dynamic values

(Sorry I think the issues template doesn't support my issue so I cleared them)

I'm fully aware of the fact that I can %group YOSWAG and %init(YOSWAG);

Can I %group com.apple.springboard and %init([NSBundle mainBundle].bundleIdentifier); ?

Thanks

EDIT:I'm fully aware that this would require a huge refactor.

Multiple conditional %init in one %ctor

Hi there,

I'm not sure if this is the right place to ask; sorry.

I want to ask, can multiple conditional %init work together in one %ctor? For example,

I have some function hooks as a group, I only want to init this group for certain condition, and other non-grouped hooks get still inited.

I have below code sample:

%ctor {
    %init();
    if (metCondition) {
        %init(SomeGroup)
    }    
}

Is this allowed? From what I tested, it seems %init(SomeGroup) will override %init(), meaning those ungrouped hooks is not initialized after %init(SomeGroup) is called.

If I am wrong, how can I achieve my goal? Thanks

`super` in %subclass is dodgy

What are the steps to reproduce this issue?

  1. Subclass an Objective-C class with %subclass.
  2. Call [super aMethod], where aMethod is a valid method, in a method.
  3. use of undeclared identifier 'super'.

What happens?

use of undeclared identifier 'super'.

What were you expecting to happen?

Succesful compilation.

Any logs, error output, etc?

Par example:

iDUTagCreationAlertCollectionViewController.x:36:13: error: use of undeclared identifier 'super'
    self = [super initWithCoder:coder];
            ^

Any other comments?

Nope.

What versions of software are you using?

Operating System: macOS 10.15.4

Toolchain Version:

SDK Version: 13.4

%c should cast the result to the input class type

For example, %c(Foo) should evaluate to

((Foo *) _logos_static_class_lookup$Foo())

instead of just

_logos_static_class_lookup$Foo()

so that type information is not lost, allowing for things like %c(Foo).classProperty

Defining %property while override setter

I'm gonna ditch the standard issue template because I don't see it fitting.

Defining a property like

%subclass NextUpMediaHeaderView : MediaControlsHeaderView
%property (nonatomic, retain) UIColor *textColor;

...

%end

is fine. However, I'd like to override the setter:

%subclass NextUpMediaHeaderView : MediaControlsHeaderView
%property (nonatomic, retain) UIColor *textColor;


- (void)setTextColor:(UIColor *)color {
    %orig;

    // some extra stuff being made here
}

...

%end

and this is not possible as it complains about it being redefined.

NextUp.xm:417:17: error: redefinition of
      '_logos_method$CustomViews$NextUpMediaHeaderView$setTextColor$'
    static void _logos_method$CustomViews$NextUpMediaHeaderView$setTextColor$(...
                ^
NextUp.xm:367:377: note: previous definition is here
  ...}__attribute__((used)) static void _logos_method$CustomViews$NextUpMediaHeader...

I know we need to define methods to set and get associated objects when defining a new property, but could it perhaps be tweaked to call a custom setter afterwards if such exists or something?

I'm aware of the obvious solution of defining a method like updateTextColor: which sets the property and does the extra work. It's just isn't that good looking code, and it would also be confusing for others using already a defined class where this approach is used.

Roadmap

logos false positives

logos picks up false method declarations in the middle of a function.
this:

while (MC.index+(int)hasPlaceHolder < (int)[icons count])
{
    SBIcon * neighbor = [icons objectAtIndex:MC.index+(int)hasPlaceHolder];
    //...
}

gets turned into this:

while (MC.indexstatic int _logos_meta_method$_ungrouped$SBAppSwitcherController$hasPlaceHolder(Class self, SEL _cmd) < (int)[icons count])
{
    SBIcon * neighbor = [icons objectAtIndex:MC.indexstatic int _logos_meta_method$_ungrouped$SBAppSwitcherController$hasPlaceHolder(Class self, SEL _cmd)];
    //...
}

%property add interface

Not really a bug or anything, just a small feature request.

Would be cool if adding a %property to a class automatically created an @interface with the property.

Experimental shift on scalar is now forbidden

(Thanks for reporting an issue! Please make sure you click the link above to view the issue guidelines, then fill out the blanks below.)

What are the steps to reproduce this issue?

  1. cd projectname
  2. make package install

What happens?

I get the error "Experimental shift on scalar is now forbidden at" followed by a string of error messages.

What were you expecting to happen?

My project to be set up

Any logs, error output, etc?

https://ghostbin.co/paste/yvad2

Any other comments?

I'm on iOS 12.4
I replaced the following:
my $functionRetval = shift $args;

my $functionName = shift $args;

with

my $functionRetval = shift @{args};

my $functionName = shift @{args};

What versions of software are you using?

Operating System: Windows 10

Toolchain Version: 4.0.3-1

SDK Version: 10.3

CGFloat %property wrongly assumes float, crashes on 32-bit

What are the steps to reproduce this issue?

  1. Create a %property (with nonatomic, assign) into a hooked class that is of type CGFloat
  2. Attempt to access this property from within the hooked code (i.e. self.MyFloat) on a 32-bit device.

What happens?

The dylib will crash.

What were you expecting to happen?

The dylib accesses the float value as expected.

Any logs, error output, etc?

You might see this in the logs:
[NSISRestrictedToZeroMarkerVariable floatValue]: unrecognized selector sent to instance 0x197a33e0

Any other comments?

@uroboro believes that this is due to the way %property is generated for CGFloat values and that is wrongly assumed to be of type float. See: https://github.com/theos/theos/blob/master/bin/lib/Logos/Generator/Base/Property.pm for the definition of a %property that is a CGFloat. My code will run perfectly fine on 64-bit devices (iPhone 6s on 9.3.3, iPhone 6s on 10.2, iPad Air on 9.3.2) but fails on 32-bit devices (iPad 4 on 9.3.3).

What versions of software are you using?

Operating System: 9.3.3 (iPad3,4 with Home Depot jailbreak)

Toolchain Version: 9.3

SDK Version: 9.3

Get pointers to original functions

Once a function is hooked using the Logos syntax (%hook or %hookf), it is no longer possible to call the original function from outside of the new function.

%hook SomeClass

// This is a method that is used and hooked by the tweak.
- (id)someMethod:(id)someArg {
    // some stuff
    return somethingOtherThanOrig;
}

%end

static void MyFunction() {
    // I want to call the original implementation but it is not possible to do that after %init.
    id value = [SomeClassInstance someMethod:NULL];

    // Maybe something like this?
    %origff(SomeClassInstance, "someMethod:", NULL);
}

%ctor {
    %init;
    MyFunction();
}

Omission of argument names results in improper selector used

If you write the following hook:

%hook PXAssetFetcher
- (id)fetchAssetsInAssetCollection:(id) withFilterPredicate:(id)
inclusionPredicate:(id) fetchLimit:(NSUInteger) sortDescriptors:(id)
reverseSortOrder:(BOOL) hideHiddenAssets:(BOOL) fetchPropertySets:(id)fetchps {
    return %orig;
}
%end

the following (incorrect) code is generated:

MSHookMessageEx(
    _logos_class$_ungrouped$PXAssetFetcher,
    @selector(fetchAssetsInAssetCollection:: :: :: ::),
    (IMP)&_logos_method$_ungrouped$PXAssetFetcher$fetchAssetsInAssetCollection$$$$$$$$,
    (IMP *)&_logos_orig$_ungrouped$PXAssetFetcher$fetchAssetsInAssetCollection$$$$$$$$);

The selector should be:

fetchAssetsInAssetCollection:withFilterPredicate:inclusionPredicate:fetchLimit:sortDescriptors:reverseSortOrder:hideHiddenAssets:fetchPropertySets:

Strangely, I can't omit the last label, fetchps. If omitted, the following error is generated:

Tweak.xm:29:337: error: expected class member or base class name
  ...BOOL fetchPropertySets):(id) {
                             ^
Tweak.xm:29:336: error: only constructors take base initializers
  ...BOOL fetchPropertySets):(id) {
                            ^

logos and #include <substrate.h>'s position

Currently, logos adds that include statement before the first hook line, the only problem with that is that you can't use anything defined in substrate.h (like objective-c runtime stuff) before that line, so any helper functions that are not hooks must be moved after the first hook line.

It's a one line fix, but I thought of letting you know:

-               splice(@lines, $firsthookline - 1, 0, "#include <substrate.h>");
+               splice(@lines, 0, 0, "#include <substrate.h>");

Defining a new %property inside %group which lies within a %hook

Hi,

So I just stumbled upon this bug:

%hook ClassToBeHooked
%property (nonatomic, retain) MyClass *baseProperty;

- (void)methodThatAlwaysShouldBeHooked {
    %orig;
    ...
}

%group ConditionalGroup
%property (nonatomic, retain) MyClass *conditionalProperty;

- (void)conditionalMethod {
    %orig;

    self.conditionalProperty = ...
    ...
}

%end
%end


%ctor {
        %init();
        if ([%c(ClassToBeHooked) instancesRespondToSelector:@selector(conditionalMethod:)])
            %init(ConditionalGroup);
    }
}

This does not work. It computes error messages when building.

==> Compiling Tweak.xm (arm64)…
Tweak.xm:157:917: error: use of undeclared identifier '_logos_class$ConditionalGroup$ClassToBeHooked'; did you mean '_logos_class$_ungrouped$ClassToBeHooked'?
  ..._typeEncoding); } { char _typeEncoding[1024]; sprintf(_typeEncoding, "%s@:", @encode(SAViewController *)); class_addMethod(_logos_class$ConditionalGroup$ClassToBeHooked, @selector(conditionalProperty), (IMP)&_logos_m...
                                                                                                                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                                                                                                                                _logos_class$_ungrouped$ClassToBeHooked
Tweak.xm:157:16: note: '_logos_class$_ungrouped$ClassToBeHooked' declared here
        {Class _logos_class$_ungrouped$ClassToBeHooked = objc_getClass("ClassToBeHooked"); MSHookMessageEx(_logos_class$_ungrouped$ClassToBeHooked, @selector(grabberTongueWillPresent:), (IMP)&_logos_method$_ungrouped...
               ^
Tweak.xm:157:1164: error: use of undeclared identifier '_logos_class$ConditionalGroup$ClassToBeHooked'; did you mean '_logos_class$_ungrouped$ClassToBeHooked'?
  ..._typeEncoding); sprintf(_typeEncoding, "v@:%s", @encode(SAViewController *)); class_addMethod(_logos_class$ConditionalGroup$ClassToBeHooked, @selector(setConditionalProperty:), (IMP)&_logos_method$ConditionalGroup$Cl...
                                                                                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                                                                                                   _logos_class$_ungrouped$ClassToBeHooked
Tweak.xm:157:16: note: '_logos_class$_ungrouped$ClassToBeHooked' declared here
        {Class _logos_class$_ungrouped$ClassToBeHooked = objc_getClass("ClassToBeHooked"); MSHookMessageEx(_logos_class$_ungrouped$ClassToBeHooked, @selector(grabberTongueWillPresent:), (IMP)&_logos_method$_ungrouped...
               ^
2 errors generated.

It can be solved by putting the %property in the original %hook'ed section and not within the conditional group.

%Property breaks depending on asterisk position

The %property declaration breaks depending on the position of the asterisk in the declaration, ex. %property (copy) NSObject* myObj doesn't work but %property (copy) NSObject *myObj does.

What are the steps to reproduce this issue?

  1. Save the following as test.xm:
%hook UIView

%property (copy) NSObject* myObj;

%end
  1. Run perl $THEOS/bin/logos.pl test.xm to get the logos output.
  2. Change test.xm so the property declaration reads %property (copy) NSObject *myObj, save the file
  3. Run the perl command again to get different logos output.

What happens?

The property declaration is left unprocessed in the output file.

What were you expecting to happen?

The property declaration should be preprocessed into associated object calls, but isn't if the asterisk isn't directly adjacent to the object name (NSObject * myObj also fails).

Any logs, error output, etc?

Output of the first perl command:

#line 1 "/Users/thomasfinch/Downloads/test.xm"

#include <substrate.h>
#if defined(__clang__)
#if __has_feature(objc_arc)
#define _LOGOS_SELF_TYPE_NORMAL __unsafe_unretained
#define _LOGOS_SELF_TYPE_INIT __attribute__((ns_consumed))
#define _LOGOS_SELF_CONST const
#define _LOGOS_RETURN_RETAINED __attribute__((ns_returns_retained))
#else
#define _LOGOS_SELF_TYPE_NORMAL
#define _LOGOS_SELF_TYPE_INIT
#define _LOGOS_SELF_CONST
#define _LOGOS_RETURN_RETAINED
#endif
#else
#define _LOGOS_SELF_TYPE_NORMAL
#define _LOGOS_SELF_TYPE_INIT
#define _LOGOS_SELF_CONST
#define _LOGOS_RETURN_RETAINED
#endif

@class UIView; 


#line 1 "/Users/thomasfinch/Downloads/test.xm"


%property (copy) NSObject* myObj;


#line 6 "/Users/thomasfinch/Downloads/test.xm"

Output of the second perl command (after change):

#line 1 "/Users/thomasfinch/Downloads/test.xm"

#include <substrate.h>
#if defined(__clang__)
#if __has_feature(objc_arc)
#define _LOGOS_SELF_TYPE_NORMAL __unsafe_unretained
#define _LOGOS_SELF_TYPE_INIT __attribute__((ns_consumed))
#define _LOGOS_SELF_CONST const
#define _LOGOS_RETURN_RETAINED __attribute__((ns_returns_retained))
#else
#define _LOGOS_SELF_TYPE_NORMAL
#define _LOGOS_SELF_TYPE_INIT
#define _LOGOS_SELF_CONST
#define _LOGOS_RETURN_RETAINED
#endif
#else
#define _LOGOS_SELF_TYPE_NORMAL
#define _LOGOS_SELF_TYPE_INIT
#define _LOGOS_SELF_CONST
#define _LOGOS_RETURN_RETAINED
#endif

@class UIView; 


#line 1 "/Users/thomasfinch/Downloads/test.xm"


static char _logos_property_key$_ungrouped$UIView$myObj;__attribute__((used)) static NSObject * _logos_method$_ungrouped$UIView$myObj$(UIView* __unused self, SEL __unused _cmd){ return objc_getAssociatedObject(self, &_logos_property_key$_ungrouped$UIView$myObj); }__attribute__((used)) static void _logos_method$_ungrouped$UIView$setMyObj$(UIView* __unused self, SEL __unused _cmd, NSObject * arg){ objc_setAssociatedObject(self, &_logos_property_key$_ungrouped$UIView$myObj, arg, OBJC_ASSOCIATION_COPY); }


static __attribute__((constructor)) void _logosLocalInit() {
{Class _logos_class$_ungrouped$UIView = objc_getClass("UIView"); { class_addMethod(_logos_class$_ungrouped$UIView, @selector(myObj), (IMP)&_logos_method$_ungrouped$UIView$myObj$, [[NSString stringWithFormat:@"%s@:", @encode(NSObject *)] UTF8String]);class_addMethod(_logos_class$_ungrouped$UIView, @selector(setMyObj:), (IMP)&_logos_method$_ungrouped$UIView$setMyObj$, [[NSString stringWithFormat:@"v@:%s", @encode(NSObject *)] UTF8String]);} } }
#line 6 "/Users/thomasfinch/Downloads/test.xm"

Any other comments?

This happens regardless of the class being hooked, the object type, or the property type.

What versions of software are you using?

Operating System: Mac OS 10.12.3

Toolchain Version: Not quite sure what this means, but using theos commit e94545975dda0c669bbcbed1eba0d7382ba49389 (current master head), clang 800.0.42.1

SDK Version: iOS 10.2 SDK, Xcode 8.2.1

Refactor %c into generic cached computation functionality

It should be possible to pass arbitrary expressions into a logos macro and have it dedupe and cache them.
Existing %c(classname) expressions could be converted to use this functionality internally.
Additionally, components within theos itself could use this functionality to trim some of the work they perform (would use this for my internal generator)

Proposed syntax:
%cached(x) yields a C rvalue that references the result of the computation x as executed from inside %init; (or the automatically generated initializer if none exists)

Potential extensions:
Nested cached expressions could be supported to eliminate duplicate work inside of cached expressions themselves. Further, cached expressions that are used only as a subexpression of other cached expressions could be optimized not to escape the scope of %init
Lazy initialization via alternate syntax (with/without thread safety?). Would allow syntax like this to workaround glacial apis:
%cached([[[NSCharacterSet characterSetWithCharactersInString:@"_1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"] invertedSet] retain], lazy)

Logify: Provide flags to filter or exclude methods

As I know,logify.pl can be used like:

logify.pl 1.h > ~/xxx/Tweak.xm
logify.pl 2.h >> ~/xxx/Tweak.xm

When I found there are around 50 or more functions in file 1.h,but the target function what I want to record is only one function,how can I use logify.pl to record only one or few functions to Tweak.xm like:

logify.pl [email protected] >> ~/xxx/Tweak.xm

Error while debugging NSBlock

What are the steps to reproduce this issue?

%hook ASDSoftwareUpdatesStore
- (void)reloadFromServerWithCompletionBlock:(void (^)(id data))block { %log; }
%end

What happens?

Here the output:
https://ghostbin.com/paste/qqma9

What were you expecting to happen?

Compile the tweak

What versions of software are you using?

Mac 0SX 10.2.1
iOS 10.2 (TARGET = iphone:clang:10.2)

Can't hook functions with a ... arg

Attempting to hook a function with a ... argument will throw a syntax error when you try to call %orig.

For example, the code:

%hookf (id, objc_msgSend, id self, SEL op, ...)
{
    NSLog(@"test");
    return %orig;
}

will throw the error:

error: expected expression
    return _logos_orig$_ungrouped$objc_msgSend(self, op, ...);
                                                         ^

Dynamic class name in %init(<class>=<expr>) and %hook <class> to assume type

TLDR

Specifying the class like %init([<class>=<expr>, …]);, results in the hooked object (self) being left without type to the compiler. I understand that not assuming any class is the most sane thing to do, but I was wondering if it would be possible to automatically set the object to a known type or to one that conforms to a protocol in order to avoid casting.

Background

I have a few hooks for iOS 11 and 12 (pre 12.2) that hooks the class MediaControlsPanelViewController in a few of my tweaks. In iOS 12.2 however, this class was renamed to MRPlatterViewController. All properties and methods seems to be the same. Thus, I would like to reuse the code within the hook, like:

%ctor {
    ...

    Class c;
    if (running iOS 12.2)
        c = %c(MRPlatterViewController);
    else
        c = %c(MediaControlsPanelViewController);
    %init(MediaControlsPanelViewController = c);
}

This works fine, but inside the actual hooked code, the compiler does no longer know which type self has.

I realize that it's possible to do something like this:

@protocol PanelViewController<NSObject>
@property (nonatomic, retain) MediaControlsParentContainerView *parentContainerView;
...
@end

@interface MediaControlsPanelViewController : UIViewController <PanelViewController>
@end

@interface MRPlatterViewController : UIViewController <PanelViewController>
@end

and then in the code cast it to an object that conforms to that protocol:

%hook MediaControlsPanelViewController

- (void)viewDidLoad {
    %orig;

    UIViewController<PanelViewController> *controller = (UIViewController<PanelViewController> *)self;

    controller.parentContainerView...
}
...

instead of using self. I was wondering if it would be possible to automatically set the object to a known type or to one that conforms to a protocol in order to avoid doing this casting. Ideally this would be done in the %ctor once instead of once in every hooked method.

Allow hooking of swift classes

(Thanks for reporting an issue! Please make sure you click the link above to view the issue guidelines, then fill out the blanks below.)

What are the steps to reproduce this issue?

  1. In swift apps some classes have a dot operator in them and when you type in %hook class.name you should expect it to work like normal.

What happens?

Tweak.xm:1:1: error: cannot use dot operator on a type

What were you expecting to happen?

Allow you to hook the class that has a dot operator in it.

Any logs, error output, etc?

Tweak.xm:1:1: error: cannot use dot operator on a type

Any other comments?

There is a simple fix for it currently using this work around here.

What versions of software are you using?

Mac OSX 10.10

iOS 9.2 SDK

Can't hook variadic methods.

%hook H
- (void)format:(NSString *)format, ... {
	%orig;
}
%end

Generates the following code:

#line 1 "Tweak.x"

#include <substrate.h>
#if defined(__clang__)
#if __has_feature(objc_arc)
#define _LOGOS_SELF_TYPE_NORMAL __unsafe_unretained
#define _LOGOS_SELF_TYPE_INIT __attribute__((ns_consumed))
#define _LOGOS_SELF_CONST const
#define _LOGOS_RETURN_RETAINED __attribute__((ns_returns_retained))
#else
#define _LOGOS_SELF_TYPE_NORMAL
#define _LOGOS_SELF_TYPE_INIT
#define _LOGOS_SELF_CONST
#define _LOGOS_RETURN_RETAINED
#endif
#else
#define _LOGOS_SELF_TYPE_NORMAL
#define _LOGOS_SELF_TYPE_INIT
#define _LOGOS_SELF_CONST
#define _LOGOS_RETURN_RETAINED
#endif

@class H;
static void (*_logos_orig$_ungrouped$H$format$)(
    _LOGOS_SELF_TYPE_NORMAL H *_LOGOS_SELF_CONST, SEL, NSString *);
static void
_logos_method$_ungrouped$H$format$(_LOGOS_SELF_TYPE_NORMAL H *_LOGOS_SELF_CONST,
                                   SEL, NSString *);

#line 1 "Tweak.x"

static void _logos_method$_ungrouped$H$format$(
    _LOGOS_SELF_TYPE_NORMAL H *_LOGOS_SELF_CONST __unused self,
    SEL __unused _cmd, NSString *format),
    ... {
  _logos_orig$_ungrouped$H$format$(self, _cmd, format);
}

static __attribute__((constructor)) void _logosLocalInit() {
  {
    Class _logos_class$_ungrouped$H = objc_getClass("H");
    MSHookMessageEx(_logos_class$_ungrouped$H, @selector(format:),
                    (IMP)&_logos_method$_ungrouped$H$format$,
                    (IMP *)&_logos_orig$_ungrouped$H$format$);
  }
}
#line 6 "Tweak.x"

The function prototypes don't contain the , ... and the function definition itself is wrongly formatted NSString *format), ... {.

Internal generator throws error while constructing a hook

What are the steps to reproduce this issue?

  1. Create Logos file containing:
%config(generator=internal);

%hook blah
- (void)thing {
    // something...
}
%end
  1. Feed it through logos.pl blah.xm

What happens?

An internal Logos error occurs.

What were you expecting to happen?

The syntax is processed successfully.

Any logs, error output, etc?

blah.xm: error: generator does not implement Method::initializers

Any other comments?

N/A

What versions of software are you using?

Operating System: OS X 10.11.3

Toolchain Version: Xcode 7.2

SDK Version: iOS 9.2

%property results in compile error

When adding a %property to a hooked class the compiler throws an error, ex:

For:

@interface SBIconController
@property (nonatomic,retain) NSMutableArray *hiddenIcons;
.....
@end  

%hook SBIconController
%property (nonatomic,retain) NSMutableArray *hiddenIcons;
....
%end

Result:
error: no matching function for call to 'objc_getAssociatedObject' __attribute__((used)) static NSMutableArray * _logos_method$_ungrouped$SBIconController$hiddenIcons(SBIconController * __unused self, SEL __unused _cmd) { return (NSMutableArray *)objc_getAssociatedObject(self, _logos_method$_ungrouped$SBIconController$hiddenIcons); }; __attribute...

Logos Improvements

  • %log() => static function (what?)
  • %init => static function (is this maybe what I meant?) (#19)
  • %config(logs=...) (#16)
  • ivar get/set/creation (for %subclass)
  • log applied hooks
  • control %log output
  • category generation for %new methods
  • %append/%prepend (=> %flag?) a la http://ghostbin.com/paste/mycpg
  • dealloc warnings
    • dealloc should be prepend, if the concept flies
  • unique noncustom classes across groups
  • refactor %c into generic cached computation functionality (#15)

Decoupling from Theos

There's a usage of HBLogDebug in bin/lib/Logos/Generator/Base/Method.pm which is defined in theos/headers/HBLog.h.

If Logos is truly meant to be decoupled, this logging facility has to be resolved in another manner, either as a builtin definition or a function name passed as a flag when running logos.pl. It should be taken into account that HBLogDebug is a macro that will end up expanding to os_log_with_type or CFLog.

%orig with different instance

There should be a way to call %orig with a different instance variable while not modifying self.

// Maybe something like this?
%origs(differentInstance); // Call %orig with different self and the original arguments
%origs(differentInstance, NULL, 42, @NO); // Call %orig with different self and arguments

%init of groups not compatible with ternary operators

It would make sense to write the snippet

if (%c(SBHomeScreenBackdropView))
    %init(SwitcherBackdrop_iOS12);
else
    %init(SwitcherBackdrop_iOS11);

as a ternary statement,

%c(SBHomeScreenBackdropView) ? %init(SwitcherBackdrop_iOS12) : %init(SwitcherBackdrop_iOS11);

but that results in errors.

==> Compiling Tweak.xm (arm64)…
Tweak.xm:804:61: error: expected expression
    _logos_static_class_lookup$SBHomeScreenBackdropView() ? {Class _logos_class$SwitcherBackdrop_iOS12$...
                                                            ^
Tweak.xm:804:61: error: expected ':'
    _logos_static_class_lookup$SBHomeScreenBackdropView() ? {Class _logos_class$SwitcherBackdrop_iOS12$...
                                                            ^
                                                            : 
Tweak.xm:804:59: note: to match this '?'
    _logos_static_class_lookup$SBHomeScreenBackdropView() ? {Class _logos_class$SwitcherBackdrop_iOS12$...
                                                          ^
Tweak.xm:804:61: error: expected expression
    _logos_static_class_lookup$SBHomeScreenBackdropView() ? {Class _logos_class$SwitcherBackdrop_iOS12$...
                                                            ^
3 errors generated.

It seems like Logos outputs a mix between a normal if statement and a ternary operator.

Dynamically looking-up classes beside bracketed math causes compiling error

example : self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y + 1 - (1 * 2), [%c(UIScreen) mainScreen].bounds.size.width, self.frame.size.height);

What are the steps to reproduce this issue?

  1. Try to use brackets in calculations next to dynamically looked-up classes
  2. Receive error when compiling

What happens?

Compiler returns expression error

What were you expecting to happen?

Compiles with no problems

Any logs, error output, etc?

==> Compiling Tweak.xm (armv7)…

Tweak.xm:11:85: error: expected expression self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y + 1 - (1 * 2), [%c(UIScreen) mainScreen].b...
^
Tweak.xm:11:88: error: unexpected interface name 'UIScreen': expected expression self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y + 1 - (1 * 2), [%c(UIScreen) mainScreen].b...

Any other comments?

Compiles fine without the brackets around (1 * 2), but obviously will not return the value needed.

Changing the positioning of the bracketed math does not overcome the error

Does not work with objc_getClass either

Adding an interface for the class will avoid the issue.

Compiling using linux toolchain, 9.2 sdk, most recent theos pull

Make Logos stderr output similar to clang

Having Logos errors follow the same format as clang will make them a bit easier to spot amongst the sea of other colors in the build output, and will also match Xcode’s regexes for error output to ensure it comes up nicely in the warnings tab for people using Theos/Logos via Xcode. (ibtool and some other tools invoked by a typical app build process do the same.)

Theos error: Can't call method "isNew" on an undefined value at /var/mobile/sbtest1/theos/bin/logos.pl line 382

(Thanks for reporting an issue! Please make sure you click the link above to view the issue guidelines, then fill out the blanks below.)

What are the steps to reproduce this issue?

  1. Create your tweak
  2. Use "make package install" in the directory
  3. Get this error

What happens?

The tweak does not compile and the error prevents you from doing anything with your code without getting an error

What were you expecting to happen?

My tweak would compile and I would get an alert when SpringBoard loads

Any logs, error output, etc?

(If it’s long, please paste to https://ghostbin.com/ and insert the link here.)
WillPhone:/var/mobile/sbtest1 root# make package install
/var/mobile/sbtest1/theos/makefiles/targets/Darwin-arm/iphone.mk:43: Targeting iOS 4.0 and higher is not supported with iphone-gcc. Forcing clang.
Making all for tweak sbtest1...
Preprocessing Tweak.xm...
Constants from lexical variables potentially modified elsewhere are deprecated at /private/var/theos/bin/lib/aliased.pm line 42.
Constants from lexical variables potentially modified elsewhere are deprecated at /private/var/theos/bin/lib/aliased.pm line 42.
Constants from lexical variables potentially modified elsewhere are deprecated at /private/var/theos/bin/lib/aliased.pm line 42.
Constants from lexical variables potentially modified elsewhere are deprecated at /private/var/theos/bin/lib/aliased.pm line 42.
Constants from lexical variables potentially modified elsewhere are deprecated at /private/var/theos/bin/lib/aliased.pm line 42.
Constants from lexical variables potentially modified elsewhere are deprecated at /private/var/theos/bin/lib/aliased.pm line 42.
Constants from lexical variables potentially modified elsewhere are deprecated at /private/var/theos/bin/lib/aliased.pm line 42.
Constants from lexical variables potentially modified elsewhere are deprecated at /private/var/theos/bin/lib/aliased.pm line 42.
Can't call method "isNew" on an undefined value at /var/mobile/sbtest1/theos/bin/logos.pl line 382.
make[2]: *** [obj/Tweak.xm.a114fd55.o] Error 255
make[1]: *** [internal-library-all_] Error 2
make: *** [sbtest1.all.tweak.variables] Error 2
WillPhone:/var/mobile/sbtest1 root#

Any other comments?

What versions of software are you using?

Operating System: iOS 8.3

Toolchain Version: 6.1-1

SDK Version: iOS 8.1

Theos should raise an exception when hooking a non-implemented selector

It's easy to make a mistake with theos by placing a method-hook under the wrong %hook class, or adding a typo to a selector name. In this case, the hooks will silently fail, and the methods will not be swizzled, leading to confusion of whether the target methods are being invoked at all.

Instead, theos should loudly fail when I provide an 'invalid hook'. This would catch this bug much earlier in development and reduce headaches.

Hook non-exported function symbols.

%hookf so far allows hooking functions known at compile time or exported at runtime:

%hookf(FILE *, fopen, const char *path, const char *mode) { ...
%hookf(BOOL, "_MGGetBoolAnswer", CFStringRef string) { ...

Taking a runtime value as a function address would allow hooking non-exported functions, simplifying the following example:

void(*old_myFun)(void);
void myFun(void) {
	old_myFun();
}

%ctor {
	MSHookFunction((void *)unslide(0x123456789), (void *)myFun, (void **)&old_myFun);
}

into:

%hookf(void, myFun, void) {
	%orig;
}

%ctor {
	%init(myFun = unslide(0x1234567890));
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.