Determine a process's architecture - macos

Is there a programmatic way to find out what architecture another process is running as on Mac OS X 10.5 and later?
Examining the process's image file is not a solution, as the image is likely to contain multiple architectures, and between arch(1) and the “Open in Rosetta” and “Open in 32-bit mode” checkboxes, there's no way to tell from the image alone which architecture is actually running.

Can you use NSRunningApplication on OSes where it is available, and fall back to sysctl stuff when it isn't? I don't think sysctl stuff is supportable API the way most stuff is, but if you're only using it on old OSes you should be okay.
Try this to get the CPU type of the process:
cpu_type_t cpuType
size_t cpuTypeSize;
int mib[CTL_MAXNAME];
size_t mibLen;
mibLen = CTL_MAXNAME;
err = sysctlnametomib("sysctl.proc_cputype", mib, &mibLen);
if (err == -1) {
err = errno;
}
if (err == 0) {
assert(mibLen < CTL_MAXNAME);
mib[mibLen] = pid;
mibLen += 1;
cpuTypeSize = sizeof(cpuType);
err = sysctl(mib, mibLen, &cpuType, &cpuTypeSize, 0, 0);
if (err == -1) {
err = errno;
}
}
And test CPU_ARCH_ABI64 to check for 64-bit.

You don't say what your requirements are, but the NSRunningApplication class introduced in 10.6 offers a really easy interface for this. The docs are currently a little off, but it is there.

Related

OSX: Detecting if audio is being played through the speakers using Core Audio

I'm learning how to build OSX applications, and I was wondering if there is a way to check if there is some audio being outputted by any application on the system? Thanks
I think this can be checked with the kAudioDevicePropertyDeviceIsRunningSomewhere property.
From the header doc:
A UInt32 where 1 means that the AudioDevice is running in at least one process on the system and 0 means that it isn't running at all.
Pseudo-y code:
bool isRunningSomewhere(AudioDeviceID deviceId) {
uint32 val;
uint32 size = sizeof(val);
AudioObjectPropertyAddress pa = { kAudioDevicePropertyDeviceIsRunningSomewhere, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
AudioObjectGetPropertyData(deviceId, &pa, 0, NULL, &size, &val);
return val == 1;
}
This should tell you if the device is being used (i.e. has an active IOProc.) But it won't tell you if that IOProc is just sending silence.
This can't be done at the user application level. It might be possible by installing an OS X kext (kernel extension) or a custom audio device driver, which requires sudo privileges and possibly a reboot.

Install winusb driver from user application

Please can anyone give me direct for realization next functional for Windows.
I have USB device which connects to the PC (it is JTAG programmer.) I know VID and PID of this hardware. I need:
1 Check what type of driver this hardware use (detecting winusb driver or not will be enough. Maybe do I need to read registry?)
2 If driver is not winusb I need to install winusb driver for this USB device from my application.
The current driver assigned to the device is stored in the registry, so you could read it directly from there. However, it is probably better to use SetupAPI, an API provided by Microsoft. The function to call is SetupDiGetDeviceRegistryProperty, and the third argument should be SPDRP_SERVICE. This will return the name of the driver as a string. Note that you will need to call several other SetupAPI functions before you have all the pieces of info you need to call SetupDiGetDeviceRegistryProperty.
I have not tried it, but libwdi has features for installing WinUSB onto a device node. It might also have functions for getting the current driver, so you should try using it before you spend too much time learning SetupAPI. The devcon utility from Microsoft (which is open source now) might be another option.
Without knowing the details of what you are doing, I question whether you really need to do this. It might be simpler to provide a signed driver package to users and instruct them to use the "Update Driver Software..." option from the Device Manager to apply it to particular device.
I made first part of task.
#ifdef Q_OS_WIN
DEFINE_GUID(GUID_DEVCLASS_WINUSB,0x88BAE032,0x5A81,0x49f0,
0xBC,0x3D,0xA4,0xFF,0x13,0x82,0x16,0xD6);
#endif
bool WinUSB::isWinUsbDriver(quint16 vid, quint16 pid)
{
#ifndef Q_OS_WIN
Q_UNUSED(vid);
Q_UNUSED(pid);
return true;
#else
HDEVINFO deviceInfoSet;
GUID *guidDev = (GUID*) &GUID_DEVCLASS_WINUSB;
deviceInfoSet = SetupDiGetClassDevs(guidDev, NULL, NULL, DIGCF_PRESENT | DIGCF_PROFILE);
DWORD buffersize =4000;
TCHAR buffer [buffersize];
int memberIndex = 0;
bool retval = false;
QString vidPid;
vidPid = "VID_" + QString("%1").arg(vid,4,16,QChar('0')) + "&";
vidPid += "PID_" + QString("%1").arg(pid,4,16,QChar('0'));
while (true)
{
SP_DEVINFO_DATA deviceInfoData;
ZeroMemory(&deviceInfoData, sizeof(SP_DEVINFO_DATA));
deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
if (SetupDiEnumDeviceInfo(deviceInfoSet, memberIndex, &deviceInfoData) == FALSE) {
if (GetLastError() == ERROR_NO_MORE_ITEMS) {
break;
}
}
DWORD nSize=0 ;
SetupDiGetDeviceInstanceId (deviceInfoSet, &deviceInfoData, buffer, sizeof(buffer), &nSize);
buffer [nSize] ='\0';
QString str = QString::fromWCharArray(buffer);
if (str.indexOf(vidPid) >= 0) {
retval = true;
break;
}
memberIndex++;
}
if (deviceInfoSet) {
SetupDiDestroyDeviceInfoList(deviceInfoSet);
}
return retval;
#endif
}

Loading and executing bundle from memory

Loading bundle from memory is possible by NSCreateObjectFileImageFromMemory function. Does anyone have successful experience in this area? Does anyone have working sample for this function?
My code is as:
text srcPath = "/Applications/TextEdit.app/Contents/MacOS/TextEdit";
data_t data;
data.loadFromFile(srcPath);
void *addr;
kern_return_t err;
NSObjectFileImage img = nil;
NSObjectFileImageReturnCode dyld_err;
err = vm_allocate(mach_task_self(), (vm_address_t *)&addr,
data.length(), true);
if(err == 0)
{
//err = vm_write(mach_task_self(), (vm_address_t)addr,
//(vm_address_t)(char*)data, data.length());
memcpy(addr, (char*)data, data.length());
if(err == 0)
dyld_err =
NSCreateObjectFileImageFromMemory(addr, data.length(), &img);
// error is NSObjectFileImageFailure
}
The img variable is null (error is NSObjectFileImageFailure). Why?
Thankyou.
From the manpage, it looks like only MH_BUNDLE files can be loaded with NSCreateObjectFileImageFromMemory() and friends.
MH_BUNDLE files are explained here.
The MH_BUNDLE file type is the type typically used by code that you
load at runtime (typically called bundles or plug-ins). By convention,
the file name extension for this format is .bundle.
Note that that manpage is for 10.4 and there does not appear to be a newer version available.

Setting process name on Mac OS X at runtime

I'm trying to change my process' name as it appears in ps and Activity Monitor at runtime. I found several notes that there is no portable way to do this (which I don't care about).
Here's what I tried. None of these approaches worked for me.
Changing argv[0] (seems to be the way to go on some Unix systems)
Calling [[NSProcessInfo processInfo] setProcessName:#"someName"]
Calling setprogname (calling getprogname returns the name I set, but that is irrelevant)
I also read about a function called setproctitle which should be defined in stdlib.h if it is available, but it's not there.
There must be a way to accomplish this because QTKitServer - the faceless decoder for QuickTime Player X - has its corresponding QuickTime Player's PID in its process name.
Does anybody have a clue about how to accomplish this? I'd very much prefer a Core Foundation or POSIXy way over an Objective-C method to do this.
Thanks,
Marco
Edit: If it is in any way relevant, I'm using Mac OS X 10.6.5 and Xcode 3.2.5
There are good reasons to change the process name. Java software should change process names because when running different java tools I want to see which java process is for which tool.
Chromium does it: http://src.chromium.org/viewvc/chrome/trunk/src/base/mac/mac_util.mm.
Node.js uses same code to implement Process.title = 'newtitle': https://github.com/joyent/node/blob/master/src/platform_darwin_proctitle.cc
Note: This fails if someone does su to a different not logged-in user: https://github.com/joyent/node/issues/1727
Here the source code in its full complex glory. By the way, someone told me it also works for Mac OS X Lion and also fails with su.
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
void SetProcessName(CFStringRef process_name) {
if (!process_name || CFStringGetLength(process_name) == 0) {
NOTREACHED() << "SetProcessName given bad name.";
return;
}
if (![NSThread isMainThread]) {
NOTREACHED() << "Should only set process name from main thread.";
return;
}
// Warning: here be dragons! This is SPI reverse-engineered from WebKit's
// plugin host, and could break at any time (although realistically it's only
// likely to break in a new major release).
// When 10.7 is available, check that this still works, and update this
// comment for 10.8.
// Private CFType used in these LaunchServices calls.
typedef CFTypeRef PrivateLSASN;
typedef PrivateLSASN (*LSGetCurrentApplicationASNType)();
typedef OSStatus (*LSSetApplicationInformationItemType)(int, PrivateLSASN,
CFStringRef,
CFStringRef,
CFDictionaryRef*);
static LSGetCurrentApplicationASNType ls_get_current_application_asn_func =
NULL;
static LSSetApplicationInformationItemType
ls_set_application_information_item_func = NULL;
static CFStringRef ls_display_name_key = NULL;
static bool did_symbol_lookup = false;
if (!did_symbol_lookup) {
did_symbol_lookup = true;
CFBundleRef launch_services_bundle =
CFBundleGetBundleWithIdentifier(CFSTR("com.apple.LaunchServices"));
if (!launch_services_bundle) {
LOG(ERROR) << "Failed to look up LaunchServices bundle";
return;
}
ls_get_current_application_asn_func =
reinterpret_cast<LSGetCurrentApplicationASNType>(
CFBundleGetFunctionPointerForName(
launch_services_bundle, CFSTR("_LSGetCurrentApplicationASN")));
if (!ls_get_current_application_asn_func)
LOG(ERROR) << "Could not find _LSGetCurrentApplicationASN";
ls_set_application_information_item_func =
reinterpret_cast<LSSetApplicationInformationItemType>(
CFBundleGetFunctionPointerForName(
launch_services_bundle,
CFSTR("_LSSetApplicationInformationItem")));
if (!ls_set_application_information_item_func)
LOG(ERROR) << "Could not find _LSSetApplicationInformationItem";
CFStringRef* key_pointer = reinterpret_cast<CFStringRef*>(
CFBundleGetDataPointerForName(launch_services_bundle,
CFSTR("_kLSDisplayNameKey")));
ls_display_name_key = key_pointer ? *key_pointer : NULL;
if (!ls_display_name_key)
LOG(ERROR) << "Could not find _kLSDisplayNameKey";
// Internally, this call relies on the Mach ports that are started up by the
// Carbon Process Manager. In debug builds this usually happens due to how
// the logging layers are started up; but in release, it isn't started in as
// much of a defined order. So if the symbols had to be loaded, go ahead
// and force a call to make sure the manager has been initialized and hence
// the ports are opened.
ProcessSerialNumber psn;
GetCurrentProcess(&psn);
}
if (!ls_get_current_application_asn_func ||
!ls_set_application_information_item_func ||
!ls_display_name_key) {
return;
}
PrivateLSASN asn = ls_get_current_application_asn_func();
// Constant used by WebKit; what exactly it means is unknown.
const int magic_session_constant = -2;
OSErr err =
ls_set_application_information_item_func(magic_session_constant, asn,
ls_display_name_key,
process_name,
NULL /* optional out param */);
LOG_IF(ERROR, err) << "Call to set process name failed, err " << err;
}
Edit: It's a complex and confusing problem.
On OS X there is no setproctitle(3). One has to write into the argv array (ugly
and a bit dangerous because it is possible to overwrite some environment variables with bogus stuff). Done correctly it works very well.
Additionally Apple has the ActivityMonitor application, something like the Task Manager under Windows. The code above manipulates ActivityMonitor but this manipulation doesn't seem to be encouraged by Apple (hence the use of undocumented functions).
Important: ps and ActivityMonitor don't show the same information.
Also important: ActivityMonitor is not available if you don't have GUI. This can happen if you ssh in to a remote Apple box and there is nobody logged in by GUI. Sadly there is a bug by Apple IMO. Just querying if there is a GUI sends an annoying warning message to stderr.
Summary: If you need to change ActivityMonitor, use the code above. If you have GUI-less situations and and dislike warnings on stderr, redirect stderr temporarily to /dev/null during the call of SetProcessName. If you need to change ps information, write into argv.
You can use the lsappinfo tool which comes with macOS since at least 10.6 and up to present day (10.13.2):
Shell:
lsappinfo setinfo <PID> --name <NAME>
C++:
#include <sstream>
#include <string>
#include <stdlib.h>
void setProcessName (pid_t pid, std::string name)
{
std::ostringstream cmd;
cmd << "/usr/bin/lsappinfo setinfo " << pid;
cmd << " --name \"" << name << "\"";
system (cmd.str().c_str());
}

iPhone dev - why is it using 8MB?

Even when I just use the Window-based application template, which does literally nothing, instruments (activity monitor) says my application's process is using 8.14MB of Real Memory! Even with this method:
void report_memory(void) {
struct task_basic_info info;
mach_msg_type_number_t size = sizeof(info);
kern_return_t kerr = task_info(mach_task_self(),
TASK_BASIC_INFO,
(task_info_t)&info,
&size);
if( kerr == KERN_SUCCESS ) {
NSLog(#"Memory in use (in bytes): %u", info.resident_size);
} else {
NSLog(#"Error with task_info(): %s", mach_error_string(kerr));
}
}
Its still ~8.14 MB! So it seems that instruments is right, but why would a UIWindow take up that much memory??
My guess would be that it's the Objective-C runtime libraries that are taking up all that space, rather than your UIWindow itself. However, all applications use a copy of these libraries, the iPhone OS may be smart enough to share that memory among all of the applications that are running (although of course, only system apps are allowed to run in the background).

Resources