Detect if Swift app is being run from Xcode - ios

I would like to programmatically determine if the iOS app is being run directly from XCode (either in the simulator or on a tethered device).
I've tried the -D DEBUG solution described here, but when I then disconnect from Xcode and re-run the app, it still thinks it's in debug mode.
I think what I'm looking for is a Swift version of this function
#include <assert.h>
#include <stdbool.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/sysctl.h>
static bool AmIBeingDebugged(void)
// Returns true if the current process is being debugged (either
// running under the debugger or has a debugger attached post facto).
{
int junk;
int mib[4];
struct kinfo_proc info;
size_t size;
// Initialize the flags so that, if sysctl fails for some bizarre
// reason, we get a predictable result.
info.kp_proc.p_flag = 0;
// Initialize mib, which tells sysctl the info we want, in this case
// we're looking for information about a specific process ID.
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PID;
mib[3] = getpid();
// Call sysctl.
size = sizeof(info);
junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
assert(junk == 0);
// We're being debugged if the P_TRACED flag is set.
return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
}

Clarification: Your C code (and the Swift version below) checks if
the program is run under debugger control, not if it's being run from
Xcode. One can debug a program outside of Xcode (by calling lldb or
gdb directly) and one can run a program from Xcode without debugging it
(if the “Debug Executable” checkbox in the scheme setting is off).
You could simply keep the C function and call it from Swift.
The recipes given in How do I call Objective-C code from Swift? apply to pure C code as well.
But it is actually not too complicated to translate that code to Swift:
func amIBeingDebugged() -> Bool {
// Buffer for "sysctl(...)" call's result.
var info = kinfo_proc()
// Counts buffer's size in bytes (like C/C++'s `sizeof`).
var size = MemoryLayout.stride(ofValue: info)
// Tells we want info about own process.
var mib : [Int32] = [CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()]
// Call the API (and assert success).
let junk = sysctl(&mib, UInt32(mib.count), &info, &size, nil, 0)
assert(junk == 0, "sysctl failed")
// Finally, checks if debugger's flag is present yet.
return (info.kp_proc.p_flag & P_TRACED) != 0
}
Update for Swift 5 (Xcode 10.7):
strideofValue and the related functions do not exist anymore,
they have been replaced by MemoryLayout.stride(ofValue:).
Remarks:
kinfo_proc() creates a fully initialized structure with all
fields set to zero, therefore setting info.kp_proc.p_flag = 0 is not necessary.
The C int type is Int32 is Swift.
sizeof(info) from the C code has to be strideOfValue(info)
in Swift to include the structure padding. With sizeofValue(info)
the above code always returned false in the Simulator for 64-bit devices. This was the most difficult part to figure out.
Swift 2 logic:
func amIBeingDebugged() -> Bool {
var info = kinfo_proc()
var mib : [Int32] = [CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()]
var size = strideofValue(info)
let junk = sysctl(&mib, UInt32(mib.count), &info, &size, nil, 0)
assert(junk == 0, "sysctl failed")
return (info.kp_proc.p_flag & P_TRACED) != 0
}

For those looking for a simpler solution - this works perfectly:
func isDebuggerAttached() -> Bool {
return getppid() != 1
}

Related

Saxon-C CentOS8 Compile

I am trying to evaluate Saxon-C 1.2.1 HE on CentOS8 and installation seems to have gone ok. Trying out the samples by cd samples/cppTests && build64-linux.sh though leads to a myriad of compilation errors to the tune of the following:
../../Saxon.C.API/SaxonProcessor.h:599:32: error: division ‘sizeof (JNINativeMethod*) / sizeof (JNINativeMethod)’ does not compute the number of array elements [-Werror=sizeof-pointer-div]
gMethods, sizeof(gMethods) / sizeof(gMethods[0]));
Before I summarily and trustfully switched off -Werror=sizeof-pointer-div i checked the source code and what's going on there do seem dubious.
bool registerCPPFunction(char * libName, JNINativeMethod * gMethods=NULL){
if(libName != NULL) {
setConfigurationProperty("extc", libName);
}
if(gMethods == NULL && nativeMethodVect.size()==0) {
return false;
} else {
if(gMethods == NULL) {
//copy vector to gMethods
gMethods = new JNINativeMethod[nativeMethodVect.size()];
}
return registerNativeMethods(sxn_environ->env, "com/saxonica/functions/>
gMethods, sizeof(gMethods) / sizeof(gMethods[0]));
}
return false;
}
more specifically sizeof(gMethods) / sizeof(gMethods[0]) would not seem to calculate anything useful by any margin. The intention was probably rather to output some code that would arrive at the same value as nativeMethodVect.size() but seeing this project's source for the very first time i might be mistaking and the division is in fact intentional ?
I am inclined to guess the intention was in fact closer to b than to a in the following example:
#include <cstdio>
struct test
{
int x, y, z;
};
int main()
{
test *a = new test[32], b[32];
printf("%d %d\n", sizeof(a)/sizeof(a[0]), sizeof(b)/sizeof(b[0]));
return 0;
}
which output 0 32 which is expected as the sizeof(a) gives the size of a pointer not the size of an array's memory region.
That bit of code is to support the feature of user defined extension functions in XSLT stylesheets and XQuery queries. If a user is not using these features then they don't need that bit of code. In fact User defined extension functions is only available in Saxon-PE/C and Saxon-EE/C so it should not be in the Saxon-HE/C code base. I have created the following bug issue to investigate the error above and to https://saxonica.plan.io/issues/4477
I would think the workaround would be to either remove the code in question if the extension function feature is not used or remove the compile flag -Werror=sizeof-pointer-div.
The intent was code is as follows:
jobject JNICALL cppNativeCall(jstring funcName, jobjectArray arguments, jobjectArray argTypes){
//native call code here
}
JNINativeMethod cppMethods[] =
{
{
fname,
funcParameters,
(void *)&cppNativeCall
}
};
bool nativeFound = processor->registerNativeMethods(env, "NativeCall",
cppMethods, sizeof(cppMethods) / sizeof(cppMethods[0]));

iOS Mach-O – Make __TEXT segment temporarily writable

I've tried a lot to finally get this working, but it still doesn't work yet.
Im trying to change some variables in the __TEXT section, which is read-only by default, like changing the cryptid (and other stuff)
It kind of worked a while ago, back on 32 bit devices. But somehow, it always fails after I used the 64bit commands.
It currently crashes if I hit the following lines:
tseg->maxprot = tseg->initprot = VM_PROT_READ | VM_PROT_EXECUTE
or
crypt->cryptid = 1.
struct mach_header_64* mach = (struct mach_header_64*) _dyld_get_image_header(0);
uint64_t header_size = 0;
struct encryption_info_command_64 *crypt;
struct segment_command_64 *tseg;
struct dylib_command *protector_cmd;
// clean up some commands
void *curloc = (void *)mach + sizeof(struct mach_header);
for (int i=0;i<mach->ncmds;i++) {
struct load_command *lcmd = curloc;
if (lcmd->cmd == LC_ENCRYPTION_INFO_64) {
// save crypt cmd
crypt = curloc;
} else if (lcmd->cmd == LC_SEGMENT_64) {
struct segment_command_64 *seg = curloc;
if (seg->fileoff == 0 && seg->filesize != 0) {
header_size = seg->vmsize;
tseg = curloc;
}
}
if(i == mach->ncmds-1){
protector_cmd = curloc;
}
curloc += lcmd->cmdsize;
}
kern_return_t err;
// make __TEXT temporarily writable
err = vm_protect(mach_task_self(), (vm_address_t)mach, (vm_size_t)header_size, false, VM_PROT_ALL);
if (err != KERN_SUCCESS) exit(1);
// modify the load commands
// change protection of __TEXT segment
tseg->maxprot = tseg->initprot = VM_PROT_READ | VM_PROT_EXECUTE;
// change cryptid
crypt->cryptid = 1;
There's no point in changing the load command. The load commands were already processed when the program was loaded (which must be before this code of yours can run). They have no further effect on the protection of pages.
You're apparently already aware of the vm_protect() function. So why aren't you using that to make the text segment itself writable rather than trying to make the load commands writable?
And it's surely simpler to use getsegmentdata() to locate the segment in memory than looking at the load commands (to which you'd have to add the slide).
Beyond that, I would be surprised if iOS lets you do that. There's a general prohibition against run-time modifiable code (with very narrow exceptions).

Get parent process information at runtime on iOS application

I'm trying to obtain some process information at runtime on iOS, particularly the parent process name.
While I'm able to obtain the current process name, it seems that I can't to do the same for its parent.
Here is what I'm doing:
static inline bool is_debugserver_present() {
int err;
int mib[4];
struct kinfo_proc info;
size_t size;
// Initialize the flags so that, if sysctl fails for some bizarre
// reason, we get a predictable result.
info.kp_proc.p_flag = 0;
// Initialize mib, which tells sysctl the info we want, in this case
// we're looking for information about a the parent process ID.
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PID;
mib[3] = getppid();
// Call sysctl.
size = sizeof(info);
int n = sizeof(mib) / sizeof(*mib);
err = sysctl(mib, n, &info, &size, NULL, 0);
return (strncmp(info.kp_proc.p_comm, "launchd", sizeof("launchd") - 1) != 0);
}
The problem is that the call to sysctl always return -1 thus an error.
The parent process id obtained by getppid()is that same if I ask to the current process for its kp_eproc.e_ppid.
Am I missing something?
You cannot obtain the information of other processes since iOS 9. sysctl is sandboxed now. You can do this only in a iDevice previous iOS 9 or a Simulator.
sysctl() retrieves system information for processes with appropriate privileges
iOS apps are not permitted to see what other apps are running
In iOS 9, the sandbox now prevents a process from accessing the kern.proc,
kern.procargs, and kern.procargs2 values for other processes
see:
WWDC Privacy Introduction
Privacy and your app (Page 29)

Getting system uptime in iOS/Swift

Is there a way to get system uptime in iOS (using Swift)? What I need is to measure time without having to worry about the user changing the time. In Android there's a elapsedCurrentTimeMillis() that returns the number of milliseconds since boot, but now I need something like that for iOS. There's an accepted answer here Getting iOS system uptime, that doesn't pause when asleep but that's for Objective C and I need it for Swift and I don't know how to convert it.
As you ask for a pure-Swift solution, I converted the ObjC code from the answer you mentioned Getting iOS system uptime, that doesn't pause when asleep.
func uptime() -> time_t {
var boottime = timeval()
var mib: [Int32] = [CTL_KERN, KERN_BOOTTIME]
var size = strideof(timeval)
var now = time_t()
var uptime: time_t = -1
time(&now)
if (sysctl(&mib, 2, &boottime, &size, nil, 0) != -1 && boottime.tv_sec != 0) {
uptime = now - boottime.tv_sec
}
return uptime
}
// print(uptime())
To make it a bit prettier, we can use sysctlbyname instead of sysctl:
// var mib: [Int32] = [CTL_KERN, KERN_BOOTTIME]
sysctlbyname("kern.boottime", &boottime, &size, nil, 0)
This is a solution in Swift 4.
var boottime = timeval()
var size = MemoryLayout<timeval>.stride
sysctlbyname("kern.boottime", &boottime, &size, nil, 0)
Updated for Swift 5 and straight from ADF post here:
func bootTime() -> Date? {
var tv = timeval()
var tvSize = MemoryLayout<timeval>.size
let err = sysctlbyname("kern.boottime", &tv, &tvSize, nil, 0);
guard err == 0, tvSize == MemoryLayout<timeval>.size else {
return nil
}
return Date(timeIntervalSince1970: Double(tv.tv_sec) + Double(tv.tv_usec) / 1_000_000.0)
}
"Be aware that this time will change if the system clock changes, that is, the value is the boot time relative to the current system clock."
You can call ObjC code from Swift:
print(SystemUtil().uptime());
Write a ObjC class like the accepted answer you mentioned: Getting iOS system uptime, that doesn't pause when asleep.
SystemUtil.h for interface:
#import <Foundation/Foundation.h>
#interface SystemUtil : NSObject
- (time_t)uptime;
#end
SystemUtil.m for implementation:
#import "SystemUtil.h"
#include <sys/sysctl.h>
#implementation SystemUtil
- (time_t)uptime
{
struct timeval boottime;
int mib[2] = {CTL_KERN, KERN_BOOTTIME};
size_t size = sizeof(boottime);
time_t now;
time_t uptime = -1;
(void)time(&now);
if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1 && boottime.tv_sec != 0) {
uptime = now - boottime.tv_sec;
}
return uptime;
}
#end
And don't forget to include a <Project>-Bridge-Header.h with the following content so that you can use the ObjC class from Swift (<Project> is your project name):
#import "SystemUtil.h"

Determine if iOS device is 32- or 64-bit

Does anyone know of an easy way to tell if an iOS7 device has 32- or 64-bit hardware? I don't mean programmatically, I just mean via settings, model number, 3rd-party app, etc.
I'm having a problem that I suspect is 64-bit related. Apple's advice is to test on the 64-bit simulator but also on an actual 64-bit device, but then doesn't say anything about how to determine that. I can write a test app to check sizeof(int) or whatever, but there's got to be some way for, say, tech support to know what they're working with.
Eric
There is no other "official" way to determine it. You can determine it using this code:
if (sizeof(void*) == 4) {
NSLog(#"32-bit App");
} else if (sizeof(void*) == 8) {
NSLog(#"64-bit App");
}
Below is the method is64bitHardware. It returns YES if the hardware is a 64-bit hardware and works on a real iOS device and in an iOS Simulator. Here is source.
#include <mach/mach.h>
+ (BOOL) is64bitHardware
{
#if __LP64__
// The app has been compiled for 64-bit intel and runs as 64-bit intel
return YES;
#endif
// Use some static variables to avoid performing the tasks several times.
static BOOL sHardwareChecked = NO;
static BOOL sIs64bitHardware = NO;
if(!sHardwareChecked)
{
sHardwareChecked = YES;
#if TARGET_IPHONE_SIMULATOR
// The app was compiled as 32-bit for the iOS Simulator.
// We check if the Simulator is a 32-bit or 64-bit simulator using the function is64bitSimulator()
// See http://blog.timac.org/?p=886
sIs64bitHardware = is64bitSimulator();
#else
// The app runs on a real iOS device: ask the kernel for the host info.
struct host_basic_info host_basic_info;
unsigned int count;
kern_return_t returnValue = host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)(&host_basic_info), &count);
if(returnValue != KERN_SUCCESS)
{
sIs64bitHardware = NO;
}
sIs64bitHardware = (host_basic_info.cpu_type == CPU_TYPE_ARM64);
#endif // TARGET_IPHONE_SIMULATOR
}
return sIs64bitHardware;
}
Totally untested, but you should be able to get the CPU via sysctl like this:
#include <sys/types.h>
#include <sys/sysctl.h>
#include <mach/machine.h>
void foo() {
size_t size;
cpu_type_t type;
size = sizeof(type);
sysctlbyname("hw.cputype", &type, &size, NULL, 0);
if (type == CPU_TYPE_ARM64) {
// ARM 64-bit CPU
} else if (type == CPU_TYPE_ARM) {
// ARM 32-bit CPU
} else {
// Something else.
}
}
In the iOS 7 SDK, CPU_TYPE_ARM64 is defined in <mach/machine.h> as:
#define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64)
A different way seems to be:
#include <mach/mach_host.h>
void foo() {
host_basic_info_data_t hostInfo;
mach_msg_type_number_t infoCount;
infoCount = HOST_BASIC_INFO_COUNT;
host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo, &infoCount);
if (hostInfo.cpu_type == CPU_TYPE_ARM64) {
// ARM 64-bit CPU
} else if (hostInfo.cpu_type == CPU_TYPE_ARM) {
// ARM 32-bit CPU
} else {
// Something else.
}
}
If you are compiling with clang, there is another way: just check if __arm__ or __arm64__ is defined.
The example code below is not tested but it should illustrate what I mean by that:
#if defined(__arm__)
NSLog(#"32-bit App");
#elif defined(__arm64__)
NSLog(#"64-bit App");
#else
NSLog(#"Not running ARM");
#endif
Note that this relies on the fact that current iOS application binaries contain both, 32bit and 64bit binaries in a single container and they will be correctly selected depending on whether your app supports executing 64bit.
You can use bitWidth on Int
https://developer.apple.com/documentation/swift/int/2885648-bitwidth
static var is32Bit: Bool {
return Int.bitWidth == 32
}
static var is64Bit: Bool {
return Int.bitWidth == 64
}
I use this in swift 4, not sure if it's the best solution but it works.
func getCPUArch()
{
#if arch(arm)
print("this is a 32bit system")
#elseif arch(arm64)
print("this is a 64bit system")
#endif
}
In runtime you can use something like this
extension UIDevice {
static let is64Bit = MemoryLayout<Int>.size == MemoryLayout<Int64>.size
}

Resources