Skip to content

Commit

Permalink
Setup theos build system
Browse files Browse the repository at this point in the history
  • Loading branch information
EthanArbuckle committed Jan 8, 2025
1 parent 611b3c4 commit 36e2493
Show file tree
Hide file tree
Showing 19 changed files with 126 additions and 36 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
xcuserdata
*.xcworkspacedata
xcshareddata
xcshareddata
packages
.theos
34 changes: 34 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
FINALPACKAGE = 1

ifneq (,$(filter rootless,$(MAKECMDGOALS)))
THEOS_PACKAGE_SCHEME = rootless
endif

ifeq ($(THEOS_PACKAGE_SCHEME),rootless)
ARCHS = arm64
TARGET = iphone:clang:latest:14.5
else
ARCHS = armv7 armv7s arm64
TARGET = iphone:clang:latest:9.3
endif

include $(THEOS)/makefiles/common.mk

TOOL_NAME = oslo
oslo_FILES = $(wildcard src/*.m) $(wildcard src/kat/*.c)
oslo_CFLAGS = -fobjc-arc -I./src/kat -I./src
oslo_CODESIGN_FLAGS = -S./other/entitlements.plist
oslo_INSTALL_PATH = /usr/local/bin

include $(THEOS_MAKE_PATH)/tool.mk

all::
@echo "Building for $(if $(THEOS_PACKAGE_SCHEME),rootless,rootful)"

rootful:
@true

rootless:
@true

.PHONY: rootful rootless
47 changes: 38 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,60 @@

An `os_log` viewer for iOS that supports streaming both real-time logs and archived logs.

## Features
- View real-time logs
- View archived logs (even if they weren't streamed live)
- Does not include logs prior to the last reboot
- View archived logs even if they weren't streamed live (starting from the last reboot)
- Unredacts `<private>` values in log messages
- Process name filtering
- Syntax highlighting by [kat](https://github.com/Theldus/kat/tree/master)
- Syntax highlighting
- PID-based grouping + last-log filtering
- "for each recent crash of `<process>`, show the last couple of logs that were printed before it terminated, grouped by PID and ordered by last-event-in-group timestamp"


## Usage
### Usage

```
oslo [-l] [-s] [-g] [ProcessName]
Options:
-l Live logs (default)
-s Stored/archived logs
-g Group logs by PID (requires -s)
-g Group logs by PID (requires -s)
ProcessName Filter by process name
```

#### Usage Examples

```
# Stream live logs from all processes
oslo -l
# View stored logs for SpringBoard
oslo -s SpringBoard
# View stored logs for TargetApp, grouped by PID and reduced to the last few logs before each termination
oslo -s -g TargetApp
```

### Requirements

* Jailbroken iOS 14.0 or later
* Earlier versions may work. iOS 14.0 - 18.2 tested
* Rootless or rootful
* Pre-compiled releases include armv7, armv7s, and arm64 slices

### Screenshots

#### Live log streaming
![oslo](./other/screenshot-allprocs-live.png)


#### Stored logs grouped by PID (and reduced to the last few logs before each crash)
![oslo](./other/screenshot-group-termination-logs-by-PID.png)


#### Demo
[![asciicast](https://asciinema.org/a/tet26ugcwutH0CIwjKeS99C1P.svg?poster=npt:07)](https://asciinema.org/a/tet26ugcwutH0CIwjKeS99C1P?poster=npt:07)


Tested on iOS 14.0 - 18.2

## Credits

* [Theldus](https://github.com/Theldus) for the [kat syntax highlighting](https://github.com/Theldus/kat/tree/master) library
9 changes: 9 additions & 0 deletions control
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Package: com.ethanarbuckle.oslo
Name: oslo
Version: 1.0.0
Architecture: iphoneos-arm
Description: os_log viewer that supports streaming both real-time logs and archived logs.
Maintainer: Ethan Arbuckle
Author: Ethan Arbuckle
Section: System
Tag: role::hacker
36 changes: 25 additions & 11 deletions oslo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@
5F03D5A72D2B68D1005BF9ED /* output.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = output.m; sourceTree = "<group>"; };
5F03D5A92D2B68ED005BF9ED /* output.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = output.h; sourceTree = "<group>"; };
5F3715F82D09AAED003DF348 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
5FE020792BFA862500D131E0 /* deploy.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = deploy.py; sourceTree = "<group>"; };
5FE0207B2BFA862B00D131E0 /* entitlements.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = entitlements.xml; sourceTree = "<group>"; };
5F92AB942D2F010400316521 /* deploy.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = deploy.py; sourceTree = "<group>"; };
5F92AB952D2F010400316521 /* entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = entitlements.plist; sourceTree = "<group>"; };
5F92AB972D2F036D00316521 /* screenshot-allprocs-live.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "screenshot-allprocs-live.png"; sourceTree = "<group>"; };
5F92AB982D2F03A200316521 /* screenshot-group-termination-logs-by-PID.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "screenshot-group-termination-logs-by-PID.png"; sourceTree = "<group>"; };
5FE020822BFA86C400D131E0 /* oslo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = oslo.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */

Expand All @@ -45,9 +47,8 @@
5F85499F2AD9E03E006D8CCD = {
isa = PBXGroup;
children = (
5FE020792BFA862500D131E0 /* deploy.py */,
5FE0207B2BFA862B00D131E0 /* entitlements.xml */,
5FE020832BFA86C400D131E0 /* oslo */,
5F92AB962D2F010400316521 /* other */,
5FE020832BFA86C400D131E0 /* src */,
5F8549A92AD9E03E006D8CCD /* Products */,
);
sourceTree = "<group>";
Expand All @@ -60,7 +61,18 @@
name = Products;
sourceTree = "<group>";
};
5FE020832BFA86C400D131E0 /* oslo */ = {
5F92AB962D2F010400316521 /* other */ = {
isa = PBXGroup;
children = (
5F92AB942D2F010400316521 /* deploy.py */,
5F92AB952D2F010400316521 /* entitlements.plist */,
5F92AB972D2F036D00316521 /* screenshot-allprocs-live.png */,
5F92AB982D2F03A200316521 /* screenshot-group-termination-logs-by-PID.png */,
);
path = other;
sourceTree = "<group>";
};
5FE020832BFA86C400D131E0 /* src */ = {
isa = PBXGroup;
children = (
5F03D56D2D2B1906005BF9ED /* kat */,
Expand All @@ -71,7 +83,7 @@
5F03D5A72D2B68D1005BF9ED /* output.m */,
5F03D5762D2B4D90005BF9ED /* LoggingSupport.h */,
);
path = oslo;
path = src;
sourceTree = "<group>";
};
/* End PBXGroup section */
Expand Down Expand Up @@ -119,7 +131,7 @@
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = 1;
LastUpgradeCheck = 1500;
LastUpgradeCheck = 1610;
TargetAttributes = {
5FE020812BFA86C400D131E0 = {
CreatedOnToolsVersion = 15.0.1;
Expand Down Expand Up @@ -170,7 +182,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "# Type a script or drag a script file from your workspace to insert its path.\npython3 deploy.py\n";
shellScript = "# Type a script or drag a script file from your workspace to insert its path.\npython3 other/deploy.py\n";
};
/* End PBXShellScriptBuildPhase section */

Expand All @@ -192,6 +204,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
Expand Down Expand Up @@ -250,6 +263,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
Expand Down Expand Up @@ -304,7 +318,7 @@
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
DEFINES_MODULE = YES;
DEFINES_MODULE = NO;
DEVELOPMENT_TEAM = J478CS4UY8;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_MODULE_VERIFIER = YES;
Expand Down Expand Up @@ -341,7 +355,7 @@
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
DEFINES_MODULE = YES;
DEFINES_MODULE = NO;
DEVELOPMENT_TEAM = J478CS4UY8;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_MODULE_VERIFIER = YES;
Expand Down
20 changes: 11 additions & 9 deletions deploy.py → other/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@
DEVICE_SSH_PORT = "2222"
DEVICE_SSH_IP = "localhost"
LOCAL_LDID2_PATH = "/opt/homebrew/bin/ldid2"

JB_ROOT_PREFIX = Path("/var/jb/")

@dataclass
class BinaryInstallInformation:
# The on-device path to copy the binary to
on_device_path: str
on_device_path: Path
# An entitlements file to sign the local binary with before copying to the device.
# If no file is specified, the binary will be signed without explicit entitlements
entitlements_file: Optional[str] = None
entitlements_file: Optional[Path] = None


BINARY_DEPLOY_INFO = {
"oslo": BinaryInstallInformation("/var/jb/usr/bin/oslo", "entitlements.xml"),
"oslo": BinaryInstallInformation(JB_ROOT_PREFIX / "usr/bin/oslo", Path("other/entitlements.plist")),
}


Expand Down Expand Up @@ -48,8 +48,6 @@ def deploy_to_device(local_path: Path, binary_deploy_info: BinaryInstallInformat
else:
ldid_cmd_args.append("-S")
ldid_cmd_args.append(local_path.as_posix())
print(ldid_cmd_args)
# print(subprocess.check_output(ldid_cmd_args))

# Delete existing binary on-device if it exists
try:
Expand All @@ -72,13 +70,17 @@ def deploy_to_device(local_path: Path, binary_deploy_info: BinaryInstallInformat
except Exception as e:
raise Exception(f"Failed to copy {binary_deploy_info.on_device_path} to device with error: {e}")

on_device_ents_path = JB_ROOT_PREFIX / "tmp/entitlements.plist"
try:
copy_file_to_device(binary_deploy_info.entitlements_file, "/tmp/entitlements.xml")
if binary_deploy_info.entitlements_file and binary_deploy_info.entitlements_file.exists():
copy_file_to_device(binary_deploy_info.entitlements_file, on_device_ents_path)
except Exception as e:
print(f"Failed to copy entitlements file to device with error: {e}")
pass

run_command_on_device(f"/var/jb/usr/bin/ldid -S/tmp/entitlements.xml {binary_deploy_info.on_device_path}")
on_device_ldid_path = JB_ROOT_PREFIX / "usr/bin/ldid"
run_command_on_device(
f"{on_device_ldid_path.as_posix()} -S{on_device_ents_path.as_posix()} {binary_deploy_info.on_device_path.as_posix()}"
)


if __name__ == "__main__":
Expand Down
File renamed without changes.
Binary file added other/screenshot-allprocs-live.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion oslo/kat/hashtable.c → src/kat/hashtable.c
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ static inline uint64_t fmix64(uint64_t k)
*/
uint64_t hashtable_MurMur3_hash(const void *key, size_t size)
{
const int nblocks = size / 4;
const uint64_t nblocks = size / 4;

/* Seeds are nulled for now. */
uint64_t h1 = 0;
Expand Down
File renamed without changes.
8 changes: 4 additions & 4 deletions oslo/kat/highlight.c → src/kat/highlight.c
Original file line number Diff line number Diff line change
Expand Up @@ -314,8 +314,8 @@ char *highlight_line(const char *line, char *hl, size_t str_size)
{
struct highlighted_line *high_line;
size_t tok_size;
int keyword_start;
int keyword_end;
uint64_t keyword_start;
uint64_t keyword_end;

/* Reset indexes. */
if (hl != NULL)
Expand Down Expand Up @@ -751,7 +751,7 @@ int str2int(int *out, char *s)
if (*end != '\0')
return (-1);

*out = l;
*out = (int)l;
return (0);
}

Expand Down Expand Up @@ -836,7 +836,7 @@ int highlight_init(const char *theme_file)

/* Copy to the list. */
COLORS[CURRENT_THEME+idx] = color;
LENGTHS[CURRENT_THEME+idx] = strlen(color);
LENGTHS[CURRENT_THEME+idx] = (int)strlen(color);
}

/* If something goes wrong. */
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion oslo/main.m → src/main.m
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ static void (^streamEventHandler)(OSLogEventProxy *) = ^void(OSLogEventProxy *lo
};

static void (^streamInvalidationHandler)(OSLogEventStream *, NSUInteger, id) = ^void(OSLogEventStream *stream, NSUInteger code, id info) {
printf("Stream invalidated with code %lu\n", code);
printf("Stream invalidated with code %lu\n", (unsigned long)code);
exit(0);
};

Expand Down
File renamed without changes.
File renamed without changes.

0 comments on commit 36e2493

Please sign in to comment.