AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Snippets and Tutorials (https://forums.alliedmods.net/forumdisplay.php?f=112)
-   -   [INC] valist.inc Variable arguments function (https://forums.alliedmods.net/showthread.php?t=300303)

Kailo 08-12-2017 10:46

[INC] valist.inc Variable arguments function
 
1 Attachment(s)
Update: 2.0 released. Check changelog below.
How? Dark Magic!

Used a few tricks i created functions for variable arguments access.

This workable only with non-array variables for now (write if it needed to add arrays/strings support).

Instruction:
1) Include valist.inc in plugin with #include directive (You must include it first among all includes for proper work).
2) Call va_start(int param_n) in variable argument function, where param_n number of argument with ..., counting of arguments start with 1.
Note for 1st version: It's important call va_start before any variable will declared. Overwise, it'll work not correct.
(In 1st version need to call va_start first in function, in 2nd not).
3) For getting next argument use va_arg(). In case if no more arguments to get, it'll throw error.
You can use va_args() for getting count of params passed in function and va_more() to check if all arguments getted.
4) When you no more needed to get arguments, you must call va_end(). Overwise, memory leaks.

Offtop: Please, if you see any grammar mistakes, notice me about it. I'm not going well in English.

Plugin example:
PHP Code:

// © Maxim "Kailo" Telezhenko, 2017

#pragma newdecls required
#pragma semicolon 1

#include <valist>

public void OnPluginStart()
{
    
RegConsoleCmd("sm_nums"Cmd_Nums);
}

public 
Action Cmd_Nums(int clientint args)
{
    
ReplyToCommand(client"Sum: %i"Sum(104050, -3080));

    return 
Plugin_Handled;
}

int Sum(int ...)
{
    
va_start(1);
    
PrintToServer("args: %i"va_args());
    
int sum 0;
    while (
va_more())
        
sum += va_arg();
    
va_end();
    return 
sum;


valist.inc code


Attention!
1st version not working in 1.9 since sourcepawn "Disallow negative indices in all array access patterns" (d7743c3) update.

Changelog:
v2: Changelog
v1: First release.

// Download latest version below in attachments.
Old versions:
v1: valist.inc

How i did this: (tricks)
1) Unchecked memory access
Then you pass array as param, plugin know only address and check index for negative value
PHP Code:

{
    
int array[1];
    
int var1 50;
    
PrintToServer("%i %i"Fn(array), var1);
}

int Fn(int[] array)
{
    return array[
1]; // will return var1 value


2) Knowledge of SourcePawn virtual machine
Plugin memory сonsists of DAT (globals, statics, consts), heap, stack (order as i wrote).
When functions calls:
1) Pass arguments in reverse order
2) Pass num of arguments
3) pass old frame address
4) pass 0
Using sipmle trick i can dump stack
PHP Code:

void Fn()
{
    
int a[1] = {777};
    
dumpstack(a);
}

stock void dumpstack(int[] anchor)
{
    for (
int a 0<= 15a++)
        
PrintToServer("%i: %i"aanchor[a]);


Using this in process of writing include i got ():
Code:

etc.
-8: 2220  // unused memory
-7: 20780 // unused memory
-6: 20776 // unused memory
-5: -5      // value of a
-4: 0        // just 0
-3: 20804 // old frame // for example look at {1}
-2: 1        // param count
-1: 20800 // 1st param; address of a // Here is started vm_start() call
0: 666    // a[1] = {666} // address of this array is 20800
/// {1} Here beging frame of vm_start(), here address is 20804
1: 0        // just 0
2: 20824 // old frame
3: 1        // param count
4: 1        // 1st param // Here is started vm_start() call
5: 0        // Valist VALIST variable
6: 0        // just 0
7: 20856 // old frame
8: 5        // arg count in Sum call
9: 2264  // 1st param
10: 2260 // 2nd param
11: 2256 // 3rd param
12: 2252 // 4th param
13: 2248 // 5th param // Here is started Sum() call; All 5 params is heap address
14: 2236 // this heap addr of where will stored result of Sum() for call ReplyToCommand in future
15: 20876  // this  addr of "Sum: %i" for call ReplyToCommand in future

All addresses is local for plugin memory.
Also as we see stack reversed in memory.
memory: DAT-start ... DAT-end, heap-start ... heap-end, stack-end ... stack-start;
3) pseudo-class based on methodmap + ArrayList
4) Some macros for good looking code

Deathknife 08-13-2017 13:27

Re: [INC] valist.inc Variable arguments function
 
This is awesome! :bacon!::bacon!::crab:

zipcore 08-14-2017 06:37

Re: [INC] valist.inc Variable arguments function
 
Yay n1

Kailo 09-11-2017 02:21

Re: [INC] valist.inc Variable arguments function
 
Not working in 1.9 since sourcepawn "Disallow negative indices in all array access patterns" (d7743c3) update.

Kailo 12-09-2017 15:27

Re: [INC] valist.inc Variable arguments function
 
New version! Now work with 1.9!

v2 changelog:
1) Now working with 1.9:
Code with negative indexes changed to trick: include declare global variable in start of DAT -> variable has low address -> get variable address -> use trick 1 with offset with difference between addresses
2) Changed way to get address and number params -> va_start no more needed to be called first in function.
3) All variables and functions marked as stocks for not including then not used.


All times are GMT -4. The time now is 23:07.

Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.