Trying to read register values of a process from task_struct - c

Currently I'm able to find the register values for the program which was written, but not for other processes.
What I have written so far is is:
#include <linux/sched.h>
struct task_struct *task_list;
for_each_process(task_list){
register int* pc asm("%pc");
register int mar asm("%mar");
register int mdr asm("%mdr");
register int cir asm("%cir");
register int acc asm("%acc");
register int ir asm("%ir");
register int eax asm("%eax");
register int ebx asm("%ebx");
register int ecx asm("%ecx");
register int edx asm("%edx");
register int ip asm("%ip");
register int esp asm("%esp");
register int ebp asm("%ebp");
register int esi asm("%esi");
register int edi asm("%edi");
register int of asm("%of");
register int df asm("%df");
register int _if asm("%if");
register int tf asm("%tf");
register int sf asm("%sf");
register int zf asm("%zf");
register int af asm("%af");
register int pf asm("%pf");
register int cf asm("%cf");
}
I realize I need to use task_list and point to an element within the struct here, but I cannot seem to locate which element contains the registers.

You can access the registers from a task_struct using the macro task_pt_regs(). It yields a pointer to a struct pt_regs (definition) which is the saved copy of all the thread's registers from when it entered the kernel.
For example:
struct task_struct *t = /* find the one you want */ ;
unsigned long tasks_eax = task_pt_regs(t)->ax;
Note despite the name, the ax member is the full 32-bit eax register (on x86-32) or 64-bit rax register (on x86-64).
See also:
Get userspace RBP register from kernel syscall
Where is eax in the pt_regs struct? Only ax is present

Related

C99: compiler optimizations when accessing global variables and aliased memory pointers

I'm writing C code for an embedded system. In this system, there are memory mapped registers at some fixed address in the memory map, and of course some RAM where my data segment / heap is.
I'm finding problems generating optimal code when my code is intermixing accesses to global variables in the data segment and accesses to hardware registers. This is a simplified snippet:
#include <stdint.h>
uint32_t * const restrict HWREGS = 0x20000;
struct {
uint32_t a, b;
} Context;
void example(void) {
Context.a = 123;
HWREGS[0x1234] = 5;
Context.b = Context.a;
}
This is the code generated on x86 (see also on godbolt):
example:
mov DWORD PTR Context[rip], 123
mov DWORD PTR ds:149712, 5
mov eax, DWORD PTR Context[rip]
mov DWORD PTR Context[rip+4], eax
ret
As you can see, after having written the hardware register, Context.a is reloaded from RAM before being stored into Context.b. This doesn't make sense because Context is at a different memory address than HWREGS. In other words, the memory pointed by HWREGS and the memory pointed by &Context do not alias, but it looks like there is not way to tell that to the compiler.
If I change HWREGS definition as this:
extern uint32_t * const restrict HWREGS;
that is, I hide the fixed memory address to the compiler, I get this:
example:
mov rax, QWORD PTR HWREGS[rip]
mov DWORD PTR [rax+18640], 5
movabs rax, 528280977531
mov QWORD PTR Context[rip], rax
ret
Context:
.zero 8
Now the two writes to Context are optimized (even coalesced to a single write), but on the other hand the access to the hardware register does not happen anymore with a direct memory access but it goes through a pointer indirection.
Is there a way to obtain optimal code here? I would like GCC to know that HWREGS is at a fixed memory address and at the same time to tell it that it does not alias Context.
If you want to avoid compilers reloading regularly values from a memory region (possibly due to aliasing), then the best is not to use global variables, or at least not to use direct accesses to global variables. The register keyword seems ignored for global variables (especially here on HWREGS) for both GCC and Clang. Using the restrict keyword on function parameters solves this problem:
#include <stdint.h>
uint32_t * const HWREGS = 0x20000;
struct Context {
uint32_t a, b;
} context;
static inline void exampleWithLocals(uint32_t* restrict localRegs, struct Context* restrict localContext) {
localContext->a = 123;
localRegs[0x1234] = 5;
localContext->b = localContext->a;
}
void example() {
exampleWithLocals(HWREGS, &context);
}
Here is the result (see also on godbolt):
example:
movabs rax, 528280977531
mov DWORD PTR ds:149712, 5
mov QWORD PTR context[rip], rax
ret
context:
.zero 8
Please note that the strict aliasing rule do not help in this case since the type of read/written variables/fields is always uint32_t.
Besides this, based on its name, the variable HWREGS looks like a hardware register. Please note that it should be put volatile so that compiler do not keep it to registers nor perform any similar optimization (like assuming the pointed value is left unchanged if the code do not change it).

Can I get RIP address in C?

Basically I am trying to get RSP, RBP and RIP addresses into pointers.
Code:
#include <stdio.h>
int main()
{
char buf[500];
int *rsp;
int *rbp;
int *rip;
strcpy(buf, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
ptr = buf;
printf("[buf:%p:%s]\n[rsp:%p:%s]\n", &buf, buf, rsp, rsp);
return 0;
}
The above pointer works just fine while getting the RSP address. But I don't know how to get the RBP and RIP addresses.
Can you tell me how can I point *rbp to RBP address and *rip to RIP address?
Current x86 hardware doesn't work that way, so you cannot get the address of the any register - it just doesn't have one.
What does it mean?
It means you can get the value of each register but you cannot get the address of the registers - they have none.
For instance, if you do at the beginning of a function the following, you'll get the address your RIP is pointing to.
void foo(param a, param b)
{
int dummy;
int* rip = &dummy;
}
But note that you this won't be accessible outside this function.

getvect function is undefined

I am trying to run this program. It uses the interrupts and when we press w, it replace it by s in keyboard buffer
#include "stdafx.h"
#include "stdio.h"
#include "bios.h"
#include <dos.h>
void interrupt_oldint15(*oldint15);
void interrupt_newint15(unsigned int BP, unsigned int DI, unsigned int SI, unsigned int DS,
unsigned int ES, unsigned int DX, unsigned int CX, unsigned int BX,
unsigned int AX, unsigned int IP, unsigned int CS, unsigned int flags);
void main ( )
{
oldint15 = getvect (0x15);
setvect (0x15, newint15);
keep (0, 1000);
}
void interrupt_newint15 (unsigned int BP, unsigned int DI, unsigned int SI, unsigned int DS, unsigned int ES, unsigned int DX, unsigned int CX, unsigned int BX, unsigned int AX, unsigned int IP, unsigned int CS, unsigned int flags )
{
if(*((char*)&AX)==0x11)
*((char*)&AX)=0x1F;
else if(*((char*)&AX)==0x1F)
*((char*)&AX)=0x11;
}
but it gives the error in getvect and setvect functions.
for one thing, interrupt functions, in C, do not have parameters, nor a returned value.
Listing all the registers is a waste of space (besides which it should not compile) as the entry into a interrupt event causes a saving of all the key registers (typically on the stack of the currently running process)
All the key registers (like the PC and Status registers) are restored upon exit from the interrupt.
The compiler will cause any general purpose registers changed in the interrupt function to be saved/restored.) If you are working at such a low level, then you should know exactly where the interrupt vectors are located, you should have a code segment that overlays the interrupt vectors and another code segment that mirrors the interrupt vectors.
Then, you copy the current set of interrupt vectors to the mirror and then replace the desired individual vector with a pointer to the interrupt function you wrote. At the end of your code, you need to copy the vector back into the original vector area.
It could be that functions you are having trouble with do those operations for you.
this, from a very old post, from a c.comp news group may be helpful:
You are mixing languages. In Borland C an "interrupt" has type
void (interrupt*)()
while in Borland C++ it has type
void (interrupt*)(...)
This affects the parameter type of setvect and the return type of
getvect which change in the same way according to the language used.
You obviously compiled your program as a C++ program and not as a C
program because according to the compiler's message 'oldvec' is
declared as a "C interrupt" and getvect returns a "C++ interrupt".
the format for using get/set vect() in C, which look nothing like your C++ example is:
tick_isr_old = getvect(0x08);
setvect(0x08, (void interrupt (*)(void)) tick_isr);
As mentioned already, the functions getvect() and setvect() are only available with Borland/Turbo C++. The functions _dos_getvect() and _dos_setvect() are almost identical and offer better portability across compilers (Borland/Turbo C++, MS Visual C++ 1.x, Open Watcom C++). They should be defined in <dos.h>.
Here is an example of their use (prints an '#' every second):
/*** Includes ***/
#include <stdint.h> // int*_t, uint*_t
#include <stdbool.h> // bool, true, false
#include <dos.h> // _chain_intr(), _dos_getvect() , _dos_setvect()
#include <stdio.h> // putchar()
/*** Definitions ***/
#define TICKS_PER_SEC 18ul
#define VECT_TIMER 0x1C
/*** Global Variables ***/
bool timer_hooked = false;
bool timer_1sec_elapsed = false;
uint32_t ticks = 0;
void (interrupt far * OrigTimerH)( ); // vector to original 0x1C handler
/*** Functions ***/
static void interrupt far TimerH( void ) {
ticks++;
if ( ticks % TICKS_PER_SEC == 0 ) {
timer_1sec_elapsed = true;
}
_chain_intr( OrigTimerH ); // handler callback
}
void TimerStart( void ) {
__asm { cli } // critical section; halt interrupts
OrigTimerH = _dos_getvect( VECT_TIMER ); // save original vector
_dos_setvect( VECT_TIMER, TimerH ); // put our handler in the vector
timer_hooked = true; // remember that we're hooked if we wanted to unhook
__asm { sti } // resume interrupts
}
int main( void ) {
TimerStart();
while ( true ) {
if ( timer_1sec_elapsed ) {
timer_1sec_elapsed = false;
putchar('#');
}
}
}

Save CPU registers to variables in GCC

I want get the values in EAX/EBX/ESP/EIP etc. and save them in C variables. For example:
int cEax;
asm("mov cEax,%eax"); ...
You can use this
register int eax asm("eax");
register int eax asm("ebx");
register int eax asm("esp");
//...
int cEax = eax;
int cEbx = ebx;
int cEsp = esp;
//...
You can also work with those registers in an expression just as any other variables or just use that register's value directly without assigning to another variable.
It's more tricky to get eip without inline assembly but in gcc you can get it with __builtin_return_address or the label as values extension.
void* getEIP()
{
return __builtin_return_address(0);
}
void *currentInstruction = getEIP();
currentAddr: void *nextInstruction = &&currentAddr;
If you want inline assembly you can use the way in this page

How do I get info from the stack, using inline assembly, to program in c?

I have a task to do and I'm asking for some help. (on simple c lang')
What I need to do?
I need to check every command on the main c program (using interrupt num 1) and printing a message only if the next command is the same procedure that was sent earlier to the stack, by some other procedure.
What I want to do?
I want to take info from the stack, using inline assembley, and put it on a variable that can be compare on c program itself after returnning to c. (volatile)
This is the program:
#include <stdio.h>
#include <dos.h>
#include <conio.h>
#include <stdlib.h>
typedef void (*FUN_PTR)(void);
void interrupt (*Int1Save) (void); //pointer to interrupt num 1//
volatile FUN_PTR our_func;
char *str2;
void interrupt my_inter (void) //New interrupt//
{volatile FUN_PTR next_command;
asm { PUSH BP
MOV BP,SP
PUSH AX
PUSH BX
PUSH ES
MOV ES,[BP+4]
MOV BX,[BP+2]
MOV AX,ES:[BX]
MOV word ptr next_command,AX
POP ES
POP BX
POP AX
pop BP}
if (our_func==next_command) printf("procedure %s has been called\n",str2);}
void animate(int *iptr,char str[],void (*funptr)(), char fstr[])
{
str2=fstr;
our_func=funptr;
Int1Save = getvect(1); // save old interrupt//
setvect(1,my_inter);
asm { pushf //TF is ON//
pop ax
or ax,100000000B
push ax
popf}}
void unanimate()
{asm { pushf //TF is OFF//
pop ax
and ax,1111111011111111B
push ax
popf}
setvect (1,Int1Save); //restore old interrupt//}
void main(void)
{int i;
int f1 = 1;
int f2 = 1;
int fibo = 1;
animate(&fibo, "fibo", sleep, "sleep");
for(i=0; i < 8; i++)
{
sleep(2);
f1 = f2;
f2 = fibo;
fibo = f1 + f2;} // for//
unanimate();} // main//
My question...
Off course the problem is at "my inter" on the inline assembly. but can't figure it out.
What am I doing wrong? (please take a look at the code above)
I wanted to save the address of the pointer for the specific procedure (sleep) in the volatile our_func. then take the info (address to each next command) from the stack to volatile next_command and then finaly returnning to c and make the compare each time. If the same value (address) is on both variables then to print a specific message.
Hope I'm clear..
10x,
Nir B
Answered as a comment by the OP
I got the answer I wanted:
asm { MOV SI,[BP+18] //Taking the address of each command//
MOV DI,[BP+20]
MOV word ptr next_command+2,DI
MOV word ptr next_command,SI}
if ((*our_func)==(*next_command)) //Making the next_command compare//
printf("procedure %s has been called\n",str2);

Resources