What are stacks in DRAM (what happens during recursion)? - recursion

I just want to get a better understanding of what a stack is in the address space (i.e you have code/text, heap, data, and a stack)
basically my understanding is that a stack contains local variables, but then what is the difference between what the data contains and what a stack contains? isn't data variables as well?
If a program has a recursive call to a function a() does it mean that for every level of recursion there is a new stack?

A stack is usually different to data only in the way it's used and managed. While non-local variables themselves usually have a known specific memory location, things on the stack are found relative to a register (stack pointer or base pointer or some such).
A stack usually contains local variables, passed parameters and control information for managing the stack itself.
And, if you make a recursive call, you don't get a new stack, just a new stack frame. A frame is a chunk of the stack relevant to the current stack depth (whether that's by recursion or just regular function calls). That's what makes recursion possible, the fact that the variables for a given depth are independent of those for other depths.
Keep in mind that this is all dependent, of course, on the architecture. My description above is a common case but there are architectures where stacks are done differently, such as SPARC, the System z and RCA1802.
More details can be found here (how frames work) and here (weird stacks).

First, a small clarification. Stacks are not necessarily in DRAM. they are just a structure that can be formed in any memory: DRAM, caches, disk.
To understand a stack, you should first understand what is a stack. It is like a stack of trays, the properties that make it a stack are:
You can only access the top element of the stack
It is Last In First Out, i.e., when you go to get a data from a stack you get the data that was stored last on the stack.
The act of storing something in a stack is called PUSH and removing it is called a POP. Say I do the following to an empty stack:
PUSH A
PUSH B
PUSH C
Then the stack will contain
C - Top
B
A
Now if I execute a POP (notice there is no operand here), it will return C and the stack will contain
B -- top of stack
A
So stack in processors is just a hardware implementation of the above algorithm.
A register contains the address of the top of stack called stack point
The ISA (Instruction Set Architecture) provides PUSH and POP instructions to access the stack variables as I showed above.
This is a very useful construct. A stack is used to store local variables, basically temporary data that you want to remove at the end of a function call. It specifically helps with function calls. When a function is called, the variables of the newly called function's local variables are pushed on the stack.
foo(){
int a;
int b; // both registers containing a and b are PUSHed here on the stack
c = bar(); // pop the stack to get value of c
print c
}
bar(){
int z; // local variables pushed on top of the stack
z = ...
return z; // pop all local variables of bar(), then push z on the stack
}
I hope the above helps.

The following program should help you understand what is going on. You will see pointer examples of text, bss, heap, and stack. Text is usually executable code, bss are static/global variables, heap is dynamically allocated memory, stack contains local variables.
#include <stdlib.h>
#include <stdio.h>
#define TESTS 10
int numfeed = 0;
int numdead = 0;
recurse(int x)
{
u_int pattern=0xfeedface;
u_int *otherpattern = malloc(4);
*otherpattern = 0xdeadbeef;
printf("Feedface %d is at %p\n",x,&pattern);
printf("deadbeef %d is at %p\n",x,otherpattern);
if (--x == 0)
{
int *off;
for(off = &pattern;numfeed<TESTS;off++)
{
if (*off == 0xfeedface)
printf("Found feedface #%d at %p\n", ++numfeed, off);
if (*off == 0xdeadbeef)
printf("Found deadbeef #%d at %p -- WHAT?!?!!?!?\n", ++numdead, off);
}
}
else
{
recurse(x);
}
// Not freeing otherpattern intentionally.
}
main()
{
u_int *otherpattern = malloc(4);
*otherpattern = 0xdeadbeef;
int *off;
recurse(TESTS);
for(off = otherpattern+1;numdead<TESTS;off++)
{
if (*off == 0xfeedface)
printf("Found feedface #%d at %p -- WHAT?!?!!!?!?\n", ++numfeed, off);
if (*off == 0xdeadbeef)
printf("Found deadbeef #%d at %p\n", 1+TESTS-(++numdead), off);
}
printf("numfeed is at %p\n",&numfeed);
printf("recurse is at %p\n",&recurse);
}

Related

Finding pointer with 'find out what writes to this address' strange offset

I'm trying to find a base pointer for UrbanTerror42.
My setup is as followed, I have a server with 2 players.
cheat-engine runs on client a.
I climb a ladder with client b and then scan for incease/decrease.
When I have found the values, I use find out what writes to this address.
But the offset are very high and point to empty memory.
I don't really know how to proceed
For the sake of clarity, I have looked up several other values and they have the same problem
I've already looked at a number of tutorials and forums, but that's always about values where the offsets are between 0 and 100 and not 80614.
I would really appreciate it if someone could tell me why this happened and what I have to do/learn to proceed.
thanks in advance
Urban Terror uses the Quake Engine. Early versions of this engine use the Quake Virtual Machine and the game logic is implemented as bytecode which is compiled into assembly by the Quake Virtual Machine. Custom allocation routines are used to load these modules into memory, relative and hardcoded offsets/addresses are created at runtime to accommodate these relocations and do not use the normal relocation table method of the portable executable file format. This is why you see these seemingly strange numbers that change every time you run the game.
The Quake Virtual Machines are file format .qvm and these qvms in memory are tracked in the QVM table. You must find the QVM table to uncover this mystery. Once you find the 2-3 QVMs and record their addresses, finding the table is easy, as you're simply doing a scan for pointers that point to these addresses and narrowing down your results by finding those which are close in memory to each other.
The QVM is defined like:
struct vmTable_t
{
vm_t vm[3];
};
struct vm_s {
// DO NOT MOVE OR CHANGE THESE WITHOUT CHANGING THE VM_OFFSET_* DEFINES
// USED BY THE ASM CODE
int programStack; // the vm may be recursively entered
intptr_t(*systemCall)(intptr_t *parms);
//------------------------------------
char name[MAX_QPATH];
// for dynamic linked modules
void *dllHandle;
intptr_t entryPoint; //(QDECL *entryPoint)(int callNum, ...);
void(*destroy)(vm_s* self);
// for interpreted modules
qboolean currentlyInterpreting;
qboolean compiled;
byte *codeBase;
int codeLength;
int *instructionPointers;
int instructionCount;
byte *dataBase;
int dataMask;
int stackBottom; // if programStack < stackBottom, error
int numSymbols;
struct vmSymbol_s *symbols;
int callLevel; // counts recursive VM_Call
int breakFunction; // increment breakCount on function entry to this
int breakCount;
BYTE *jumpTableTargets;
int numJumpTableTargets;
};
typedef struct vm_s vm_t;
The value in EAX in your original screenshot should be the same as either the codeBase or dataBase member variable of the QVM structure. The offsets are just relative to these addresses. Similarly to how you deal with ASLR, you must calculate the addresses at runtime.
Here is a truncated version of my code that does exactly this and additionally grabs important structures from memory, as an example:
void OA_t::GetVM()
{
cg = nullptr;
cgs = nullptr;
cgents = nullptr;
bLocalGame = false;
cgame = nullptr;
for (auto &vm : vmTable->vm)
{
if (strstr(vm.name, "qagame")) { bLocalGame = true; continue; }
if (strstr(vm.name, "cgame"))
{
cgame = &vm;
gamestatus = GSTAT_GAME;
//char* gamestring = Cvar_VariableString("fs_game");
switch (cgame->instructionCount)
{
case 136054: //version 88
cgents = (cg_entities*)(cgame->dataBase + 0x1649c);
cg = (cg_t*)(cgame->dataBase + 0xCC49C);
cgs = (cgs_t*)(cgame->dataBase + 0xf2720);
return;
Full source code for reference available at OpenArena Aimbot Source Code, it even includes a video overview of the code.
Full disclosure: that is a link to my website and the only viable resource I know of that covers this topic.

Understanding the method for OpenCL reduction on float

Following this link, I try to understand the operating of kernel code (there are 2 versions of this kernel code, one with volatile local float *source and the other with volatile global float *source, i.e local and global versions). Below I take local version :
float sum=0;
void atomic_add_local(volatile local float *source, const float operand) {
union {
unsigned int intVal;
float floatVal;
} newVal;
union {
unsigned int intVal;
float floatVal;
} prevVal;
do {
prevVal.floatVal = *source;
newVal.floatVal = prevVal.floatVal + operand;
} while (atomic_cmpxchg((volatile local unsigned int *)source, prevVal.intVal, newVal.intVal) != prevVal.intVal);
}
If I understand well, each work-item shares the access to source variable thanks to the qualifier "volatile", doesn't it?
Afterwards, if I take a work-item, the code will add operand value to newVal.floatVal variable. Then, after this operation, I call atomic_cmpxchg function which check if previous assignment (preVal.floatVal = *source; and newVal.floatVal = prevVal.floatVal + operand; ) has been done, i.e by comparing the value stored at address source with the preVal.intVal.
During this atomic operation (which is not uninterruptible by definition), as value stored at source is different from prevVal.intVal, the new value stored at source is newVal.intVal, which is actually a float (because it is coded on 4 bytes like integer).
Can we say that each work-item has a mutex access (I mean a locked access) to value located at source address.
But for each work-item thread, is there only one iteration into the while loop?
I think there will be one iteration because the comparison "*source== prevVal.int ? newVal.intVal : newVal.intVal" will always assign newVal.intVal value to value stored at source address, won't it?
I have not understood all the subtleties of this trick for this kernel code.
Update
Sorry, I almost understand all the subtleties, especially in the while loop :
First case : for a given single thread, before the call of atomic_cmpxchg, if prevVal.floatVal is still equal to *source, then atomic_cmpxchg will change the value contained in source pointer and return the value contained in old pointer, which is equal to prevVal.intVal, so we break from the while loop.
Second case : If between the prevVal.floatVal = *source; instruction and the call of atomic_cmpxchg, the value *source has changed (by another thread ??) then atomic_cmpxchg returns old value which is no more equal to prevVal.floatVal, so the condition into while loop is true and we stay in this loop until previous condition isn't checked any more.
Is my interpretation correct?
If I understand well, each work-item shares the access to source variable thanks to the qualifier "volatile", doesn't it?
volatile is a keyword of the C language that prevents the compiler from optimizing accesses to a specific location in memory (in other words, force a load/store at each read/write of said memory location). It has no impact on the ownership of the underlying storage. Here, it is used to force the compiler to re-read source from memory at each loop iteration (otherwise the compiler would be allowed to move that load outside the loop, which breaks the algorithm).
do {
prevVal.floatVal = *source; // Force read, prevent hoisting outside loop.
newVal.floatVal = prevVal.floatVal + operand;
} while(atomic_cmpxchg((volatile local unsigned int *)source, prevVal.intVal, newVal.intVal) != prevVal.intVal)
After removing qualifiers (for simplicity) and renaming parameters, the signature of atomic_cmpxchg is the following:
int atomic_cmpxchg(int *ptr, int expected, int new)
What it does is:
atomically {
int old = *ptr;
if (old == expected) {
*ptr = new;
}
return old;
}
To summarize, each thread, individually, does:
Load current value of *source from memory into preVal.floatVal
Compute desired value of *source in newVal.floatVal
Execute the atomic compare-exchange described above (using the type-punned values)
If the result of atomic_cmpxchg == newVal.intVal, it means the compare-exchange was successful, break. Otherwise, the exchange didn't happen, go to 1 and try again.
The above loop eventually terminates, because eventually, each thread succeeds in doing their atomic_cmpxchg.
Can we say that each work-item has a mutex access (I mean a locked access) to value located at source address.
Mutexes are locks, while this is a lock-free algorithm. OpenCL can simulate mutexes with spinlocks (also implemented with atomics) but this is not one.

realloc() invalid pointer glibc error

I'm new to pointers and realloc. I know what is going wrong, but I don't know how to solve it.
I create a struct with an array of pointers:
struct DB_SLOT
{
MYSQL *MYSQL_Connection[10];
char *DB_NAME_Connection[10];
};
struct DB_SLOT DB_Conn_SLOT;
I allocate memory with realloc in a loop and (this is where it is getting wrong) I print the address of pointer 2 on the screens.
If I then try to realloc the same amount of memory (just for test purposes). it gives a glibc invalid pointer. Before realloc I print the address of pointer 2 again and it is not the same.
The code for this:
int MallocLoop;
for (MallocLoop = 0;MallocLoop < 10;MallocLoop++)
{
DB_Conn_SLOT.MYSQL_Connection[MallocLoop] = realloc(DB_Conn_SLOT.MYSQL_Connection[MallocLoop],(sizeof(MYSQL)));
DB_Conn_SLOT.DB_NAME_Connection[MallocLoop]=realloc(DB_Conn_SLOT.DB_NAME_Connection[MallocLoop],(sizeof(char)));
if (MallocLoop == 2)
{
printf("pointer 1 %d \n",DB_Conn_SLOT.DB_NAME_Connection[MallocLoop]);
}
DB_Conn_SLOT.DB_NAME_Connection[MallocLoop] ="\0";
}
MallocLoop = 2;
printf("pointer 2 %d \n",DB_Conn_SLOT.DB_NAME_Connection[MallocLoop]);
DB_Conn_SLOT.DB_NAME_Connection[MallocLoop] = realloc(DB_Conn_SLOT.DB_NAME_Connection[MallocLoop], (sizeof(char)));
The result of printing the address of the pointer results in 2 different addresses. How do i solve this??
You have the following two lines:
DB_Conn_SLOT.DB_NAME_Connection[MallocLoop]=realloc(...); ...
DB_Conn_SLOT.DB_NAME_Connection[MallocLoop] ="\0";
Let's simplify this to:
p = realloc(...);
p = "\0";
The first line makes p point at dynamically allocated memory block. The second line leaks that memory (you no longer have a pointer to it), and makes p point to a block of memory inside the .data section.
When you loop again, and pass the .data pointer to realloc, it correctly complains: it is not valid to pass non-dynamically allocated memory to realloc.
What you probably wanted to do was this:
p = realloc(...);
p[0] = '\0';
That makes p point to a dynamically allocated memory block, and makes that block be an empty string.

passing pointer to SDL function

I'm trying to understand why method1 works, and method2 doesnt work, when I'm passing "offset" to SDL_BlitSurface function.
USAGE:
int SDL_BlitSurface(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect);
In my mind, both should work, since SDL_BlitSurface function asks SDL_Rect* as the 4th input argument. And in both cases I have passed a SDL_Rect* to the function. However method2 yields "Unhandled exception Access violation writing location error". Please help!
method1:
SDL_Rect offset;
offset.x = 1;
SDL_BlitSurface( source, NULL, destination, &offset );
method2:
SDL_Rect* offset = NULL;
offset->x = 1;
SDL_BlitSurface( source, NULL, destination, offset );
(Code from Lazy Foo's tutorial Lesson 2)
A pointer variable (like offset) holds an address, just like a house address.
The structure tells the computer who lives in the house in each room (the rooms have names, for example x).
The problem is that you first say: "offset is a fake address (call it NULL)." and then you say "and in room x lives 1". So this doesn't make sense - the number 1 can live in room x only if the address is real. Nobody can live in a fake address.
Unfortunately, you can write whatever you want in the code. Only when you run it and try to put 1 in room x the computer shouts. "Access violation" basically means: "you're trying to put some data in an address that you don't have access to". In this case, the fake address NULL is not an address you can store anything in.
If you follow Armin's suggestion, then offset will point to a valid address, and that will allow you to store 1 in the room x. Method 1 solves the problem by passing the address of a pre-allocated structure offset (it's allocated automatically by the compiler on the stack).
In the second case you haven't reserved any memory for offset since SDL_Rect* offset is just a pointer, you have to allocate memory for it to point to something:
Example in c:
SDL_Rect* offset = malloc( sizeof( SDL_Rect ) );
Then you second method will work.

Problems with a structure copy

I am having a compiler issue in Visual Studio 2005 using the standard C compiler when trying to do a structure copy from one location to another.
The types are defined in a file as follows:
definition.h
#define MAX 7
typedef struct{
char recordtext[18];
boolean recordvalid;
}recordtype;
typdef recordtype tabletype[MAX];
typedef struct{
tabletype table;
}global_s;
Let us pretend that a global_s "object" is instantiated and initialized somewhere and a pointer to this structure is created.
#include "definition.h"
global_s global;
global_s* pglobal = &global;
init(&pglobal);
Meanwhile, in another file (and this is where my problem is) i am trying to create a local tabletype object, and fill it with the global table member, using a get method to protect the global (lets pretend it is "static")
#include "definition.h"
extern global_s* pglobal;
tabletype t;
gettable(&t);
void gettabl (tabletype* pt)
{
*pt = pglobal->table;
}
When I go to compile, the line in the gettable function throws a compiler error "error C2106: '=': left operand must be l-value. It looks as though this should behave as a normal copy operation, and in fact if I perform a similar operation on a more basic structure I do not get the error. For example If I copy a structure only containing two integers.
Does anyone have a solid explanation as to why this operation seems to be incorrect?
(Disclaimer: I have developed this code as a scrubbed version of my actual code for example purposes so it may not be 100% correct syntactically, I will edit the question if anyone points out an issue or something needs to be clarified.)
It's the arrays in the struct; they cannot be assigned. You should define an operator=() for each of the structs, and use memcpy on the arrays, or copy them in a loop element by element.
(IF you want to get a reference to your global variable):
I am not sure, if this is correct (and the problem), but I think besides function prototypes, arrays and pointers (to arrays 1. element) are NOT exactly the same thing. And there is a difference between pointer to array and pointer to the 1. element of an array)
Maybe taking the adress of the array:
*pt = &(pglobal->table);
Anyway it might be better not to fetch the address of the whole array but the address of the first element, so that the resulting pointer can be used directly as record array (without dereferencing it)
recordtype* gettable (size_t* puLength)
{
*puLength = MAX;
return &(pglobal->table[0]);
}
(IF you want a copy of the table):
Arrays can't be copied inplace in C90, and of course you have to provide target memory. You would then define a function get table like this:
void gettable (recordtype * const targetArr)
{
size_t i = 0;
for (; i < MAX; i++) targetArr[i] = pglobal->table[i];
return;
}
an fully equivalent function prototype for gettable is:
void gettable(recordtype[] targetArr);
Arrays are provided by refernce as pointer to the first element, when it comes to function parameters. You could again ask for an pointer to the whole array, and dereference it inside gettable. But you always have to copy elementwise.
You can use memcopy to do the job as 1-liner. Modern compilers should generate equally efficent code AFAIK.

Resources