When disassembling functions, gdb will display memory addresses in base 16, but offsets in base 10.
Example:
(gdb) disassemble unregister_sysctl_table
Dump of assembler code for function unregister_sysctl_table:
0x00037080 <+0>: push %ebp
0x00037081 <+1>: mov %esp,%ebp
0x00037083 <+3>: sub $0x14,%esp
0x00037086 <+6>: mov %ebx,-0xc(%ebp)
0x00037089 <+9>: mov %esi,-0x8(%ebp)
0x0003708c <+12>:mov %eax,%ebx
0x0003708e <+14>:mov %edi,-0x4(%ebp)
The function offsets are the <+N> next to the address, and as you can see they are in base 10.
When the Linux kernel crashes, it displays a backtrace using base 16:
[ 0.524380] [<c10381d5>] unregister_sysctl_table+0x65/0x70
It's very annoying to have to convert backtrace addresses from base 16 to base 10 to be able to find the desired instruction.
Can gdb be told to display disassembly output with base 16 offsets?
GDB currently uses hard-coded '%d' for the offset.
It's very annoying to have to convert backtrace addresses ... to be able to find the desired instruction
You do realize that you can simply do
x/i 0xc10381d5 # the crashing instruction (if looking at the inner frame)
x/i 0xc10381d5-5 # the call (if looking at caller frame)
x/10i 0xc10381d5-20 # context around the desired location
you have to patch gdb to show offset in hex.
for example, in gdb 6.8,
change *_field_int in cli-out.c, mi/mi-out.c, tui/tui-out.c
void
cli_field_int (struct ui_out *uiout, int fldno, int width,
enum ui_align alignment,
const char *fldname, int value)
{
char buffer[40]; /* FIXME: how many chars long a %d can become? */
cli_out_data *data = ui_out_data (uiout);
if (data->suppress_output)
return;
sprintf (buffer, "%d:%X", value, value);
cli_field_string (uiout, fldno, width, alignment, fldname, buffer);
Related
I'm working on following access violation:
Unhandled exception at 0x77DB2A10 (ntdll.dll) in <Process>.exe.dmp:
0xC0000005: Access violation reading location 0x184487B8. occurred
The source code looks as follows:
Result CParameter::SetValue(..., ..., <internal_Class>* pBlock, ...)
{
...
<internal_Class>* pStore = nullptr;
if (!pBlock)
{
pStore = &m_Data; // m_Data is a global variable
}
else pStore = pBlock;
if (pStore->pbData)
{
pStore->Clear(); // here we have the crash
}
The call stack looks as follows:
ntdll.dll!_RtlpCoalesceFreeBlocks#16() Unknown Non-user code. Symbols loaded.
ntdll.dll!#RtlpFreeHeap#16() Unknown Non-user code. Symbols loaded.
ntdll.dll!_RtlFreeHeap#12() Unknown Non-user code. Symbols loaded.
ole32.dll!CRetailMalloc_Free(IMalloc * pThis=0x777476bc, void * pv=0x1842de40) Line 687 C++ Non-user code. Symbols loaded.
ole32.dll!CoTaskMemFree(void * pv=0x1842de40) Line 475 C++ Non-user code. Symbols loaded.
=> <Process>.exe!CParameter::SetValue(..., <internal_Class> * pBlock=0x00000000, ...) Line 5528 C++ Symbols loaded.
Within the watch-window, I see the following value for &m_Data:
0x77e4f9ae {Inside ntdll.dll!_RtlpAnalyzeHeapFailure#12()} {pbData=0xd2b70f3d <Error reading characters of string.> ...}
More information:
The value of pBlock is NULL
The value of pStore is unknown by the debugger
Questions:
Where is the function "Clear()" in the call stack?
What about the value "RtlpAnalyzeHeapFailure" in the watch-window? Does it mean that my dump is that much corrupted that I can't get any useful information out of it?
Thanks in advance
Where is the function "Clear()" in the call stack?
This looks like it was inlined.
The value of pStore is unknown by the debugger
Isn't it still from m_Data?
If you look at the code near the crash point, you can see which register it has been in recently, and if it is preserved, then you should be able to see it saved at some point.
The error is due to the memory system detecting that the memory is being incorrectly freed. This may be that m_Data held a floating value, or had already been deleted.
I have produced a similar function.
__declspec(noinline) void Type::Clear()
{
delete pbData;
pbData = nullptr;
}
__declspec(noinline) void SetValue(Type * pBlock)
{
Type * pStore = nullptr;
if (!pBlock)
{
pStore = &m_Data; // m_Data is a global variable
}
else pStore = pBlock;
if (pStore->pbData)
{
pStore->Clear(); // here we have the crash
}
}
Its disassembly (from windbg) is :-
0:000:x86> uf debugging2!SetValue
debugging2!Type::Clear [c:\source\example\debugging2\debugging2.cpp # 17]:
17 01041020 56 push esi
17 01041021 8bf1 mov esi,ecx
18 01041023 6a00 push 0
18 01041025 ff36 push dword ptr [esi]
18 01041027 e85c000000 call debugging2!operator delete (01041088)
18 0104102c 83c408 add esp,8
19 0104102f c70600000000 mov dword ptr [esi],0
19 01041035 5e pop esi
20 01041036 c3 ret
debugging2!SetValue [c:\source\example\debugging2\debugging2.cpp # 23]:
23 01041040 833df833040100 cmp dword ptr [debugging2!m_Data (010433f8)],0
31 01041047 740a je debugging2!SetValue+0x13 (01041053)
Branch
debugging2!SetValue+0x9 [c:\source\example\debugging2\debugging2.cpp # 33]:
33 01041049 b9f8330401 mov ecx,offset debugging2!m_Data (010433f8)
33 0104104e e9cdffffff jmp debugging2!Type::Clear (01041020) Branch
debugging2!SetValue+0x13 [c:\source\example\debugging2\debugging2.cpp # 35]:
35 01041053 c3 ret Branch
This shows (in my case) the call to Clear() has been replaced by a jump, hiding it from the stack with an optimization.
This also shows that at address 01041049 ecx is loaded with the value for the call.
MSDN : x86 calling conventions
Ecx is not a preserved value, so we would not be able to find what value it held (other than it seems to be &m_Data from your comments).
But we can look at the functions up the stack...
In the ::Clear function ecx is moved to esi. So esi (which is preserved) now has the same value.
Looking at the next function (operator delete),
debugging2!operator delete
[f:\dd\vctools\crt\vcstartup\src\heap\delete_scalar_size.cpp # 14]:
14 01041088 55 push ebp
14 01041089 8bec mov ebp,esp
15 0104108b ff7508 push dword ptr [ebp+8]
15 0104108e e890030000 call debugging2!operator delete (01041423)
15 01041093 59 pop ecx
16 01041094 5d pop ebp
16 01041095 c3 ret
We see the esi is not changed, nor saved. So we look at the next function on the stack....
0:000:x86> uf 01041423
Flow analysis was incomplete, some code may be missing
debugging2!operator delete
[f:\dd\vctools\crt\vcstartup\src\heap\delete_scalar.cpp # 15]:
15 01041423 e982090000 jmp debugging2!free (01041daa) Branch
In each case we are looking for esi to be stored somewhere on the stack, so we can find it...
I have been wondering how V8 JavaScript Engine and any other JIT compilers execute the generated code.
Here are the articles I read during my attempt to write a small demo.
http://eli.thegreenplace.net/2013/11/05/how-to-jit-an-introduction
http://nullprogram.com/blog/2015/03/19/
I only know very little about assembly, so I initially used http://gcc.godbolt.org/ to write a function and get the disassembled output, but the code is not working on Windows.
I then wrote a small C++ code, compiled with -g -Og, then get disassmbled output with gdb.
#include <stdio.h>
int square(int num) {
return num * num;
}
int main() {
printf("%d\n", square(10));
return 0;
}
Output:
Dump of assembler code for function square(int):
=> 0x00000000004015b0 <+0>: imul %ecx,%ecx
0x00000000004015b3 <+3>: mov %ecx,%eax
0x00000000004015b5 <+5>: retq
I copy-pasted the output ('%' removed) to online x86 assembler and get { 0x0F, 0xAF, 0xC9, 0x89, 0xC1, 0xC3 }.
Here is my final code. if I compiled it with gcc, I always get 1. If I compiled it with VC++, I get random number. What is going on?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <windows.h>
typedef unsigned char byte;
typedef int (*int0_int)(int);
const byte square_code[] = {
0x0f, 0xaf, 0xc9,
0x89, 0xc1,
0xc3
};
int main() {
byte* buf = reinterpret_cast<byte*>(VirtualAlloc(0, 1 << 8, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE));
if (buf == nullptr) return 0;
memcpy(buf, square_code, sizeof(square_code));
{
DWORD old;
VirtualProtect(buf, 1 << 8, PAGE_EXECUTE_READ, &old);
}
int0_int square = reinterpret_cast<int0_int>(buf);
int ans = square(100);
printf("%d\n", ans);
VirtualFree(buf, 0, MEM_RELEASE);
return 0;
}
Note
I am trying to learn how JIT works, so please do not suggest me to use LLVM or any library. I promise I will use a proper JIT library in real project rather than writing from scratch.
Note: as Ben Voigt points out in the comments, this is really only valid for x86, not x86_64. For x86_64 you just have some errors in your assembly (which are still errors in x86 as well) as Ben Voigt points out as well in his answer.
This is happening because your compiler could see both sides of the function call when you generated your assembly. Since the compiler was in control of generating code for both the caller and the callee, it didn't have to follow the cdecl calling convention, and it didn't.
The default calling convention for MSVC is cdecl. Basically, function parameters are pushed onto the stack in the reverse of the order they're listed, so a call to foo(10, 100) could result in the assembly:
push 100
push 10
call foo(int, int)
In your case, the compiler will generate something like the following at the call site:
push 100
call esi ; assuming the address of your code is in the register esi
That's not what your code is expecting though. Your code is expecting its argument to be passed in the register ecx, not the stack.
The compiler has used what looks like the fastcall calling convention. If I compile a similar program (I get slightly different assembly) I get the expected result:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <windows.h>
typedef unsigned char byte;
typedef int (_fastcall *int0_int)(int);
const byte square_code[] = {
0x8b, 0xc1,
0x0f, 0xaf, 0xc0,
0xc3
};
int main() {
byte* buf = reinterpret_cast<byte*>(VirtualAlloc(0, 1 << 8, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE));
if (buf == nullptr) return 0;
memcpy(buf, square_code, sizeof(square_code));
{
DWORD old;
VirtualProtect(buf, 1 << 8, PAGE_EXECUTE_READ, &old);
}
int0_int square = reinterpret_cast<int0_int>(buf);
int ans = square(100);
printf("%d\n", ans);
VirtualFree(buf, 0, MEM_RELEASE);
return 0;
}
Note that I've told the compiler to use the _fastcall calling convention. If you want to use cdecl, the assembly would need to look more like this:
push ebp
mov ebp, esp
mov eax, DWORD PTR _n$[ebp]
imul eax, eax
pop ebp
ret 0
(DISCLAMER: I'm not great at assembly, and that was generated by Visual Studio)
I copy-pasted the output ('%' removed)
Well, that means your second instruction was
mov ecx, eax
which makes no sense at all (it overwrites the result of the multiplication with the uninitialized return value).
On the other hand
mov eax, foo
ret
is a very common pattern for ending a function with non-void return type.
The difference between your two assembly languages (AT&T style vs Intel style) is more than just the % marker, the operand order is reversed and pointers and offsets are denoted very differently as well.
You'll want to issue a set disassembly-flavor intel command in gdb
I am implementing mmap function using system call.(I am implementing mmap manually because of some reasons.)
But I am getting return value -14 (-EFAULT, I checked with GDB) whith this message:
WARN Nar::Mmap: Memory allocation failed.
Here is function:
void *Mmap(void *Address, size_t Length, int Prot, int Flags, int Fd, off_t Offset) {
MmapArgument ma;
ma.Address = (unsigned long)Address;
ma.Length = (unsigned long)Length;
ma.Prot = (unsigned long)Prot;
ma.Flags = (unsigned long)Flags;
ma.Fd = (unsigned long)Fd;
ma.Offset = (unsigned long)Offset;
void *ptr = (void *)CallSystem(SysMmap, (uint64_t)&ma, Unused, Unused, Unused, Unused);
int errCode = (int)ptr;
if(errCode < 0) {
Print("WARN Nar::Mmap: Memory allocation failed.\n");
return NULL;
}
return ptr;
}
I wrote a macro(To use like malloc() function):
#define Malloc(x) Mmap(0, x, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)
and I used like this:
Malloc(45);
I looked at man page. I couldn't find about EFAULT on mmap man page, but I found something about EFAULT on mmap2 man page.
EFAULT Problem with getting the data from user space.
I think this means something is wrong with passing struct to system call.
But I believe nothing is wrong with my struct:
struct MmapArgument {
unsigned long Address;
unsigned long Length;
unsigned long Prot;
unsigned long Flags;
unsigned long Fd;
unsigned long Offset;
};
Maybe something is wrong with handing result value?
Openning a file (which doesn't exist) with CallSystem gave me -2(-ENOENT), which is correct.
EDIT: Full source of CallSystem. open, write, close works, but mmap(or old_mmap) not works.
All of the arguments were passed well.
section .text
global CallSystem
CallSystem:
mov rax, rdi ;RAX
mov rbx, rsi ;RBX
mov r10, rdx
mov r11, rcx
mov rcx, r10 ;RCX
mov rdx, r11 ;RDX
mov rsi, r8 ;RSI
mov rdi, r9 ;RDI
int 0x80
mov rdx, 0 ;Upper 64bit
ret ;Return
It is unclear why you are calling mmap via your CallSystem function, I'll assume it is a requirement of your assignment.
The main problem with your code is that you are using int 0x80. This will only work if all the addresses passed to int 0x80 can be expressed in a 32-bit integer. That isn't the case in your code. This line:
MmapArgument ma;
places your structure on the stack. In 64-bit code the stack is at the top end of the addressable address space well beyond what can be represented in a 32-bit address. Usually the bottom of the stack is somewhere in the region of 0x00007FFFFFFFFFFF. int 0x80 only works on the bottom half of the 64-bit registers, so effectively stack based addresses get truncated, resulting in an incorrect address. To make proper 64-bit system calls it is preferable to use the syscall instruction
The 64-bit System V ABI has a section on the general mechanism for the syscall interface in section A.2.1 AMD64 Linux Kernel Conventions. It says:
User-level applications use as integer registers for passing the sequence %rdi, %rsi, %rdx, %rcx, %r8 and %r9. The kernel interface uses %rdi,
%rsi, %rdx, %r10, %r8 and %r9.
A system-call is done via the syscall instruction. The kernel destroys
registers %rcx and %r11.
We can create a simplified version of your SystemCall code by placing the systemcallnum as the last parameter. As the 7th parameter it will be the first and only value passed on the stack. We can move that value from the stack into RAX to be used as the system call number. The first 6 values are passed in the registers, and with the exception of RCX we can simply keep all the registers as-is. RCX has to be moved to R10 because the 4th parameter differs between a normal function call and the Linux kernel SYSCALL convention.
Some simplified code for demonstration purposes could look like:
global CallSystem
section .text
CallSystem:
mov rax, [rsp+8] ; CallSystem 7th arg is 1st val passed on stack
mov r10, rcx ; 4th argument passed to syscall in r10
; RDI, RSI, RDX, R8, R9 are passed straight through
; to the sycall because they match the inputs to CallSystem
syscall
ret
The C++ could look like:
#include <stdlib.h>
#include <sys/mman.h>
#include <stdint.h>
#include <iostream>
using namespace std;
extern "C" uint64_t CallSystem (uint64_t arg1, uint64_t arg2,
uint64_t arg3, uint64_t arg4,
uint64_t arg5, uint64_t arg6,
uint64_t syscallnum);
int main()
{
uint64_t addr;
addr = CallSystem(static_cast<uint64_t>(NULL), 45,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS,
-1, 0, 0x9);
cout << reinterpret_cast<void *>(addr) << endl;
}
In the case of mmap the syscall is 0x09. That can be found in the file asm/unistd_64.h:
#define __NR_mmap 9
The rest of the arguments are typical of the newer form of mmap. From the manpage:
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
If your run strace on your executable (ie strace ./a.out) you should find a line that looks like this if it works:
mmap(NULL, 45, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fed8e7cc000
The return value will differ, but it should match what the demonstration program displays.
You should be able to adapt this code to what you are doing. This should at least be a reasonable starting point.
If you want to pass the syscallnum as the first parameter to CallSystem you will have to modify the assembly code to move all the registers so that they align properly between the function call convention and syscall conventions. I leave that as a simple exercise to the reader. Doing so will yield a lot less efficient code.
I am doing a stack-smashing exercise for coursework, and I have already completed the assignment, but there is one aspect that I do not understand.
Here is the target program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int bar(char *arg, char *out)
{
strcpy(out, arg);
return 0;
}
void foo(char *argv[])
{
char buf[256];
bar(argv[1], buf);
}
int main(int argc, char *argv[])
{
if (argc != 2)
{
fprintf(stderr, "target1: argc != 2\n");
exit(EXIT_FAILURE);
}
foo(argv);
return 0;
}
Here are the commands used to compile it, on an x86 virtual machine running Ubuntu 12.04, with ASLR disabled.
gcc -ggdb -m32 -g -std=c99 -D_GNU_SOURCE -fno-stack-protector -m32 target1.c -o target1
execstack -s target1
When I look at the memory of this program on the stack, I see that buf has the address 0xbffffc40. Moreover, the saved frame pointer is stored at 0xbffffd48, and the return address is stored at 0xbffffd4c.
These specific addresses are not relevant, but I observe that even though buf only has length 256, the distance 0xbffffd48 - 0xbffffc40 = 264. Symbolically, this computation is $fp - buf.
Why are there 8 extra bytes between the end of buf and the stored frame pointer on the stack?
Here is some disassembly of the function foo. I have already examined it, but I did not see any obvious usage of that memory region, unless it was implicit (ie a side effect of some instruction).
0x080484ab <+0>: push %ebp
0x080484ac <+1>: mov %esp,%ebp
0x080484ae <+3>: sub $0x118,%esp
0x080484b4 <+9>: mov 0x8(%ebp),%eax
0x080484b7 <+12>: add $0x4,%eax
0x080484ba <+15>: mov (%eax),%eax
0x080484bc <+17>: lea -0x108(%ebp),%edx
0x080484c2 <+23>: mov %edx,0x4(%esp)
0x080484c6 <+27>: mov %eax,(%esp)
0x080484c9 <+30>: call 0x804848c <bar>
0x080484ce <+35>: leave
0x080484cf <+36>: ret
Basile Starynkevitch gets the prize for mentioning alignment.
It turns out that gcc 4.7.2 defaults to aligning the frame boundary to a 4-word boundary. On 32-bit emulated hardware, that is 16 bytes. Since the saved frame pointer and the saved instruction pointer together only take up 8 bytes, the compiler put in another 8 bytes after the end of buf to align the top of the stack frame to a 16 byte boundary.
Using the following additional compiler flag, the 8 bytes disappears, because the 8 bytes is enough to align to a 2-word boundary.
-mpreferred-stack-boundary=2
My application running on Mac OS X that needs to retrieve details about the machine it is running on to report for system information. One of the items I need is details about the processor(s) installed in the computer.
My code currently works, but is far from an ideal solution, in fact I consider it a bad solution, but I have had no luck in finding a better one.
The information I report currently and after some formatting looks like:
Processor: Intel Core 2 Duo 2.1 GHz, Family 6 Model 23 Stepping 6
All of the info I get is through command-line utilities called from a popen(). The readable part of the processor description is taken from the "system_profiler" command output and the Family, Model, and Stepping values are taken from the "sysctl" command.
These command-line utilities must be getting there information from somewhere. I'm wondering if there is an programmatic interface available to get this same info?
Related:
How can display driver version be obtained on the Mac?
Use sysctlbyname rather than sysctl, e.g.
#include <stdio.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/sysctl.h>
uint64_t get_cpu_freq(void)
{
uint64_t freq = 0;
size_t size = sizeof(freq);
if (sysctlbyname("hw.cpufrequency", &freq, &size, NULL, 0) < 0)
{
perror("sysctl");
}
return freq;
}
You can get a list of the names that can be passed to systctlbyname by looking at the output of sysctl -a from the command line.
You need to look at the IOKit APIs. The IORegistryExplorer application (part of the standard devtools installation) will help you locate what you're looking for.
For instance, on my MacBook Pro, in IORegistryExplorer I select 'IODeviceTree' from the pull-down at the top-left of the window, and I can see two CPUs in the tree view below. Selecting either one gets me the following information:
IORegistryExplorer screenshot http://blog.alanquatermain.net/images/IORegistryExplorer-CPUs.png
'bus-frequency' and 'clock-frequency', and 'timebase-frequency' are all 32-bit integers wrapper in data objects, and must therefore be byte-swapped to interpret here (little-endian i386 machine words), and work out to the following values:
bus-frequency: 1064000000 Hz => 1.064 GHz
clock-frequency:2530000000 Hz => 2.53 GHz
timebase-frequency: 1000000000 HZ => 1.0 GHz
If you're reading these via IOKit however, you'll get back a CFDataRef, and can just copy the bytes into your own uint32_t like so:
uint32_t bus_frequency = 0;
CFDataGetBytes( theData, (UInt8 *) &bus_frequency, sizeof(uint32_t) );
Next, you can get processor info using the NXArchInfo() call obtained by including <mach-o/arch.h>. This will return a structure containing cpu type and subtype codes along with C-string names and descriptions. If that doesn't include a stepping ID, the only way I can think of to obtain that (off the top of my head) is via the CPUID instruction. Create a .s and .h file, and put in the following code:
.s file:
#ifdef __i386__ || __x86_64__
.macro ENTRY
.text
.private_extern $0
.align 4, 0x90
$0:
.endmacro
// __private_extern__ unsigned long GetCPUSteppingID( void )
ENTRY _GetCPUSteppingID
push %ebp // store existing frame pointer
mov %esp,%ebp // make a new frame pointer from stack pointer
#if __x86_64__
push %rbx
#endif
push %ebx // we save %ebx because the cpuid instruction
// will overwrite it, and it's expected
// to be unchanged in the caller after
// calling another function
movl $1,%eax // fetch cpu info
cpuid // stepping-id is in low 4 bits of %edx now
and $0x0000000f,%edx // clear out everything we don't want
#if __x86_64__
mov %edx,%rax // %rax is 64-bit arch result register
#else
mov %edx,%eax // %eax is 32-bit arch result register
#endif
pop %ebx // restore saved value of %ebx
#if __x86_64__
pop %rbx // restore saved value of %rbx
#endif
leave // restores prior stack frame from %ebp
ret // returns to caller
#endif // __i386__ || __x86_64__
.h file:
#ifndef __GET_STEPPING_ID__
#define __GET_STEPPING_ID__
/* unsigned long is register-sized on both 32-bit and 64-bit OS X */
__private_extern__ unsigned long GetSteppingID( void );
#endif /* __GET_STEPPING_ID__ */
Please note that I'm not certain about the x86_64 bit above; in theory what I've typed there will ensure that the same code compiles for 64-bit, and will return a 64-bit value in that case. It will also save/restore the %rbx register, the 64-bit version of the %ebx register. Theoretically that will cover all bases.
sysctl(3) is probably a good place to start. You probably want the stuff defined by the CTL_HW selectors.
A variant of Paul R's method
#include <iostream>
#include <stdio.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/sysctl.h>
void show_cpu_info(void)
{
char buffer[1024];
size_t size=sizeof(buffer);
if (sysctlbyname("machdep.cpu.brand_string", &buffer, &size, NULL, 0) < 0) {
perror("sysctl");
}
std::cout << buffer << '\n';
}
will directly show something like Intel(R) Core(TM)2 Duo CPU L9400 # 1.86GHz.
If you specifically want CPU information then use cpuid (in C __asm cpuid) instruction. It gives all possible information of a CPU including its family, model, company, number of cores etc. Primarily all APIs use this instruction to retrieve CPU information. You can get detailed information on CPUID on the web, including sample code and tutorials.