Skip to content

Instantly share code, notes, and snippets.

@beltex
Last active January 16, 2024 09:26
Show Gist options
  • Save beltex/acbbeef815a7be938abf to your computer and use it in GitHub Desktop.
Save beltex/acbbeef815a7be938abf to your computer and use it in GitHub Desktop.
Read SMC keys that Apple's powermetrics tool uses. Requires OS X 10.10
/*******************************************************************************
WHAT: Read SMC keys that Apple's powermetrics tool uses. Requires OS X 10.10
RUN: sudo dtrace -qCs powermetrics.d -c 'powermetrics --sampler smc -n 1'
DETAIL: This lets us see what hardware components/functions they map to.
LICENSE: MIT
AUTHOR: beltex <http://beltex.github.io>
REFERENCES:
- Advanced Mac OS X Programming: The Big Nerd Ranch Guide
- DTrace: Dynamic Tracing in Oracle Solaris, Mac OS X, and FreeBSD
- https://www.bignerdranch.com/blog/hooked-on-dtrace-part-1/
- http://dtrace.org/blogs/brendan/2011/02/11/dtrace-pid-provider-arguments/
*******************************************************************************/
/*
We need to define the SMCParamStruct here so we can cast the inputStruct arg
in IOConnectCallStructMethod() which is void and not defined in any public
headers. See link below for information about it.
https://github.com/beltex/SMCKit/blob/v0.0.13/SMCKit/SMC.swift#L450-468
*/
typedef struct SMCVersion {
unsigned char major;
unsigned char minor;
unsigned char build;
unsigned char reserved;
unsigned short release;
} SMCVersion;
typedef struct SMCPLimitData {
uint16_t version;
uint16_t length;
uint32_t cpuPLimit;
uint32_t gpuPLimit;
uint32_t memPLimit;
} SMCPLimitData;
typedef struct SMCKeyInfoData {
uint32_t dataSize;
uint32_t dataType;
uint8_t dataAttributes;
} SMCKeyInfoData;
typedef struct SMCParamStruct {
uint32_t key;
SMCVersion vers;
SMCPLimitData pLimitData;
SMCKeyInfoData keyInfo;
uint8_t result;
uint8_t status;
uint8_t data8;
uint32_t data32;
uint8_t bytes[32];
} SMCParamStruct;
/*
Probe to detect when powermetrics makes a call to IOConnectCallStructMethod()
This is the main I/O Kit function call that is made to interface with the SMC.
Passes in a void pointer to an SMCParamStruct which contains the SMC key that is
to be read. See IOKitLib.h for function signature.
*/
pid$target::IOConnectCallStructMethod:entry
{
/*
Since DTrace executes in kernel-space, the void pointer we have (arg2) is to
a user-space address. Thus, we use DTrace's copyin() to copy the data into
kernel-space (DTrace scratch buffer), at which point we can cast it.
*/
inputStruct = (struct SMCParamStruct *) copyin(arg2, sizeof(struct SMCParamStruct));
/* Decode UInt32 key to human readable. SMC keys are 4 char constants */
printf("Key: %c%c%c%c\n", inputStruct->key >> 24 & 0xff,
inputStruct->key >> 16 & 0xff,
inputStruct->key >> 8 & 0xff,
inputStruct->key & 0xff);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment