Compare commits

...

16 Commits

  1. 4
      .gitignore
  2. 7
      LICENSE
  3. 31
      Makefile
  4. 13
      NEWS.md
  5. 43
      README.md
  6. 284
      archinfo.c
  7. 340
      archinfo.xcodeproj/project.pbxproj
  8. 78
      archinfo.xcodeproj/xcshareddata/xcschemes/archinfo.xcscheme
  9. 12
      archinfo/Info.plist
  10. 7
      archinfo/archinfo-Bridging-Header.h
  11. 10
      archinfo/main.swift
  12. 19
      archinfo/procHelper.h
  13. 115
      archinfo/procHelper.m

4
.gitignore

@ -1,3 +1,7 @@
archinfo
.DS_Store
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore

7
LICENSE

@ -0,0 +1,7 @@
Copyright 2021 Bob Rudis
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

31
Makefile

@ -0,0 +1,31 @@
# replace this with yours if you want to codesign your own binary
IDENTITY="Apple Development: Bob Rudis (9V3BZ2VH79)"
archinfo:
$(CC) archinfo.c -o x86_app -target x86_64-apple-macos10.12
$(CC) archinfo.c -o arm_app -target arm64-apple-macos11
lipo -create -output archinfo x86_app arm_app && rm x86_app arm_app
leaks: archinfo
leaks --readonlyContent -atExit -- ./archinfo | grep LEAK: || true
leaks --readonlyContent -atExit -- ./archinfo --json | grep LEAK: || true
leaks --readonlyContent -atExit -- ./archinfo --json | grep LEAK: || true
sign: archinfo
codesign --force --verify --verbose --sign ${IDENTITY} archinfo
clean:
rm -f archinfo
install: archinfo
codesign --force --verify --verbose --sign ${IDENTITY} archinfo
cp archinfo /usr/local/bin
test: archinfo
@./archinfo | grep -q tccd && echo "Columns: PASSED (list)" || echo "Columns: FAILED (list)"
@./archinfo --columns | grep -q tccd && echo "Columns: PASSED (list, explicit)" || echo "Columns: FAILED (list, explicit)"
@./archinfo --json | grep -q 'tccd"}' && echo " JSON: PASSED (list)" || echo " JSON: FAILED (list)"
@(./archinfo --pid `pgrep keyboardservicesd` | grep -q '64') && echo "Columns: PASSED (single)" || echo "Columns: FAILED (single)"
@(./archinfo --columns --pid `pgrep keyboardservicesd` | grep -q '64') && echo "Columns: PASSED (single, explicit)" || echo "Columns: FAILED (single, explicit)"
@(./archinfo --json --pid `pgrep keyboardservicesd` | grep -q '"}') && echo " JSON: PASSED (single)" || echo " JSON: FAILED (single)"

13
NEWS.md

@ -0,0 +1,13 @@
* 0.4.0 • 2021-05-25
- added options for only showing X86_64 or ARM64 processes
# 0.3.0 • 2021-03-14
- added option for retrieving process info for a single pid
- added more tests
- added leak check Makefile option
# 0.2.0 • 2021-03-14
- removed Xcode dependency
- added codesigning option
- added option for either columnar output or ndjson output
# 0.1.0 • 2021-03-13
- initial release

43
README.md

@ -0,0 +1,43 @@
# archinfo
Returns a list of running processes and the architecture they are running under.
Apple M1/Apple Silicon/arm64 macOS can run x86_64 programs via Rosetta and most M1 systems currently (~March 2021) very likely run a mix of x86_64 and arm64 processes.
Activity Monitor can show the architecture, but command line tools such as `ps` and `top` do not due to Apple hiding the details of the proper `sysctl()` incantations necessary to get this info.
Patrick Wardle reverse-engineered Activity Monitor — <https://www.patreon.com/posts/45121749> — and I slapped that hack into a bare-bones command line utility `archinfo`.
It returns columnar output or JSON (via `--json`) — that will work nicely with `jq` — of running processes and their respective architectures.
Build from source or grab from the releases.
```bash
$ archinfo
...
5949 arm64 /System/Library/Frameworks/AudioToolbox.framework/AudioComponentRegistrar
5923 arm64 /System/Library/CoreServices/LocationMenu.app/Contents/MacOS/LocationMenu
5901 x86_64 /Library/Application Support/Adobe/Adobe Desktop Common/IPCBox/AdobeIPCBroker.app/Contents/MacOS/AdobeIPCBroker
5873 arm64 /Applications/Utilities/Adobe Creative Cloud Experience/CCXProcess/CCXProcess.app/Contents/MacOS/../libs/Adobe_CCXProcess.node
5863 arm64 /bin/sleep
5861 x86_64 /Applications/Tailscale.app/Contents/PlugIns/IPNExtension.appex/Contents/MacOS/IPNExtension
5855 x86_64 /Applications/Elgato Control Center.app/Contents/MacOS/Elgato Control Center
5852 x86_64 /Applications/Tailscale.app/Contents/MacOS/Tailscale
5849 arm64 /System/Library/CoreServices/TextInputSwitcher.app/Contents/MacOS/TextInputSwitcher
...
```
```bash
$ archinfo --pid $(pgrep keyboardservicesd)
60298 x86_64 /usr/libexec/keyboardservicesd
$ archinfo --json --pid $(pgrep keyboardservicesd)
{"pid":60298,"arch":"x86_64","name":"/usr/libexec/keyboardservicesd"}
```
```
Rscript -e 'table(jsonlite::stream_in(textConnection(system("/usr/local/bin/archinfo --json", intern=TRUE)))$arch)'
##
## arm64 x86_64
## 419 29
```

284
archinfo.c

@ -0,0 +1,284 @@
#include <unistd.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <mach/machine.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <libgen.h>
#define VERSION "0.4.0"
#define noErr 0
#define DEFAULT_BUFFER_SIZE 4096
#define SYSCTL_ERROR 1
#define is_match(x) (x == 0)
enum fmt { JSON=0, COLUMNS };
enum show { ALL=0, ARM64, X86_64 };
static int max_arg_size = 0;
typedef struct ProcInfo {
bool ok;
char *name;
char arch[10];
} procinfo;
// arch_info() is due to the spelunking work of Patrick Wardle <https://www.patreon.com/posts/45121749>
static char *arch_info(pid_t pid) {
size_t size;
cpu_type_t type = -1;
int mib[CTL_MAXNAME] = {0};
size_t length = CTL_MAXNAME;
struct kinfo_proc procInfo = {0};
if (noErr != sysctlnametomib("sysctl.proc_cputype", mib, &length)) return("unknown");
mib[length] = pid;
length++;
size = sizeof(cpu_type_t);
if (noErr != sysctl(mib, (u_int)length, &type, &size, 0, 0)) return("unknown");
if (CPU_TYPE_X86_64 == type) return("x86_64");
if (CPU_TYPE_ARM64 == type) {
mib[0] = CTL_KERN; //(re)init mib
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PID;
mib[3] = pid;
length = 4; //(re)set length
size = sizeof(procInfo); //(re)set size
if(noErr != sysctl(mib, (u_int)length, &procInfo, &size, NULL, 0)) return("arm64"); //get proc info
//'P_TRANSLATED' set? set architecture to 'x86_64'
return( (P_TRANSLATED == (P_TRANSLATED & procInfo.kp_proc.p_flag)) ? "x86_64" : "arm64");
}
return("unknown");
}
// retrieve process info
procinfo proc_info(pid_t pid) {
size_t size = max_arg_size;
procinfo p;
int mib[3] = { CTL_KERN, KERN_PROCARGS2, pid };
struct kinfo_proc *info;
size_t length;
int count;
// get size for buffer
(void)sysctl(mib, 3, NULL, &length, NULL, 0);
char* buffer = (char *)calloc(length+32, sizeof(char)); // need +32 b/c this is busted on Big Sur
// get the info
if (sysctl(mib, 3, buffer, &size, NULL, 0) == 0) {
// copy the info
p.ok = TRUE;
p.name = buffer;
strncpy(p.arch, arch_info(pid), 10);
} else {
free(buffer);
p.ok = FALSE;
}
return(p);
}
// output one line of process info with architecture info
void output_one(enum fmt output_type, pid_t pid, procinfo p, bool only_basename) {
if (output_type == COLUMNS) {
printf(
"%7d %6s %s\n",
pid,
p.arch,
(only_basename ? basename((char *)(p.name+sizeof(int))) : p.name+sizeof(int))
);
} else if (output_type == JSON) {
printf(
"{\"pid\":%d,\"arch\":\"%s\",\"name\":\"%s\"}\n",
pid,
p.arch,
(only_basename ? basename((char *)(p.name+sizeof(int))) : p.name+sizeof(int))
);
}
}
// walk through process list, get PID and name, then pass that on to output_one() to
// grab the architecture and do the actual output
int enumerate_processes(enum fmt output_type, enum show to_show, bool only_basename) {
int mib[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
struct kinfo_proc *info;
size_t length;
int count;
// get the running process list
if (sysctl(mib, 3, NULL, &length, NULL, 0) < 0) return(SYSCTL_ERROR);
// make some room for results
if (!(info = calloc(length, sizeof(char)))) return(SYSCTL_ERROR);
// get the results
if (sysctl(mib, 3, info, &length, NULL, 0) < 0) {
free(info);
return(SYSCTL_ERROR);
}
// how many results?
count = (int)(length / sizeof(struct kinfo_proc));
// for each result
for (int i = 0; i < count; i++) {
pid_t pid = info[i].kp_proc.p_pid; // get PID
if (pid == 0) continue;
procinfo p = proc_info(pid); // get process info
if (p.ok) {
if (
(to_show == ALL) ||
((to_show == ARM64) && is_match(strncmp("arm", p.arch, 3))) ||
((to_show == X86_64) && is_match(strncmp("x86", p.arch, 3)))
) {
output_one(output_type, pid, p, only_basename);
}
free(p.name);
}
}
free(info);
return(0);
}
// call to display cmdline tool help
void help() {
printf("archinfo %s\n", VERSION);
printf("boB Rudis <bob@rud.is>\n");
printf("\n");
printf("archinfo outputs a list of running processes with architecture (x86_64/amd64) information\n");
printf("\n");
printf("USAGE:\n");
printf(" archinfo [--arm|--x86] [--basename] [--columns|--json] [--pid #]\n");
printf("\n");
printf("FLAGS/OPTIONS:\n");
printf(" --arm Only show arm64 processes (default is to show both)\n");
printf(" --x86 Only show x86_64 processes (default is to show both)\n");
printf(" --basename Only show basename of process executable\n");
printf(" --columns Output process list in columns (default)\n");
printf(" --json Output process list in ndjson\n");
printf(" --pid # Output process architecture info for the specified process\n");
printf(" --help Display this help text\n");
}
void init() {
if (max_arg_size == 0) {
size_t size = sizeof(max_arg_size);
if (sysctl((int[]) { CTL_KERN, KERN_ARGMAX }, 2, &max_arg_size, &size, NULL, 0) == -1) {
perror("sysctl argument size");
max_arg_size = DEFAULT_BUFFER_SIZE;
}
}
}
int main(int argc, char** argv) {
int c;
enum show to_show = ALL;
bool show_help = FALSE;
bool do_one = FALSE;
bool only_basename = FALSE;
pid_t pid = -1;
enum fmt output_type = COLUMNS;
while(true) {
int this_option_optind = optind ? optind : 1;
int option_index = 0;
static struct option long_options[] = {
{ "arm", no_argument, 0, 'a' },
{ "x86", no_argument, 0, 'x' },
{ "basename", no_argument, 0, 'b' },
{ "json", no_argument, 0, 'j' },
{ "columns", no_argument, 0, 'c' },
{ "help", no_argument, 0, 'h' },
{ "pid", required_argument, 0, 'p' },
{ 0, 0, 0, 0 }
};
c = getopt_long(argc, argv, "axbjchp:", long_options, &option_index);
if (c == -1) break;
switch(c) {
case 'a': to_show = ARM64; break;
case 'x': to_show = X86_64; break;
case 'b': only_basename = TRUE; break;
case 'p': do_one = TRUE; pid = atoi(optarg); break;
case 'h': show_help = TRUE; break;
case 'j': output_type = JSON; break;
case 'c': output_type = COLUMNS; break;
}
}
init();
// only show help if --help is in the arg list
if (show_help) {
help();
return(0);
}
// only do one process if --pid is in the arg list
if (do_one) {
if (pid > 0) {
procinfo p = proc_info(pid);
if (p.ok) {
output_one(output_type, pid, p, only_basename);
free(p.name);
return(0);
}
}
return(SYSCTL_ERROR);
}
// otherwise do them all
return(enumerate_processes(output_type, to_show, only_basename));
}

340
archinfo.xcodeproj/project.pbxproj

@ -1,340 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objects = {
/* Begin PBXBuildFile section */
01B369A425FD38490064ACA1 /* libbsm.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 01C9201925FD0A3C0097CD09 /* libbsm.tbd */; };
01C9200B25FD06D20097CD09 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01C9200A25FD06D20097CD09 /* main.swift */; };
01C9201325FD07020097CD09 /* procHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 01C9201225FD07020097CD09 /* procHelper.m */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
01C9200525FD06D20097CD09 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
01B369A325FD35360064ACA1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
01C9200725FD06D20097CD09 /* archinfo */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = archinfo; sourceTree = BUILT_PRODUCTS_DIR; };
01C9200A25FD06D20097CD09 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
01C9201125FD07000097CD09 /* archinfo-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "archinfo-Bridging-Header.h"; sourceTree = "<group>"; };
01C9201225FD07020097CD09 /* procHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = procHelper.m; sourceTree = "<group>"; };
01C9201625FD07160097CD09 /* procHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = procHelper.h; sourceTree = "<group>"; };
01C9201925FD0A3C0097CD09 /* libbsm.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libbsm.tbd; path = usr/lib/libbsm.tbd; sourceTree = SDKROOT; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
01C9200425FD06D20097CD09 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
01B369A425FD38490064ACA1 /* libbsm.tbd in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
01C91FFE25FD06D20097CD09 = {
isa = PBXGroup;
children = (
01C9200925FD06D20097CD09 /* archinfo */,
01C9200825FD06D20097CD09 /* Products */,
01C9201825FD0A3B0097CD09 /* Frameworks */,
);
sourceTree = "<group>";
};
01C9200825FD06D20097CD09 /* Products */ = {
isa = PBXGroup;
children = (
01C9200725FD06D20097CD09 /* archinfo */,
);
name = Products;
sourceTree = "<group>";
};
01C9200925FD06D20097CD09 /* archinfo */ = {
isa = PBXGroup;
children = (
01C9201625FD07160097CD09 /* procHelper.h */,
01C9201225FD07020097CD09 /* procHelper.m */,
01C9200A25FD06D20097CD09 /* main.swift */,
01B369A325FD35360064ACA1 /* Info.plist */,
01C9201125FD07000097CD09 /* archinfo-Bridging-Header.h */,
);
path = archinfo;
sourceTree = "<group>";
};
01C9201825FD0A3B0097CD09 /* Frameworks */ = {
isa = PBXGroup;
children = (
01C9201925FD0A3C0097CD09 /* libbsm.tbd */,
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
01C9200625FD06D20097CD09 /* archinfo */ = {
isa = PBXNativeTarget;
buildConfigurationList = 01C9200E25FD06D20097CD09 /* Build configuration list for PBXNativeTarget "archinfo" */;
buildPhases = (
01C9200325FD06D20097CD09 /* Sources */,
01C9200425FD06D20097CD09 /* Frameworks */,
01C9200525FD06D20097CD09 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = archinfo;
productName = archinfo;
productReference = 01C9200725FD06D20097CD09 /* archinfo */;
productType = "com.apple.product-type.tool";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
01C91FFF25FD06D20097CD09 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1250;
LastUpgradeCheck = 1250;
TargetAttributes = {
01C9200625FD06D20097CD09 = {
CreatedOnToolsVersion = 12.5;
LastSwiftMigration = 1250;
};
};
};
buildConfigurationList = 01C9200225FD06D20097CD09 /* Build configuration list for PBXProject "archinfo" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 01C91FFE25FD06D20097CD09;
productRefGroup = 01C9200825FD06D20097CD09 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
01C9200625FD06D20097CD09 /* archinfo */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
01C9200325FD06D20097CD09 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
01C9200B25FD06D20097CD09 /* main.swift in Sources */,
01C9201325FD07020097CD09 /* procHelper.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
01C9200C25FD06D20097CD09 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = NO;
SDKROOT = macosx;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
01C9200D25FD06D20097CD09 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = macosx;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
};
name = Release;
};
01C9200F25FD06D20097CD09 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 0.1.0;
DEVELOPMENT_TEAM = CBY22P58G8;
ENABLE_HARDENED_RUNTIME = NO;
INFOPLIST_FILE = /Users/hrbrmstr/Development/archinfo/archinfo/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/../Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/archinfo",
);
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "archinfo/archinfo-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
};
name = Debug;
};
01C9201025FD06D20097CD09 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 0.1.0;
DEVELOPMENT_TEAM = CBY22P58G8;
ENABLE_HARDENED_RUNTIME = NO;
INFOPLIST_FILE = /Users/hrbrmstr/Development/archinfo/archinfo/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/../Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/archinfo",
);
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "archinfo/archinfo-Bridging-Header.h";
SWIFT_VERSION = 5.0;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
01C9200225FD06D20097CD09 /* Build configuration list for PBXProject "archinfo" */ = {
isa = XCConfigurationList;
buildConfigurations = (
01C9200C25FD06D20097CD09 /* Debug */,
01C9200D25FD06D20097CD09 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
01C9200E25FD06D20097CD09 /* Build configuration list for PBXNativeTarget "archinfo" */ = {
isa = XCConfigurationList;
buildConfigurations = (
01C9200F25FD06D20097CD09 /* Debug */,
01C9201025FD06D20097CD09 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 01C91FFF25FD06D20097CD09 /* Project object */;
}

78
archinfo.xcodeproj/xcshareddata/xcschemes/archinfo.xcscheme

@ -1,78 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1250"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "01C9200625FD06D20097CD09"
BuildableName = "archinfo"
BlueprintName = "archinfo"
ReferencedContainer = "container:archinfo.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "01C9200625FD06D20097CD09"
BuildableName = "archinfo"
BlueprintName = "archinfo"
ReferencedContainer = "container:archinfo.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "01C9200625FD06D20097CD09"
BuildableName = "archinfo"
BlueprintName = "archinfo"
ReferencedContainer = "container:archinfo.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

12
archinfo/Info.plist

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>is.rud.archinfo</string>
<key>CFBundleName</key>
<string>archinfo</string>
<key>CFBundleShortVersionString</key>
<string>1</string>
</dict>
</plist>

7
archinfo/archinfo-Bridging-Header.h

@ -1,7 +0,0 @@
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
#import <Foundation/Foundation.h>
#include "procHelper.h"

10
archinfo/main.swift

@ -1,10 +0,0 @@
//
// main.swift
// archinfo
//
// Created by boB Rudis on 3/13/21.
//
import Foundation
print(processListToJSON(allProcesses()) ?? "{}")

19
archinfo/procHelper.h

@ -1,19 +0,0 @@
//
// procHelper.h
// RSwitch
//
// Created by hrbrmstr on 8/25/19.
// Copyright © 2019 Bob Rudis. All rights reserved.
//
#ifndef procHelper_h
#define procHelper_h
#include <stdio.h>
#import <Foundation/Foundation.h>
NSString* archInfo(pid_t pid);
NSArray* allProcesses(void);
NSString *processListToJSON(NSArray * processListDict);
#endif /* procHelper_h */

115
archinfo/procHelper.m

@ -1,115 +0,0 @@
#import <sys/sysctl.h>
#import <Foundation/Foundation.h>
#include "procHelper.h"
// archInfo() is due to the spelunking work of Patrick Wardle <https://www.patreon.com/posts/45121749>
NSString* archInfo(pid_t pid) {
size_t size;
cpu_type_t type = -1;
int mib[CTL_MAXNAME] = {0};
size_t length = CTL_MAXNAME;
struct kinfo_proc procInfo = {0};
if (noErr != sysctlnametomib("sysctl.proc_cputype", mib, &length)) return(@"unknown");
mib[length] = pid;
length++;
size = sizeof(cpu_type_t);
if (noErr != sysctl(mib, (u_int)length, &type, &size, 0, 0)) return(@"unknown");
if (CPU_TYPE_X86_64 == type) return(@"x86_64");
if (CPU_TYPE_ARM64 == type) {
mib[0] = CTL_KERN; //(re)init mib
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PID;
mib[3] = pid;
length = 4; //(re)set length
size = sizeof(procInfo); //(re)set size
if(noErr != sysctl(mib, (u_int)length, &procInfo, &size, NULL, 0)) return(@"arm64"); //get proc info
//'P_TRANSLATED' set? set architecture to 'Intel'
return( (P_TRANSLATED == (P_TRANSLATED & procInfo.kp_proc.p_flag)) ? @"x86_64" : @"arm64");
}
return(@"unknown");
}
// The below is modified code from: <https://gist.github.com/s4y/1173880/9ea0ed9b8a55c23f10ecb67ce288e09f08d9d1e5>
//
// Copyright (c) 2020 DeepTech, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
// to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
NSArray* allProcesses(){
static int maxArgumentSize = 0;
if (maxArgumentSize == 0) {
size_t size = sizeof(maxArgumentSize);
if (sysctl((int[]) { CTL_KERN, KERN_ARGMAX }, 2, &maxArgumentSize, &size, NULL, 0) == -1) {
perror("sysctl argument size");
maxArgumentSize = 4096; // Default
}
}
NSMutableArray *processes = [NSMutableArray array];
int mib[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
struct kinfo_proc *info;
size_t length;
int count;
if (sysctl(mib, 3, NULL, &length, NULL, 0) < 0) return nil;
if (!(info = malloc(length))) return nil;
if (sysctl(mib, 3, info, &length, NULL, 0) < 0) {
free(info);
return nil;
}
count = (int)(length / sizeof(struct kinfo_proc));
for (int i = 0; i < count; i++) {
pid_t pid = info[i].kp_proc.p_pid;
if (pid == 0) continue;
size_t size = maxArgumentSize;
char* buffer = (char *)malloc(length);
if (sysctl((int[]){ CTL_KERN, KERN_PROCARGS2, pid }, 3, buffer, &size, NULL, 0) == 0) {
NSString* executable = [NSString stringWithCString:(buffer+sizeof(int)) encoding:NSUTF8StringEncoding];
[processes addObject:[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:pid], @"pid",
executable, @"executable",
archInfo(pid), @"arch",
nil]];
}
free(buffer);
}
free(info);
return processes;
}
NSString *processListToJSON(NSArray * processListDict) {
NSError * err;
NSData * jsonData = [NSJSONSerialization dataWithJSONObject:processListDict options:0 error:&err];
return([[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]);
}
Loading…
Cancel
Save